ggplot2-python 4.0.2.9000.post1__tar.gz → 4.0.2.9000.post2__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.
Files changed (58) hide show
  1. {ggplot2_python-4.0.2.9000.post1 → ggplot2_python-4.0.2.9000.post2}/.gitignore +1 -0
  2. {ggplot2_python-4.0.2.9000.post1 → ggplot2_python-4.0.2.9000.post2}/PKG-INFO +1 -1
  3. {ggplot2_python-4.0.2.9000.post1 → ggplot2_python-4.0.2.9000.post2}/ggplot2_py/__init__.py +39 -4
  4. {ggplot2_python-4.0.2.9000.post1 → ggplot2_python-4.0.2.9000.post2}/ggplot2_py/aes.py +32 -4
  5. ggplot2_python-4.0.2.9000.post2/ggplot2_py/autoplot.py +79 -0
  6. {ggplot2_python-4.0.2.9000.post1 → ggplot2_python-4.0.2.9000.post2}/ggplot2_py/coord.py +1265 -0
  7. {ggplot2_python-4.0.2.9000.post1 → ggplot2_python-4.0.2.9000.post2}/ggplot2_py/coords/__init__.py +10 -0
  8. {ggplot2_python-4.0.2.9000.post1 → ggplot2_python-4.0.2.9000.post2}/ggplot2_py/facet.py +248 -81
  9. ggplot2_python-4.0.2.9000.post2/ggplot2_py/fortify.py +273 -0
  10. {ggplot2_python-4.0.2.9000.post1 → ggplot2_python-4.0.2.9000.post2}/ggplot2_py/geom.py +205 -32
  11. {ggplot2_python-4.0.2.9000.post1 → ggplot2_python-4.0.2.9000.post2}/ggplot2_py/ggproto.py +50 -0
  12. {ggplot2_python-4.0.2.9000.post1 → ggplot2_python-4.0.2.9000.post2}/ggplot2_py/guide.py +1778 -16
  13. {ggplot2_python-4.0.2.9000.post1 → ggplot2_python-4.0.2.9000.post2}/ggplot2_py/labeller.py +99 -0
  14. {ggplot2_python-4.0.2.9000.post1 → ggplot2_python-4.0.2.9000.post2}/ggplot2_py/layer.py +78 -14
  15. {ggplot2_python-4.0.2.9000.post1 → ggplot2_python-4.0.2.9000.post2}/ggplot2_py/plot.py +30 -20
  16. {ggplot2_python-4.0.2.9000.post1 → ggplot2_python-4.0.2.9000.post2}/ggplot2_py/plot_render.py +264 -37
  17. {ggplot2_python-4.0.2.9000.post1 → ggplot2_python-4.0.2.9000.post2}/ggplot2_py/position.py +14 -9
  18. {ggplot2_python-4.0.2.9000.post1 → ggplot2_python-4.0.2.9000.post2}/ggplot2_py/scale.py +42 -6
  19. {ggplot2_python-4.0.2.9000.post1 → ggplot2_python-4.0.2.9000.post2}/ggplot2_py/stat.py +1452 -399
  20. {ggplot2_python-4.0.2.9000.post1 → ggplot2_python-4.0.2.9000.post2}/ggplot2_py/theme.py +14 -0
  21. {ggplot2_python-4.0.2.9000.post1 → ggplot2_python-4.0.2.9000.post2}/ggplot2_py/theme_defaults.py +35 -13
  22. {ggplot2_python-4.0.2.9000.post1 → ggplot2_python-4.0.2.9000.post2}/pyproject.toml +1 -1
  23. ggplot2_python-4.0.2.9000.post1/ggplot2_py/fortify.py +0 -95
  24. {ggplot2_python-4.0.2.9000.post1 → ggplot2_python-4.0.2.9000.post2}/.gitattributes +0 -0
  25. {ggplot2_python-4.0.2.9000.post1 → ggplot2_python-4.0.2.9000.post2}/LICENSE +0 -0
  26. {ggplot2_python-4.0.2.9000.post1 → ggplot2_python-4.0.2.9000.post2}/README.md +0 -0
  27. {ggplot2_python-4.0.2.9000.post1 → ggplot2_python-4.0.2.9000.post2}/ggplot2_py/_compat.py +0 -0
  28. {ggplot2_python-4.0.2.9000.post1 → ggplot2_python-4.0.2.9000.post2}/ggplot2_py/_plugins.py +0 -0
  29. {ggplot2_python-4.0.2.9000.post1 → ggplot2_python-4.0.2.9000.post2}/ggplot2_py/_utils.py +0 -0
  30. {ggplot2_python-4.0.2.9000.post1 → ggplot2_python-4.0.2.9000.post2}/ggplot2_py/annotation.py +0 -0
  31. {ggplot2_python-4.0.2.9000.post1 → ggplot2_python-4.0.2.9000.post2}/ggplot2_py/datasets.py +0 -0
  32. {ggplot2_python-4.0.2.9000.post1 → ggplot2_python-4.0.2.9000.post2}/ggplot2_py/draw_key.py +0 -0
  33. {ggplot2_python-4.0.2.9000.post1 → ggplot2_python-4.0.2.9000.post2}/ggplot2_py/geoms/__init__.py +0 -0
  34. {ggplot2_python-4.0.2.9000.post1 → ggplot2_python-4.0.2.9000.post2}/ggplot2_py/guide_axis.py +0 -0
  35. {ggplot2_python-4.0.2.9000.post1 → ggplot2_python-4.0.2.9000.post2}/ggplot2_py/guide_colourbar.py +0 -0
  36. {ggplot2_python-4.0.2.9000.post1 → ggplot2_python-4.0.2.9000.post2}/ggplot2_py/guide_legend.py +0 -0
  37. {ggplot2_python-4.0.2.9000.post1 → ggplot2_python-4.0.2.9000.post2}/ggplot2_py/guides/__init__.py +0 -0
  38. {ggplot2_python-4.0.2.9000.post1 → ggplot2_python-4.0.2.9000.post2}/ggplot2_py/labels.py +0 -0
  39. {ggplot2_python-4.0.2.9000.post1 → ggplot2_python-4.0.2.9000.post2}/ggplot2_py/layout.py +0 -0
  40. {ggplot2_python-4.0.2.9000.post1 → ggplot2_python-4.0.2.9000.post2}/ggplot2_py/limits.py +0 -0
  41. {ggplot2_python-4.0.2.9000.post1 → ggplot2_python-4.0.2.9000.post2}/ggplot2_py/protocols.py +0 -0
  42. {ggplot2_python-4.0.2.9000.post1 → ggplot2_python-4.0.2.9000.post2}/ggplot2_py/py.typed +0 -0
  43. {ggplot2_python-4.0.2.9000.post1 → ggplot2_python-4.0.2.9000.post2}/ggplot2_py/qplot.py +0 -0
  44. {ggplot2_python-4.0.2.9000.post1 → ggplot2_python-4.0.2.9000.post2}/ggplot2_py/resources/diamonds.csv +0 -0
  45. {ggplot2_python-4.0.2.9000.post1 → ggplot2_python-4.0.2.9000.post2}/ggplot2_py/resources/economics.csv +0 -0
  46. {ggplot2_python-4.0.2.9000.post1 → ggplot2_python-4.0.2.9000.post2}/ggplot2_py/resources/economics_long.csv +0 -0
  47. {ggplot2_python-4.0.2.9000.post1 → ggplot2_python-4.0.2.9000.post2}/ggplot2_py/resources/faithfuld.csv +0 -0
  48. {ggplot2_python-4.0.2.9000.post1 → ggplot2_python-4.0.2.9000.post2}/ggplot2_py/resources/luv_colours.csv +0 -0
  49. {ggplot2_python-4.0.2.9000.post1 → ggplot2_python-4.0.2.9000.post2}/ggplot2_py/resources/midwest.csv +0 -0
  50. {ggplot2_python-4.0.2.9000.post1 → ggplot2_python-4.0.2.9000.post2}/ggplot2_py/resources/mpg.csv +0 -0
  51. {ggplot2_python-4.0.2.9000.post1 → ggplot2_python-4.0.2.9000.post2}/ggplot2_py/resources/msleep.csv +0 -0
  52. {ggplot2_python-4.0.2.9000.post1 → ggplot2_python-4.0.2.9000.post2}/ggplot2_py/resources/presidential.csv +0 -0
  53. {ggplot2_python-4.0.2.9000.post1 → ggplot2_python-4.0.2.9000.post2}/ggplot2_py/resources/seals.csv +0 -0
  54. {ggplot2_python-4.0.2.9000.post1 → ggplot2_python-4.0.2.9000.post2}/ggplot2_py/resources/txhousing.csv +0 -0
  55. {ggplot2_python-4.0.2.9000.post1 → ggplot2_python-4.0.2.9000.post2}/ggplot2_py/save.py +0 -0
  56. {ggplot2_python-4.0.2.9000.post1 → ggplot2_python-4.0.2.9000.post2}/ggplot2_py/scales/__init__.py +0 -0
  57. {ggplot2_python-4.0.2.9000.post1 → ggplot2_python-4.0.2.9000.post2}/ggplot2_py/stats/__init__.py +0 -0
  58. {ggplot2_python-4.0.2.9000.post1 → ggplot2_python-4.0.2.9000.post2}/ggplot2_py/theme_elements.py +0 -0
@@ -29,3 +29,4 @@ Thumbs.db
29
29
  site/
30
30
  .cache/
31
31
  .ipynb_checkpoints/
32
+ validation/
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ggplot2-python
3
- Version: 4.0.2.9000.post1
3
+ Version: 4.0.2.9000.post2
4
4
  Summary: Python port of the R ggplot2 package (tracks R ggplot2 4.0.2.9000)
5
5
  Project-URL: Homepage, https://github.com/Bio-Babel/ggplot2-python
6
6
  Project-URL: Repository, https://github.com/Bio-Babel/ggplot2-python
@@ -460,7 +460,9 @@ from ggplot2_py.coord import (
460
460
  CoordFixed,
461
461
  CoordFlip,
462
462
  CoordPolar,
463
+ CoordQuickmap,
463
464
  CoordRadial,
465
+ CoordSf,
464
466
  CoordTrans,
465
467
  CoordTransform,
466
468
  coord_cartesian,
@@ -468,11 +470,14 @@ from ggplot2_py.coord import (
468
470
  coord_fixed,
469
471
  coord_flip,
470
472
  coord_polar,
473
+ coord_quickmap,
471
474
  coord_radial,
475
+ coord_sf,
472
476
  coord_trans,
473
477
  coord_transform,
474
478
  coord_munch,
475
479
  is_coord,
480
+ sf_transform_xy,
476
481
  )
477
482
 
478
483
  # ---------------------------------------------------------------------------
@@ -535,6 +540,8 @@ from ggplot2_py.guide import (
535
540
  guide_bins,
536
541
  guide_colourbar,
537
542
  guide_colorbar,
543
+ guide_old_colourbar,
544
+ guide_old_colorbar,
538
545
  guide_coloursteps,
539
546
  guide_colorsteps,
540
547
  guide_custom,
@@ -637,8 +644,26 @@ from ggplot2_py.draw_key import (
637
644
  # Save, fortify, qplot
638
645
  # ---------------------------------------------------------------------------
639
646
  from ggplot2_py.save import ggsave, check_device
640
- from ggplot2_py.fortify import fortify
647
+ from ggplot2_py.fortify import (
648
+ fortify,
649
+ fortify_lm,
650
+ fortify_dispatch,
651
+ fortify_glht,
652
+ fortify_confint_glht,
653
+ fortify_summary_glht,
654
+ fortify_cld,
655
+ )
641
656
  from ggplot2_py.qplot import qplot, quickplot
657
+ from ggplot2_py.labeller import (
658
+ label_value,
659
+ label_both,
660
+ label_context,
661
+ label_parsed,
662
+ label_bquote,
663
+ label_wrap_gen,
664
+ as_labeller,
665
+ )
666
+ from ggplot2_py.autoplot import autoplot, autolayer
642
667
 
643
668
  # ---------------------------------------------------------------------------
644
669
  # Utility re-exports (matching R namespace)
@@ -778,9 +803,10 @@ __all__ = [
778
803
  "scale_stroke", "scale_stroke_continuous",
779
804
  # Coords
780
805
  "Coord", "CoordCartesian", "CoordFixed", "CoordFlip",
781
- "CoordPolar", "CoordRadial", "CoordTrans", "CoordTransform",
806
+ "CoordPolar", "CoordQuickmap", "CoordRadial", "CoordTrans", "CoordTransform",
782
807
  "coord_cartesian", "coord_equal", "coord_fixed", "coord_flip",
783
- "coord_polar", "coord_radial", "coord_trans", "coord_transform",
808
+ "coord_polar", "coord_quickmap", "coord_radial", "coord_sf", "coord_trans", "coord_transform",
809
+ "CoordSf",
784
810
  "coord_munch", "is_coord",
785
811
  # Facets
786
812
  "Facet", "FacetNull", "FacetGrid", "FacetWrap",
@@ -797,6 +823,7 @@ __all__ = [
797
823
  "GuideAxisTheta", "GuideBins", "GuideColourbar", "GuideColoursteps",
798
824
  "GuideCustom", "GuideLegend", "GuideNone",
799
825
  "guide_axis", "guide_legend", "guide_colourbar", "guide_colorbar",
826
+ "guide_old_colourbar", "guide_old_colorbar",
800
827
  "guide_coloursteps", "guide_colorsteps", "guide_bins",
801
828
  "guide_custom", "guide_none", "guides", "is_guide",
802
829
  # Themes
@@ -823,7 +850,15 @@ __all__ = [
823
850
  "draw_key_pointrange", "draw_key_smooth", "draw_key_text",
824
851
  "draw_key_abline", "draw_key_vline", "draw_key_timeseries", "draw_key_vpath",
825
852
  # Save, fortify, qplot
826
- "ggsave", "check_device", "fortify", "qplot", "quickplot",
853
+ "ggsave", "check_device",
854
+ "fortify", "fortify_lm", "fortify_dispatch",
855
+ "fortify_glht", "fortify_confint_glht", "fortify_summary_glht", "fortify_cld",
856
+ "qplot", "quickplot",
857
+ # Labellers
858
+ "label_value", "label_both", "label_context", "label_parsed",
859
+ "label_bquote", "label_wrap_gen", "as_labeller",
860
+ # autoplot / autolayer generics
861
+ "autoplot", "autolayer",
827
862
  # Utilities
828
863
  "resolution", "remove_missing",
829
864
  "unit", "arrow", "alpha",
@@ -446,10 +446,23 @@ def aes(
446
446
  raw["y"] = y
447
447
  raw.update(kwargs)
448
448
 
449
- # Standardise names (e.g. "color" -> "colour").
449
+ # Standardise names (e.g. "color" -> "colour"). R's ``aes()`` also
450
+ # ``cli::cli_abort``s on duplicate x/y (aes.R:103-106). Python's
451
+ # ``**kwargs`` makes literal duplicates a ``SyntaxError`` at parse
452
+ # time, but ``color=`` + ``colour=`` both collapse to ``colour`` — we
453
+ # catch that post-standardisation because both refer to the same
454
+ # aesthetic.
450
455
  result = Mapping()
456
+ seen_aliases: Dict[str, str] = {}
451
457
  for key, value in raw.items():
452
458
  canonical = _standardise_single(key)
459
+ if canonical in seen_aliases and seen_aliases[canonical] != key:
460
+ from ggplot2_py._compat import cli_abort
461
+ cli_abort(
462
+ f"Duplicate aesthetic {canonical!r} — passed as both "
463
+ f"{seen_aliases[canonical]!r} and {key!r}."
464
+ )
465
+ seen_aliases[canonical] = key
453
466
  result[canonical] = value
454
467
 
455
468
  return result
@@ -500,6 +513,10 @@ def standardise_aes_names(aes_names: Iterable[str]) -> List[str]:
500
513
  def rename_aes(mapping: Mapping) -> Mapping:
501
514
  """Return a copy of *mapping* with all keys standardised.
502
515
 
516
+ Port of R ``rename_aes`` (aes.R:193-201): standardises every key of
517
+ an aesthetic mapping and warns when collapsing duplicates (e.g. when
518
+ both ``color`` and ``colour`` are supplied).
519
+
503
520
  Parameters
504
521
  ----------
505
522
  mapping : Mapping
@@ -515,9 +532,20 @@ def rename_aes(mapping: Mapping) -> Mapping:
515
532
  >>> rename_aes(Mapping(color="class"))
516
533
  aes(colour='class')
517
534
  """
518
- return Mapping(
519
- {_standardise_single(k): v for k, v in mapping.items()}
520
- )
535
+ items = [(_standardise_single(k), v) for k, v in mapping.items()]
536
+ # R warns on duplicated names after standardisation.
537
+ seen: Dict[str, int] = {}
538
+ for k, _ in items:
539
+ seen[k] = seen.get(k, 0) + 1
540
+ dupes = sorted({k for k, c in seen.items() if c > 1})
541
+ if dupes:
542
+ from ggplot2_py._compat import cli_warn as _cli_warn
543
+ _cli_warn(
544
+ "Duplicated aesthetics after name standardisation: "
545
+ + ", ".join(dupes)
546
+ )
547
+ # Later entry wins (dict semantics) — matches R's ``names(x) <- ...``.
548
+ return Mapping(dict(items))
521
549
 
522
550
 
523
551
  # ---------------------------------------------------------------------------
@@ -0,0 +1,79 @@
1
+ """
2
+ autoplot / autolayer — generic plot-and-layer factories for user classes.
3
+
4
+ Port of R's S3 generics ``autoplot()`` and ``autolayer()`` (autoplot.R,
5
+ autolayer.R). Downstream packages register methods for their own classes
6
+ so a single call ``autoplot(obj)`` produces a full ggplot, or
7
+ ``autolayer(obj)`` produces a layer.
8
+
9
+ In R these are dispatched via ``UseMethod``; here we use
10
+ :func:`functools.singledispatch`. Users extend via
11
+ ``@autoplot.register(MyClass)`` / ``@autolayer.register(MyClass)``.
12
+
13
+ The default method raises :class:`TypeError` — matching the user-visible
14
+ semantics of R's default, which calls ``cli::cli_abort(...)``.
15
+
16
+ R references
17
+ ------------
18
+ * ``ggplot2/R/autoplot.R`` -- autoplot generic + default.
19
+ * ``ggplot2/R/autolayer.R`` -- autolayer generic + default.
20
+ """
21
+
22
+ from __future__ import annotations
23
+
24
+ from functools import singledispatch
25
+ from typing import Any
26
+
27
+ __all__ = ["autoplot", "autolayer"]
28
+
29
+
30
+ @singledispatch
31
+ def autoplot(obj: Any, *args: Any, **kwargs: Any):
32
+ """Create a complete ggplot appropriate to a particular data type.
33
+
34
+ Mirrors R's ``autoplot()`` S3 generic. The default method raises
35
+ :class:`TypeError`; downstream packages extend it via
36
+ ``@autoplot.register(MyClass)``.
37
+
38
+ Parameters
39
+ ----------
40
+ obj : any
41
+ An object whose type determines the dispatched method.
42
+ *args, **kwargs
43
+ Forwarded to the registered method.
44
+
45
+ Returns
46
+ -------
47
+ GGPlot
48
+ A full ggplot, as produced by the registered method.
49
+ """
50
+ raise TypeError(
51
+ f"No autoplot method defined for {type(obj).__name__!r}. "
52
+ "Have you registered one via `@autoplot.register(...)`?"
53
+ )
54
+
55
+
56
+ @singledispatch
57
+ def autolayer(obj: Any, *args: Any, **kwargs: Any):
58
+ """Create a ggplot layer appropriate to a particular data type.
59
+
60
+ Mirrors R's ``autolayer()`` S3 generic. The default method raises
61
+ :class:`TypeError`; downstream packages extend it via
62
+ ``@autolayer.register(MyClass)``.
63
+
64
+ Parameters
65
+ ----------
66
+ obj : any
67
+ An object whose type determines the dispatched method.
68
+ *args, **kwargs
69
+ Forwarded to the registered method.
70
+
71
+ Returns
72
+ -------
73
+ Layer
74
+ A ggplot layer, as produced by the registered method.
75
+ """
76
+ raise TypeError(
77
+ f"No autolayer method defined for {type(obj).__name__!r}. "
78
+ "Have you registered one via `@autolayer.register(...)`?"
79
+ )