plotnine 0.15.0a5__py3-none-any.whl → 0.15.0a6__py3-none-any.whl

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.
@@ -13,7 +13,7 @@ if TYPE_CHECKING:
13
13
  from matplotlib.figure import Figure
14
14
 
15
15
  from plotnine import ggplot
16
- from plotnine.plot_composition import Compose
16
+ from plotnine.composition import Arrange
17
17
 
18
18
 
19
19
  class PlotnineLayoutEngine(LayoutEngine):
@@ -54,7 +54,7 @@ class PlotnineCompositionLayoutEngine(LayoutEngine):
54
54
  _adjust_compatible = True
55
55
  _colorbar_gridspec = False
56
56
 
57
- def __init__(self, composition: Compose):
57
+ def __init__(self, composition: Arrange):
58
58
  self.composition = composition
59
59
 
60
60
  def execute(self, fig: Figure):
@@ -7,7 +7,7 @@ from typing import TYPE_CHECKING, cast
7
7
 
8
8
  import numpy as np
9
9
 
10
- from plotnine.plot_composition import OR
10
+ from plotnine.composition import Beside
11
11
 
12
12
  from ._spaces import LayoutSpaces
13
13
 
@@ -16,7 +16,7 @@ if TYPE_CHECKING:
16
16
 
17
17
  from plotnine import ggplot
18
18
  from plotnine._mpl.gridspec import p9GridSpec
19
- from plotnine.plot_composition import Compose
19
+ from plotnine.composition import Arrange
20
20
 
21
21
 
22
22
  @dataclass
@@ -82,7 +82,7 @@ class LayoutTree:
82
82
 
83
83
  @staticmethod
84
84
  def create(
85
- cmp: Compose,
85
+ cmp: Arrange,
86
86
  lookup_spaces: dict[ggplot, LayoutSpaces],
87
87
  ) -> LayoutTree:
88
88
  """
@@ -109,7 +109,7 @@ class LayoutTree:
109
109
  else:
110
110
  nodes.append(LayoutTree.create(item, lookup_spaces))
111
111
 
112
- if isinstance(cmp, OR):
112
+ if isinstance(cmp, Beside):
113
113
  return ColumnsTree(cmp.gridspec, nodes)
114
114
  else:
115
115
  return RowsTree(cmp.gridspec, nodes)
@@ -1194,3 +1194,16 @@ def va_as_float(va: VerticalJustification | float) -> float:
1194
1194
  "center_baseline": 0.5,
1195
1195
  }
1196
1196
  return lookup[va] if isinstance(va, str) else va
1197
+
1198
+
1199
+ def has_alpha_channel(c: str | tuple) -> bool:
1200
+ """
1201
+ Return True if c a color with an alpha value
1202
+
1203
+ Either a 9 character hex string e.g. #AABBCC88 or
1204
+ an RGBA tuple e.g. (.6, .7, .8, .5)
1205
+ """
1206
+ if isinstance(c, str):
1207
+ return c.startswith("#") and len(c) == 9
1208
+ else:
1209
+ return color_utils.is_color_tuple(c) and len(c) == 4
@@ -0,0 +1,11 @@
1
+ from ._arrange import Arrange
2
+ from ._beside import Beside
3
+ from ._plot_spacer import plot_spacer
4
+ from ._stack import Stack
5
+
6
+ __all__ = (
7
+ "Arrange",
8
+ "Stack",
9
+ "Beside",
10
+ "plot_spacer",
11
+ )
@@ -2,7 +2,7 @@ from __future__ import annotations
2
2
 
3
3
  import abc
4
4
  from copy import deepcopy
5
- from dataclasses import dataclass
5
+ from dataclasses import dataclass, field
6
6
  from io import BytesIO
7
7
  from typing import TYPE_CHECKING
8
8
 
@@ -24,9 +24,15 @@ if TYPE_CHECKING:
24
24
  from plotnine.ggplot import PlotAddable, ggplot
25
25
 
26
26
 
27
- class Compose:
27
+ @dataclass
28
+ class Arrange:
28
29
  """
29
- Arrange two or more plots
30
+ Base class for those that create plot compositions
31
+
32
+ As a user, you will never directly work with this class, except
33
+ the operators [`|`](`plotnine.composition.Beside`) and
34
+ [`/`](`plotnine.composition.Stack`) that are powered by subclasses
35
+ of this class.
30
36
 
31
37
  Parameters
32
38
  ----------
@@ -34,27 +40,26 @@ class Compose:
34
40
  The objects to be put together (composed).
35
41
  """
36
42
 
37
- def __init__(self, operands: list[ggplot | Compose]):
38
- self.operands = operands
43
+ operands: list[ggplot | Arrange]
39
44
 
40
- # These are created in the _create_figure method
41
- self.figure: Figure
42
- self.plotspecs: list[plotspec]
43
- self.gridspec: p9GridSpec
45
+ # These are created in the _create_figure method
46
+ figure: Figure = field(init=False, repr=False)
47
+ plotspecs: list[plotspec] = field(init=False, repr=False)
48
+ gridspec: p9GridSpec = field(init=False, repr=False)
44
49
 
45
50
  @abc.abstractmethod
46
- def __or__(self, rhs: ggplot | Compose) -> Compose:
51
+ def __or__(self, rhs: ggplot | Arrange) -> Arrange:
47
52
  """
48
53
  Add rhs as a column
49
54
  """
50
55
 
51
56
  @abc.abstractmethod
52
- def __truediv__(self, rhs: ggplot | Compose) -> Compose:
57
+ def __truediv__(self, rhs: ggplot | Arrange) -> Arrange:
53
58
  """
54
59
  Add rhs as a row
55
60
  """
56
61
 
57
- def __add__(self, rhs: ggplot | Compose | PlotAddable) -> Compose:
62
+ def __add__(self, rhs: ggplot | Arrange | PlotAddable) -> Arrange:
58
63
  """
59
64
  Add rhs to the composition
60
65
 
@@ -65,13 +70,13 @@ class Compose:
65
70
  """
66
71
  from plotnine import ggplot
67
72
 
68
- if not isinstance(rhs, (ggplot, Compose)):
73
+ if not isinstance(rhs, (ggplot, Arrange)):
69
74
  cmp = deepcopy(self)
70
75
  cmp.last_plot = cmp.last_plot + rhs
71
76
  return cmp
72
77
  return self.__class__([*self, rhs])
73
78
 
74
- def __sub__(self, rhs: ggplot | Compose) -> Compose:
79
+ def __sub__(self, rhs: ggplot | Arrange) -> Arrange:
75
80
  """
76
81
  Add the rhs besides the composition
77
82
 
@@ -82,7 +87,7 @@ class Compose:
82
87
  """
83
88
  return self.__class__([self, rhs])
84
89
 
85
- def __and__(self, rhs: PlotAddable) -> Compose:
90
+ def __and__(self, rhs: PlotAddable) -> Arrange:
86
91
  """
87
92
  Add rhs to all plots in the composition
88
93
 
@@ -93,9 +98,9 @@ class Compose:
93
98
  """
94
99
  self = deepcopy(self)
95
100
 
96
- def add_other(op: Compose):
101
+ def add_other(op: Arrange):
97
102
  for item in op:
98
- if isinstance(item, Compose):
103
+ if isinstance(item, Arrange):
99
104
  add_other(item)
100
105
  else:
101
106
  item += rhs
@@ -103,7 +108,7 @@ class Compose:
103
108
  add_other(self)
104
109
  return self
105
110
 
106
- def __mul__(self, rhs: PlotAddable) -> Compose:
111
+ def __mul__(self, rhs: PlotAddable) -> Arrange:
107
112
  """
108
113
  Add rhs to the outermost nesting level of the composition
109
114
 
@@ -127,7 +132,7 @@ class Compose:
127
132
  """
128
133
  return len(self.operands)
129
134
 
130
- def __iter__(self) -> Iterator[ggplot | Compose]:
135
+ def __iter__(self) -> Iterator[ggplot | Arrange]:
131
136
  """
132
137
  Return an iterable of all the operands
133
138
  """
@@ -227,7 +232,7 @@ class Compose:
227
232
  from plotnine._mpl.gridspec import p9GridSpec
228
233
 
229
234
  def _make_plotspecs(
230
- cmp: Compose, parent_gridspec: p9GridSpec | None
235
+ cmp: Arrange, parent_gridspec: p9GridSpec | None
231
236
  ) -> Generator[plotspec]:
232
237
  """
233
238
  Return the plot specification for each subplot in the composition
@@ -289,7 +294,7 @@ class Compose:
289
294
 
290
295
  def draw(self, *, show: bool = False) -> Figure:
291
296
  """
292
- Render the composed plots
297
+ Render the arranged plots
293
298
 
294
299
  Parameters
295
300
  ----------
@@ -315,9 +320,15 @@ class Compose:
315
320
  )
316
321
  return figure
317
322
 
318
- def save(self, filename: str | Path | BytesIO, format: str | None = None):
323
+ def save(
324
+ self,
325
+ filename: str | Path | BytesIO,
326
+ format: str | None = None,
327
+ dpi: int | None = None,
328
+ **kwargs,
329
+ ):
319
330
  """
320
- Save a Compose object as an image file
331
+ Save a composition as an image file
321
332
 
322
333
  Parameters
323
334
  ----------
@@ -326,14 +337,25 @@ class Compose:
326
337
  format :
327
338
  Image format to use, automatically extract from
328
339
  file name extension.
329
- """
330
- figure = self.draw()
340
+ dpi :
341
+ DPI to use for raster graphics. If None, defaults to using
342
+ the `dpi` of theme to the first plot.
343
+ kwargs :
344
+ These are ignored. Here to "softly" match the API of
345
+ `ggplot.save()`.
346
+ """
347
+ from plotnine import theme
348
+
349
+ # To set the dpi, we only need to change the dpi of
350
+ # the last plot and theme gets added to the last plot
351
+ plot = (self + theme(dpi=dpi)) if dpi else self
352
+ figure = plot.draw()
331
353
  figure.savefig(filename, format=format)
332
354
 
333
355
 
334
356
  @dataclass
335
357
  class plot_composition_context:
336
- cmp: Compose
358
+ cmp: Arrange
337
359
  show: bool
338
360
 
339
361
  def __post_init__(self):
@@ -368,95 +390,3 @@ class plot_composition_context:
368
390
  plt.close(self.cmp.figure)
369
391
 
370
392
  self._rc_context.__exit__(exc_type, exc_value, exc_traceback)
371
-
372
-
373
- class OR(Compose):
374
- """
375
- Compose by adding a column
376
- """
377
-
378
- @property
379
- def nrow(self) -> int:
380
- return 1
381
-
382
- @property
383
- def ncol(self) -> int:
384
- return len(self)
385
-
386
- def __or__(self, rhs: ggplot | Compose) -> Compose:
387
- """
388
- Add rhs as a column
389
- """
390
- # This is adjacent or i.e. (OR | rhs) so we collapse the
391
- # operands into a single operation
392
- return OR([*self, rhs])
393
-
394
- def __truediv__(self, rhs: ggplot | Compose) -> Compose:
395
- """
396
- Add rhs as a row
397
- """
398
- return DIV([self, rhs])
399
-
400
-
401
- class DIV(Compose):
402
- """
403
- Compose by adding a row
404
- """
405
-
406
- @property
407
- def nrow(self) -> int:
408
- return len(self)
409
-
410
- @property
411
- def ncol(self) -> int:
412
- return 1
413
-
414
- def __truediv__(self, rhs: ggplot | Compose) -> Compose:
415
- """
416
- Add rhs as a row
417
- """
418
- # This is an adjacent div i.e. (DIV | rhs) so we collapse the
419
- # operands into a single operation
420
- return DIV([*self, rhs])
421
-
422
- def __or__(self, rhs: ggplot | Compose) -> Compose:
423
- """
424
- Add rhs as a column
425
- """
426
- return OR([self, rhs])
427
-
428
-
429
- class ADD(Compose):
430
- """
431
- Compose by adding
432
- """
433
-
434
- @property
435
- def nrow(self) -> int:
436
- from plotnine.facets.facet_wrap import wrap_dims
437
-
438
- return wrap_dims(len(self))[0]
439
-
440
- @property
441
- def ncol(self) -> int:
442
- from plotnine.facets.facet_wrap import wrap_dims
443
-
444
- return wrap_dims(len(self))[1]
445
-
446
- def __or__(self, rhs: ggplot | Compose) -> Compose:
447
- """
448
- Add rhs as a column
449
- """
450
- return OR([self, rhs])
451
-
452
- def __truediv__(self, rhs: ggplot | Compose) -> Compose:
453
- """
454
- Add rhs as a row
455
- """
456
- return DIV([self, rhs])
457
-
458
- def __sub__(self, rhs: ggplot | Compose) -> Compose:
459
- """
460
- Add rhs as a column
461
- """
462
- return OR([self, rhs])
@@ -0,0 +1,47 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING
4
+
5
+ from ._arrange import Arrange
6
+
7
+ if TYPE_CHECKING:
8
+ from plotnine.ggplot import ggplot
9
+
10
+
11
+ class Beside(Arrange):
12
+ """
13
+ Place plots or compositions side by side
14
+
15
+ **Usage**
16
+
17
+ plot | plot
18
+ plot | composition
19
+ composition | plot
20
+ composition | composition
21
+
22
+ Typically, you will use this class through the `|` operator.
23
+ """
24
+
25
+ @property
26
+ def nrow(self) -> int:
27
+ return 1
28
+
29
+ @property
30
+ def ncol(self) -> int:
31
+ return len(self)
32
+
33
+ def __or__(self, rhs: ggplot | Arrange) -> Arrange:
34
+ """
35
+ Add rhs as a column
36
+ """
37
+ # This is adjacent or i.e. (OR | rhs) so we collapse the
38
+ # operands into a single operation
39
+ return Beside([*self, rhs])
40
+
41
+ def __truediv__(self, rhs: ggplot | Arrange) -> Arrange:
42
+ """
43
+ Add rhs as a row
44
+ """
45
+ from ._stack import Stack
46
+
47
+ return Stack([self, rhs])
@@ -0,0 +1,49 @@
1
+ from __future__ import annotations
2
+
3
+ from copy import deepcopy
4
+
5
+ from plotnine import element_rect, ggplot, theme, theme_void
6
+
7
+
8
+ class plot_spacer(ggplot):
9
+ """
10
+ Blank area as wide or as tall as a plot
11
+
12
+ Parameters
13
+ ----------
14
+ fill :
15
+ Background color. The default is a transparent area, but it
16
+ can be changed through this parameter.
17
+
18
+ The color can also be modified by adding a [](`~plotnine.theme`)
19
+ and setting the [](`~plotnine.themes.themeable.plot_background`).
20
+ """
21
+
22
+ def __init__(
23
+ self,
24
+ fill: (
25
+ str
26
+ | tuple[float, float, float]
27
+ | tuple[float, float, float, float]
28
+ | None
29
+ ) = None,
30
+ ):
31
+ super().__init__()
32
+ self.theme = theme_void()
33
+ if fill:
34
+ self.theme += theme(plot_background=element_rect(fill=fill))
35
+
36
+ def __add__(self, rhs) -> plot_spacer:
37
+ """
38
+ Add to spacer
39
+
40
+ All added objects are no ops except the `plot_background` in
41
+ in a theme.
42
+ """
43
+ self = deepcopy(self)
44
+ if isinstance(rhs, theme):
45
+ fill = rhs.getp(("plot_background", "facecolor"))
46
+ self.theme += theme(
47
+ plot_background=element_rect(fill=fill),
48
+ )
49
+ return self
@@ -0,0 +1,47 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING
4
+
5
+ from ._arrange import Arrange
6
+
7
+ if TYPE_CHECKING:
8
+ from plotnine.ggplot import ggplot
9
+
10
+
11
+ class Stack(Arrange):
12
+ """
13
+ Place plots or compositions on top of each other
14
+
15
+ **Usage**
16
+
17
+ plot / plot
18
+ plot / composition
19
+ composition / plot
20
+ composition / composition
21
+
22
+ Typically, you will use this class through the `/` operator.
23
+ """
24
+
25
+ @property
26
+ def nrow(self) -> int:
27
+ return len(self)
28
+
29
+ @property
30
+ def ncol(self) -> int:
31
+ return 1
32
+
33
+ def __truediv__(self, rhs: ggplot | Arrange) -> Arrange:
34
+ """
35
+ Add rhs as a row
36
+ """
37
+ # This is an adjacent div i.e. (DIV | rhs) so we collapse the
38
+ # operands into a single operation
39
+ return Stack([*self, rhs])
40
+
41
+ def __or__(self, rhs: ggplot | Arrange) -> Arrange:
42
+ """
43
+ Add rhs as a column
44
+ """
45
+ from ._beside import Beside
46
+
47
+ return Beside([self, rhs])
@@ -14,12 +14,12 @@ class geom_area(geom_ribbon):
14
14
  """
15
15
  Area plot
16
16
 
17
+ {usage}
18
+
17
19
  An area plot is a special case of geom_ribbon,
18
20
  where the minimum of the range is fixed to 0,
19
21
  and the position adjustment defaults to 'stack'.
20
22
 
21
- {usage}
22
-
23
23
  Parameters
24
24
  ----------
25
25
  {common_parameters}
@@ -7,13 +7,13 @@ class geom_bin_2d(geom_rect):
7
7
  """
8
8
  Heatmap of 2d bin counts
9
9
 
10
+ {usage}
11
+
10
12
  Divides the plane into rectangles, counts the number of
11
13
  cases in each rectangle, and then (by default) maps the number
12
14
  of cases to the rectangle's fill. This is a useful alternative
13
15
  to geom_point in the presence of overplotting.
14
16
 
15
- {usage}
16
-
17
17
  Parameters
18
18
  ----------
19
19
  {common_parameters}
@@ -7,13 +7,13 @@ class geom_col(geom_bar):
7
7
  """
8
8
  Bar plot with base on the x-axis
9
9
 
10
+ {usage}
11
+
10
12
  This is an alternate version of [](`~plotnine.geoms.geom_bar`) that maps
11
13
  the height of bars to an existing variable in your data. If
12
14
  you want the height of the bar to represent a count of cases,
13
15
  use [](`~plotnine.geoms.geom_bar`).
14
16
 
15
- {usage}
16
-
17
17
  Parameters
18
18
  ----------
19
19
  {common_parameters}
@@ -7,12 +7,12 @@ class geom_count(geom_point):
7
7
  """
8
8
  Plot overlapping points
9
9
 
10
+ {usage}
11
+
10
12
  This is a variant [](`~plotnine.geoms.geom_point`) that counts the number
11
13
  of observations at each location, then maps the count to point
12
14
  area. It useful when you have discrete data and overplotting.
13
15
 
14
- {usage}
15
-
16
16
  Parameters
17
17
  ----------
18
18
  {common_parameters}
@@ -7,10 +7,10 @@ class geom_density_2d(geom_path):
7
7
  """
8
8
  2D density estimate
9
9
 
10
- This is a 2d version of [](`~plotnine.geoms.geom_density`).
11
-
12
10
  {usage}
13
11
 
12
+ This is a 2d version of [](`~plotnine.geoms.geom_density`).
13
+
14
14
  Parameters
15
15
  ----------
16
16
  {common_parameters}
@@ -33,10 +33,10 @@ class geom_map(geom):
33
33
  """
34
34
  Draw map feature
35
35
 
36
- The map feature are drawn without any special projections.
37
-
38
36
  {usage}
39
37
 
38
+ The map feature are drawn without any special projections.
39
+
40
40
  Parameters
41
41
  ----------
42
42
  {common_parameters}
@@ -7,13 +7,13 @@ class geom_sina(geom_point):
7
7
  """
8
8
  Draw a sina plot
9
9
 
10
+ {usage}
11
+
10
12
  A sina plot is a data visualization chart suitable for plotting
11
13
  any single variable in a multiclass dataset. It is an enhanced
12
14
  jitter strip chart, where the width of the jitter is controlled
13
15
  by the density distribution of the data within each class.
14
16
 
15
- {usage}
16
-
17
17
  Parameters
18
18
  ----------
19
19
  {common_parameters}
plotnine/ggplot.py CHANGED
@@ -13,7 +13,6 @@ from typing import (
13
13
  Iterable,
14
14
  Optional,
15
15
  cast,
16
- overload,
17
16
  )
18
17
  from warnings import warn
19
18
 
@@ -53,10 +52,10 @@ if TYPE_CHECKING:
53
52
 
54
53
  from plotnine import watermark
55
54
  from plotnine._mpl.gridspec import p9GridSpec
55
+ from plotnine.composition import Arrange
56
56
  from plotnine.coords.coord import coord
57
57
  from plotnine.facets.facet import facet
58
58
  from plotnine.layer import layer
59
- from plotnine.plot_composition import Compose
60
59
  from plotnine.typing import DataLike
61
60
 
62
61
  class PlotAddable(Protocol):
@@ -230,18 +229,10 @@ class ggplot:
230
229
  other.__radd__(self)
231
230
  return self
232
231
 
233
- @overload
234
- def __add__(
235
- self, rhs: PlotAddable | list[PlotAddable] | None
236
- ) -> ggplot: ...
237
-
238
- @overload
239
- def __add__(self, rhs: ggplot | Compose) -> Compose: ...
240
-
241
232
  def __add__(
242
233
  self,
243
- rhs: PlotAddable | list[PlotAddable] | None | ggplot | Compose,
244
- ) -> ggplot | Compose:
234
+ rhs: PlotAddable | list[PlotAddable] | None,
235
+ ) -> ggplot:
245
236
  """
246
237
  Add to ggplot
247
238
 
@@ -251,37 +242,32 @@ class ggplot:
251
242
  Either an object that knows how to "radd"
252
243
  itself to a ggplot, or a list of such objects.
253
244
  """
254
- from .plot_composition import ADD, Compose
255
-
256
- if isinstance(rhs, (ggplot, Compose)):
257
- return ADD([self, rhs])
258
-
259
245
  self = deepcopy(self)
260
246
  return self.__iadd__(rhs)
261
247
 
262
- def __or__(self, rhs: ggplot | Compose) -> Compose:
248
+ def __or__(self, rhs: ggplot | Arrange) -> Arrange:
263
249
  """
264
250
  Compose 2 plots columnwise
265
251
  """
266
- from .plot_composition import OR
252
+ from .composition import Beside
267
253
 
268
- return OR([self, rhs])
254
+ return Beside([self, rhs])
269
255
 
270
- def __truediv__(self, rhs: ggplot | Compose) -> Compose:
256
+ def __truediv__(self, rhs: ggplot | Arrange) -> Arrange:
271
257
  """
272
258
  Compose 2 plots rowwise
273
259
  """
274
- from .plot_composition import DIV
260
+ from .composition import Stack
275
261
 
276
- return DIV([self, rhs])
262
+ return Stack([self, rhs])
277
263
 
278
- def __sub__(self, rhs: ggplot | Compose) -> Compose:
264
+ def __sub__(self, rhs: ggplot | Arrange) -> Arrange:
279
265
  """
280
266
  Compose 2 plots columnwise
281
267
  """
282
- from .plot_composition import OR
268
+ from .composition import Beside
283
269
 
284
- return OR([self, rhs])
270
+ return Beside([self, rhs])
285
271
 
286
272
  def __rrshift__(self, other: DataLike) -> ggplot:
287
273
  """
@@ -1,5 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
+ from collections.abc import Mapping
3
4
  from dataclasses import KW_ONLY, InitVar, dataclass
4
5
  from typing import Any, Sequence
5
6
  from warnings import warn
@@ -29,6 +30,7 @@ class _scale_manual(scale_discrete):
29
30
  isinstance(self.breaks, Iterable)
30
31
  and isinstance(self.breaks, Sized)
31
32
  and len(self.breaks) == len(values)
33
+ and not isinstance(values, Mapping)
32
34
  ):
33
35
  values = dict(zip(self.breaks, values))
34
36
 
@@ -5,7 +5,7 @@ from typing import TYPE_CHECKING
5
5
  from .element_base import element_base
6
6
 
7
7
  if TYPE_CHECKING:
8
- from typing import Any, Literal, Optional, Sequence
8
+ from typing import Any, Literal, Sequence
9
9
 
10
10
 
11
11
  class element_line(element_base):
@@ -26,6 +26,8 @@ class element_line(element_base):
26
26
  using tuples, see [](`~matplotlib.lines.line2D.set_linestyle`).
27
27
  size : float
28
28
  line thickness
29
+ alpha : float
30
+ Opacity value
29
31
  kwargs : dict
30
32
  Parameters recognised by [](`~matplotlib.lines.line2d`).
31
33
  """
@@ -33,31 +35,37 @@ class element_line(element_base):
33
35
  def __init__(
34
36
  self,
35
37
  *,
36
- color: Optional[
38
+ color: (
37
39
  str
38
40
  | tuple[float, float, float]
39
41
  | tuple[float, float, float, float]
40
- ] = None,
41
- size: Optional[float] = None,
42
- linetype: Optional[str | Sequence[int]] = None,
43
- lineend: Optional[Literal["butt", "projecting", "round"]] = None,
44
- colour: Optional[
42
+ | None
43
+ ) = None,
44
+ size: float | None = None,
45
+ linetype: str | Sequence[int] | None = None,
46
+ lineend: Literal["butt", "projecting", "round"] | None = None,
47
+ colour: (
45
48
  str
46
49
  | tuple[float, float, float]
47
50
  | tuple[float, float, float, float]
48
- ] = None,
51
+ | None
52
+ ) = None,
53
+ alpha: float | None = None,
49
54
  **kwargs: Any,
50
55
  ):
51
56
  super().__init__()
52
57
  self.properties.update(**kwargs)
53
58
 
54
- color = color if color else colour
59
+ color = color if color is not None else colour
60
+
55
61
  if color:
56
62
  self.properties["color"] = color
57
63
  if size:
58
64
  self.properties["linewidth"] = size
59
65
  if linetype:
60
66
  self.properties["linestyle"] = linetype
67
+ if alpha is not None:
68
+ self.properties["alpha"] = alpha
61
69
 
62
70
  if linetype in ("solid", "-") and lineend:
63
71
  self.properties["solid_capstyle"] = lineend
@@ -17,7 +17,7 @@ from warnings import warn
17
17
 
18
18
  import numpy as np
19
19
 
20
- from .._utils import to_rgba
20
+ from .._utils import has_alpha_channel, to_rgba
21
21
  from .._utils.registry import RegistryHierarchyMeta
22
22
  from ..exceptions import PlotnineError, deprecated_themeable_name
23
23
  from .elements import element_blank
@@ -504,6 +504,25 @@ class MixinSequenceOfValues(themeable):
504
504
  a.set(**{name: value})
505
505
 
506
506
 
507
+ def blend_alpha(
508
+ properties: dict[str, Any], key: str = "color"
509
+ ) -> dict[str, Any]:
510
+ """
511
+ Blend color with alpha
512
+
513
+ When setting color property values of matplotlib objects,
514
+ for a color with an alpha channel, we don't want the alpha
515
+ property if any to have any effect on that color.
516
+ """
517
+ if (color := properties.get(key)) is not None:
518
+ if "alpha" in properties:
519
+ properties[key] = to_rgba(color, properties["alpha"])
520
+ properties["alpha"] = None
521
+ elif has_alpha_channel(color):
522
+ properties["alpha"] = None
523
+ return properties
524
+
525
+
507
526
  # element_text themeables
508
527
 
509
528
 
@@ -1366,7 +1385,7 @@ class panel_grid_major_x(themeable):
1366
1385
 
1367
1386
  def apply_ax(self, ax: Axes):
1368
1387
  super().apply_ax(ax)
1369
- ax.xaxis.grid(which="major", **self.properties)
1388
+ ax.xaxis.grid(which="major", **blend_alpha(self.properties))
1370
1389
 
1371
1390
  def blank_ax(self, ax: Axes):
1372
1391
  super().blank_ax(ax)
@@ -1384,7 +1403,7 @@ class panel_grid_major_y(themeable):
1384
1403
 
1385
1404
  def apply_ax(self, ax: Axes):
1386
1405
  super().apply_ax(ax)
1387
- ax.yaxis.grid(which="major", **self.properties)
1406
+ ax.yaxis.grid(which="major", **blend_alpha(self.properties))
1388
1407
 
1389
1408
  def blank_ax(self, ax: Axes):
1390
1409
  super().blank_ax(ax)
@@ -1612,11 +1631,7 @@ class panel_background(legend_key):
1612
1631
 
1613
1632
  def apply_ax(self, ax: Axes):
1614
1633
  super().apply_ax(ax)
1615
- d = self.properties
1616
- if "facecolor" in d and "alpha" in d:
1617
- d["facecolor"] = to_rgba(d["facecolor"], d["alpha"])
1618
- del d["alpha"]
1619
-
1634
+ d = blend_alpha(self.properties, "facecolor")
1620
1635
  d["edgecolor"] = "none"
1621
1636
  d["linewidth"] = 0
1622
1637
  ax.patch.set(**d)
@@ -1642,16 +1657,12 @@ class panel_border(MixinSequenceOfValues):
1642
1657
  if not (rects := targets.panel_border):
1643
1658
  return
1644
1659
 
1645
- d = self.properties
1660
+ d = blend_alpha(self.properties, "edgecolor")
1646
1661
 
1647
1662
  with suppress(KeyError):
1648
1663
  if d["edgecolor"] == "none" or d["size"] == 0:
1649
1664
  return
1650
1665
 
1651
- if "edgecolor" in d and "alpha" in d:
1652
- d["edgecolor"] = to_rgba(d["edgecolor"], d["alpha"])
1653
- del d["alpha"]
1654
-
1655
1666
  self.set(rects, d)
1656
1667
 
1657
1668
  def blank_figure(self, figure: Figure, targets: ThemeTargets):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: plotnine
3
- Version: 0.15.0a5
3
+ Version: 0.15.0a6
4
4
  Summary: A Grammar of Graphics for Python
5
5
  Author-email: Hassan Kibirige <has2k1@gmail.com>
6
6
  License: The MIT License (MIT)
@@ -2,7 +2,7 @@ plotnine/__init__.py,sha256=HrJhd65bnny1t-TawUgvApVj4p-gDZ0ftpr2NKZeW_s,10316
2
2
  plotnine/animation.py,sha256=izJZ4Gy0cBHEBc8ehofsWSWOzZW8UEroy1Uvw86Igb0,7521
3
3
  plotnine/doctools.py,sha256=JBF55q1MX2fXYQcGDpVrGPdlKf5OiQ5gyTdWhnM_IzU,14558
4
4
  plotnine/exceptions.py,sha256=SgTxBHkV65HjGI3aFy2q1_lHP9HAdiuxVLN3U-PJWSQ,1616
5
- plotnine/ggplot.py,sha256=xFj9iWAyBvnhitCrpgdNonQIqqjBQ2aDgkqpvHbH364,24823
5
+ plotnine/ggplot.py,sha256=Nl41v1zRUulyIBMzrzIE4IgIrHU0bicL2YH4x01wHt8,24457
6
6
  plotnine/helpers.py,sha256=4R3KZmtGH46-kRNSGOA0JxZaLKBo0ge8Vnx1cDQ8_gI,966
7
7
  plotnine/iapi.py,sha256=jNLmUSoh5g9kNdhOoXSqNcqOdd2-6xdWAmst-YGU41U,9095
8
8
  plotnine/labels.py,sha256=3pOXth2Xma_qCqB_xXAGIkPQ9gcaUaaFEAsa5if1iR0,2830
@@ -21,17 +21,23 @@ plotnine/_mpl/ticker.py,sha256=RY_7AdTggc7QBq9_t0KBJXg36oxKfB-Vtc9FzLnaGnQ,393
21
21
  plotnine/_mpl/transforms.py,sha256=DNaOlNq76xlT696sN8ot1bmYyp4mmrjXQHk3kTi4HIg,76
22
22
  plotnine/_mpl/utils.py,sha256=0GY3CWWXZiNHe333v9GAquRe5naO54JeiPt67-UvVYw,4147
23
23
  plotnine/_mpl/layout_manager/__init__.py,sha256=IXpPF5Oycc45uFpK4MJ6kcQCe1u5VUfnHLNZGcnrJCg,157
24
- plotnine/_mpl/layout_manager/_engine.py,sha256=ESUvbLAlZApFbBi6w7gZA7S4guS0Rmrj-us-gzYP2ZM,2809
24
+ plotnine/_mpl/layout_manager/_engine.py,sha256=m6FDFc1XELfzNSIXaFiN3ruoTgub2PaV3wPQWP0IBYE,2804
25
25
  plotnine/_mpl/layout_manager/_layout_items.py,sha256=3XRBl7xEdBKdhrexRmnVe7k919po6nkyE0q5Hx7j5cQ,29642
26
- plotnine/_mpl/layout_manager/_layout_tree.py,sha256=O6U78CYOjSwS4lt56YF3YiOCXdxmV_oy3lYS4gMmzSc,26447
26
+ plotnine/_mpl/layout_manager/_layout_tree.py,sha256=yFNt7fsv2VhEt3261OfLP7kgPYNd_npLoNDLp_QJi3Y,26445
27
27
  plotnine/_mpl/layout_manager/_spaces.py,sha256=ahBpKt-q1kVOTGiGliwl_DNB6pTEekAzA_7-GXwFlBk,35789
28
- plotnine/_utils/__init__.py,sha256=czHi-uv4eIBCDf6td11bGA41PMXaJ5j7t-avx_JbYgY,30636
28
+ plotnine/_utils/__init__.py,sha256=3tcSTng6Mtk1o6NPEikALHKD3ZGuAYofjQJREHX84a4,30992
29
29
  plotnine/_utils/context.py,sha256=HPQy_uyNXdS0s9URD7ZePyuc5hFU2XrRBLDTqRDLJzY,1708
30
30
  plotnine/_utils/dev.py,sha256=0qgRbMhcd4dfuLuYxx0skocKAtfwHF02ntyILRBogbg,1629
31
31
  plotnine/_utils/ipython.py,sha256=5Obr73xJ-4dzJEdBrFA8z9TXuxY7pIjKmzdTzWwnxNk,1884
32
32
  plotnine/_utils/quarto.py,sha256=bwbU3ork8wuUIW5VDJ73J_DbWWzpYWpAd76cHMzCRao,890
33
33
  plotnine/_utils/registry.py,sha256=HoiB2NnbEHufXjYnVJyrJKflk2RwKtTYk2L3n7tH4XA,3321
34
34
  plotnine/_utils/yippie.py,sha256=DbmxvVrd34P24CCmOZrAulyGQ35rXNaSr8BuutS2Uio,2392
35
+ plotnine/composition/__init__.py,sha256=WXkLaqbgpOquCbq_hakUUQlcIka9fN0IMKNm-DOns6E,198
36
+ plotnine/composition/_arrange.py,sha256=-ZPe3JydfVAvVYiTI0W7aJaUySonpE2o76aKaxfjS84,11040
37
+ plotnine/composition/_beside.py,sha256=DAMZfIrOfz4mQSqro22GpooaCnm8ns6lG6vIp8SnAtg,993
38
+ plotnine/composition/_plot_spacer.py,sha256=gjAymmjOVZwwT0Y01MqHA3tAEDAr0mcWSX07npzo1Hw,1298
39
+ plotnine/composition/_plotspec.py,sha256=0F7q7PjDMDqcallpnBdX3N2iSRjdBTyjSvMFf83uvPU,1015
40
+ plotnine/composition/_stack.py,sha256=TXvy8FQ7CNNzntkjz4h4R_6-LxYSNFF5ri9E82dv17Q,1007
35
41
  plotnine/coords/__init__.py,sha256=inM-9JwSPvYLlOy6opye0YV2EGWsI4708wGKdHvQvVM,301
36
42
  plotnine/coords/coord.py,sha256=Yu2xj4BqFBWlS0XHNDa6h8Dek0_PA6Lssv3M9EneSB8,6883
37
43
  plotnine/coords/coord_cartesian.py,sha256=vGeSFe9UyycUkbjdjoPNSQJwnnU7fEmsk0nl_oBvzxY,3038
@@ -71,16 +77,16 @@ plotnine/geoms/annotation_logticks.py,sha256=6iGdo5szck0_nXdHnvMaRMZuRbH8Tg87tJ_
71
77
  plotnine/geoms/annotation_stripes.py,sha256=4Cw7TJ4SZChm_ioqfiiku0cPNnLruGuAP-4vyRao-9Y,6080
72
78
  plotnine/geoms/geom.py,sha256=ayhBEoPc-9MLpu18HkwLoby4NIKC68ED4Pq0ioa4I9c,17687
73
79
  plotnine/geoms/geom_abline.py,sha256=6oxAJl_yFKKmf7OTHvACw6fg6kgJEN54hGKkyWOLr6o,3188
74
- plotnine/geoms/geom_area.py,sha256=wvQ4nNvhJNN3nfn6Bv1gCARC6IWTjOjOfHPfSmg6Sxc,818
80
+ plotnine/geoms/geom_area.py,sha256=QtS9NO17v-i5gvfakN8L96xwjt3dFuyZdYN8oXaXWOY,818
75
81
  plotnine/geoms/geom_bar.py,sha256=SnqS4hPTfqXzdPh1U-kNuBg0LNX9_tQC9OKhIlB7cy0,1732
76
- plotnine/geoms/geom_bin_2d.py,sha256=b2fAQVywug-ey3KtqeOoYQ2RNRSRE_fa4s7M41W-_FE,574
82
+ plotnine/geoms/geom_bin_2d.py,sha256=IhlpR62o4Y6qe-tNUywOMjhseJNPV3c-x2QB6D11EPU,574
77
83
  plotnine/geoms/geom_blank.py,sha256=38BpE9iSh3ktbOe9ayNer6IDD1q7E4EiKS_KnFSko0c,770
78
84
  plotnine/geoms/geom_boxplot.py,sha256=OISXd3CCuH06sKqOB8xlfUPrwUX_FUKQauSqE7L-PhQ,9778
79
- plotnine/geoms/geom_col.py,sha256=sGZZzkXgwlgI2D-M1UE1QAWsWZqtP1z8R0HjrnW9hkY,1187
80
- plotnine/geoms/geom_count.py,sha256=IRIlQqwt0kIHf9swYZbFqd5RSQCYRyFKm5hp1C9xHB4,511
85
+ plotnine/geoms/geom_col.py,sha256=KCpme3vsc_tTbjGvL7ZhJZ4KFrQDQw3K8JyO6EBFn4E,1187
86
+ plotnine/geoms/geom_count.py,sha256=4quwvXQSrdDdlQfaSRmkBzpEP6qCRPB9SS6_5UV037M,511
81
87
  plotnine/geoms/geom_crossbar.py,sha256=0NGUY4fhL8VxpGaBgjKQNJy85XJeLc6GiPCs5LZQuCc,6242
82
88
  plotnine/geoms/geom_density.py,sha256=UwUkJxI79L3z19tmoSI6ZYs418XTbRznd-Abzrec3VY,526
83
- plotnine/geoms/geom_density_2d.py,sha256=V37QYpdZpZvYxishlN1UBmyyRC3U2eOqR-gaIPxQqS4,400
89
+ plotnine/geoms/geom_density_2d.py,sha256=xEtQTTQnBzOs5PMDViZNQoSiXduU93SGmTN0u77RPj4,400
84
90
  plotnine/geoms/geom_dotplot.py,sha256=ZHmRCEGS3Nv2tiNwALBC7ewBg1prcb_FOxAImTGKP3c,8680
85
91
  plotnine/geoms/geom_errorbar.py,sha256=jpCuQ8CE2RKfRR8Aw_3s473HXrOk-WPOl46n4oC-8UI,2199
86
92
  plotnine/geoms/geom_errorbarh.py,sha256=mgRo8KngGyKVSPPF8vUYlzdslBJEIe9QJC--DlWL5t4,2213
@@ -91,7 +97,7 @@ plotnine/geoms/geom_jitter.py,sha256=mJCLt2SoZN_tx_3XS8oF5JojtL2m5HO1bEqdN-JEPUg
91
97
  plotnine/geoms/geom_label.py,sha256=lPxmDlS6VgEHqD3Ac1Q-Zxs75JcnduoXjJ_D1AzzWew,2835
92
98
  plotnine/geoms/geom_line.py,sha256=IzKVPwF_Oe3uwRpuh5Xu9LFvz0XcKqCL4pN03iGHBdk,522
93
99
  plotnine/geoms/geom_linerange.py,sha256=dkgQ28YZfjyMb_y8s0wfcAz5mHF7f7y_h1Den5wHyJk,1282
94
- plotnine/geoms/geom_map.py,sha256=E2DVSMx9-8-4duCUOd-4n-Lqu_VDL5qzQrt2PCLkMzY,9602
100
+ plotnine/geoms/geom_map.py,sha256=tvzFVNOtSOfof1NQFduB8SV143o2irNsQrM8BgYiEKU,9602
95
101
  plotnine/geoms/geom_path.py,sha256=nDrlmqPn869vyUF4RYbLKkbQka14SWJu9pqCN-cdKbQ,17106
96
102
  plotnine/geoms/geom_point.py,sha256=KWM511zxIpKQzxI_NJpFqEszNWg5E7iHZJylKvvaK2c,4607
97
103
  plotnine/geoms/geom_pointdensity.py,sha256=TKaxAUPwdrVMw0MVYe14apBsRfW_5_zXFLSlOS60Zlw,372
@@ -105,7 +111,7 @@ plotnine/geoms/geom_rect.py,sha256=dGOAkVXf5NSJgIbaVezg1ac78GqimElB9Ua0L_SH_YM,3
105
111
  plotnine/geoms/geom_ribbon.py,sha256=af9uElWaJQSc4taTLZ7ZDzng2Zw4IrIfNPrus4OuTmM,5771
106
112
  plotnine/geoms/geom_rug.py,sha256=2Sdarf5z3w4JbklVUk7JykWdbBNKaT0Wl5NMBl4LqT4,3520
107
113
  plotnine/geoms/geom_segment.py,sha256=v63MoKlK4aNengCXYdPeQrcBIgBCis8QobpF3CJOf5U,3052
108
- plotnine/geoms/geom_sina.py,sha256=oyCiBCdsWjrSNaS2jOpu0Ng8nEl_peaCT-EuHE9jG34,912
114
+ plotnine/geoms/geom_sina.py,sha256=JspG0o_K4px0KKZVaVeuBnk0iGjVJnB9PGjt8UAf08I,912
109
115
  plotnine/geoms/geom_smooth.py,sha256=8jSxQFTdoo7RmeTrGl2j-iE6lfydUPitz-dKvxKk0Kw,3545
110
116
  plotnine/geoms/geom_spoke.py,sha256=s-kug0H-YGhyjso9W43XvzJf9-g6inh8zzuSFeXzSaU,977
111
117
  plotnine/geoms/geom_step.py,sha256=tTohADfGyC3M4zCzxLUhzkA2XsHBeH0eaWq-m2DQEQQ,2371
@@ -125,10 +131,6 @@ plotnine/mapping/_env.py,sha256=ZXlTt2THRIcWb2WGk9fCpCMdVynlUX_BpG0Uwj7axi0,6072
125
131
  plotnine/mapping/_eval_environment.py,sha256=PTrnnqrxMXqjt23t2NGRcU9i8Jie3ZaMe6W5aKtI7bI,2502
126
132
  plotnine/mapping/aes.py,sha256=eqNTBHqFnSBPoVNdrUB7pYM-ShlUTYvmwdQRXh9beV4,16717
127
133
  plotnine/mapping/evaluation.py,sha256=kblTxVv3M4xIGnHyReUU0RtmmIN77Or2JBcci0nGGfE,5913
128
- plotnine/plot_composition/__init__.py,sha256=ZJYpfVF158cQZ1zREXy6wHNJ4FbSmqWxIkHWZwX3QT8,148
129
- plotnine/plot_composition/_compose.py,sha256=6UgXs6VBH0LIXW2uQlBQy-URh_mM948F5GOwN6IV734,12167
130
- plotnine/plot_composition/_plotspec.py,sha256=0F7q7PjDMDqcallpnBdX3N2iSRjdBTyjSvMFf83uvPU,1015
131
- plotnine/plot_composition/_spacer.py,sha256=vaC4F5tHhvL7T7Ns9zxUbytqwB6MLNhm5jtiKG0vAiU,798
132
134
  plotnine/positions/__init__.py,sha256=DQZE6duMUNRQifpa6SBrOKxZpGDk4NqQSGZLr9Yc9GI,595
133
135
  plotnine/positions/position.py,sha256=BRD_dUh9dhdSP4SQfl8_u_VpaY_s3A2zuznwOn5M_80,8325
134
136
  plotnine/positions/position_dodge.py,sha256=6PbAhWDfNK7NK6FZZOcfr4mdmVOUV9VLH8xD0dbQFEU,3941
@@ -152,7 +154,7 @@ plotnine/scales/scale_datetime.py,sha256=OM9gfHKGkQIBrgqCEE00zUV0cMXXxTIS7wc9dYQ
152
154
  plotnine/scales/scale_discrete.py,sha256=UwAB0icMljH-eW6mK3g0YWAVzuE4P_91ZMYJhoMoMV4,9431
153
155
  plotnine/scales/scale_identity.py,sha256=-PL9vJn0C_wOgrOQpqYSQbTWFSALoRPFzGXzebABTv8,2211
154
156
  plotnine/scales/scale_linetype.py,sha256=pwLTmglN6d4bnChbuBi6HWbDP_nsE4viXD8CK6XKBPw,1373
155
- plotnine/scales/scale_manual.py,sha256=oMnIfQNfxO4qw-gkBG3ikyuXdeoMgstRSdiibLc_DAA,4525
157
+ plotnine/scales/scale_manual.py,sha256=FmzF4gRxdiDVgryodN2Mx6Gr1FHW0grKO3WiL1ffkTc,4609
156
158
  plotnine/scales/scale_shape.py,sha256=I0JdYDreCbznQilaTi6m27F91N5daCj9D2ZPuP2Szls,2081
157
159
  plotnine/scales/scale_size.py,sha256=04nUQzKB_qpuQrcg8C7jYmLDYtdnlg6PkY7SivP5OlY,3273
158
160
  plotnine/scales/scale_stroke.py,sha256=7LKAg6-Q3VTuw78N2XEjFFzBa8yY5NVnfBSoJGsBS5o,1711
@@ -204,16 +206,16 @@ plotnine/themes/theme_seaborn.py,sha256=8giJh8QvkMJ8pr_XXHPDMfkysoI2_yr0vJhz48_s
204
206
  plotnine/themes/theme_tufte.py,sha256=qUOrZhQyfJgc0fmy8Es7tT7aYqUSzCjvkP7-dBilwHE,1926
205
207
  plotnine/themes/theme_void.py,sha256=gYXr367zYNhvt_NXlDUx0rBPUYJa1F6adnANn5HEx5A,3407
206
208
  plotnine/themes/theme_xkcd.py,sha256=5MOdj_H23Kr_jbDnepmq1DQDbn8-TfUmtzYBZTb4RB4,2207
207
- plotnine/themes/themeable.py,sha256=aMm5MxbsmEV1XX87AFPPBfAgkJP3Vm0_z9_tKZwsxxY,71321
209
+ plotnine/themes/themeable.py,sha256=Px91yh5pft24mC-4uUFLYpU-45iX6cE64j3t-a20wug,71744
208
210
  plotnine/themes/elements/__init__.py,sha256=xV1la_mTv1BQ3zQp7ZGVGPdV6KohvEVhKAi1uPTeAs0,327
209
211
  plotnine/themes/elements/element_base.py,sha256=D7cfEglzsSuhW91KpZVAZ2MAHWZp64r9Aajoh8uMGZ4,832
210
212
  plotnine/themes/elements/element_blank.py,sha256=4r7-6HeR1494oWNIGQh0ASrFQ4SLvYa6aQHA85eH-Ds,187
211
- plotnine/themes/elements/element_line.py,sha256=xF6xW-iA66YEP_fN7ooqaYry8_8qZT-eT5wvKwXg3to,1838
213
+ plotnine/themes/elements/element_line.py,sha256=yZvj9B3M2a7a8o2J0n-q0uviNv34PtJVUr_UefZ-v5I,2005
212
214
  plotnine/themes/elements/element_rect.py,sha256=w5cLH-Sr4cTRXVdkRiu8kBqFt3TXHhIb1MUITfi89gE,1767
213
215
  plotnine/themes/elements/element_text.py,sha256=8yhwBa9s9JKCtBcqcBNybbCGK6ieDnZv4SHiC4Sy2qc,6255
214
216
  plotnine/themes/elements/margin.py,sha256=jMHe-UKHHer_VYwAVDC-Tz2-AP_4YDuXPTWAuacoqgU,4080
215
- plotnine-0.15.0a5.dist-info/licenses/LICENSE,sha256=GY4tQiUd17Tq3wWR42Zs9MRTFOTf6ahIXhZTcwAdOeU,1082
216
- plotnine-0.15.0a5.dist-info/METADATA,sha256=HJHt2oWR1vudsK80OUWXBGCkU_d_Q6TWUlvo2d9w-nQ,9407
217
- plotnine-0.15.0a5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
218
- plotnine-0.15.0a5.dist-info/top_level.txt,sha256=t340Mbko1ZbmvYPkQ81dIiPHcaQdTUszYz-bWUpr8ys,9
219
- plotnine-0.15.0a5.dist-info/RECORD,,
217
+ plotnine-0.15.0a6.dist-info/licenses/LICENSE,sha256=GY4tQiUd17Tq3wWR42Zs9MRTFOTf6ahIXhZTcwAdOeU,1082
218
+ plotnine-0.15.0a6.dist-info/METADATA,sha256=FDNoeUumEK4SXTfxin727GT3RL94ky46x9L5e5fNQ-g,9407
219
+ plotnine-0.15.0a6.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
220
+ plotnine-0.15.0a6.dist-info/top_level.txt,sha256=t340Mbko1ZbmvYPkQ81dIiPHcaQdTUszYz-bWUpr8ys,9
221
+ plotnine-0.15.0a6.dist-info/RECORD,,
@@ -1,10 +0,0 @@
1
- from ._compose import ADD, DIV, OR, Compose
2
- from ._spacer import spacer
3
-
4
- __all__ = (
5
- "Compose",
6
- "ADD",
7
- "DIV",
8
- "OR",
9
- "spacer",
10
- )
@@ -1,32 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from copy import deepcopy
4
-
5
- from plotnine import element_rect, ggplot, theme, theme_void
6
-
7
-
8
- class spacer(ggplot):
9
- """
10
- An empty plot
11
- """
12
-
13
- def __init__(self):
14
- super().__init__()
15
- self.theme = theme_void()
16
-
17
- def __add__(self, rhs) -> spacer: # pyright: ignore[reportIncompatibleMethodOverride]
18
- """
19
- Add to spacer
20
-
21
- All added objects are no ops except the plot_background,
22
- i.e.:
23
-
24
- theme(plot_background=element_rect(fill="red"))
25
- """
26
- self = deepcopy(self)
27
- if isinstance(rhs, theme):
28
- fill = rhs.getp(("plot_background", "facecolor"))
29
- self.theme += theme(
30
- plot_background=element_rect(fill=fill),
31
- )
32
- return self
File without changes