tidy3syntax 0.1.2__tar.gz → 0.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {tidy3syntax-0.1.2 → tidy3syntax-0.2.0}/CHANGELOG.md +14 -0
- {tidy3syntax-0.1.2/src/tidy3syntax.egg-info → tidy3syntax-0.2.0}/PKG-INFO +11 -9
- {tidy3syntax-0.1.2 → tidy3syntax-0.2.0}/README.md +10 -8
- {tidy3syntax-0.1.2 → tidy3syntax-0.2.0}/docs/design.md +3 -3
- tidy3syntax-0.2.0/src/tidy3syntax/__version__.py +1 -0
- {tidy3syntax-0.1.2 → tidy3syntax-0.2.0}/src/tidy3syntax/dialect.py +9 -5
- {tidy3syntax-0.1.2 → tidy3syntax-0.2.0}/src/tidy3syntax/repairs.py +2 -2
- {tidy3syntax-0.1.2 → tidy3syntax-0.2.0/src/tidy3syntax.egg-info}/PKG-INFO +11 -9
- {tidy3syntax-0.1.2 → tidy3syntax-0.2.0}/tests/test_ipython.py +2 -2
- {tidy3syntax-0.1.2 → tidy3syntax-0.2.0}/tests/test_reinterpretations.py +2 -2
- tidy3syntax-0.1.2/src/tidy3syntax/__version__.py +0 -1
- {tidy3syntax-0.1.2 → tidy3syntax-0.2.0}/LICENSE +0 -0
- {tidy3syntax-0.1.2 → tidy3syntax-0.2.0}/MANIFEST.in +0 -0
- {tidy3syntax-0.1.2 → tidy3syntax-0.2.0}/pyproject.toml +0 -0
- {tidy3syntax-0.1.2 → tidy3syntax-0.2.0}/setup.cfg +0 -0
- {tidy3syntax-0.1.2 → tidy3syntax-0.2.0}/src/tidy3syntax/__init__.py +0 -0
- {tidy3syntax-0.1.2 → tidy3syntax-0.2.0}/src/tidy3syntax/continuation.py +0 -0
- {tidy3syntax-0.1.2 → tidy3syntax-0.2.0}/src/tidy3syntax/ipython.py +0 -0
- {tidy3syntax-0.1.2 → tidy3syntax-0.2.0}/src/tidy3syntax/ownership.py +0 -0
- {tidy3syntax-0.1.2 → tidy3syntax-0.2.0}/src/tidy3syntax/pipeline.py +0 -0
- {tidy3syntax-0.1.2 → tidy3syntax-0.2.0}/src/tidy3syntax/placeholders.py +0 -0
- {tidy3syntax-0.1.2 → tidy3syntax-0.2.0}/src/tidy3syntax/py.typed +0 -0
- {tidy3syntax-0.1.2 → tidy3syntax-0.2.0}/src/tidy3syntax/scanner.py +0 -0
- {tidy3syntax-0.1.2 → tidy3syntax-0.2.0}/src/tidy3syntax.egg-info/SOURCES.txt +0 -0
- {tidy3syntax-0.1.2 → tidy3syntax-0.2.0}/src/tidy3syntax.egg-info/dependency_links.txt +0 -0
- {tidy3syntax-0.1.2 → tidy3syntax-0.2.0}/src/tidy3syntax.egg-info/requires.txt +0 -0
- {tidy3syntax-0.1.2 → tidy3syntax-0.2.0}/src/tidy3syntax.egg-info/top_level.txt +0 -0
- {tidy3syntax-0.1.2 → tidy3syntax-0.2.0}/tests/dialects.py +0 -0
- {tidy3syntax-0.1.2 → tidy3syntax-0.2.0}/tests/test_continuation.py +0 -0
- {tidy3syntax-0.1.2 → tidy3syntax-0.2.0}/tests/test_integration.py +0 -0
- {tidy3syntax-0.1.2 → tidy3syntax-0.2.0}/tests/test_properties.py +0 -0
- {tidy3syntax-0.1.2 → tidy3syntax-0.2.0}/tests/test_repairs.py +0 -0
- {tidy3syntax-0.1.2 → tidy3syntax-0.2.0}/tests/test_scanner.py +0 -0
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.2.0 — 2026-11-02
|
|
4
|
+
|
|
5
|
+
Phase 7 of [the design](docs/design.md).
|
|
6
|
+
|
|
7
|
+
### Changed
|
|
8
|
+
|
|
9
|
+
- `Dialect.mask` takes the notebook's imports as a third argument,
|
|
10
|
+
`mask(source, known, context)`, so a package's export masking can tell its
|
|
11
|
+
own calls from another package's; `Dialect.export_imports` lists the lines
|
|
12
|
+
an exported script needs once the mask changed something (`import tidy3a`).
|
|
13
|
+
- A formula being quoted turns only `__r_name__` back into a backtick name;
|
|
14
|
+
tidy3's `__tidy3_bt__` and plot3's `__plot3_bt__`, which no release of
|
|
15
|
+
either writes since tidy3 0.17 and plot3 0.10, are no longer read.
|
|
16
|
+
|
|
3
17
|
## 0.1.2 — 2026-11-01
|
|
4
18
|
|
|
5
19
|
Phase 6a of [the design](docs/design.md): continuation lines and the coordinator.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: tidy3syntax
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0
|
|
4
4
|
Summary: R syntax in notebook cells, rewritten to Python: shared by tidy3, tidy3a, plot3 and stats3
|
|
5
5
|
Author: Rigoberto Leyva Salmeron
|
|
6
6
|
License-Expression: MIT
|
|
@@ -115,11 +115,12 @@ the ownership rule and the two reinterpretations, used by tidy3 0.15.1, tidy3a
|
|
|
115
115
|
tidy3, `+` for plot3) and the coordinator, in 0.1.2, which tidy3 0.16, tidy3a
|
|
116
116
|
0.17, plot3 0.9 and stats3 0.7 register with.
|
|
117
117
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
`
|
|
118
|
+
Phase 7, in 0.2.0: `__r_name__` and `__r_assign__` are the only
|
|
119
|
+
placeholders any package writes or reads; the packages' own names from before
|
|
120
|
+
(`__tidy3_bt__`, `__plot3_bt__`) are gone. Inside its own calls each
|
|
121
|
+
package's AST pass renames `__r_assign__` to a private name of its own
|
|
122
|
+
(`__tidy3_assign__`, `__tidy3a_assign__`), since the shared name's value in a
|
|
123
|
+
namespace can belong to no single package.
|
|
123
124
|
|
|
124
125
|
Where the output differs from a package's own rewrite before the switch:
|
|
125
126
|
|
|
@@ -129,9 +130,10 @@ Where the output differs from a package's own rewrite before the switch:
|
|
|
129
130
|
(`df.select(a = x, b)`) is rewritten like the verb, as `!` in one already
|
|
130
131
|
was; backticks inside strings and comments stay; a backtick assignment is
|
|
131
132
|
rewritten only as a call argument.
|
|
132
|
-
- tidy3a: its placeholder is `__r_assign__
|
|
133
|
-
- plot3: a
|
|
134
|
-
(`facet_wrap(~
|
|
133
|
+
- tidy3a: its placeholder is `__r_assign__`.
|
|
134
|
+
- plot3: a backtick name inside a one-sided facet formula that another
|
|
135
|
+
package's rewrite reached first (`facet_wrap(~__r_name__('a b'))`) becomes
|
|
136
|
+
the name again: `'~a b'`.
|
|
135
137
|
|
|
136
138
|
`scripts/family/` runs all five suites together on another machine: `sync.sh`
|
|
137
139
|
copies the working trees and starts `run.sh` in a tmux session there, and
|
|
@@ -95,11 +95,12 @@ the ownership rule and the two reinterpretations, used by tidy3 0.15.1, tidy3a
|
|
|
95
95
|
tidy3, `+` for plot3) and the coordinator, in 0.1.2, which tidy3 0.16, tidy3a
|
|
96
96
|
0.17, plot3 0.9 and stats3 0.7 register with.
|
|
97
97
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
`
|
|
98
|
+
Phase 7, in 0.2.0: `__r_name__` and `__r_assign__` are the only
|
|
99
|
+
placeholders any package writes or reads; the packages' own names from before
|
|
100
|
+
(`__tidy3_bt__`, `__plot3_bt__`) are gone. Inside its own calls each
|
|
101
|
+
package's AST pass renames `__r_assign__` to a private name of its own
|
|
102
|
+
(`__tidy3_assign__`, `__tidy3a_assign__`), since the shared name's value in a
|
|
103
|
+
namespace can belong to no single package.
|
|
103
104
|
|
|
104
105
|
Where the output differs from a package's own rewrite before the switch:
|
|
105
106
|
|
|
@@ -109,9 +110,10 @@ Where the output differs from a package's own rewrite before the switch:
|
|
|
109
110
|
(`df.select(a = x, b)`) is rewritten like the verb, as `!` in one already
|
|
110
111
|
was; backticks inside strings and comments stay; a backtick assignment is
|
|
111
112
|
rewritten only as a call argument.
|
|
112
|
-
- tidy3a: its placeholder is `__r_assign__
|
|
113
|
-
- plot3: a
|
|
114
|
-
(`facet_wrap(~
|
|
113
|
+
- tidy3a: its placeholder is `__r_assign__`.
|
|
114
|
+
- plot3: a backtick name inside a one-sided facet formula that another
|
|
115
|
+
package's rewrite reached first (`facet_wrap(~__r_name__('a b'))`) becomes
|
|
116
|
+
the name again: `'~a b'`.
|
|
115
117
|
|
|
116
118
|
`scripts/family/` runs all five suites together on another machine: `sync.sh`
|
|
117
119
|
copies the working trees and starts `run.sh` in a tmux session there, and
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# A shared package for R syntax in notebooks
|
|
2
2
|
|
|
3
|
-
Status: accepted 2026-11-01; phases 1 to
|
|
3
|
+
Status: accepted 2026-11-01; phases 1 to 6 (§8) implemented and released (tidy3syntax 0.1.2, tidy3 0.16.0, tidy3a 0.17.0, plot3 0.9.0, stats3 0.7.0); phase 7 released in tidy3syntax 0.2.0, tidy3 0.17.0, tidy3a 0.18.0, plot3 0.10.0 and stats3 0.8.0.
|
|
4
4
|
|
|
5
5
|
tidy3, tidy3a, plot3 and stats3 each let notebook cells use R syntax that Python
|
|
6
6
|
cannot parse: bare column names, `` `odd names` ``, `!` for negation, `name =
|
|
@@ -409,10 +409,10 @@ tidy3 0.14's backtick pass rewrites backticks inside string literals too. When i
|
|
|
409
409
|
6. **Coordinator, continuation lines and ownership in the AST passes.** Install the single transformer and the entry points; move tidy3's `>>` and plot3's `+` continuation lines; let each package's AST pass use the shared `Owners`. Delete tidy3's plot3 hook and plot3 imports from `export.py`. Exit check: the four-package notebook passes in all 24 load orders. In three steps, each released on its own (planned 2026-11-01):
|
|
410
410
|
- **6a, tidy3syntax only (0.1.2, additive).** Continuation lines: a line starting with `>>` continues the statement above, a repair (tidy3's `_wrap_pipe_statements`, and `join_broken_pipe`, which joins a broken pipe with backslashes so Python names the real error); an indented `+` line is a repair; an unindented `+` line is a reinterpretation, joined only when the call after `+` is owned by the dialect that lists it and the statement above starts with an owned call or ends a pipe whose last step is one. tidy3 today joins a `+` line after any pipe by name, the §1.3 bug for `+`; this replaces it. The coordinator, `tidy3syntax.ipython`: one input transformer for every registered dialect, kept ahead of CRAFT's router before each cell (tidy3's `pre_run_cell` hook does this today), the importing cell (§4.7), and entry points. The integration test: a notebook with the four packages in all 24 load orders, run in this repository's CI on pull requests and weekly.
|
|
411
411
|
- **6b, each package (one release each).** Register with the coordinator instead of installing a transformer; delete its continuation code, its handling of the other packages' placeholders and hooks (tidy3's plot3 hook and `export.py`'s plot3 imports); write the neutral names; use `Owners` in its AST pass. Packages on 6b and packages not yet on it must still share a notebook: the coordinator leaves a package's own transformer in place until that package registers.
|
|
412
|
-
- **6c.** The integration test passes against the four packages' releases.
|
|
412
|
+
- **6c.** The integration test passes against the four packages' releases. *Done 2026-11-01:* tidy3syntax's CI installed tidy3 0.16.0, tidy3a 0.17.0, plot3 0.9.0 and stats3 0.7.0 from PyPI with tidy3syntax 0.1.2, and all 24 load orders passed.
|
|
413
413
|
|
|
414
414
|
Progress (2026-11-02): 6a is committed (continuation lines, the coordinator, the integration test). 6b is done in the four packages' working trees, not released: each registers with the coordinator and declares an entry point; stats3, tidy3a and plot3 read `__r_name__` as a column; each AST pass renames `__r_assign__` to its own private name inside its own calls (`__tidy3_assign__`, `__tidy3a_assign__`), since the shared name's value in the namespace can belong to no single package; plot3's AST pass checks ownership with `Owners`; tidy3a takes `>>` continuation lines; tidy3's `pre_run_cell` hook and plot3 hook are gone, and plot3 no longer looks for tidy3's preparser. tidy3's `nb_export`, partial runs and CRAFT path rewrite through tidy3syntax as well (2026-11-02): an entry point names a function returning the package's dialect, whose `extension` is its notebook loader and whose `mask` applies its AST pass to source text; `tidy3syntax.installed()` lists them, so `export.py` finds plot3 without importing it. tidy3a's and stats3's dialects have no `mask` yet: their AST passes write internal names an export cannot turn into public code, and tidy3's export did not handle them before either. At release, tidy3 should require the plot3 release that has the entry point.
|
|
415
|
-
7. **Drop the old placeholder aliases** two minor releases after phase 2.
|
|
415
|
+
7. **Drop the old placeholder aliases** two minor releases after phase 2. *Done 2026-11-01, one minor release after phase 2 at the owner's choice, and released 2026-11-02:* the source passes write only `__r_name__` and `__r_assign__`, and no AST pass reads `__tidy3_bt__` or `__plot3_bt__`, or another package's assignment name; tidy3a no longer hands `__r_assign__` to tidy3. What stays are the private runtime names each AST pass renames `__r_assign__` to inside its own calls (`__tidy3_assign__`, `__tidy3a_assign__`), which no source text holds; scripts `nb_export` wrote define `__tidy3_assign__` themselves, so they keep running. A notebook mixing these releases with tidy3 0.15, tidy3a 0.16, plot3 0.8 or stats3 0.6 or older can lose backtick names in the other package's calls.
|
|
416
416
|
|
|
417
417
|
Phases 2 to 5 are independent once phase 1 is released. Phase 6 needs all four.
|
|
418
418
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.2.0"
|
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
import importlib
|
|
6
|
-
from collections.abc import Callable, Iterable
|
|
6
|
+
from collections.abc import Callable, Iterable, Mapping
|
|
7
7
|
from dataclasses import dataclass, field
|
|
8
|
-
from typing import Literal
|
|
8
|
+
from typing import Any, Literal
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
def _names(values: Iterable[str]) -> frozenset[str]:
|
|
@@ -51,9 +51,13 @@ class Dialect:
|
|
|
51
51
|
# The package's notebook loader, "module:function" taking the shell (its load_ipython_extension):
|
|
52
52
|
# the coordinator calls it for a cell that imports the package.
|
|
53
53
|
extension: str | None = field(default=None, compare=False)
|
|
54
|
-
# The package's AST pass on source text,
|
|
55
|
-
#
|
|
56
|
-
|
|
54
|
+
# The package's AST pass on source text, for an export: mask(source, known, context) -> source,
|
|
55
|
+
# where known holds the names that are not columns (the notebook's imports and assignments) and
|
|
56
|
+
# context maps the names the notebook imports to their modules (ownership.imported_names). The
|
|
57
|
+
# result is public code a plain script can run, given the dialect's export_imports.
|
|
58
|
+
mask: Callable[[str, frozenset[str], Mapping[str, Any]], str] | None = field(default=None, compare=False)
|
|
59
|
+
# Lines an exported script needs once the mask has changed a cell ("import tidy3a").
|
|
60
|
+
export_imports: tuple[str, ...] = field(default=(), compare=False)
|
|
57
61
|
|
|
58
62
|
def __post_init__(self) -> None:
|
|
59
63
|
for name in (
|
|
@@ -32,8 +32,8 @@ from tidy3syntax.scanner import (
|
|
|
32
32
|
)
|
|
33
33
|
|
|
34
34
|
_BACKTICK = re.compile(r"`([^`\n]+)`")
|
|
35
|
-
#
|
|
36
|
-
_NAME_CALL = re.compile(r"
|
|
35
|
+
# A backtick name another rewrite already turned into the placeholder, inside a formula being quoted.
|
|
36
|
+
_NAME_CALL = re.compile(r"__r_name__\((['\"])(.*?)\1\)")
|
|
37
37
|
|
|
38
38
|
|
|
39
39
|
def _union(dialects: Iterable[Dialect], field: str) -> frozenset[str]:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: tidy3syntax
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0
|
|
4
4
|
Summary: R syntax in notebook cells, rewritten to Python: shared by tidy3, tidy3a, plot3 and stats3
|
|
5
5
|
Author: Rigoberto Leyva Salmeron
|
|
6
6
|
License-Expression: MIT
|
|
@@ -115,11 +115,12 @@ the ownership rule and the two reinterpretations, used by tidy3 0.15.1, tidy3a
|
|
|
115
115
|
tidy3, `+` for plot3) and the coordinator, in 0.1.2, which tidy3 0.16, tidy3a
|
|
116
116
|
0.17, plot3 0.9 and stats3 0.7 register with.
|
|
117
117
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
`
|
|
118
|
+
Phase 7, in 0.2.0: `__r_name__` and `__r_assign__` are the only
|
|
119
|
+
placeholders any package writes or reads; the packages' own names from before
|
|
120
|
+
(`__tidy3_bt__`, `__plot3_bt__`) are gone. Inside its own calls each
|
|
121
|
+
package's AST pass renames `__r_assign__` to a private name of its own
|
|
122
|
+
(`__tidy3_assign__`, `__tidy3a_assign__`), since the shared name's value in a
|
|
123
|
+
namespace can belong to no single package.
|
|
123
124
|
|
|
124
125
|
Where the output differs from a package's own rewrite before the switch:
|
|
125
126
|
|
|
@@ -129,9 +130,10 @@ Where the output differs from a package's own rewrite before the switch:
|
|
|
129
130
|
(`df.select(a = x, b)`) is rewritten like the verb, as `!` in one already
|
|
130
131
|
was; backticks inside strings and comments stay; a backtick assignment is
|
|
131
132
|
rewritten only as a call argument.
|
|
132
|
-
- tidy3a: its placeholder is `__r_assign__
|
|
133
|
-
- plot3: a
|
|
134
|
-
(`facet_wrap(~
|
|
133
|
+
- tidy3a: its placeholder is `__r_assign__`.
|
|
134
|
+
- plot3: a backtick name inside a one-sided facet formula that another
|
|
135
|
+
package's rewrite reached first (`facet_wrap(~__r_name__('a b'))`) becomes
|
|
136
|
+
the name again: `'~a b'`.
|
|
135
137
|
|
|
136
138
|
`scripts/family/` runs all five suites together on another machine: `sync.sh`
|
|
137
139
|
copies the working trees and starts `run.sh` in a tmux session there, and
|
|
@@ -144,13 +144,13 @@ def test_entry_points_name_a_function_returning_the_dialect(shell, monkeypatch):
|
|
|
144
144
|
module.loaded = []
|
|
145
145
|
module.dialect = lambda: Dialect(
|
|
146
146
|
"fakeplot", power_calls={"geom_function"}, exports={"geom_function"},
|
|
147
|
-
extension="fakeplot:load", mask=lambda source, known: source.replace("MASKED", "masked"),
|
|
147
|
+
extension="fakeplot:load", mask=lambda source, known, context: source.replace("MASKED", "masked"),
|
|
148
148
|
)
|
|
149
149
|
module.load = lambda shell: (module.loaded.append(shell), coordinator.register(shell, module.dialect()))
|
|
150
150
|
_entry_points(monkeypatch, ("fakeplot", "fakeplot:dialect"), ("broken", "nowhere_at_all:dialect"))
|
|
151
151
|
|
|
152
152
|
assert [d.package for d in coordinator.installed()] == ["fakeplot"]
|
|
153
|
-
assert coordinator.installed()[0].mask("MASKED", frozenset()) == "masked"
|
|
153
|
+
assert coordinator.installed()[0].mask("MASKED", frozenset(), {}) == "masked"
|
|
154
154
|
|
|
155
155
|
coordinator.register(shell, VERBS)
|
|
156
156
|
ns = run(shell, "from fakeplot import geom_function\nr = geom_function(lambda x: x ^ 2)")
|
|
@@ -38,8 +38,8 @@ USER_GEOM_FUNCTION = "def geom_function(fun):\n return fun(3)\n"
|
|
|
38
38
|
("facet_wrap( ~ cyl , ncol=2)", "facet_wrap( '~ cyl' , ncol=2)"),
|
|
39
39
|
("p + facet_wrap(\n ~ gear,\n ncol=2)", "p + facet_wrap(\n '~ gear',\n ncol=2)"),
|
|
40
40
|
('facet_wrap("~cyl")', None),
|
|
41
|
-
#
|
|
42
|
-
("facet_wrap(~
|
|
41
|
+
# A backtick name the backtick repair already rewrote keeps its name inside the formula.
|
|
42
|
+
("facet_wrap(~__r_name__('my col'))", "facet_wrap('~my col')"),
|
|
43
43
|
],
|
|
44
44
|
)
|
|
45
45
|
def test_only_plot3_calls_are_reinterpreted(cell, expected):
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.1.2"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|