From 1a4bacd374407beb21ebbbe4b18876d29fbc71eb Mon Sep 17 00:00:00 2001 From: Carlos Adir Date: Wed, 9 Jul 2025 20:34:09 +0200 Subject: [PATCH 01/31] style: fix style using black --- tests/test_bool_no_intersect.py | 9 +++++++-- tests/test_contains.py | 4 +++- tests/test_curve.py | 5 ++++- tests/test_jordan_curve.py | 2 +- tests/test_jordan_polygon.py | 26 ++++++++++++++++++++------ 5 files changed, 35 insertions(+), 11 deletions(-) diff --git a/tests/test_bool_no_intersect.py b/tests/test_bool_no_intersect.py index f2f6a539..17db7d27 100644 --- a/tests/test_bool_no_intersect.py +++ b/tests/test_bool_no_intersect.py @@ -116,7 +116,9 @@ class TestTwoCenteredSquares: """ @pytest.mark.order(9) - @pytest.mark.dependency(depends=["test_begin", "TestEqualSquare::test_end"]) + @pytest.mark.dependency( + depends=["test_begin", "TestEqualSquare::test_end"] + ) def test_begin(self): pass @@ -336,7 +338,10 @@ def test_or(self): @pytest.mark.order(9) @pytest.mark.timeout(40) @pytest.mark.dependency( - depends=["TestEqualHollowSquare::test_begin", "TestEqualHollowSquare::test_or"] + depends=[ + "TestEqualHollowSquare::test_begin", + "TestEqualHollowSquare::test_or", + ] ) def test_and(self): big = Primitive.square(side=2, center=(0, 0)) diff --git a/tests/test_contains.py b/tests/test_contains.py index 18f4215e..be549479 100644 --- a/tests/test_contains.py +++ b/tests/test_contains.py @@ -184,7 +184,9 @@ class TestObjectsInJordan: """ @pytest.mark.order(7) - @pytest.mark.dependency(depends=["test_begin", "TestObjectsInEmptyWhole::test_end"]) + @pytest.mark.dependency( + depends=["test_begin", "TestObjectsInEmptyWhole::test_end"] + ) def test_begin(self): pass diff --git a/tests/test_curve.py b/tests/test_curve.py index 28c6e8f1..139b61c7 100644 --- a/tests/test_curve.py +++ b/tests/test_curve.py @@ -302,7 +302,10 @@ def test_winding_triangles(self): @pytest.mark.order(3) @pytest.mark.timeout(10) @pytest.mark.dependency( - depends=["TestIntegrate::test_begin", "TestIntegrate::test_winding_triangles"] + depends=[ + "TestIntegrate::test_begin", + "TestIntegrate::test_winding_triangles", + ] ) def test_winding_unit_circle(self): ntests = 1000 diff --git a/tests/test_jordan_curve.py b/tests/test_jordan_curve.py index 9b0b4196..36bf37a6 100644 --- a/tests/test_jordan_curve.py +++ b/tests/test_jordan_curve.py @@ -5,9 +5,9 @@ from fractions import Fraction import numpy as np +import pynurbs import pytest -import pynurbs from shapepy import Point2D from shapepy.jordancurve import JordanCurve diff --git a/tests/test_jordan_polygon.py b/tests/test_jordan_polygon.py index 38364b1e..d60a2a9d 100644 --- a/tests/test_jordan_polygon.py +++ b/tests/test_jordan_polygon.py @@ -41,7 +41,10 @@ def test_creation(self): @pytest.mark.order(4) @pytest.mark.timeout(10) @pytest.mark.dependency( - depends=["TestJordanPolygon::test_begin", "TestJordanPolygon::test_creation"] + depends=[ + "TestJordanPolygon::test_begin", + "TestJordanPolygon::test_creation", + ] ) def test_error_creation(self): with pytest.raises(TypeError): @@ -482,7 +485,10 @@ def test_end(self): class TestOthers: @pytest.mark.order(4) @pytest.mark.dependency( - depends=["TestJordanPolygon::test_end", "TestTransformationPolygon::test_end"] + depends=[ + "TestJordanPolygon::test_end", + "TestTransformationPolygon::test_end", + ] ) def test_begin(self): pass @@ -511,13 +517,21 @@ def test_self_intersection(self): assert id(jordana) != id(jordanb) inters = jordana & jordanb assert not bool(inters) - inters = jordana.intersection(jordanb, equal_beziers=False, end_points=False) + inters = jordana.intersection( + jordanb, equal_beziers=False, end_points=False + ) assert not bool(inters) - inters = jordana.intersection(jordanb, equal_beziers=False, end_points=True) + inters = jordana.intersection( + jordanb, equal_beziers=False, end_points=True + ) assert bool(inters) - inters = jordana.intersection(jordanb, equal_beziers=True, end_points=False) + inters = jordana.intersection( + jordanb, equal_beziers=True, end_points=False + ) assert bool(inters) - inters = jordana.intersection(jordanb, equal_beziers=True, end_points=True) + inters = jordana.intersection( + jordanb, equal_beziers=True, end_points=True + ) assert bool(inters) @pytest.mark.order(4) From e269fe9fb9f38e87d29f3d3b7ef90662aa738304 Mon Sep 17 00:00:00 2001 From: Carlos Adir Date: Wed, 9 Jul 2025 20:35:53 +0200 Subject: [PATCH 02/31] make flake8 ignore error E203 --- tox.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/tox.ini b/tox.ini index 56d20745..5076954c 100644 --- a/tox.ini +++ b/tox.ini @@ -69,3 +69,4 @@ commands = [flake8] per-file-ignores = __init__.py:F401 +extend-ignore=E203 From 599852250080bec8d9c922cb52076f6ac5c88a00 Mon Sep 17 00:00:00 2001 From: Carlos Adir Date: Wed, 9 Jul 2025 20:38:26 +0200 Subject: [PATCH 03/31] make flake8 ignore error E231 --- tox.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index 5076954c..3c443e31 100644 --- a/tox.ini +++ b/tox.ini @@ -69,4 +69,4 @@ commands = [flake8] per-file-ignores = __init__.py:F401 -extend-ignore=E203 +extend-ignore=E203,E231 From 94a00abd67e8ac8ec592a9edddc9270722fa97e0 Mon Sep 17 00:00:00 2001 From: Carlos Adir Date: Wed, 9 Jul 2025 20:56:31 +0200 Subject: [PATCH 04/31] add prefix 'r' in function docstring to handle equations --- src/shapepy/shape.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/shapepy/shape.py b/src/shapepy/shape.py index e4e09f6a..7dcd16f7 100644 --- a/src/shapepy/shape.py +++ b/src/shapepy/shape.py @@ -40,18 +40,18 @@ class IntegrateShape: def polynomial( shape: BaseShape, expx: int, expy: int, nnodes: Optional[int] = None ) -> float: - """ + r""" Computes the integral .. math:: - I = \\int_D x^a \\cdot y^b \\cdot dA + I = \int_D x^a \cdot y^b \cdot dA Which :math:`D` is the region defined by shape We transform this integral into a boundary integral .. math:: - I = \dfrac{1}{a+1} \\cdot \\int_C x^{a+ 1} \\cdot y^b \\cdot dy + I = \dfrac{1}{a+1} \cdot \int_C x^{a+ 1} \cdot y^b \cdot dy Parameters ---------- From d7c8ae5c054cdc44640dd6773e8b43bcc1c5c52a Mon Sep 17 00:00:00 2001 From: Carlos Adir Date: Wed, 9 Jul 2025 21:03:58 +0200 Subject: [PATCH 05/31] reduce line length up to 79 chars --- src/shapepy/jordancurve.py | 35 ++++++++++++++++++++++++----------- src/shapepy/polygon.py | 11 ++++++----- src/shapepy/primitive.py | 8 +++++--- src/shapepy/shape.py | 9 ++++++--- 4 files changed, 41 insertions(+), 22 deletions(-) diff --git a/src/shapepy/jordancurve.py b/src/shapepy/jordancurve.py index 56292c21..26d3a8bc 100644 --- a/src/shapepy/jordancurve.py +++ b/src/shapepy/jordancurve.py @@ -204,7 +204,8 @@ def from_ctrlpoints( def from_full_curve(cls, full_curve) -> JordanCurve: """Initialize a JordanCurve from a full curve, - :param full_curve: The full curve to split. Ideally ``pynurbs.Curve`` instance + :param full_curve: The full curve to split. + Ideally ``pynurbs.Curve`` instance :type full_curve: Point2D :return: The created jordan curve :rtype: JordanCurve @@ -442,11 +443,13 @@ def split(self, indexs: Tuple[int], nodes: Tuple[float]) -> None: """Divides the jordan curve in some nodes Given ``indexs = [a0, a1, ..., an]`` and ``nodes = [u0, u1, ..., un]`` - then for each pair ``(ai, ui)``, split the ``self.segments[ai]`` at ``ui`` + then for each pair ``(ai, ui)``, + split the ``self.segments[ai]`` at ``ui`` .. note: ``node = 0`` or ``node = 1`` are ignored - :param indexs: The number of interior points, ``0 <= index < len(segments)`` + :param indexs: The number of interior points, + ``0 <= index < len(segments)`` :type indexs: tuple[int] :param nodes: The nodes to split, ``0 <= node <= 1`` :type nodes: tuple[float] @@ -742,19 +745,25 @@ def intersection( equal_beziers: bool = True, end_points: bool = True, ) -> Tuple[Tuple[int, int, float, float]]: - """Computes the intersection between two jordan curves + r"""Computes the intersection between two jordan curves - Finds the values of (:math:`a^{\\star}`, :math:`b^{\\star}`, :math:`u^{\\star}`, :math:`v^{\\star}`) such + Finds the values of (:math:`a^{\star}`, :math:`b^{\star}`, + :math:`u^{\star}`, :math:`v^{\star}`) such .. math:: - S_{a^{\\star}}(u^{\\star}) == O_{b^{\\star}}(v^{\\star}) + S_{a^{\star}}(u^{\star}) == O_{b^{\star}}(v^{\star}) It computes the intersection between each pair of segments from ``self`` and ``other`` and returns the matrix of coefficients .. math:: - \\begin{bmatrix} a_0 & b_0 & u_0 & v_0 \\\\ a_1 & b_1 & u_1 & v_1 \\\\ \\vdots & \\vdots & \\vdots & \\vdots \\\\ a_{n} & b_{n} & u_{n} & v_{n} \\end{bmatrix} + \begin{bmatrix} + a_0 & b_0 & u_0 & v_0 \\ + a_1 & b_1 & u_1 & v_1 \\ + \vdots & \vdots & \vdots & \vdots \\ + a_{n} & b_{n} & u_{n} & v_{n} + \end{bmatrix} If two bezier curves are equal, then ``u_i = v_i = None`` @@ -770,14 +779,18 @@ def intersection( equal_beziers : bool, default = True Flag to return (or not) when two segments are equal - If the flag ``equal_beziers`` are inactive, then will remove when ``(ui, vi) == (None, None)``. + If the flag ``equal_beziers`` are inactive, + then will remove when ``(ui, vi) == (None, None)``. end_points : bool, default = True - Flag to return (or not) when jordans intersect at end points, defaults to ``True`` + Flag to return (or not) when jordans intersect at end points - If the flag ``end_points`` are inactive, then will remove when ``(ui, vi)`` are ``(0, 0)``, ``(0, 1)``, ``(1, 0)`` or ``(1, 1)`` + If the flag ``end_points`` are inactive, + then will remove when ``(ui, vi)`` are + ``(0, 0)``, ``(0, 1)``, ``(1, 0)`` or ``(1, 1)`` - :return: The matrix of coefficients ``[(ai, bi, ui, vi)]`` or an empty tuple in case of non-intersection + :return: The matrix of coefficients ``[(ai, bi, ui, vi)]`` + or an empty tuple in case of non-intersection :rtype: tuple[(int, int, float, float)] diff --git a/src/shapepy/polygon.py b/src/shapepy/polygon.py index 03abf603..ae734fa8 100644 --- a/src/shapepy/polygon.py +++ b/src/shapepy/polygon.py @@ -203,12 +203,13 @@ def scale(self, xscale: float, yscale: float) -> Point2D: class Box: """ - Box class, which speeds up the evaluation of - ``__contains__`` in classes like ``PlanarCurve``, ``JordanCurve`` and ``SimpleShape``. + Box class, which speeds up the evaluation of ``__contains__`` + in classes like ``PlanarCurve``, ``JordanCurve`` and ``SimpleShape``. - Since it's faster to evaluate if a point is in a rectangle (this box), we avoid some - computations like projecting the point on a curve and verifying if the distance is - big enough to consider whether the point is the object + Since it's faster to evaluate if a point is in a rectangle (this box), + we avoid some computations like projecting the point on a curve and + verifying if the distance is big enough to consider whether the point + is the object """ diff --git a/src/shapepy/primitive.py b/src/shapepy/primitive.py index 83dcec6b..9d55fffa 100644 --- a/src/shapepy/primitive.py +++ b/src/shapepy/primitive.py @@ -24,7 +24,8 @@ class Primitive: Primitive class with functions to create classical shapes such as `circle`, `triangle`, `square`, `regular_polygon` and a generic `polygon` - .. note:: This class also contains ``empty`` and ``whole`` instances to easy access + .. note:: This class also contains ``empty`` and ``whole`` + instances to easy access """ @@ -212,8 +213,9 @@ def circle( .. note:: We represent the circle by many quadratic segments. - NURBS are not implemented in this code to represent exactly circles. - You can choose the number of quadratic terms by changing ``ndivangle``. + NURBS are not implemented in this code to represent + exactly circles. You can choose the number of quadratic + terms by changing ``ndivangle``. """ try: diff --git a/src/shapepy/shape.py b/src/shapepy/shape.py index 7dcd16f7..1648dd13 100644 --- a/src/shapepy/shape.py +++ b/src/shapepy/shape.py @@ -506,7 +506,8 @@ def __sub__(self, other: BaseShape) -> BaseShape: class DefinedShape(BaseShape): """ - DefinedShape is the base class for SimpleShape, ConnectedShape and DisjointShape + DefinedShape is the base class for SimpleShape, + ConnectedShape and DisjointShape """ @@ -679,7 +680,8 @@ def contains_point( point : Point2D The point to verify if is inside boundary : bool, default = True - The flag to decide if a boundary point is considered inside or outside. + The flag to decide if a boundary point is considered + inside or outside. If ``True``, then a boundary point is considered inside. :return: Whether the point is inside or not @@ -714,7 +716,8 @@ def contains_jordan( jordan : JordanCurve The jordan curve to verify boundary : bool, default = True - The flag to check if jordan is inside a closed (True) or open (False) set + The flag to check if jordan is inside a closed (True) + or open (False) set :return: Whether the jordan is inside or not :rtype: bool From ed0d624e1d7bc99d9c976646f9ceae2536d1c9fc Mon Sep 17 00:00:00 2001 From: Carlos Adir Date: Wed, 9 Jul 2025 21:04:12 +0200 Subject: [PATCH 06/31] fix flake8 error of E731 --- src/shapepy/shape.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/shapepy/shape.py b/src/shapepy/shape.py index 1648dd13..139bc9da 100644 --- a/src/shapepy/shape.py +++ b/src/shapepy/shape.py @@ -1021,7 +1021,10 @@ def subshapes(self, values: Tuple[SimpleShape]): for value in values: assert isinstance(value, SimpleShape) areas = map(float, values) - algori = lambda pair: pair[0] + + def algori(pair): + return pair[0] + values = sorted(zip(areas, values), key=algori, reverse=True) values = tuple(val[1] for val in values) self.__subshapes = tuple(values) @@ -1185,7 +1188,10 @@ def subshapes(self, values: Tuple[BaseShape]): assert isinstance(value, (SimpleShape, ConnectedShape)) areas = map(float, values) lenghts = map(float, [val.jordans[0] for val in values]) - algori = lambda triple: triple[:2] + + def algori(triple): + return triple[:2] + values = sorted(zip(areas, lenghts, values), key=algori, reverse=True) values = tuple(val[2] for val in values) self.__subshapes = tuple(values) From 2cd92d44ef809b8c884be919e97e900d3323c527 Mon Sep 17 00:00:00 2001 From: Carlos Adir Date: Wed, 9 Jul 2025 21:16:45 +0200 Subject: [PATCH 07/31] docs: add docstrings for curve.py file --- src/shapepy/curve.py | 91 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) diff --git a/src/shapepy/curve.py b/src/shapepy/curve.py index 2fb8c3d7..1ddb51bf 100644 --- a/src/shapepy/curve.py +++ b/src/shapepy/curve.py @@ -1,3 +1,15 @@ +""" +File that defines the classes + +* Math: to store mathematical methods used +* BaseCurve: Defines a parent of BezierCurve and PlanarCurve +* Operations +* Intersection +* Projection +* Derivate +* IntegratePlanar +""" + from __future__ import annotations import math @@ -12,6 +24,17 @@ class Math: + """ + Defines the mathematical functions used for the package + + The methods are + * comb + * horner_method + * bezier_caract_matrix + * closed_linspace + * open_linspace + """ + __caract_matrix = {} @staticmethod @@ -63,12 +86,38 @@ def bezier_caract_matrix(degree: int) -> Tuple[Tuple[int]]: @staticmethod def closed_linspace(npts: int) -> Tuple[Fraction]: + """ + Gives a set of numbers in interval [0, 1] + + Example + ------- + >>> closed_linspace(2) + (0, 1) + >>> closed_linspace(3) + (0, 0.5, 1) + >>> closed_linspace(4) + (0, 0.33, 0.66, 1) + >>> closed_linspace(5) + (0, 0.25, 0.5, 0.75, 1) + """ assert isinstance(npts, int) assert npts >= 2 return tuple(Fraction(num, npts - 1) for num in range(npts)) @staticmethod def open_linspace(npts: int) -> Tuple[Fraction]: + """ + Gives a set of numbers in interval (0, 1) + + Example + ------- + >>> open_linspace(1) + (0.5, ) + >>> open_linspace(2) + (0.33, 0.66) + >>> open_linspace(3) + (0.25, 0.50, 0.75) + """ assert isinstance(npts, int) assert npts >= 1 return tuple( @@ -77,6 +126,10 @@ def open_linspace(npts: int) -> Tuple[Fraction]: class BaseCurve(object): + """ + Defines a parent class of BezierCurve and PlanarCurve + """ + def __call__( self, nodes: Union[float, Tuple[float]] ) -> Union[Any, Tuple[Any]]: @@ -184,6 +237,11 @@ def split(self, nodes: Tuple[float]) -> Tuple[BezierCurve]: class PlanarCurve(BaseCurve): + """ + Defines a planar curve in the plane, + that contains a bezier curve inside it + """ + def __init__(self, ctrlpoints: Tuple[Point2D]): ctrlpoints = list(ctrlpoints) for i, point in enumerate(ctrlpoints): @@ -291,18 +349,33 @@ def __contains__(self, point: Point2D) -> bool: @property def degree(self) -> int: + """ + The degree of the bezier curve + + Degree = 1 -> Linear curve + Degree = 2 -> Quadratic + """ return self.__planar.degree @property def npts(self) -> int: + """ + The number of control points used by the curve + """ return self.__planar.npts @property def ctrlpoints(self) -> Tuple[Point2D]: + """ + The control points that defines the planar curve + """ return self.__planar.ctrlpoints @property def weights(self) -> Tuple[float]: + """ + The weights of the control points, used for rational curves + """ raise NotImplementedError @ctrlpoints.setter @@ -313,9 +386,15 @@ def ctrlpoints(self, points: Tuple[Point2D]): self.__planar.ctrlpoints = points def eval(self, nodes: Tuple[float]) -> Tuple[Any]: + """ + Evaluates the nodes, giving the points + """ return self.__planar.eval(nodes) def derivate(self, times: Optional[int] = 1) -> PlanarCurve: + """ + Gives the first derivative of the curve + """ assert isinstance(times, int) assert times > 0 matrix = Derivate.non_rational_bezier(self.degree, times) @@ -351,6 +430,10 @@ def __deepcopy__(self, memo) -> PlanarCurve: return self.__class__(ctrlpoints) def invert(self) -> PlanarCurve: + """ + Inverts the direction of the curve. + If the curve is clockwise, it becomes counterclockwise + """ points = self.ctrlpoints npts = len(points) new_ctrlpoints = tuple(points[i] for i in range(npts - 1, -1, -1)) @@ -358,6 +441,9 @@ def invert(self) -> PlanarCurve: return self def split(self, nodes: Tuple[float]) -> Tuple[PlanarCurve]: + """ + Splits the curve into more segments + """ beziers = self.__planar.split(nodes) planars = tuple(PlanarCurve(bezier.ctrlpoints) for bezier in beziers) return planars @@ -712,6 +798,11 @@ def area(curve: PlanarCurve, nnodes: Optional[int] = None): def winding_number_linear( pointa: Point2D, pointb: Point2D, center: Point2D ) -> float: + """ + Computes the winding number defined by the given points. + It means, it's the angle made between the vector + (pointb - center) and (pointa - center) + """ anglea = np.arctan2( float(pointa[1] - center[1]), float(pointa[0] - center[0]) ) From 9c23efde164bdfcf37fcdb2273529656d918dd4c Mon Sep 17 00:00:00 2001 From: Carlos Adir Date: Wed, 9 Jul 2025 21:22:14 +0200 Subject: [PATCH 08/31] docs: add docstrings for plot.py file --- src/shapepy/plot.py | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/src/shapepy/plot.py b/src/shapepy/plot.py index 80586aed..5bfda556 100644 --- a/src/shapepy/plot.py +++ b/src/shapepy/plot.py @@ -1,3 +1,8 @@ +""" +Defines functions that allows plotting the figures made, +like shapes, curves, points, doing projections and so on +""" + from __future__ import annotations from typing import Optional @@ -21,6 +26,9 @@ def patch_segment(segment: PlanarCurve): + """ + Creates the commands for matplotlib to plot the segment + """ vertices = [] commands = [] if segment.degree == 1: @@ -33,6 +41,9 @@ def patch_segment(segment: PlanarCurve): def path_shape(connected: ConnectedShape) -> Path: + """ + Creates the commands for matplotlib to plot the shape + """ vertices = [] commands = [] for jordan in connected.jordans: @@ -49,6 +60,9 @@ def path_shape(connected: ConnectedShape) -> Path: def path_jordan(jordan: JordanCurve) -> Path: + """ + Creates the commands for matplotlib to plot the jordan curve + """ vertices = [jordan.segments[0].ctrlpoints[0]] commands = [Path.MOVETO] for segment in jordan.segments: @@ -65,6 +79,18 @@ def path_jordan(jordan: JordanCurve) -> Path: class ShapePloter: + """ + Class which is a wrapper of the matplotlib.pyplot.plt + + You can create the instance of this class and call the same way as plt + + Example + ------- + >>> plt = ShapePloter() + >>> plot.plot([0, 1], [3, -2]) + >>> plt.show() + """ + Figure = matplotlib.figure.Figure Axes = matplotlib.axes._axes.Axes @@ -91,21 +117,33 @@ def __init__( self.__ax = ax def gcf(self) -> ShapePloter.Figure: + """ + Gets the current figure + """ return self.__fig def gca(self) -> ShapePloter.Axes: + """ + Gets the current axis + """ return self.__ax def __getattr__(self, attr): return getattr(matplotlib.pyplot, attr) def plot(self, *args, **kwargs): + """ + A wrapper of the matplotlib.pyplot.plt.plot + """ if isinstance(args[0], BaseShape): self.plot_shape(args[0], kwargs=kwargs) else: return self.gca().plot(*args, **kwargs) def plot_shape(self, shape: BaseShape, *, kwargs={}): + """ + Plots a BaseShape, which can be Empty, Whole, Simple, etc + """ assert isinstance(shape, BaseShape) if isinstance(shape, EmptyShape): return From 9e2365179f667cccf8c3c8f1ff97f8c4273e64f4 Mon Sep 17 00:00:00 2001 From: Carlos Adir Date: Wed, 9 Jul 2025 21:25:38 +0200 Subject: [PATCH 09/31] refactor using pylint hints --- src/shapepy/plot.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/shapepy/plot.py b/src/shapepy/plot.py index 5bfda556..e568dfaa 100644 --- a/src/shapepy/plot.py +++ b/src/shapepy/plot.py @@ -136,11 +136,10 @@ def plot(self, *args, **kwargs): A wrapper of the matplotlib.pyplot.plt.plot """ if isinstance(args[0], BaseShape): - self.plot_shape(args[0], kwargs=kwargs) - else: - return self.gca().plot(*args, **kwargs) + return self.plot_shape(args[0], kwargs=kwargs) + return self.gca().plot(*args, **kwargs) - def plot_shape(self, shape: BaseShape, *, kwargs={}): + def plot_shape(self, shape: BaseShape, *, kwargs): """ Plots a BaseShape, which can be Empty, Whole, Simple, etc """ From e61464af7d5f45b626039bc16da2b84d688c1cba Mon Sep 17 00:00:00 2001 From: Carlos Adir Date: Wed, 9 Jul 2025 21:29:52 +0200 Subject: [PATCH 10/31] add docstrings for polygon --- src/shapepy/polygon.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/shapepy/polygon.py b/src/shapepy/polygon.py index ae734fa8..d6348f6a 100644 --- a/src/shapepy/polygon.py +++ b/src/shapepy/polygon.py @@ -1,3 +1,8 @@ +""" +Module that defines the basic geometric classes used for the package + +They are used to encapsulate some commands +""" from __future__ import annotations import fractions @@ -8,6 +13,10 @@ class Point2D(object): + """ + Defines a Point in the plane, that has 2 coordinates (x, y) + """ + def __new__(cls, *point: Tuple[float]): if isinstance(point[0], cls): return point[0] @@ -46,6 +55,9 @@ def cross(self, other: Point2D) -> float: return self[0] * other[1] - self[1] * other[0] def norm2(self) -> float: + """ + Computes the L2 norm square = + """ return self.inner(self) def __abs__(self) -> float: @@ -194,6 +206,9 @@ def rotate(self, angle: float) -> Point2D: return self def scale(self, xscale: float, yscale: float) -> Point2D: + """ + Gives the new point (xscale * x0, yscale * y0) + """ float(xscale) float(yscale) self._x *= xscale From 1ab9374338807f7758ddaaaeb3fde90c670a8601 Mon Sep 17 00:00:00 2001 From: Carlos Adir Date: Wed, 9 Jul 2025 21:32:11 +0200 Subject: [PATCH 11/31] use pylint to improve code quality --- src/shapepy/polygon.py | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/shapepy/polygon.py b/src/shapepy/polygon.py index d6348f6a..ed1bbbe9 100644 --- a/src/shapepy/polygon.py +++ b/src/shapepy/polygon.py @@ -12,7 +12,7 @@ import numpy as np -class Point2D(object): +class Point2D: """ Defines a Point in the plane, that has 2 coordinates (x, y) """ @@ -23,11 +23,7 @@ def __new__(cls, *point: Tuple[float]): return super().__new__(cls) def __init__(self, *point: Tuple[float]): - try: - x, y = point if len(point) == 2 else point[0] - except ValueError: - error_msg = f"Invalid input for point: {point}" - raise ValueError(error_msg) + x, y = point if len(point) == 2 else point[0] if isinstance(x, str) or isinstance(y, str): raise TypeError float(x) @@ -93,7 +89,7 @@ def __iter__(self): def __getitem__(self, index: int): assert isinstance(index, int) - assert index == 0 or index == 1 + assert index in {0, 1} return self._x if index == 0 else self._y def __str__(self) -> str: @@ -115,7 +111,7 @@ def __str__(self) -> str: ) else: ymsg = str(self._y) - return "(%s, %s)" % (xmsg, ymsg) + return f"({xmsg}, {ymsg})" def __repr__(self) -> str: return self.__str__() @@ -254,7 +250,7 @@ def __contains__(self, point: Point2D) -> bool: return False if self.toppt[0] + self.dx < point[0]: return False - return not (self.toppt[1] + self.dy < point[1]) + return not self.toppt[1] + self.dy < point[1] def __or__(self, other: Box) -> Box: xmin = min(self.lowpt[0], other.lowpt[0]) From dcdca50403e6e44f830baf6b1118cf1c3d50cfbd Mon Sep 17 00:00:00 2001 From: Carlos Adir Date: Wed, 9 Jul 2025 21:37:04 +0200 Subject: [PATCH 12/31] fix: verifications on primitive Regular Polygon function --- src/shapepy/primitive.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/shapepy/primitive.py b/src/shapepy/primitive.py index 9d55fffa..ab740dc7 100644 --- a/src/shapepy/primitive.py +++ b/src/shapepy/primitive.py @@ -9,6 +9,7 @@ import math from copy import copy from fractions import Fraction +from numbers import Real from typing import Tuple import numpy as np @@ -66,14 +67,15 @@ def regular_polygon( .. image:: ../img/primitive/regular5.svg """ - try: - assert isinstance(nsides, int) - assert nsides >= 3 - float(radius) - assert radius > 0 - center = Point2D(center) - except (ValueError, TypeError, AssertionError): - raise ValueError("Input invalid") + if not isinstance(nsides, int): + raise ValueError + if nsides < 3: + raise ValueError + if not isinstance(radius, Real): + raise ValueError + if radius <= 0: + raise ValueError + center = Point2D(center) if nsides == 4: vertices = [(radius, 0), (0, radius), (-radius, 0), (0, -radius)] vertices = tuple([center + Point2D(vertex) for vertex in vertices]) From 10b45d6e8fe3f0fdad5397d1b0fa4a372d4bc812 Mon Sep 17 00:00:00 2001 From: Carlos Adir Date: Wed, 9 Jul 2025 21:42:14 +0200 Subject: [PATCH 13/31] improve code smell using pylint --- src/shapepy/primitive.py | 28 +++++++++++----------------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/src/shapepy/primitive.py b/src/shapepy/primitive.py index ab740dc7..a029c132 100644 --- a/src/shapepy/primitive.py +++ b/src/shapepy/primitive.py @@ -78,13 +78,13 @@ def regular_polygon( center = Point2D(center) if nsides == 4: vertices = [(radius, 0), (0, radius), (-radius, 0), (0, -radius)] - vertices = tuple([center + Point2D(vertex) for vertex in vertices]) + vertices = tuple(center + Point2D(vertex) for vertex in vertices) else: vertices = np.empty((nsides, 2), dtype="float64") theta = np.linspace(0, math.tau, nsides, endpoint=False) vertices[:, 0] = radius * np.cos(theta) vertices[:, 1] = radius * np.sin(theta) - vertices = tuple([center + Point2D(vertex) for vertex in vertices]) + vertices = tuple(center + Point2D(vertex) for vertex in vertices) return Primitive.polygon(vertices) @staticmethod @@ -169,12 +169,9 @@ def square(side: float = 1, center: Point2D = (0, 0)) -> SimpleShape: .. image:: ../img/primitive/square.svg """ - try: - float(side) - assert side > 0 - center = Point2D(center) - except (ValueError, TypeError, AssertionError): - raise ValueError("Input invalid") + if not isinstance(side, Real) or side <= 0: + raise ValueError + center = Point2D(center) if isinstance(side, int): side = Fraction(side) @@ -220,14 +217,11 @@ def circle( terms by changing ``ndivangle``. """ - try: - float(radius) - assert radius > 0 - center = Point2D(center) - assert isinstance(ndivangle, int) - assert ndivangle >= 4 - except (ValueError, TypeError, AssertionError): - raise ValueError("Input invalid") + if not isinstance(radius, Real) or radius <= 0: + raise ValueError + if not isinstance(ndivangle, int) or ndivangle < 4: + raise ValueError + center = Point2D(center) angle = math.tau / ndivangle height = np.tan(angle / 2) @@ -235,7 +229,7 @@ def circle( start_point = radius * Point2D(1, 0) middle_point = radius * Point2D(1, height) beziers = [] - for i in range(ndivangle - 1): + for _ in range(ndivangle - 1): end_point = copy(start_point).rotate(angle) new_bezier = PlanarCurve([start_point, middle_point, end_point]) beziers.append(new_bezier) From f0c81084cfb0a9e2e30181b44db6dd42445fb75e Mon Sep 17 00:00:00 2001 From: Carlos Adir Date: Wed, 9 Jul 2025 21:45:38 +0200 Subject: [PATCH 14/31] use pylint to improve plot.py code smell --- src/shapepy/plot.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/shapepy/plot.py b/src/shapepy/plot.py index e568dfaa..7e4060f9 100644 --- a/src/shapepy/plot.py +++ b/src/shapepy/plot.py @@ -91,8 +91,8 @@ class ShapePloter: >>> plt.show() """ - Figure = matplotlib.figure.Figure - Axes = matplotlib.axes._axes.Axes + Figure = matplotlib.pyplot.gcf() + Axes = matplotlib.pyplot.gca() def __init__( self, @@ -139,6 +139,7 @@ def plot(self, *args, **kwargs): return self.plot_shape(args[0], kwargs=kwargs) return self.gca().plot(*args, **kwargs) + #pylint: disable=too-many-locals def plot_shape(self, shape: BaseShape, *, kwargs): """ Plots a BaseShape, which can be Empty, Whole, Simple, etc From 64aaefda626cd530648b547536d456ef14c7cd79 Mon Sep 17 00:00:00 2001 From: Carlos Adir Date: Wed, 9 Jul 2025 21:49:37 +0200 Subject: [PATCH 15/31] use pylint to improve code smell --- src/shapepy/jordancurve.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/shapepy/jordancurve.py b/src/shapepy/jordancurve.py index 26d3a8bc..12219641 100644 --- a/src/shapepy/jordancurve.py +++ b/src/shapepy/jordancurve.py @@ -15,6 +15,10 @@ class IntegrateJordan: + """ + Defines functions to integrate over the internal area + defined by the jordan curve. + """ @staticmethod def vertical( jordan: JordanCurve, expx: int, expy: int, nnodes: Optional[int] = None @@ -429,7 +433,7 @@ def __split_segment(self, index: int, nodes: Tuple[float]) -> None: points = list(new_segments[-1].ctrlpoints) points[-1] = segment.ctrlpoints[-1] new_segments[-1].ctrlpoints = points - for i, node in enumerate(nodes): + for i in range(len(nodes)): points = list(new_segments[i + 1].ctrlpoints) points[0] = new_segments[i].ctrlpoints[-1] new_segments[i + 1].ctrlpoints = points @@ -711,8 +715,8 @@ def __float__(self) -> float: def __abs__(self) -> JordanCurve: """Returns the same curve, but in positive direction""" - copy = self.__copy__() - return copy if float(self) > 0 else copy.invert() + curve = self.__copy__() + return curve if float(self) > 0 else curve.invert() def __intersection( self, other: JordanCurve @@ -814,7 +818,7 @@ def intersection( intersections.remove((ai, bi, ui, vi)) if not end_points: for ai, bi, ui, vi in tuple(intersections): - if ui is None or (0 < ui and ui < 1) or (0 < vi and vi < 1): + if ui is None or (0 < ui < 1) or (0 < vi < 1): continue intersections.remove((ai, bi, ui, vi)) return tuple(sorted(intersections)) From 304c8eaabc22dcd43c9efa9304ddffd27896d476 Mon Sep 17 00:00:00 2001 From: Carlos Adir Date: Wed, 9 Jul 2025 21:56:23 +0200 Subject: [PATCH 16/31] add docstrings --- src/shapepy/curve.py | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/src/shapepy/curve.py b/src/shapepy/curve.py index 1ddb51bf..d668c69a 100644 --- a/src/shapepy/curve.py +++ b/src/shapepy/curve.py @@ -160,20 +160,38 @@ def __or__(self, other: BezierCurve) -> BezierCurve: @property def degree(self) -> int: + """ + The polynomial degree used by the Bezier Curve + """ return self.npts - 1 @property def npts(self) -> int: + """ + The number of control points used by the curve + """ return len(self.ctrlpoints) @property def ctrlpoints(self) -> Tuple[Point2D]: + """ + The control points that defines the cdurve + """ return self.__ctrlpoints @ctrlpoints.setter def ctrlpoints(self, other: Tuple[Any]): self.__ctrlpoints = tuple(other) + def __call__( + self, nodes: Union[float, Tuple[float]] + ) -> Union[Any, Tuple[Any]]: + try: + iter(nodes) + return self.eval(nodes) + except TypeError: + return self.eval((nodes,))[0] + def __str__(self) -> str: msg = f"BezierCurve of degree {self.degree} and " msg += f"control points {str(self.ctrlpoints)}" @@ -200,6 +218,9 @@ def eval(self, nodes: Tuple[float]) -> Tuple[Any]: return tuple(results) def derivate(self, times: Optional[int] = 1) -> BezierCurve: + """ + Computes the derivative of the Bezier Curve + """ assert isinstance(times, int) assert times > 0 matrix = Derivate.non_rational_bezier(self.degree, times) @@ -229,6 +250,9 @@ def clean(self, tolerance: Optional[float] = 1e-9) -> BezierCurve: return self def split(self, nodes: Tuple[float]) -> Tuple[BezierCurve]: + """ + Splits the Bezier Curve into the given segments + """ knotvector = pynurbs.GeneratorKnotVector.bezier(self.degree) curve = pynurbs.Curve(knotvector, self.ctrlpoints) beziers = curve.split(nodes) @@ -450,6 +474,9 @@ def split(self, nodes: Tuple[float]) -> Tuple[PlanarCurve]: class Operations: + """ + Defines the operation of over the bezier curves + """ __degree_decre = {} @staticmethod @@ -485,6 +512,9 @@ def degree_decrease(degree: int, times: int) -> Tuple[Tuple[Tuple[float]]]: class Intersection: + """ + Defines the methods used to compute the intersection between curves + """ tol_du = 1e-9 # tolerance convergence tol_norm = 1e-9 # tolerance convergence max_denom = math.ceil(1 / tol_du) @@ -566,6 +596,10 @@ def filter_distance( pairs: Tuple[Tuple[float]], max_dist: float, ) -> Tuple[Tuple[float]]: + """ + Filter the pairs values, since the intersection pair + (0.5, 1) is almost the same as (1e-6, 0.99999) + """ pairs = list(pairs) index = 0 while index < len(pairs): @@ -581,6 +615,9 @@ def filter_distance( def filter_parameters( pairs: Tuple[Tuple[float]], max_dist: float ) -> Tuple[Tuple[float]]: + """ + Filter the parameters values, cause 0 is almost the same as 1e-6 + """ pairs = list(pairs) index = 0 while index < len(pairs): @@ -598,6 +635,9 @@ def filter_parameters( class Projection: + """ + Defines the methods used to find the projection of a point into a curve + """ @staticmethod def point_on_curve(point: Point2D, curve: PlanarCurve) -> float: """Finds parameter u* such abs(C(u*)) is minimal @@ -658,6 +698,9 @@ def newton_iteration( class Derivate: + """ + Defines the functions to derivate the bezier curve + """ __non_rat_bezier_once = {} @staticmethod From e9f642b1dfca4a3431a124660ad0c64c10ad2e7a Mon Sep 17 00:00:00 2001 From: Carlos Adir Date: Wed, 9 Jul 2025 22:04:23 +0200 Subject: [PATCH 17/31] use pylint to improve code smell --- src/shapepy/curve.py | 39 +++++++++++++++++---------------------- 1 file changed, 17 insertions(+), 22 deletions(-) diff --git a/src/shapepy/curve.py b/src/shapepy/curve.py index d668c69a..342485b9 100644 --- a/src/shapepy/curve.py +++ b/src/shapepy/curve.py @@ -125,22 +125,7 @@ def open_linspace(npts: int) -> Tuple[Fraction]: ) -class BaseCurve(object): - """ - Defines a parent class of BezierCurve and PlanarCurve - """ - - def __call__( - self, nodes: Union[float, Tuple[float]] - ) -> Union[Any, Tuple[Any]]: - try: - iter(nodes) - return self.eval(nodes) - except TypeError: - return self.eval((nodes,))[0] - - -class BezierCurve(BaseCurve): +class BezierCurve: """BezierCurve object""" def __init__(self, ctrlpoints: Tuple[Any]): @@ -244,7 +229,7 @@ def clean(self, tolerance: Optional[float] = 1e-9) -> BezierCurve: break times += 1 if times == 0: - return + return self mattrans, _ = Operations.degree_decrease(degree, times) self.ctrlpoints = tuple(np.dot(mattrans, points)) return self @@ -260,7 +245,7 @@ def split(self, nodes: Tuple[float]) -> Tuple[BezierCurve]: return planars -class PlanarCurve(BaseCurve): +class PlanarCurve: """ Defines a planar curve in the plane, that contains a bezier curve inside it @@ -321,13 +306,13 @@ def __and__(self, other: PlanarCurve) -> Union[None, Tuple[Tuple[int]]]: return tuple() if self.degree == 1 and other.degree == 1: params = Intersection.lines(self, other) - return (params,) if len(params) else tuple() + return (params,) if len(params) != 0 else tuple() usample = list(Math.closed_linspace(self.npts + 3)) vsample = list(Math.closed_linspace(other.npts + 3)) pairs = [] - for i, ui in enumerate(usample): + for ui in usample: pairs += [(ui, vj) for vj in vsample] - for k in range(3): + for _ in range(3): pairs = Intersection.bezier_and_bezier(self, other, pairs) pairs.insert(0, (0, 0)) pairs.insert(0, (0, 1)) @@ -371,6 +356,16 @@ def __contains__(self, point: Point2D) -> bool: return True return False + + def __call__( + self, nodes: Union[float, Tuple[float]] + ) -> Union[Any, Tuple[Any]]: + try: + iter(nodes) + return self.eval(nodes) + except TypeError: + return self.eval((nodes,))[0] + @property def degree(self) -> int: """ @@ -557,7 +552,7 @@ def bezier_and_bezier( ddcurveb = dcurveb.derivate() # Start newton iteration - for k in range(20): # Number of newton iteration + for _ in range(20): # Number of newton iteration new_pairs = set() for u, v in pairs: ssu = curvea(u) From 778dcf931fb04d03930ae42559d48fa77ca08c71 Mon Sep 17 00:00:00 2001 From: Carlos Adir Date: Wed, 9 Jul 2025 22:06:31 +0200 Subject: [PATCH 18/31] disable some pylint. Needs further refacto --- src/shapepy/curve.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/shapepy/curve.py b/src/shapepy/curve.py index 342485b9..34d484ad 100644 --- a/src/shapepy/curve.py +++ b/src/shapepy/curve.py @@ -468,6 +468,7 @@ def split(self, nodes: Tuple[float]) -> Tuple[PlanarCurve]: return planars +#pylint: disable=too-few-public-methods class Operations: """ Defines the operation of over the bezier curves @@ -538,6 +539,7 @@ def lines(curvea: PlanarCurve, curveb: PlanarCurve) -> Tuple[float]: return tuple() # Parallel, but not colinear return tuple() + #pylint: disable=too-many-locals @staticmethod def bezier_and_bezier( curvea: PlanarCurve, curveb: PlanarCurve, pairs: Tuple[Tuple[float]] @@ -660,6 +662,7 @@ def point_on_curve(point: Point2D, curve: PlanarCurve) -> float: params.append(usample[i]) return tuple(params) + #pylint: disable=too-many-locals @staticmethod def newton_iteration( point: Point2D, curve: PlanarCurve, usample: Tuple[float] From 2a4bdfd8313ee538a13dea010a36392a5f1082e6 Mon Sep 17 00:00:00 2001 From: Carlos Adir Date: Wed, 9 Jul 2025 22:13:21 +0200 Subject: [PATCH 19/31] fix plot use of Matplotlib reference to Figure class --- src/shapepy/plot.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/shapepy/plot.py b/src/shapepy/plot.py index 7e4060f9..b61055e3 100644 --- a/src/shapepy/plot.py +++ b/src/shapepy/plot.py @@ -109,9 +109,9 @@ def __init__( if isinstance(ax, list) and len(ax) == 0: ax = pyplot.gca() else: - if not isinstance(fig, ShapePloter.Figure): + if not isinstance(fig, matplotlib.figure.Figure): raise TypeError - if not isinstance(ax, ShapePloter.Axes): + if not isinstance(ax, type(matplotlib.pyplot.gca())): raise TypeError self.__fig = fig self.__ax = ax From 3a22e26d2fa8f1071af0614685b239e4158148ed Mon Sep 17 00:00:00 2001 From: Carlos Adir Date: Wed, 9 Jul 2025 22:24:21 +0200 Subject: [PATCH 20/31] remove unused __or__ method --- src/shapepy/curve.py | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/shapepy/curve.py b/src/shapepy/curve.py index 34d484ad..dd71fb6c 100644 --- a/src/shapepy/curve.py +++ b/src/shapepy/curve.py @@ -131,17 +131,6 @@ class BezierCurve: def __init__(self, ctrlpoints: Tuple[Any]): self.ctrlpoints = ctrlpoints - def __or__(self, other: BezierCurve) -> BezierCurve: - """ - Unite a set of bezier curves - - If the error for unite is bigger than tolerance, raises ValueError - """ - assert isinstance(other, BezierCurve) - final_curve = Operations.unite(self.ctrlpoints, other.ctrlpoints) - if final_curve.degree + 1 != final_curve.npts: - raise ValueError("Union is not a bezier curve!") - return self.__class__(final_curve.ctrlpoints) @property def degree(self) -> int: From 1babe22176ca1e7aafb7b419c7f1b97f23e6362e Mon Sep 17 00:00:00 2001 From: Carlos Adir Date: Wed, 9 Jul 2025 22:40:06 +0200 Subject: [PATCH 21/31] general improvements on code smell with pylint --- src/shapepy/shape.py | 68 ++++++++++++++++++++++---------------------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/src/shapepy/shape.py b/src/shapepy/shape.py index 139bc9da..061813f9 100644 --- a/src/shapepy/shape.py +++ b/src/shapepy/shape.py @@ -20,8 +20,8 @@ class SuperclassMeta(type): - def __new__(mcls, classname, bases, cls_dict): - cls = super().__new__(mcls, classname, bases, cls_dict) + def __new__(mcs, classname, bases, cls_dict): + cls = super().__new__(mcs, classname, bases, cls_dict) for name, member in cls_dict.items(): if not getattr(member, "__doc__"): try: @@ -314,7 +314,7 @@ def midpoints_shapes( indexsa = FollowPath.midpoints_one_shape( shapea, shapeb, closed, inside ) - indexsb = FollowPath.midpoints_one_shape( + indexsb = FollowPath.midpoints_one_shape( # pylint: disable=W1114 shapeb, shapea, closed, inside ) indexsa = list(indexsa) @@ -352,7 +352,7 @@ def and_shapes(shapea: BaseShape, shapeb: BaseShape) -> Tuple[JordanCurve]: return new_jordans -class BaseShape(object, metaclass=SuperclassMeta): +class BaseShape(metaclass=SuperclassMeta): """ Class which allows operations like: - move @@ -370,17 +370,14 @@ def __init__(self): @abc.abstractmethod def __invert__(self) -> BaseShape: """Invert shape""" - pass @abc.abstractmethod - def __or__(self) -> BaseShape: + def __or__(self, other: BaseShape) -> BaseShape: """Union shapes""" - pass @abc.abstractmethod - def __and__(self) -> BaseShape: + def __and__(self, other: BaseShape) -> BaseShape: """Intersection shapes""" - pass def __neg__(self) -> BaseShape: """Invert the BaseShape""" @@ -512,14 +509,14 @@ class DefinedShape(BaseShape): """ def __init__(self, *args, **kwargs): - self.__box = None + pass def __copy__(self) -> DefinedShape: return self.__deepcopy__(None) def __deepcopy__(self, memo) -> DefinedShape: jordans = tuple(copy(jordan) for jordan in self.jordans) - return ShapeFromJordans(jordans) + return shape_from_jordans(jordans) def box(self) -> Box: """ @@ -546,7 +543,7 @@ def box(self) -> Box: return box def __invert__(self) -> BaseShape: - return ShapeFromJordans(tuple(~jordan for jordan in self.jordans)) + return shape_from_jordans(tuple(~jordan for jordan in self.jordans)) def __or__(self, other: BaseShape) -> BaseShape: assert isinstance(other, BaseShape) @@ -561,7 +558,7 @@ def __or__(self, other: BaseShape) -> BaseShape: new_jordans = FollowPath.or_shapes(self, other) if len(new_jordans) == 0: return WholeShape() - return ShapeFromJordans(new_jordans) + return shape_from_jordans(new_jordans) def __and__(self, other: BaseShape) -> BaseShape: assert isinstance(other, BaseShape) @@ -576,7 +573,7 @@ def __and__(self, other: BaseShape) -> BaseShape: new_jordans = FollowPath.and_shapes(self, other) if len(new_jordans) == 0: return EmptyShape() - return ShapeFromJordans(new_jordans) + return shape_from_jordans(new_jordans) def __contains__( self, other: Union[Point2D, JordanCurve, BaseShape] @@ -768,15 +765,17 @@ def contains_shape(self, other: BaseShape) -> bool: return self._contains_shape(other) @abc.abstractmethod - def _contains_point(point: Point2D, boundary: Optional[bool] = True): + def _contains_point(self, point: Point2D, boundary: Optional[bool] = True): pass @abc.abstractmethod - def _contains_jordan(jordan: JordanCurve, boundary: Optional[bool] = True): + def _contains_jordan( + self, jordan: JordanCurve, boundary: Optional[bool] = True + ): pass @abc.abstractmethod - def _contains_shape(other: BaseShape): + def _contains_shape(self, other: BaseShape): pass @@ -798,7 +797,7 @@ def __init__(self, jordancurve: JordanCurve): def __str__(self) -> str: area = float(self) vertices = self.jordans[0].vertices - vertices = tuple([tuple(vertex) for vertex in vertices]) + vertices = tuple(tuple(vertex) for vertex in vertices) msg = f"Simple Shape of area {area:.2f} with vertices:\n" msg += str(np.array(vertices, dtype="float64")) return msg @@ -923,19 +922,19 @@ def _contains_shape(self, other: DefinedShape) -> bool: def __contains_simple(self, other: SimpleShape) -> bool: assert isinstance(other, SimpleShape) - areaA = float(other) - areaB = float(self) + areaa = float(other) + areab = float(self) jordana = other.jordans[0] jordanb = self.jordans[0] - if areaA < 0 and areaB > 0: + if areaa < 0 and areab > 0: return False - if not (self.box() & other.box()): - return areaA > 0 and areaB < 0 - if areaA > 0 and areaB < 0: + if not self.box() & other.box(): + return areaa > 0 and areab < 0 + if areaa > 0 and areab < 0: return jordana in self and jordanb not in other - if areaA > areaB or jordana not in self: + if areaa > areab or jordana not in self: return False - if areaA > 0: + if areaa > 0: return True # If simple shape is not a square # may happens error here @@ -1092,7 +1091,7 @@ def __eq__(self, other: BaseShape): self_subshapes = list(self.subshapes) othe_subshapes = list(other.subshapes) # Compare if a curve is inside another - while len(self_subshapes) and len(othe_subshapes): + while len(self_subshapes) != 0 and len(othe_subshapes) != 0: for j, osbshape in enumerate(othe_subshapes): if osbshape == self_subshapes[0]: self_subshapes.pop(0) @@ -1138,6 +1137,7 @@ def _contains_shape(self, other: DefinedShape) -> bool: if subshape not in self: return False return True + raise NotImplementedError @property def jordans(self) -> Tuple[JordanCurve]: @@ -1197,7 +1197,7 @@ def algori(triple): self.__subshapes = tuple(values) -def DivideConnecteds( +def divide_connecteds( simples: Tuple[SimpleShape], ) -> Tuple[Union[SimpleShape, ConnectedShape]]: """ @@ -1213,13 +1213,13 @@ def DivideConnecteds( externals = [] connected = [] simples = list(simples) - while len(simples): + while len(simples) != 0: areas = map(float, simples) absareas = tuple(map(abs, areas)) index = absareas.index(max(absareas)) connected.append(simples.pop(index)) internal = [] - while len(simples): # Divide in two groups + while len(simples) != 0: # Divide in two groups simple = simples.pop(0) jordan = simple.jordans[0] for subsimple in connected: @@ -1234,10 +1234,10 @@ def DivideConnecteds( connected = connected[0] else: connected = ConnectedShape(connected) - return (connected,) + DivideConnecteds(externals) + return (connected,) + divide_connecteds(externals) -def ShapeFromJordans(jordans: Tuple[JordanCurve]) -> BaseShape: +def shape_from_jordans(jordans: Tuple[JordanCurve]) -> BaseShape: """Returns the correspondent shape This function don't do entry validation @@ -1245,14 +1245,14 @@ def ShapeFromJordans(jordans: Tuple[JordanCurve]) -> BaseShape: Example ---------- - >>> ShapeFromJordans([]) + >>> shape_from_jordans([]) EmptyShape """ assert len(jordans) != 0 simples = tuple(map(SimpleShape, jordans)) if len(simples) == 1: return simples[0] - connecteds = DivideConnecteds(simples) + connecteds = divide_connecteds(simples) if len(connecteds) == 1: return connecteds[0] return DisjointShape(connecteds) From 505c836d477e6e70a53c20660249fe9da8153d7a Mon Sep 17 00:00:00 2001 From: Carlos Adir Date: Wed, 9 Jul 2025 22:41:26 +0200 Subject: [PATCH 22/31] fix format with black --- src/shapepy/curve.py | 14 ++++++++------ src/shapepy/jordancurve.py | 1 + src/shapepy/plot.py | 2 +- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/shapepy/curve.py b/src/shapepy/curve.py index dd71fb6c..815356e3 100644 --- a/src/shapepy/curve.py +++ b/src/shapepy/curve.py @@ -131,7 +131,6 @@ class BezierCurve: def __init__(self, ctrlpoints: Tuple[Any]): self.ctrlpoints = ctrlpoints - @property def degree(self) -> int: """ @@ -345,7 +344,6 @@ def __contains__(self, point: Point2D) -> bool: return True return False - def __call__( self, nodes: Union[float, Tuple[float]] ) -> Union[Any, Tuple[Any]]: @@ -457,11 +455,12 @@ def split(self, nodes: Tuple[float]) -> Tuple[PlanarCurve]: return planars -#pylint: disable=too-few-public-methods +# pylint: disable=too-few-public-methods class Operations: """ Defines the operation of over the bezier curves """ + __degree_decre = {} @staticmethod @@ -500,6 +499,7 @@ class Intersection: """ Defines the methods used to compute the intersection between curves """ + tol_du = 1e-9 # tolerance convergence tol_norm = 1e-9 # tolerance convergence max_denom = math.ceil(1 / tol_du) @@ -528,7 +528,7 @@ def lines(curvea: PlanarCurve, curveb: PlanarCurve) -> Tuple[float]: return tuple() # Parallel, but not colinear return tuple() - #pylint: disable=too-many-locals + # pylint: disable=too-many-locals @staticmethod def bezier_and_bezier( curvea: PlanarCurve, curveb: PlanarCurve, pairs: Tuple[Tuple[float]] @@ -584,7 +584,7 @@ def filter_distance( ) -> Tuple[Tuple[float]]: """ Filter the pairs values, since the intersection pair - (0.5, 1) is almost the same as (1e-6, 0.99999) + (0.5, 1) is almost the same as (1e-6, 0.99999) """ pairs = list(pairs) index = 0 @@ -624,6 +624,7 @@ class Projection: """ Defines the methods used to find the projection of a point into a curve """ + @staticmethod def point_on_curve(point: Point2D, curve: PlanarCurve) -> float: """Finds parameter u* such abs(C(u*)) is minimal @@ -651,7 +652,7 @@ def point_on_curve(point: Point2D, curve: PlanarCurve) -> float: params.append(usample[i]) return tuple(params) - #pylint: disable=too-many-locals + # pylint: disable=too-many-locals @staticmethod def newton_iteration( point: Point2D, curve: PlanarCurve, usample: Tuple[float] @@ -688,6 +689,7 @@ class Derivate: """ Defines the functions to derivate the bezier curve """ + __non_rat_bezier_once = {} @staticmethod diff --git a/src/shapepy/jordancurve.py b/src/shapepy/jordancurve.py index 12219641..41b373e4 100644 --- a/src/shapepy/jordancurve.py +++ b/src/shapepy/jordancurve.py @@ -19,6 +19,7 @@ class IntegrateJordan: Defines functions to integrate over the internal area defined by the jordan curve. """ + @staticmethod def vertical( jordan: JordanCurve, expx: int, expy: int, nnodes: Optional[int] = None diff --git a/src/shapepy/plot.py b/src/shapepy/plot.py index b61055e3..08233782 100644 --- a/src/shapepy/plot.py +++ b/src/shapepy/plot.py @@ -139,7 +139,7 @@ def plot(self, *args, **kwargs): return self.plot_shape(args[0], kwargs=kwargs) return self.gca().plot(*args, **kwargs) - #pylint: disable=too-many-locals + # pylint: disable=too-many-locals def plot_shape(self, shape: BaseShape, *, kwargs): """ Plots a BaseShape, which can be Empty, Whole, Simple, etc From 17fdb0d8118a8271cc36edf1164ac1008cb284c0 Mon Sep 17 00:00:00 2001 From: Carlos Adir Date: Wed, 9 Jul 2025 22:43:32 +0200 Subject: [PATCH 23/31] pylint ignore chained comparaison for specific function --- src/shapepy/shape.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/shapepy/shape.py b/src/shapepy/shape.py index 061813f9..1156ad18 100644 --- a/src/shapepy/shape.py +++ b/src/shapepy/shape.py @@ -920,6 +920,7 @@ def _contains_shape(self, other: DefinedShape) -> bool: return False return True + # pylint: disable=chained-comparison def __contains_simple(self, other: SimpleShape) -> bool: assert isinstance(other, SimpleShape) areaa = float(other) From 08a8e2d5d9c613441e9e4d2b82ec368bf520ac2c Mon Sep 17 00:00:00 2001 From: Carlos Adir Date: Wed, 9 Jul 2025 22:45:08 +0200 Subject: [PATCH 24/31] make BaseShape inherit again from object --- src/shapepy/shape.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shapepy/shape.py b/src/shapepy/shape.py index 1156ad18..f04aef79 100644 --- a/src/shapepy/shape.py +++ b/src/shapepy/shape.py @@ -352,7 +352,7 @@ def and_shapes(shapea: BaseShape, shapeb: BaseShape) -> Tuple[JordanCurve]: return new_jordans -class BaseShape(metaclass=SuperclassMeta): +class BaseShape(object, metaclass=SuperclassMeta): """ Class which allows operations like: - move From 29b4c18d3a91a8827a4d1f25e102c54af4b61cae Mon Sep 17 00:00:00 2001 From: Carlos Adir Date: Wed, 9 Jul 2025 22:54:56 +0200 Subject: [PATCH 25/31] docs: add missing docstrings for shape.py module --- src/shapepy/shape.py | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/src/shapepy/shape.py b/src/shapepy/shape.py index f04aef79..b6291787 100644 --- a/src/shapepy/shape.py +++ b/src/shapepy/shape.py @@ -20,6 +20,11 @@ class SuperclassMeta(type): + """ + This class is the parent of other classes such + still gets the docstrings of their parent + """ + def __new__(mcs, classname, bases, cls_dict): cls = super().__new__(mcs, classname, bases, cls_dict) for name, member in cls_dict.items(): @@ -311,6 +316,10 @@ def midpoints_one_shape( def midpoints_shapes( shapea: BaseShape, shapeb: BaseShape, closed: bool, inside: bool ) -> Tuple[Tuple[int]]: + """ + This function computes the indexes of the midpoints from + both shapes, shifting the indexs of shapeb.jordans + """ indexsa = FollowPath.midpoints_one_shape( shapea, shapeb, closed, inside ) @@ -325,6 +334,10 @@ def midpoints_shapes( @staticmethod def or_shapes(shapea: BaseShape, shapeb: BaseShape) -> Tuple[JordanCurve]: + """ + Computes the set of jordan curves that defines the boundary of + the union between the two base shapes + """ assert isinstance(shapea, BaseShape) assert isinstance(shapeb, BaseShape) for jordana in shapea.jordans: @@ -339,6 +352,10 @@ def or_shapes(shapea: BaseShape, shapeb: BaseShape) -> Tuple[JordanCurve]: @staticmethod def and_shapes(shapea: BaseShape, shapeb: BaseShape) -> Tuple[JordanCurve]: + """ + Computes the set of jordan curves that defines the boundary of + the intersection between the two base shapes + """ assert isinstance(shapea, BaseShape) assert isinstance(shapeb, BaseShape) for jordana in shapea.jordans: @@ -352,6 +369,8 @@ def and_shapes(shapea: BaseShape, shapeb: BaseShape) -> Tuple[JordanCurve]: return new_jordans +# Inherit from object is needed +# pylint: disable=useless-object-inheritance class BaseShape(object, metaclass=SuperclassMeta): """ Class which allows operations like: @@ -404,6 +423,7 @@ def __bool__(self) -> bool: return float(self) > 0 +# pylint: disable=abstract-method class SingletonShape(BaseShape): """SingletonShape""" @@ -501,6 +521,7 @@ def __sub__(self, other: BaseShape) -> BaseShape: return ~other +# pylint: disable=no-member class DefinedShape(BaseShape): """ DefinedShape is the base class for SimpleShape, @@ -830,6 +851,11 @@ def __invert__(self) -> SimpleShape: @property def jordans(self) -> Tuple[JordanCurve]: + """ + The jordans curve that define the SimpleShape + + It has only one jordan curve inside it + """ return (self.__jordancurve,) def __set_jordancurve(self, other: JordanCurve): @@ -1074,7 +1100,7 @@ def __new__(cls, subshapes: Tuple[ConnectedShape]): instance.subshapes = subshapes return instance - def __init__(self, subshapes: Tuple[ConnectedShape]): + def __init__(self, _: Tuple[ConnectedShape]): super().__init__() def __float__(self) -> float: From a6283e3da36513865fcb410be2d77f129a2d011a Mon Sep 17 00:00:00 2001 From: Carlos Adir Date: Wed, 9 Jul 2025 22:55:07 +0200 Subject: [PATCH 26/31] dev: add pylint configuration file --- .pylintrc | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 .pylintrc diff --git a/.pylintrc b/.pylintrc new file mode 100644 index 00000000..1097b815 --- /dev/null +++ b/.pylintrc @@ -0,0 +1,4 @@ +[MAIN] + +disable= + too-many-lines, From 39222ff4b7556b9ad61023a29e686c3182236373 Mon Sep 17 00:00:00 2001 From: Carlos Adir Date: Wed, 9 Jul 2025 23:24:35 +0200 Subject: [PATCH 27/31] improve quality code with pylint and black --- src/shapepy/jordancurve.py | 1 + src/shapepy/polygon.py | 1 + src/shapepy/shape.py | 1 + tests/test_bool_finite_intersect.py | 7 +++---- tests/test_bool_no_intersect.py | 2 +- tests/test_contains.py | 6 +++--- tests/test_plot.py | 2 +- tests/test_shape.py | 4 ++-- 8 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/shapepy/jordancurve.py b/src/shapepy/jordancurve.py index 41b373e4..076460de 100644 --- a/src/shapepy/jordancurve.py +++ b/src/shapepy/jordancurve.py @@ -2,6 +2,7 @@ This modules contains a powerful class called JordanCurve which is in fact, stores a list of spline-curves. """ + from __future__ import annotations from copy import copy diff --git a/src/shapepy/polygon.py b/src/shapepy/polygon.py index ed1bbbe9..11fd47c2 100644 --- a/src/shapepy/polygon.py +++ b/src/shapepy/polygon.py @@ -3,6 +3,7 @@ They are used to encapsulate some commands """ + from __future__ import annotations import fractions diff --git a/src/shapepy/shape.py b/src/shapepy/shape.py index b6291787..b1177586 100644 --- a/src/shapepy/shape.py +++ b/src/shapepy/shape.py @@ -6,6 +6,7 @@ You can assemble JordanCurves to create shapes with holes, or even unconnected shapes. """ + from __future__ import annotations import abc diff --git a/tests/test_bool_finite_intersect.py b/tests/test_bool_finite_intersect.py index f75abf3e..eb3a9aab 100644 --- a/tests/test_bool_finite_intersect.py +++ b/tests/test_bool_finite_intersect.py @@ -1,10 +1,8 @@ """ Tests related to shape module, more specifically about the class SimpleShape -Which are in fact positive shapes defined only by one jordan curve +Which are in fact positive shapes defined only by one jordan curve """ -import math - import pytest from shapepy.jordancurve import JordanCurve @@ -30,7 +28,8 @@ def test_begin(): class TestIntersectionSimple: """ - Tests between two simple shapes such they have a finite number of intersection points + Tests between two simple shapes such they have a finite number + of intersection points """ @pytest.mark.order(9) diff --git a/tests/test_bool_no_intersect.py b/tests/test_bool_no_intersect.py index 17db7d27..1ba0f684 100644 --- a/tests/test_bool_no_intersect.py +++ b/tests/test_bool_no_intersect.py @@ -1,6 +1,6 @@ """ Tests related to shape module, more specifically about the class SimpleShape -Which are in fact positive shapes defined only by one jordan curve +Which are in fact positive shapes defined only by one jordan curve """ import pytest diff --git a/tests/test_contains.py b/tests/test_contains.py index be549479..167201d5 100644 --- a/tests/test_contains.py +++ b/tests/test_contains.py @@ -1,6 +1,6 @@ """ -This file contains the code to test the relative position of an object with respect -to another +This file contains the code to test the relative position +of an object with respect to another """ from fractions import Fraction @@ -653,7 +653,7 @@ def test_simple(self): def test_connected(self): small_square = Primitive.square(side=2) big_square = Primitive.square(side=4) - connected = ConnectedShape([big_square, ~small_square]) + _ = ConnectedShape([big_square, ~small_square]) assert (~small_square) in (~small_square) assert (~big_square) in (~small_square) diff --git a/tests/test_plot.py b/tests/test_plot.py index 52895a01..e367516b 100644 --- a/tests/test_plot.py +++ b/tests/test_plot.py @@ -1,6 +1,6 @@ """ Tests related to shape module, more specifically about the class SimpleShape -Which are in fact positive shapes defined only by one jordan curve +Which are in fact positive shapes defined only by one jordan curve """ import pytest diff --git a/tests/test_shape.py b/tests/test_shape.py index 44f44f6c..0db91c64 100644 --- a/tests/test_shape.py +++ b/tests/test_shape.py @@ -1,6 +1,6 @@ """ Tests related to shape module, more specifically about the class SimpleShape -Which are in fact positive shapes defined only by one jordan curve +Which are in fact positive shapes defined only by one jordan curve """ import math @@ -9,7 +9,7 @@ from shapepy.jordancurve import JordanCurve from shapepy.primitive import Primitive -from shapepy.shape import EmptyShape, IntegrateShape, SimpleShape, WholeShape +from shapepy.shape import IntegrateShape, SimpleShape @pytest.mark.order(8) From e698b7a6c8cc577fdcb2155aa00bf137ee411c80 Mon Sep 17 00:00:00 2001 From: Carlos Adir Date: Wed, 9 Jul 2025 23:26:47 +0200 Subject: [PATCH 28/31] dev: update poetry dependencies for development --- pyproject.toml | 18 +++++++++++------- tox.ini | 4 ---- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index ab5902e6..2b7dcf45 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -13,14 +13,18 @@ pynurbs = "^1.0.7" python = "^3.9" [tool.poetry.dev-dependencies] -pytest = "^5.2" -pynurbs = "^1.0.7" -black = "^23.0.0" -isort = "^5.12.0" -flake8 = "^5.0.0" -pylint = "^3.0.0" +pytest = "*" +pynurbs = "*" +black = "*" +isort = "*" +flake8 = "*" +pylint = "*" pre-commit = "^3.0.0" -mypy = "^1.0.0" +coverage = "^7" +pytest-cov = "^6" +pytest-order = "^1.0" +pytest-timeout = "^1.0" +pytest-dependency = "^0.6" [tool.poetry.group.dev.dependencies] pre-commit = "^3.3.3" diff --git a/tox.ini b/tox.ini index 3c443e31..60ecbce0 100644 --- a/tox.ini +++ b/tox.ini @@ -49,15 +49,11 @@ commands = [testenv:format] deps = - numpy black flake8 - isort - mccabe pylint commands = black --check src/shapepy - isort --check src/shapepy flake8 src/shapepy --max-complexity 10 pylint src/shapepy From 874888b373d62bd314da78599cc2fd1c3fd8ad70 Mon Sep 17 00:00:00 2001 From: Carlos Adir Date: Wed, 9 Jul 2025 23:29:19 +0200 Subject: [PATCH 29/31] update poetry lock file --- poetry.lock | 405 +++++++++++++++++++++++++++++++--------------------- 1 file changed, 246 insertions(+), 159 deletions(-) diff --git a/poetry.lock b/poetry.lock index 20688f34..3b82c2b3 100644 --- a/poetry.lock +++ b/poetry.lock @@ -14,16 +14,6 @@ files = [ [package.dependencies] typing-extensions = {version = ">=4", markers = "python_version < \"3.11\""} -[[package]] -name = "atomicwrites" -version = "1.4.1" -description = "Atomic file writes." -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -files = [ - {file = "atomicwrites-1.4.1.tar.gz", hash = "sha256:81b2c9071a49367a7f770170e5eec8cb66567cfbbc8c73d20ce5ca4a8d71cf11"}, -] - [[package]] name = "attrs" version = "25.3.0" @@ -45,33 +35,33 @@ tests-mypy = ["mypy (>=1.11.1)", "pytest-mypy-plugins"] [[package]] name = "black" -version = "23.12.1" +version = "25.1.0" description = "The uncompromising code formatter." optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "black-23.12.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e0aaf6041986767a5e0ce663c7a2f0e9eaf21e6ff87a5f95cbf3675bfd4c41d2"}, - {file = "black-23.12.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c88b3711d12905b74206227109272673edce0cb29f27e1385f33b0163c414bba"}, - {file = "black-23.12.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a920b569dc6b3472513ba6ddea21f440d4b4c699494d2e972a1753cdc25df7b0"}, - {file = "black-23.12.1-cp310-cp310-win_amd64.whl", hash = "sha256:3fa4be75ef2a6b96ea8d92b1587dd8cb3a35c7e3d51f0738ced0781c3aa3a5a3"}, - {file = "black-23.12.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8d4df77958a622f9b5a4c96edb4b8c0034f8434032ab11077ec6c56ae9f384ba"}, - {file = "black-23.12.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:602cfb1196dc692424c70b6507593a2b29aac0547c1be9a1d1365f0d964c353b"}, - {file = "black-23.12.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c4352800f14be5b4864016882cdba10755bd50805c95f728011bcb47a4afd59"}, - {file = "black-23.12.1-cp311-cp311-win_amd64.whl", hash = "sha256:0808494f2b2df923ffc5723ed3c7b096bd76341f6213989759287611e9837d50"}, - {file = "black-23.12.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:25e57fd232a6d6ff3f4478a6fd0580838e47c93c83eaf1ccc92d4faf27112c4e"}, - {file = "black-23.12.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2d9e13db441c509a3763a7a3d9a49ccc1b4e974a47be4e08ade2a228876500ec"}, - {file = "black-23.12.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d1bd9c210f8b109b1762ec9fd36592fdd528485aadb3f5849b2740ef17e674e"}, - {file = "black-23.12.1-cp312-cp312-win_amd64.whl", hash = "sha256:ae76c22bde5cbb6bfd211ec343ded2163bba7883c7bc77f6b756a1049436fbb9"}, - {file = "black-23.12.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1fa88a0f74e50e4487477bc0bb900c6781dbddfdfa32691e780bf854c3b4a47f"}, - {file = "black-23.12.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a4d6a9668e45ad99d2f8ec70d5c8c04ef4f32f648ef39048d010b0689832ec6d"}, - {file = "black-23.12.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b18fb2ae6c4bb63eebe5be6bd869ba2f14fd0259bda7d18a46b764d8fb86298a"}, - {file = "black-23.12.1-cp38-cp38-win_amd64.whl", hash = "sha256:c04b6d9d20e9c13f43eee8ea87d44156b8505ca8a3c878773f68b4e4812a421e"}, - {file = "black-23.12.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3e1b38b3135fd4c025c28c55ddfc236b05af657828a8a6abe5deec419a0b7055"}, - {file = "black-23.12.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4f0031eaa7b921db76decd73636ef3a12c942ed367d8c3841a0739412b260a54"}, - {file = "black-23.12.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:97e56155c6b737854e60a9ab1c598ff2533d57e7506d97af5481141671abf3ea"}, - {file = "black-23.12.1-cp39-cp39-win_amd64.whl", hash = "sha256:dd15245c8b68fe2b6bd0f32c1556509d11bb33aec9b5d0866dd8e2ed3dba09c2"}, - {file = "black-23.12.1-py3-none-any.whl", hash = "sha256:78baad24af0f033958cad29731e27363183e140962595def56423e626f4bee3e"}, - {file = "black-23.12.1.tar.gz", hash = "sha256:4ce3ef14ebe8d9509188014d96af1c456a910d5b5cbf434a09fef7e024b3d0d5"}, + {file = "black-25.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:759e7ec1e050a15f89b770cefbf91ebee8917aac5c20483bc2d80a6c3a04df32"}, + {file = "black-25.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0e519ecf93120f34243e6b0054db49c00a35f84f195d5bce7e9f5cfc578fc2da"}, + {file = "black-25.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:055e59b198df7ac0b7efca5ad7ff2516bca343276c466be72eb04a3bcc1f82d7"}, + {file = "black-25.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:db8ea9917d6f8fc62abd90d944920d95e73c83a5ee3383493e35d271aca872e9"}, + {file = "black-25.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a39337598244de4bae26475f77dda852ea00a93bd4c728e09eacd827ec929df0"}, + {file = "black-25.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:96c1c7cd856bba8e20094e36e0f948718dc688dba4a9d78c3adde52b9e6c2299"}, + {file = "black-25.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bce2e264d59c91e52d8000d507eb20a9aca4a778731a08cfff7e5ac4a4bb7096"}, + {file = "black-25.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:172b1dbff09f86ce6f4eb8edf9dede08b1fce58ba194c87d7a4f1a5aa2f5b3c2"}, + {file = "black-25.1.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4b60580e829091e6f9238c848ea6750efed72140b91b048770b64e74fe04908b"}, + {file = "black-25.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1e2978f6df243b155ef5fa7e558a43037c3079093ed5d10fd84c43900f2d8ecc"}, + {file = "black-25.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3b48735872ec535027d979e8dcb20bf4f70b5ac75a8ea99f127c106a7d7aba9f"}, + {file = "black-25.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:ea0213189960bda9cf99be5b8c8ce66bb054af5e9e861249cd23471bd7b0b3ba"}, + {file = "black-25.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8f0b18a02996a836cc9c9c78e5babec10930862827b1b724ddfe98ccf2f2fe4f"}, + {file = "black-25.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:afebb7098bfbc70037a053b91ae8437c3857482d3a690fefc03e9ff7aa9a5fd3"}, + {file = "black-25.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:030b9759066a4ee5e5aca28c3c77f9c64789cdd4de8ac1df642c40b708be6171"}, + {file = "black-25.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:a22f402b410566e2d1c950708c77ebf5ebd5d0d88a6a2e87c86d9fb48afa0d18"}, + {file = "black-25.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a1ee0a0c330f7b5130ce0caed9936a904793576ef4d2b98c40835d6a65afa6a0"}, + {file = "black-25.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f3df5f1bf91d36002b0a75389ca8663510cf0531cca8aa5c1ef695b46d98655f"}, + {file = "black-25.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d9e6827d563a2c820772b32ce8a42828dc6790f095f441beef18f96aa6f8294e"}, + {file = "black-25.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:bacabb307dca5ebaf9c118d2d2f6903da0d62c9faa82bd21a33eecc319559355"}, + {file = "black-25.1.0-py3-none-any.whl", hash = "sha256:95e8176dae143ba9097f351d174fdaf0ccd29efb414b362ae3fd72bf0f710717"}, + {file = "black-25.1.0.tar.gz", hash = "sha256:33496d5cd1222ad73391352b4ae8da15253c5de89b93a80b3e2c8d9a19ec2666"}, ] [package.dependencies] @@ -85,7 +75,7 @@ typing-extensions = {version = ">=4.0.1", markers = "python_version < \"3.11\""} [package.extras] colorama = ["colorama (>=0.4.3)"] -d = ["aiohttp (>=3.7.4)", "aiohttp (>=3.7.4,!=3.9.0)"] +d = ["aiohttp (>=3.10)"] jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] uvloop = ["uvloop (>=0.15.2)"] @@ -335,6 +325,88 @@ mypy = ["contourpy[bokeh,docs]", "docutils-stubs", "mypy (==1.11.1)", "types-Pil test = ["Pillow", "contourpy[test-no-images]", "matplotlib"] test-no-images = ["pytest", "pytest-cov", "pytest-rerunfailures", "pytest-xdist", "wurlitzer"] +[[package]] +name = "coverage" +version = "7.9.2" +description = "Code coverage measurement for Python" +optional = false +python-versions = ">=3.9" +files = [ + {file = "coverage-7.9.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:66283a192a14a3854b2e7f3418d7db05cdf411012ab7ff5db98ff3b181e1f912"}, + {file = "coverage-7.9.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4e01d138540ef34fcf35c1aa24d06c3de2a4cffa349e29a10056544f35cca15f"}, + {file = "coverage-7.9.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f22627c1fe2745ee98d3ab87679ca73a97e75ca75eb5faee48660d060875465f"}, + {file = "coverage-7.9.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4b1c2d8363247b46bd51f393f86c94096e64a1cf6906803fa8d5a9d03784bdbf"}, + {file = "coverage-7.9.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c10c882b114faf82dbd33e876d0cbd5e1d1ebc0d2a74ceef642c6152f3f4d547"}, + {file = "coverage-7.9.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:de3c0378bdf7066c3988d66cd5232d161e933b87103b014ab1b0b4676098fa45"}, + {file = "coverage-7.9.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:1e2f097eae0e5991e7623958a24ced3282676c93c013dde41399ff63e230fcf2"}, + {file = "coverage-7.9.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:28dc1f67e83a14e7079b6cea4d314bc8b24d1aed42d3582ff89c0295f09b181e"}, + {file = "coverage-7.9.2-cp310-cp310-win32.whl", hash = "sha256:bf7d773da6af9e10dbddacbf4e5cab13d06d0ed93561d44dae0188a42c65be7e"}, + {file = "coverage-7.9.2-cp310-cp310-win_amd64.whl", hash = "sha256:0c0378ba787681ab1897f7c89b415bd56b0b2d9a47e5a3d8dc0ea55aac118d6c"}, + {file = "coverage-7.9.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a7a56a2964a9687b6aba5b5ced6971af308ef6f79a91043c05dd4ee3ebc3e9ba"}, + {file = "coverage-7.9.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:123d589f32c11d9be7fe2e66d823a236fe759b0096f5db3fb1b75b2fa414a4fa"}, + {file = "coverage-7.9.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:333b2e0ca576a7dbd66e85ab402e35c03b0b22f525eed82681c4b866e2e2653a"}, + {file = "coverage-7.9.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:326802760da234baf9f2f85a39e4a4b5861b94f6c8d95251f699e4f73b1835dc"}, + {file = "coverage-7.9.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:19e7be4cfec248df38ce40968c95d3952fbffd57b400d4b9bb580f28179556d2"}, + {file = "coverage-7.9.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0b4a4cb73b9f2b891c1788711408ef9707666501ba23684387277ededab1097c"}, + {file = "coverage-7.9.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:2c8937fa16c8c9fbbd9f118588756e7bcdc7e16a470766a9aef912dd3f117dbd"}, + {file = "coverage-7.9.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:42da2280c4d30c57a9b578bafd1d4494fa6c056d4c419d9689e66d775539be74"}, + {file = "coverage-7.9.2-cp311-cp311-win32.whl", hash = "sha256:14fa8d3da147f5fdf9d298cacc18791818f3f1a9f542c8958b80c228320e90c6"}, + {file = "coverage-7.9.2-cp311-cp311-win_amd64.whl", hash = "sha256:549cab4892fc82004f9739963163fd3aac7a7b0df430669b75b86d293d2df2a7"}, + {file = "coverage-7.9.2-cp311-cp311-win_arm64.whl", hash = "sha256:c2667a2b913e307f06aa4e5677f01a9746cd08e4b35e14ebcde6420a9ebb4c62"}, + {file = "coverage-7.9.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:ae9eb07f1cfacd9cfe8eaee6f4ff4b8a289a668c39c165cd0c8548484920ffc0"}, + {file = "coverage-7.9.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9ce85551f9a1119f02adc46d3014b5ee3f765deac166acf20dbb851ceb79b6f3"}, + {file = "coverage-7.9.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f8f6389ac977c5fb322e0e38885fbbf901743f79d47f50db706e7644dcdcb6e1"}, + {file = "coverage-7.9.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ff0d9eae8cdfcd58fe7893b88993723583a6ce4dfbfd9f29e001922544f95615"}, + {file = "coverage-7.9.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fae939811e14e53ed8a9818dad51d434a41ee09df9305663735f2e2d2d7d959b"}, + {file = "coverage-7.9.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:31991156251ec202c798501e0a42bbdf2169dcb0f137b1f5c0f4267f3fc68ef9"}, + {file = "coverage-7.9.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:d0d67963f9cbfc7c7f96d4ac74ed60ecbebd2ea6eeb51887af0f8dce205e545f"}, + {file = "coverage-7.9.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:49b752a2858b10580969ec6af6f090a9a440a64a301ac1528d7ca5f7ed497f4d"}, + {file = "coverage-7.9.2-cp312-cp312-win32.whl", hash = "sha256:88d7598b8ee130f32f8a43198ee02edd16d7f77692fa056cb779616bbea1b355"}, + {file = "coverage-7.9.2-cp312-cp312-win_amd64.whl", hash = "sha256:9dfb070f830739ee49d7c83e4941cc767e503e4394fdecb3b54bfdac1d7662c0"}, + {file = "coverage-7.9.2-cp312-cp312-win_arm64.whl", hash = "sha256:4e2c058aef613e79df00e86b6d42a641c877211384ce5bd07585ed7ba71ab31b"}, + {file = "coverage-7.9.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:985abe7f242e0d7bba228ab01070fde1d6c8fa12f142e43debe9ed1dde686038"}, + {file = "coverage-7.9.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:82c3939264a76d44fde7f213924021ed31f55ef28111a19649fec90c0f109e6d"}, + {file = "coverage-7.9.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ae5d563e970dbe04382f736ec214ef48103d1b875967c89d83c6e3f21706d5b3"}, + {file = "coverage-7.9.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bdd612e59baed2a93c8843c9a7cb902260f181370f1d772f4842987535071d14"}, + {file = "coverage-7.9.2-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:256ea87cb2a1ed992bcdfc349d8042dcea1b80436f4ddf6e246d6bee4b5d73b6"}, + {file = "coverage-7.9.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f44ae036b63c8ea432f610534a2668b0c3aee810e7037ab9d8ff6883de480f5b"}, + {file = "coverage-7.9.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:82d76ad87c932935417a19b10cfe7abb15fd3f923cfe47dbdaa74ef4e503752d"}, + {file = "coverage-7.9.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:619317bb86de4193debc712b9e59d5cffd91dc1d178627ab2a77b9870deb2868"}, + {file = "coverage-7.9.2-cp313-cp313-win32.whl", hash = "sha256:0a07757de9feb1dfafd16ab651e0f628fd7ce551604d1bf23e47e1ddca93f08a"}, + {file = "coverage-7.9.2-cp313-cp313-win_amd64.whl", hash = "sha256:115db3d1f4d3f35f5bb021e270edd85011934ff97c8797216b62f461dd69374b"}, + {file = "coverage-7.9.2-cp313-cp313-win_arm64.whl", hash = "sha256:48f82f889c80af8b2a7bb6e158d95a3fbec6a3453a1004d04e4f3b5945a02694"}, + {file = "coverage-7.9.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:55a28954545f9d2f96870b40f6c3386a59ba8ed50caf2d949676dac3ecab99f5"}, + {file = "coverage-7.9.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:cdef6504637731a63c133bb2e6f0f0214e2748495ec15fe42d1e219d1b133f0b"}, + {file = "coverage-7.9.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bcd5ebe66c7a97273d5d2ddd4ad0ed2e706b39630ed4b53e713d360626c3dbb3"}, + {file = "coverage-7.9.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9303aed20872d7a3c9cb39c5d2b9bdbe44e3a9a1aecb52920f7e7495410dfab8"}, + {file = "coverage-7.9.2-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc18ea9e417a04d1920a9a76fe9ebd2f43ca505b81994598482f938d5c315f46"}, + {file = "coverage-7.9.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6406cff19880aaaadc932152242523e892faff224da29e241ce2fca329866584"}, + {file = "coverage-7.9.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:2d0d4f6ecdf37fcc19c88fec3e2277d5dee740fb51ffdd69b9579b8c31e4232e"}, + {file = "coverage-7.9.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:c33624f50cf8de418ab2b4d6ca9eda96dc45b2c4231336bac91454520e8d1fac"}, + {file = "coverage-7.9.2-cp313-cp313t-win32.whl", hash = "sha256:1df6b76e737c6a92210eebcb2390af59a141f9e9430210595251fbaf02d46926"}, + {file = "coverage-7.9.2-cp313-cp313t-win_amd64.whl", hash = "sha256:f5fd54310b92741ebe00d9c0d1d7b2b27463952c022da6d47c175d246a98d1bd"}, + {file = "coverage-7.9.2-cp313-cp313t-win_arm64.whl", hash = "sha256:c48c2375287108c887ee87d13b4070a381c6537d30e8487b24ec721bf2a781cb"}, + {file = "coverage-7.9.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ddc39510ac922a5c4c27849b739f875d3e1d9e590d1e7b64c98dadf037a16cce"}, + {file = "coverage-7.9.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a535c0c7364acd55229749c2b3e5eebf141865de3a8f697076a3291985f02d30"}, + {file = "coverage-7.9.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:df0f9ef28e0f20c767ccdccfc5ae5f83a6f4a2fbdfbcbcc8487a8a78771168c8"}, + {file = "coverage-7.9.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2f3da12e0ccbcb348969221d29441ac714bbddc4d74e13923d3d5a7a0bebef7a"}, + {file = "coverage-7.9.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0a17eaf46f56ae0f870f14a3cbc2e4632fe3771eab7f687eda1ee59b73d09fe4"}, + {file = "coverage-7.9.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:669135a9d25df55d1ed56a11bf555f37c922cf08d80799d4f65d77d7d6123fcf"}, + {file = "coverage-7.9.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:9d3a700304d01a627df9db4322dc082a0ce1e8fc74ac238e2af39ced4c083193"}, + {file = "coverage-7.9.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:71ae8b53855644a0b1579d4041304ddc9995c7b21c8a1f16753c4d8903b4dfed"}, + {file = "coverage-7.9.2-cp39-cp39-win32.whl", hash = "sha256:dd7a57b33b5cf27acb491e890720af45db05589a80c1ffc798462a765be6d4d7"}, + {file = "coverage-7.9.2-cp39-cp39-win_amd64.whl", hash = "sha256:f65bb452e579d5540c8b37ec105dd54d8b9307b07bcaa186818c104ffda22441"}, + {file = "coverage-7.9.2-pp39.pp310.pp311-none-any.whl", hash = "sha256:8a1166db2fb62473285bcb092f586e081e92656c7dfa8e9f62b4d39d7e6b5050"}, + {file = "coverage-7.9.2-py3-none-any.whl", hash = "sha256:e425cd5b00f6fc0ed7cdbd766c70be8baab4b7839e4d4fe5fac48581dd968ea4"}, + {file = "coverage-7.9.2.tar.gz", hash = "sha256:997024fa51e3290264ffd7492ec97d0690293ccd2b45a6cd7d82d945a4a80c8b"}, +] + +[package.dependencies] +tomli = {version = "*", optional = true, markers = "python_full_version <= \"3.11.0a6\" and extra == \"toml\""} + +[package.extras] +toml = ["tomli"] + [[package]] name = "cycler" version = "0.12.1" @@ -376,6 +448,23 @@ files = [ {file = "distlib-0.3.9.tar.gz", hash = "sha256:a60f20dea646b8a33f3e7772f74dc0b2d0772d2837ee1342a00645c81edf9403"}, ] +[[package]] +name = "exceptiongroup" +version = "1.3.0" +description = "Backport of PEP 654 (exception groups)" +optional = false +python-versions = ">=3.7" +files = [ + {file = "exceptiongroup-1.3.0-py3-none-any.whl", hash = "sha256:4d111e6e0c13d0644cad6ddaa7ed0261a0b36971f6d23e7ec9b4b9097da78a10"}, + {file = "exceptiongroup-1.3.0.tar.gz", hash = "sha256:b241f5885f560bc56a59ee63ca4c6a8bfa46ae4ad651af316d4e81817bb9fd88"}, +] + +[package.dependencies] +typing-extensions = {version = ">=4.6.0", markers = "python_version < \"3.13\""} + +[package.extras] +test = ["pytest (>=6)"] + [[package]] name = "filelock" version = "3.18.0" @@ -394,19 +483,19 @@ typing = ["typing-extensions (>=4.12.2)"] [[package]] name = "flake8" -version = "5.0.4" +version = "7.3.0" description = "the modular source code checker: pep8 pyflakes and co" optional = false -python-versions = ">=3.6.1" +python-versions = ">=3.9" files = [ - {file = "flake8-5.0.4-py2.py3-none-any.whl", hash = "sha256:7a1cf6b73744f5806ab95e526f6f0d8c01c66d7bbe349562d22dfca20610b248"}, - {file = "flake8-5.0.4.tar.gz", hash = "sha256:6fbe320aad8d6b95cec8b8e47bc933004678dc63095be98528b7bdd2a9f510db"}, + {file = "flake8-7.3.0-py2.py3-none-any.whl", hash = "sha256:b9696257b9ce8beb888cdbe31cf885c90d31928fe202be0889a7cdafad32f01e"}, + {file = "flake8-7.3.0.tar.gz", hash = "sha256:fe044858146b9fc69b551a4b490d69cf960fcb78ad1edcb84e7fbb1b4a8e3872"}, ] [package.dependencies] mccabe = ">=0.7.0,<0.8.0" -pycodestyle = ">=2.9.0,<2.10.0" -pyflakes = ">=2.5.0,<2.6.0" +pycodestyle = ">=2.14.0,<2.15.0" +pyflakes = ">=3.4.0,<3.5.0" [[package]] name = "fonttools" @@ -523,19 +612,31 @@ enabler = ["pytest-enabler (>=2.2)"] test = ["jaraco.test (>=5.4)", "pytest (>=6,!=8.1.*)", "zipp (>=3.17)"] type = ["pytest-mypy"] +[[package]] +name = "iniconfig" +version = "2.1.0" +description = "brain-dead simple config-ini parsing" +optional = false +python-versions = ">=3.8" +files = [ + {file = "iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760"}, + {file = "iniconfig-2.1.0.tar.gz", hash = "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7"}, +] + [[package]] name = "isort" -version = "5.13.2" +version = "6.0.1" description = "A Python utility / library to sort Python imports." optional = false -python-versions = ">=3.8.0" +python-versions = ">=3.9.0" files = [ - {file = "isort-5.13.2-py3-none-any.whl", hash = "sha256:8ca5e72a8d85860d5a3fa69b8745237f2939afe12dbf656afbcb47fe72d947a6"}, - {file = "isort-5.13.2.tar.gz", hash = "sha256:48fdfcb9face5d58a4f6dde2e72a1fb8dcaf8ab26f95ab49fab84c2ddefb0109"}, + {file = "isort-6.0.1-py3-none-any.whl", hash = "sha256:2dc5d7f65c9678d94c88dfc29161a320eec67328bc97aad576874cb4be1e9615"}, + {file = "isort-6.0.1.tar.gz", hash = "sha256:1cb5df28dfbc742e490c5e41bad6da41b805b0a8be7bc93cd0fb2a8a890ac450"}, ] [package.extras] -colors = ["colorama (>=0.4.6)"] +colors = ["colorama"] +plugins = ["setuptools"] [[package]] name = "jinja2" @@ -858,71 +959,6 @@ files = [ {file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"}, ] -[[package]] -name = "more-itertools" -version = "10.7.0" -description = "More routines for operating on iterables, beyond itertools" -optional = false -python-versions = ">=3.9" -files = [ - {file = "more_itertools-10.7.0-py3-none-any.whl", hash = "sha256:d43980384673cb07d2f7d2d918c616b30c659c089ee23953f601d6609c67510e"}, - {file = "more_itertools-10.7.0.tar.gz", hash = "sha256:9fddd5403be01a94b204faadcff459ec3568cf110265d3c54323e1e866ad29d3"}, -] - -[[package]] -name = "mypy" -version = "1.16.1" -description = "Optional static typing for Python" -optional = false -python-versions = ">=3.9" -files = [ - {file = "mypy-1.16.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b4f0fed1022a63c6fec38f28b7fc77fca47fd490445c69d0a66266c59dd0b88a"}, - {file = "mypy-1.16.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:86042bbf9f5a05ea000d3203cf87aa9d0ccf9a01f73f71c58979eb9249f46d72"}, - {file = "mypy-1.16.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ea7469ee5902c95542bea7ee545f7006508c65c8c54b06dc2c92676ce526f3ea"}, - {file = "mypy-1.16.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:352025753ef6a83cb9e7f2427319bb7875d1fdda8439d1e23de12ab164179574"}, - {file = "mypy-1.16.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ff9fa5b16e4c1364eb89a4d16bcda9987f05d39604e1e6c35378a2987c1aac2d"}, - {file = "mypy-1.16.1-cp310-cp310-win_amd64.whl", hash = "sha256:1256688e284632382f8f3b9e2123df7d279f603c561f099758e66dd6ed4e8bd6"}, - {file = "mypy-1.16.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:472e4e4c100062488ec643f6162dd0d5208e33e2f34544e1fc931372e806c0cc"}, - {file = "mypy-1.16.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ea16e2a7d2714277e349e24d19a782a663a34ed60864006e8585db08f8ad1782"}, - {file = "mypy-1.16.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:08e850ea22adc4d8a4014651575567b0318ede51e8e9fe7a68f25391af699507"}, - {file = "mypy-1.16.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:22d76a63a42619bfb90122889b903519149879ddbf2ba4251834727944c8baca"}, - {file = "mypy-1.16.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:2c7ce0662b6b9dc8f4ed86eb7a5d505ee3298c04b40ec13b30e572c0e5ae17c4"}, - {file = "mypy-1.16.1-cp311-cp311-win_amd64.whl", hash = "sha256:211287e98e05352a2e1d4e8759c5490925a7c784ddc84207f4714822f8cf99b6"}, - {file = "mypy-1.16.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:af4792433f09575d9eeca5c63d7d90ca4aeceda9d8355e136f80f8967639183d"}, - {file = "mypy-1.16.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:66df38405fd8466ce3517eda1f6640611a0b8e70895e2a9462d1d4323c5eb4b9"}, - {file = "mypy-1.16.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:44e7acddb3c48bd2713994d098729494117803616e116032af192871aed80b79"}, - {file = "mypy-1.16.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0ab5eca37b50188163fa7c1b73c685ac66c4e9bdee4a85c9adac0e91d8895e15"}, - {file = "mypy-1.16.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:dedb6229b2c9086247e21a83c309754b9058b438704ad2f6807f0d8227f6ebdd"}, - {file = "mypy-1.16.1-cp312-cp312-win_amd64.whl", hash = "sha256:1f0435cf920e287ff68af3d10a118a73f212deb2ce087619eb4e648116d1fe9b"}, - {file = "mypy-1.16.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ddc91eb318c8751c69ddb200a5937f1232ee8efb4e64e9f4bc475a33719de438"}, - {file = "mypy-1.16.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:87ff2c13d58bdc4bbe7dc0dedfe622c0f04e2cb2a492269f3b418df2de05c536"}, - {file = "mypy-1.16.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0a7cfb0fe29fe5a9841b7c8ee6dffb52382c45acdf68f032145b75620acfbd6f"}, - {file = "mypy-1.16.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:051e1677689c9d9578b9c7f4d206d763f9bbd95723cd1416fad50db49d52f359"}, - {file = "mypy-1.16.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:d5d2309511cc56c021b4b4e462907c2b12f669b2dbeb68300110ec27723971be"}, - {file = "mypy-1.16.1-cp313-cp313-win_amd64.whl", hash = "sha256:4f58ac32771341e38a853c5d0ec0dfe27e18e27da9cdb8bbc882d2249c71a3ee"}, - {file = "mypy-1.16.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7fc688329af6a287567f45cc1cefb9db662defeb14625213a5b7da6e692e2069"}, - {file = "mypy-1.16.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5e198ab3f55924c03ead626ff424cad1732d0d391478dfbf7bb97b34602395da"}, - {file = "mypy-1.16.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:09aa4f91ada245f0a45dbc47e548fd94e0dd5a8433e0114917dc3b526912a30c"}, - {file = "mypy-1.16.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:13c7cd5b1cb2909aa318a90fd1b7e31f17c50b242953e7dd58345b2a814f6383"}, - {file = "mypy-1.16.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:58e07fb958bc5d752a280da0e890c538f1515b79a65757bbdc54252ba82e0b40"}, - {file = "mypy-1.16.1-cp39-cp39-win_amd64.whl", hash = "sha256:f895078594d918f93337a505f8add9bd654d1a24962b4c6ed9390e12531eb31b"}, - {file = "mypy-1.16.1-py3-none-any.whl", hash = "sha256:5fc2ac4027d0ef28d6ba69a0343737a23c4d1b83672bf38d1fe237bdc0643b37"}, - {file = "mypy-1.16.1.tar.gz", hash = "sha256:6bd00a0a2094841c5e47e7374bb42b83d64c527a502e3334e1173a0c24437bab"}, -] - -[package.dependencies] -mypy_extensions = ">=1.0.0" -pathspec = ">=0.9.0" -tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} -typing_extensions = ">=4.6.0" - -[package.extras] -dmypy = ["psutil (>=4.0)"] -faster-cache = ["orjson"] -install-types = ["pip"] -mypyc = ["setuptools (>=50)"] -reports = ["lxml"] - [[package]] name = "mypy-extensions" version = "1.1.0" @@ -1154,17 +1190,18 @@ type = ["mypy (>=1.14.1)"] [[package]] name = "pluggy" -version = "0.13.1" +version = "1.6.0" description = "plugin and hook calling mechanisms for python" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +python-versions = ">=3.9" files = [ - {file = "pluggy-0.13.1-py2.py3-none-any.whl", hash = "sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d"}, - {file = "pluggy-0.13.1.tar.gz", hash = "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0"}, + {file = "pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746"}, + {file = "pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3"}, ] [package.extras] dev = ["pre-commit", "tox"] +testing = ["coverage", "pytest", "pytest-benchmark"] [[package]] name = "pre-commit" @@ -1185,38 +1222,41 @@ pyyaml = ">=5.1" virtualenv = ">=20.10.0" [[package]] -name = "py" -version = "1.11.0" -description = "library with cross-python path, ini-parsing, io, code, log facilities" +name = "pycodestyle" +version = "2.14.0" +description = "Python style guide checker" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +python-versions = ">=3.9" files = [ - {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"}, - {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"}, + {file = "pycodestyle-2.14.0-py2.py3-none-any.whl", hash = "sha256:dd6bf7cb4ee77f8e016f9c8e74a35ddd9f67e1d5fd4184d86c3b98e07099f42d"}, + {file = "pycodestyle-2.14.0.tar.gz", hash = "sha256:c4b5b517d278089ff9d0abdec919cd97262a3367449ea1c8b49b91529167b783"}, ] [[package]] -name = "pycodestyle" -version = "2.9.1" -description = "Python style guide checker" +name = "pyflakes" +version = "3.4.0" +description = "passive checker of Python programs" optional = false -python-versions = ">=3.6" +python-versions = ">=3.9" files = [ - {file = "pycodestyle-2.9.1-py2.py3-none-any.whl", hash = "sha256:d1735fc58b418fd7c5f658d28d943854f8a849b01a5d0a1e6f3f3fdd0166804b"}, - {file = "pycodestyle-2.9.1.tar.gz", hash = "sha256:2c9607871d58c76354b697b42f5d57e1ada7d261c261efac224b664affdc5785"}, + {file = "pyflakes-3.4.0-py2.py3-none-any.whl", hash = "sha256:f742a7dbd0d9cb9ea41e9a24a918996e8170c799fa528688d40dd582c8265f4f"}, + {file = "pyflakes-3.4.0.tar.gz", hash = "sha256:b24f96fafb7d2ab0ec5075b7350b3d2d2218eab42003821c06344973d3ea2f58"}, ] [[package]] -name = "pyflakes" -version = "2.5.0" -description = "passive checker of Python programs" +name = "pygments" +version = "2.19.2" +description = "Pygments is a syntax highlighting package written in Python." optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" files = [ - {file = "pyflakes-2.5.0-py2.py3-none-any.whl", hash = "sha256:4579f67d887f804e67edb544428f264b7b24f435b263c4614f384135cea553d2"}, - {file = "pyflakes-2.5.0.tar.gz", hash = "sha256:491feb020dca48ccc562a8c0cbe8df07ee13078df59813b83959cbdada312ea3"}, + {file = "pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b"}, + {file = "pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887"}, ] +[package.extras] +windows-terminal = ["colorama (>=0.4.6)"] + [[package]] name = "pylint" version = "3.3.7" @@ -1274,28 +1314,86 @@ diagrams = ["jinja2", "railroad-diagrams"] [[package]] name = "pytest" -version = "5.4.3" +version = "8.4.1" description = "pytest: simple powerful testing with Python" optional = false -python-versions = ">=3.5" +python-versions = ">=3.9" +files = [ + {file = "pytest-8.4.1-py3-none-any.whl", hash = "sha256:539c70ba6fcead8e78eebbf1115e8b589e7565830d7d006a8723f19ac8a0afb7"}, + {file = "pytest-8.4.1.tar.gz", hash = "sha256:7c67fd69174877359ed9371ec3af8a3d2b04741818c51e5e99cc1742251fa93c"}, +] + +[package.dependencies] +colorama = {version = ">=0.4", markers = "sys_platform == \"win32\""} +exceptiongroup = {version = ">=1", markers = "python_version < \"3.11\""} +iniconfig = ">=1" +packaging = ">=20" +pluggy = ">=1.5,<2" +pygments = ">=2.7.2" +tomli = {version = ">=1", markers = "python_version < \"3.11\""} + +[package.extras] +dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "requests", "setuptools", "xmlschema"] + +[[package]] +name = "pytest-cov" +version = "6.2.1" +description = "Pytest plugin for measuring coverage." +optional = false +python-versions = ">=3.9" files = [ - {file = "pytest-5.4.3-py3-none-any.whl", hash = "sha256:5c0db86b698e8f170ba4582a492248919255fcd4c79b1ee64ace34301fb589a1"}, - {file = "pytest-5.4.3.tar.gz", hash = "sha256:7979331bfcba207414f5e1263b5a0f8f521d0f457318836a7355531ed1a4c7d8"}, + {file = "pytest_cov-6.2.1-py3-none-any.whl", hash = "sha256:f5bc4c23f42f1cdd23c70b1dab1bbaef4fc505ba950d53e0081d0730dd7e86d5"}, + {file = "pytest_cov-6.2.1.tar.gz", hash = "sha256:25cc6cc0a5358204b8108ecedc51a9b57b34cc6b8c967cc2c01a4e00d8a67da2"}, ] [package.dependencies] -atomicwrites = {version = ">=1.0", markers = "sys_platform == \"win32\""} -attrs = ">=17.4.0" -colorama = {version = "*", markers = "sys_platform == \"win32\""} -more-itertools = ">=4.0.0" -packaging = "*" -pluggy = ">=0.12,<1.0" -py = ">=1.5.0" -wcwidth = "*" +coverage = {version = ">=7.5", extras = ["toml"]} +pluggy = ">=1.2" +pytest = ">=6.2.5" [package.extras] -checkqa-mypy = ["mypy (==v0.761)"] -testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xmlschema"] +testing = ["fields", "hunter", "process-tests", "pytest-xdist", "virtualenv"] + +[[package]] +name = "pytest-dependency" +version = "0.6.0" +description = "Manage dependencies of tests" +optional = false +python-versions = ">=3.4" +files = [ + {file = "pytest-dependency-0.6.0.tar.gz", hash = "sha256:934b0e6a39d95995062c193f7eaeed8a8ffa06ff1bcef4b62b0dc74a708bacc1"}, +] + +[[package]] +name = "pytest-order" +version = "1.3.0" +description = "pytest plugin to run your tests in a specific order" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pytest_order-1.3.0-py3-none-any.whl", hash = "sha256:2cd562a21380345dd8d5774aa5fd38b7849b6ee7397ca5f6999bbe6e89f07f6e"}, + {file = "pytest_order-1.3.0.tar.gz", hash = "sha256:51608fec3d3ee9c0adaea94daa124a5c4c1d2bb99b00269f098f414307f23dde"}, +] + +[package.dependencies] +pytest = [ + {version = ">=5.0", markers = "python_version < \"3.10\""}, + {version = ">=6.2.4", markers = "python_version >= \"3.10\""}, +] + +[[package]] +name = "pytest-timeout" +version = "1.4.2" +description = "py.test plugin to abort hanging tests" +optional = false +python-versions = "*" +files = [ + {file = "pytest-timeout-1.4.2.tar.gz", hash = "sha256:20b3113cf6e4e80ce2d403b6fb56e9e1b871b510259206d40ff8d609f48bda76"}, + {file = "pytest_timeout-1.4.2-py2.py3-none-any.whl", hash = "sha256:541d7aa19b9a6b4e475c759fd6073ef43d7cdc9a92d95644c260076eb257a063"}, +] + +[package.dependencies] +pytest = ">=3.6.0" [[package]] name = "python-dateutil" @@ -1529,17 +1627,6 @@ platformdirs = ">=3.9.1,<5" docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.2,!=7.3)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"] test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.4)", "pytest-env (>=0.8.2)", "pytest-freezer (>=0.4.8)", "pytest-mock (>=3.11.1)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=68)", "time-machine (>=2.10)"] -[[package]] -name = "wcwidth" -version = "0.2.13" -description = "Measures the displayed width of unicode strings in a terminal" -optional = false -python-versions = "*" -files = [ - {file = "wcwidth-0.2.13-py2.py3-none-any.whl", hash = "sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859"}, - {file = "wcwidth-0.2.13.tar.gz", hash = "sha256:72ea0c06399eb286d978fdedb6923a9eb47e1c486ce63e9b4e64fc18303972b5"}, -] - [[package]] name = "zipp" version = "3.23.0" @@ -1565,4 +1652,4 @@ mesh = [] [metadata] lock-version = "2.0" python-versions = "^3.9" -content-hash = "697a8f173378e7f9f27bdd1d68768ffd8b0d498866a1223abfa9884766a7ceeb" +content-hash = "4872820bde970d0961250c1c9688d46553573b057c8981a841d2eafe8ed7612f" From d46754f396cf4d61b7d7bcad69de91ff53db8f55 Mon Sep 17 00:00:00 2001 From: Carlos Adir Date: Wed, 9 Jul 2025 23:30:04 +0200 Subject: [PATCH 30/31] dev: update version to 1.1.2 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 2b7dcf45..3972d681 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "shapepy" -version = "1.1.1" +version = "1.1.2" description = "Geometric 2D library" authors = ["Carlos Adir "] readme = "README.md" From ecd609e3b1caf433539b0906a6af234108468170 Mon Sep 17 00:00:00 2001 From: Carlos Adir Date: Wed, 9 Jul 2025 23:43:08 +0200 Subject: [PATCH 31/31] fix upload to coverage --- .github/workflows/codecov.yaml | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codecov.yaml b/.github/workflows/codecov.yaml index 09e8e707..e0b76d87 100644 --- a/.github/workflows/codecov.yaml +++ b/.github/workflows/codecov.yaml @@ -39,7 +39,12 @@ jobs: - name: Run coverage run: tox -e coverage - - name: Upload coverage reports to Codecov - uses: codecov/codecov-action@v3 + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v5 with: - fail_ci_if_error: true + token: ${{ secrets.CODECOV_TOKEN }} + - name: Upload test results to Codecov + if: ${{ !cancelled() }} + uses: codecov/test-results-action@v1 + with: + token: ${{ secrets.CODECOV_TOKEN }}