plot3 0.8.1__tar.gz → 0.9.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.
- {plot3-0.8.1 → plot3-0.9.0}/PKG-INFO +2 -2
- plot3-0.9.0/plot3/__version__.py +1 -0
- {plot3-0.8.1 → plot3-0.9.0}/plot3/jupyter.py +57 -49
- {plot3-0.8.1 → plot3-0.9.0}/plot3/masking.py +20 -1
- {plot3-0.8.1 → plot3-0.9.0}/plot3.egg-info/PKG-INFO +2 -2
- {plot3-0.8.1 → plot3-0.9.0}/plot3.egg-info/SOURCES.txt +1 -0
- plot3-0.9.0/plot3.egg-info/entry_points.txt +2 -0
- {plot3-0.8.1 → plot3-0.9.0}/plot3.egg-info/requires.txt +1 -1
- {plot3-0.8.1 → plot3-0.9.0}/pyproject.toml +6 -1
- {plot3-0.8.1 → plot3-0.9.0}/tests/test_masking.py +21 -11
- plot3-0.8.1/plot3/__version__.py +0 -1
- {plot3-0.8.1 → plot3-0.9.0}/LICENSE +0 -0
- {plot3-0.8.1 → plot3-0.9.0}/README.md +0 -0
- {plot3-0.8.1 → plot3-0.9.0}/plot3/__init__.py +0 -0
- {plot3-0.8.1 → plot3-0.9.0}/plot3/aesexpr.py +0 -0
- {plot3-0.8.1 → plot3-0.9.0}/plot3/build.py +0 -0
- {plot3-0.8.1 → plot3-0.9.0}/plot3/calculus.py +0 -0
- {plot3-0.8.1 → plot3-0.9.0}/plot3/compose.py +0 -0
- {plot3-0.8.1 → plot3-0.9.0}/plot3/contour.py +0 -0
- {plot3-0.8.1 → plot3-0.9.0}/plot3/craft.py +0 -0
- {plot3-0.8.1 → plot3-0.9.0}/plot3/encode.py +0 -0
- {plot3-0.8.1 → plot3-0.9.0}/plot3/expr.py +0 -0
- {plot3-0.8.1 → plot3-0.9.0}/plot3/flip.py +0 -0
- {plot3-0.8.1 → plot3-0.9.0}/plot3/function.py +0 -0
- {plot3-0.8.1 → plot3-0.9.0}/plot3/geoms.py +0 -0
- {plot3-0.8.1 → plot3-0.9.0}/plot3/ggplot.py +0 -0
- {plot3-0.8.1 → plot3-0.9.0}/plot3/io.py +0 -0
- {plot3-0.8.1 → plot3-0.9.0}/plot3/kde.py +0 -0
- {plot3-0.8.1 → plot3-0.9.0}/plot3/latexin.py +0 -0
- {plot3-0.8.1 → plot3-0.9.0}/plot3/mathtext.py +0 -0
- {plot3-0.8.1 → plot3-0.9.0}/plot3/payload.py +0 -0
- {plot3-0.8.1 → plot3-0.9.0}/plot3/remote.py +0 -0
- {plot3-0.8.1 → plot3-0.9.0}/plot3/scales.py +0 -0
- {plot3-0.8.1 → plot3-0.9.0}/plot3/scaling.py +0 -0
- {plot3-0.8.1 → plot3-0.9.0}/plot3/special.py +0 -0
- {plot3-0.8.1 → plot3-0.9.0}/plot3/stat2d.py +0 -0
- {plot3-0.8.1 → plot3-0.9.0}/plot3/static.py +0 -0
- {plot3-0.8.1 → plot3-0.9.0}/plot3/stats3d.py +0 -0
- {plot3-0.8.1 → plot3-0.9.0}/plot3/table.py +0 -0
- {plot3-0.8.1 → plot3-0.9.0}/plot3/themes.py +0 -0
- {plot3-0.8.1 → plot3-0.9.0}/plot3/viewer.py +0 -0
- {plot3-0.8.1 → plot3-0.9.0}/plot3.egg-info/dependency_links.txt +0 -0
- {plot3-0.8.1 → plot3-0.9.0}/plot3.egg-info/top_level.txt +0 -0
- {plot3-0.8.1 → plot3-0.9.0}/setup.cfg +0 -0
- {plot3-0.8.1 → plot3-0.9.0}/tests/test_2d_density.py +0 -0
- {plot3-0.8.1 → plot3-0.9.0}/tests/test_3d.py +0 -0
- {plot3-0.8.1 → plot3-0.9.0}/tests/test_animation.py +0 -0
- {plot3-0.8.1 → plot3-0.9.0}/tests/test_annotate.py +0 -0
- {plot3-0.8.1 → plot3-0.9.0}/tests/test_api_public.py +0 -0
- {plot3-0.8.1 → plot3-0.9.0}/tests/test_array_backend.py +0 -0
- {plot3-0.8.1 → plot3-0.9.0}/tests/test_arrow.py +0 -0
- {plot3-0.8.1 → plot3-0.9.0}/tests/test_build_contract.py +0 -0
- {plot3-0.8.1 → plot3-0.9.0}/tests/test_contour.py +0 -0
- {plot3-0.8.1 → plot3-0.9.0}/tests/test_everyday_ggplot2.py +0 -0
- {plot3-0.8.1 → plot3-0.9.0}/tests/test_expr.py +0 -0
- {plot3-0.8.1 → plot3-0.9.0}/tests/test_facets_compose.py +0 -0
- {plot3-0.8.1 → plot3-0.9.0}/tests/test_fast_paths.py +0 -0
- {plot3-0.8.1 → plot3-0.9.0}/tests/test_geom_function.py +0 -0
- {plot3-0.8.1 → plot3-0.9.0}/tests/test_geoms_ds.py +0 -0
- {plot3-0.8.1 → plot3-0.9.0}/tests/test_ggplot2_extras2.py +0 -0
- {plot3-0.8.1 → plot3-0.9.0}/tests/test_ggplot2_parity.py +0 -0
- {plot3-0.8.1 → plot3-0.9.0}/tests/test_ggplot_extras.py +0 -0
- {plot3-0.8.1 → plot3-0.9.0}/tests/test_grammar.py +0 -0
- {plot3-0.8.1 → plot3-0.9.0}/tests/test_latex_input.py +0 -0
- {plot3-0.8.1 → plot3-0.9.0}/tests/test_lidar_scene.py +0 -0
- {plot3-0.8.1 → plot3-0.9.0}/tests/test_math_layers.py +0 -0
- {plot3-0.8.1 → plot3-0.9.0}/tests/test_mathtext.py +0 -0
- {plot3-0.8.1 → plot3-0.9.0}/tests/test_payload.py +0 -0
- {plot3-0.8.1 → plot3-0.9.0}/tests/test_payload_display.py +0 -0
- {plot3-0.8.1 → plot3-0.9.0}/tests/test_point_cloud.py +0 -0
- {plot3-0.8.1 → plot3-0.9.0}/tests/test_r_oracle_parity.py +0 -0
- {plot3-0.8.1 → plot3-0.9.0}/tests/test_readme.py +0 -0
- {plot3-0.8.1 → plot3-0.9.0}/tests/test_remote_bridge.py +0 -0
- {plot3-0.8.1 → plot3-0.9.0}/tests/test_review_fixes.py +0 -0
- {plot3-0.8.1 → plot3-0.9.0}/tests/test_save_menu.py +0 -0
- {plot3-0.8.1 → plot3-0.9.0}/tests/test_scales_api.py +0 -0
- {plot3-0.8.1 → plot3-0.9.0}/tests/test_scales_themes.py +0 -0
- {plot3-0.8.1 → plot3-0.9.0}/tests/test_special.py +0 -0
- {plot3-0.8.1 → plot3-0.9.0}/tests/test_stat2d.py +0 -0
- {plot3-0.8.1 → plot3-0.9.0}/tests/test_static_save.py +0 -0
- {plot3-0.8.1 → plot3-0.9.0}/tests/test_stats_semantic.py +0 -0
- {plot3-0.8.1 → plot3-0.9.0}/tests/test_step3_geoms.py +0 -0
- {plot3-0.8.1 → plot3-0.9.0}/tests/test_table_backends.py +0 -0
- {plot3-0.8.1 → plot3-0.9.0}/tests/test_titles_theme.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: plot3
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.9.0
|
|
4
4
|
Summary: ggplot2 grammar of graphics for Python: interactive WebGL figures and journal-ready PNG, SVG, and PDF
|
|
5
5
|
Author: Rigoberto Leyva Salmeron
|
|
6
6
|
License-Expression: MIT
|
|
@@ -17,7 +17,7 @@ Description-Content-Type: text/markdown
|
|
|
17
17
|
License-File: LICENSE
|
|
18
18
|
Requires-Dist: numpy>=1.24
|
|
19
19
|
Requires-Dist: pandas>=2.0
|
|
20
|
-
Requires-Dist: tidy3syntax<0.2,>=0.1
|
|
20
|
+
Requires-Dist: tidy3syntax<0.2,>=0.1.2
|
|
21
21
|
Provides-Extra: pdf
|
|
22
22
|
Requires-Dist: cairosvg>=2.7; extra == "pdf"
|
|
23
23
|
Provides-Extra: dev
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.9.0"
|
|
@@ -4,10 +4,12 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
import json
|
|
6
6
|
import shlex
|
|
7
|
+
import dataclasses
|
|
7
8
|
from typing import Any
|
|
8
9
|
|
|
9
10
|
import numpy as np
|
|
10
11
|
import pandas as pd
|
|
12
|
+
import tidy3syntax.ipython
|
|
11
13
|
|
|
12
14
|
try:
|
|
13
15
|
from IPython import get_ipython
|
|
@@ -17,13 +19,11 @@ except Exception: # pragma: no cover
|
|
|
17
19
|
from plot3.io import ssh_bytes
|
|
18
20
|
from plot3.masking import (
|
|
19
21
|
BT_NAME,
|
|
22
|
+
DIALECT,
|
|
20
23
|
Plot3MaskTransformer,
|
|
24
|
+
_plot3_names,
|
|
21
25
|
is_backtick_transformer,
|
|
22
26
|
is_mask_transformer,
|
|
23
|
-
is_tidy3_backtick_transformer,
|
|
24
|
-
plot3_backtick_transform,
|
|
25
|
-
plot3_formula_transform,
|
|
26
|
-
plot3_layer_transform,
|
|
27
27
|
)
|
|
28
28
|
|
|
29
29
|
# R-style bare-name / backtick masking for aes() / facet_wrap().
|
|
@@ -60,34 +60,39 @@ def enable_r_style(ipython: Any | None = None) -> bool:
|
|
|
60
60
|
if ns is not None:
|
|
61
61
|
# Escape hatch if AST missed a sentinel (still a valid column string).
|
|
62
62
|
ns[BT_NAME] = _bt_fallback
|
|
63
|
-
# When tidy3 is not loaded, leave tidy3 sentinel unset; plot3 AST
|
|
64
|
-
# still rewrites __tidy3_bt__ if tidy3's preparser ran first.
|
|
65
63
|
|
|
66
|
-
#
|
|
67
|
-
#
|
|
64
|
+
# The source rewrites (backticks, facet formulas, ^ in geom_function,
|
|
65
|
+
# + layer lines) go through tidy3syntax's coordinator, one transformer
|
|
66
|
+
# shared with tidy3, tidy3a and stats3; the AST pass masks aes() names.
|
|
67
|
+
_remove_own(ipython)
|
|
68
|
+
tidy3syntax.ipython.register(ipython, _dialect(), ast_transformer=Plot3MaskTransformer())
|
|
69
|
+
return True
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def _dialect():
|
|
73
|
+
"""plot3's dialect, with every public plot3 name as a layer a "+" line may add."""
|
|
74
|
+
return dataclasses.replace(DIALECT, layer_calls=frozenset(_plot3_names()))
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def _layers_only():
|
|
78
|
+
"""Only the "+" layer lines, for R-style masking turned off."""
|
|
79
|
+
return dataclasses.replace(
|
|
80
|
+
_dialect(), formula_calls=(), formula_keywords=(), power_calls=(), unary_formula_calls=()
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def _remove_own(ipython: Any) -> None:
|
|
85
|
+
"""An earlier plot3's own transformers, from before the coordinator."""
|
|
68
86
|
for attr in ("input_transformers_cleanup", "input_transformers_post"):
|
|
69
87
|
transformers = getattr(ipython, attr, None)
|
|
70
|
-
if
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
tidy3_at = [
|
|
76
|
-
i for i, t in enumerate(transformers) if is_tidy3_backtick_transformer(t)
|
|
77
|
-
]
|
|
78
|
-
if tidy3_at:
|
|
79
|
-
transformers.insert(tidy3_at[-1] + 1, plot3_formula_transform)
|
|
80
|
-
else:
|
|
81
|
-
transformers.insert(0, plot3_backtick_transform)
|
|
82
|
-
|
|
83
|
-
# AST pass for bare names inside aes / facet_wrap.
|
|
88
|
+
if isinstance(transformers, list):
|
|
89
|
+
transformers[:] = [
|
|
90
|
+
t for t in transformers
|
|
91
|
+
if not is_backtick_transformer(t) and getattr(t, "__name__", "") != "plot3_layer_transform"
|
|
92
|
+
]
|
|
84
93
|
ast_transformers = getattr(ipython, "ast_transformers", None)
|
|
85
94
|
if isinstance(ast_transformers, list):
|
|
86
|
-
ast_transformers[:] = [
|
|
87
|
-
t for t in ast_transformers if not is_mask_transformer(t)
|
|
88
|
-
]
|
|
89
|
-
ast_transformers.append(Plot3MaskTransformer())
|
|
90
|
-
return True
|
|
95
|
+
ast_transformers[:] = [t for t in ast_transformers if not is_mask_transformer(t)]
|
|
91
96
|
|
|
92
97
|
|
|
93
98
|
def disable_r_style(ipython: Any | None = None) -> None:
|
|
@@ -101,17 +106,9 @@ def disable_r_style(ipython: Any | None = None) -> None:
|
|
|
101
106
|
ipython = None
|
|
102
107
|
if ipython is None:
|
|
103
108
|
return
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
transformers[:] = [
|
|
108
|
-
t for t in transformers if not is_backtick_transformer(t)
|
|
109
|
-
]
|
|
110
|
-
ast_transformers = getattr(ipython, "ast_transformers", None)
|
|
111
|
-
if isinstance(ast_transformers, list):
|
|
112
|
-
ast_transformers[:] = [
|
|
113
|
-
t for t in ast_transformers if not is_mask_transformer(t)
|
|
114
|
-
]
|
|
109
|
+
_remove_own(ipython)
|
|
110
|
+
# The "+" layer lines stay, as before: only the R-style masking goes.
|
|
111
|
+
tidy3syntax.ipython.register(ipython, _layers_only())
|
|
115
112
|
|
|
116
113
|
|
|
117
114
|
def r_style_enabled() -> bool:
|
|
@@ -482,20 +479,20 @@ def enable_layer_lines(ipython: Any | None = None) -> bool:
|
|
|
482
479
|
ipython = get_ipython() if get_ipython is not None else None
|
|
483
480
|
except Exception:
|
|
484
481
|
ipython = None
|
|
485
|
-
|
|
486
|
-
if not isinstance(transformers, list):
|
|
482
|
+
if ipython is None or not isinstance(getattr(ipython, "input_transformers_cleanup", None), list):
|
|
487
483
|
return False
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
transformers.append(plot3_layer_transform)
|
|
484
|
+
# The layer lines are part of plot3's dialect in tidy3syntax's coordinator.
|
|
485
|
+
if "plot3" not in tidy3syntax.ipython.registered(ipython):
|
|
486
|
+
tidy3syntax.ipython.register(ipython, _layers_only())
|
|
492
487
|
return True
|
|
493
488
|
|
|
494
489
|
|
|
495
|
-
def register_plot3(*, quiet=True, r_style: bool = True) -> bool:
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
490
|
+
def register_plot3(*, quiet=True, r_style: bool = True, ipython: Any | None = None) -> bool:
|
|
491
|
+
ip = ipython
|
|
492
|
+
if ip is None:
|
|
493
|
+
if get_ipython is None:
|
|
494
|
+
return False
|
|
495
|
+
ip = get_ipython()
|
|
499
496
|
if ip is None:
|
|
500
497
|
return False
|
|
501
498
|
ok = False
|
|
@@ -546,4 +543,15 @@ def register_plot3(*, quiet=True, r_style: bool = True) -> bool:
|
|
|
546
543
|
|
|
547
544
|
|
|
548
545
|
def load_ipython_extension(ip=None):
|
|
549
|
-
register_plot3(quiet=True)
|
|
546
|
+
register_plot3(quiet=True, ipython=ip)
|
|
547
|
+
|
|
548
|
+
|
|
549
|
+
def dialect():
|
|
550
|
+
"""plot3's dialect for tidy3syntax (its ``tidy3syntax.dialects`` entry point): the
|
|
551
|
+
notebook loader, and plot3's bare-name masking for exports."""
|
|
552
|
+
from plot3.masking import apply_masking, default_known_names
|
|
553
|
+
|
|
554
|
+
def mask(source: str, known: frozenset[str]) -> str:
|
|
555
|
+
return apply_masking(source, known=set(known) | default_known_names(), backticks=False)
|
|
556
|
+
|
|
557
|
+
return dataclasses.replace(_dialect(), extension="plot3.jupyter:load_ipython_extension", mask=mask)
|
|
@@ -43,7 +43,8 @@ from tidy3syntax.scanner import Spans, apply
|
|
|
43
43
|
# Sentinels (plot3 own + tidy3 compatibility).
|
|
44
44
|
BT_NAME = "__plot3_bt__"
|
|
45
45
|
TIDY3_BT_NAME = "__tidy3_bt__"
|
|
46
|
-
|
|
46
|
+
# tidy3syntax's neutral name too: another package's pass (tidy3a's) may rewrite a backtick in aes() first.
|
|
47
|
+
_BT_SENTINELS = frozenset({BT_NAME, TIDY3_BT_NAME, tidy3syntax.NAME})
|
|
47
48
|
|
|
48
49
|
# Calls whose arguments / keywords are column *selectors* (→ strings).
|
|
49
50
|
_SELECTOR_FUNCS = frozenset(
|
|
@@ -493,6 +494,22 @@ class Plot3MaskTransformer(ast.NodeTransformer):
|
|
|
493
494
|
|
|
494
495
|
def __init__(self, known: set[str] | None = None):
|
|
495
496
|
self._known_static = known
|
|
497
|
+
self._owners: tidy3syntax.Owners | None = None
|
|
498
|
+
|
|
499
|
+
def visit_Module(self, node: ast.Module) -> ast.AST:
|
|
500
|
+
# Whose aes() or facet_wrap() each call is: a notebook's own function of that name keeps
|
|
501
|
+
# its arguments as written (tidy3syntax's rule, as for the source rewrites).
|
|
502
|
+
namespace = None if self._known_static is not None else _session_namespace(_SESSION)
|
|
503
|
+
self._owners = tidy3syntax.Owners(node, namespace, [DIALECT])
|
|
504
|
+
try:
|
|
505
|
+
return self.generic_visit(node)
|
|
506
|
+
finally:
|
|
507
|
+
self._owners = None
|
|
508
|
+
|
|
509
|
+
def _plot3s(self, func: ast.AST) -> bool:
|
|
510
|
+
if self._owners is None:
|
|
511
|
+
return True
|
|
512
|
+
return self._owners.owner(func, (func.lineno, func.col_offset)) == "plot3"
|
|
496
513
|
|
|
497
514
|
def _known(self) -> set[str]:
|
|
498
515
|
if self._known_static is not None:
|
|
@@ -541,6 +558,8 @@ class Plot3MaskTransformer(ast.NodeTransformer):
|
|
|
541
558
|
return self.generic_visit(node)
|
|
542
559
|
|
|
543
560
|
name = node.func.id
|
|
561
|
+
if (name in _FORMULA_CALLS or name in _SELECTOR_FUNCS) and not self._plot3s(node.func):
|
|
562
|
+
return self.generic_visit(node)
|
|
544
563
|
if name in _FORMULA_CALLS:
|
|
545
564
|
return self._visit_geom_function(node)
|
|
546
565
|
if name not in _SELECTOR_FUNCS:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: plot3
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.9.0
|
|
4
4
|
Summary: ggplot2 grammar of graphics for Python: interactive WebGL figures and journal-ready PNG, SVG, and PDF
|
|
5
5
|
Author: Rigoberto Leyva Salmeron
|
|
6
6
|
License-Expression: MIT
|
|
@@ -17,7 +17,7 @@ Description-Content-Type: text/markdown
|
|
|
17
17
|
License-File: LICENSE
|
|
18
18
|
Requires-Dist: numpy>=1.24
|
|
19
19
|
Requires-Dist: pandas>=2.0
|
|
20
|
-
Requires-Dist: tidy3syntax<0.2,>=0.1
|
|
20
|
+
Requires-Dist: tidy3syntax<0.2,>=0.1.2
|
|
21
21
|
Provides-Extra: pdf
|
|
22
22
|
Requires-Dist: cairosvg>=2.7; extra == "pdf"
|
|
23
23
|
Provides-Extra: dev
|
|
@@ -24,13 +24,18 @@ dependencies = [
|
|
|
24
24
|
"pandas>=2.0",
|
|
25
25
|
# The notebook syntax tidy3, tidy3a, plot3 and stats3 share (facet
|
|
26
26
|
# formulas, ^ in geom_function, backtick names). Standard library only.
|
|
27
|
-
"tidy3syntax>=0.1,<0.2",
|
|
27
|
+
"tidy3syntax>=0.1.2,<0.2",
|
|
28
28
|
]
|
|
29
29
|
|
|
30
30
|
[project.optional-dependencies]
|
|
31
31
|
pdf = ["cairosvg>=2.7"]
|
|
32
32
|
dev = ["pytest>=7.0", "polars>=1.0", "contourpy>=1.0"]
|
|
33
33
|
|
|
34
|
+
# A notebook cell that imports plot3 gets its syntax in that same cell
|
|
35
|
+
# (its dialect names the notebook loader tidy3syntax's coordinator calls).
|
|
36
|
+
[project.entry-points."tidy3syntax.dialects"]
|
|
37
|
+
plot3 = "plot3.jupyter:dialect"
|
|
38
|
+
|
|
34
39
|
[project.urls]
|
|
35
40
|
Homepage = "https://github.com/rleyvasal/plot3"
|
|
36
41
|
Changelog = "https://github.com/rleyvasal/plot3/blob/main/CHANGELOG.md"
|
|
@@ -309,11 +309,10 @@ _fake_tidy3_transform.__module__ = "tidy3.masking"
|
|
|
309
309
|
_fake_tidy3_transform.__name__ = "tidy3_backtick_transform"
|
|
310
310
|
|
|
311
311
|
|
|
312
|
-
def
|
|
313
|
-
#
|
|
314
|
-
#
|
|
312
|
+
def test_one_coordinator_ahead_of_other_transformers():
|
|
313
|
+
# plot3's source rewrites run in tidy3syntax's coordinator, one transformer
|
|
314
|
+
# for every package, put first; other packages' transformers stay.
|
|
315
315
|
from plot3.jupyter import enable_r_style
|
|
316
|
-
from plot3.masking import plot3_formula_transform
|
|
317
316
|
|
|
318
317
|
def other(lines):
|
|
319
318
|
return lines
|
|
@@ -321,15 +320,21 @@ def test_formula_rewrites_run_after_tidy3_preparser():
|
|
|
321
320
|
ip = _shell(_fake_tidy3_transform, other)
|
|
322
321
|
enable_r_style(ip)
|
|
323
322
|
enable_r_style(ip) # idempotent
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
]
|
|
327
|
-
out = "".join(
|
|
323
|
+
coordinator, *rest = ip.input_transformers_cleanup
|
|
324
|
+
assert getattr(coordinator, "tidy3syntax", False)
|
|
325
|
+
assert rest == [_fake_tidy3_transform, other]
|
|
326
|
+
out = "".join(coordinator(["p = geom_function(y = x^3) + facet_wrap(~cyl)\n"]))
|
|
328
327
|
assert out == "p = geom_function(y = x**3) + facet_wrap('~cyl')\n"
|
|
328
|
+
assert out == "".join(coordinator([out])) # a second pass changes nothing
|
|
329
329
|
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
330
|
+
|
|
331
|
+
def test_a_notebooks_own_aes_keeps_its_arguments():
|
|
332
|
+
from plot3.masking import Plot3MaskTransformer
|
|
333
|
+
|
|
334
|
+
tree = ast.parse("def aes(**kw):\n return kw\nr = aes(x=wt)")
|
|
335
|
+
assert "x=wt" in ast.unparse(Plot3MaskTransformer(known=default_known_names()).visit(tree))
|
|
336
|
+
tree = ast.parse("r = aes(x=wt)")
|
|
337
|
+
assert "x='wt'" in ast.unparse(Plot3MaskTransformer(known=default_known_names()).visit(tree))
|
|
333
338
|
|
|
334
339
|
|
|
335
340
|
# ── Valid Python keeps its meaning outside plot3's calls ─────────────────────
|
|
@@ -435,3 +440,8 @@ def test_plot3_calls_still_take_r_syntax_in_a_notebook():
|
|
|
435
440
|
from IPython.core.interactiveshell import InteractiveShell
|
|
436
441
|
|
|
437
442
|
InteractiveShell.clear_instance()
|
|
443
|
+
|
|
444
|
+
|
|
445
|
+
def test_the_shared_backtick_placeholder_is_a_column_name():
|
|
446
|
+
# tidy3a's notebook pass may rewrite `First Name` in aes() before plot3's runs.
|
|
447
|
+
assert _norm("aes(x=__r_name__('First Name'), y=mpg)") == "aes(x='First Name', y='mpg')"
|
plot3-0.8.1/plot3/__version__.py
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.8.1"
|
|
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
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|