posit-dev / posit-dev/py-shiny
Express: Support trailing semicolon as a signal to not display that expression
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 1.8k
- Forks
- 135
- Avg merge
- 2d 18h
- Merged PRs (30d)
- 21
Description
In Jupyter, you can give an expression a trailing semicolon to suppress display.
"hello";
will show nothing.
Below is some code, inspired by IPython.core.displayhook, that will determine if an AST node has a trailing semicolon. (This information is not included in the AST so we have to go back and tokenize the source code.)
This should be very easy to integration into @display_body/@render.display because those functions already descend down to the level of each auto-displayed expression and wrap them with sys.displayhook(). This code can be used to decide on a node-by-node basis whether to skip that transformation.
However, it's not as easy with shiny.express._run, which executes e.g. with sidebar(): and its contents as a single top-level node. In order to support the semicolon check, we'd have to either do more AST transformation up front, or change the implementation of shiny.express._run to work more like @display_body.
def expr_ends_in_semicolon(node: ast.AST, filename: str) -> bool:
if node.end_lineno is None:
return False
end_line: int = node.end_lineno
last_line = linecache.getline(filename, end_line)
if last_line == "":
# The line could not be loaded (file not found?)
return False
# Do a cheap check first
if ";" not in last_line:
return False
def lines():
lineno = node.lineno
while lineno <= end_line:
line = linecache.getline(filename, lineno)
# if lineno == node.end_lineno:
# line = line[: node.end_col_offset]
if lineno == node.lineno:
line = line[node.col_offset :]
yield line
lineno += 1
yield ""
gen_lines = lines()
tokens = list(tokenize.generate_tokens(lambda: next(gen_lines, "")))
for token in reversed(tokens):
if token[0] in (
tokenize.ENDMARKER,
tokenize.NL,
tokenize.NEWLINE,
tokenize.COMMENT,
):
continue
if (token[0] == tokenize.OP) and (token[1] == ";"):
return True
else:
return False
return False
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reading @display_body, @render.display, and shiny.express._run to understand how expressions are auto-displayed and how top-level blocks are executed. Use the provided expr_ends_in_semicolon logic and the Jupyter example as behavioral references; done means trailing-semicolon expressions are suppressed without affecting other expressions, including the relevant execution paths.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- backend
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 38/100