svg-ultralight 0.33.0__tar.gz → 0.34.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of svg-ultralight might be problematic. Click here for more details.
- {svg_ultralight-0.33.0/src/svg_ultralight.egg-info → svg_ultralight-0.34.0}/PKG-INFO +1 -1
- {svg_ultralight-0.33.0 → svg_ultralight-0.34.0}/pyproject.toml +2 -2
- {svg_ultralight-0.33.0 → svg_ultralight-0.34.0}/src/svg_ultralight/__init__.py +8 -0
- {svg_ultralight-0.33.0 → svg_ultralight-0.34.0}/src/svg_ultralight/bounding_boxes/bound_helpers.py +74 -0
- {svg_ultralight-0.33.0 → svg_ultralight-0.34.0}/src/svg_ultralight/layout.py +4 -1
- {svg_ultralight-0.33.0 → svg_ultralight-0.34.0/src/svg_ultralight.egg-info}/PKG-INFO +1 -1
- {svg_ultralight-0.33.0 → svg_ultralight-0.34.0}/tests/test_bounding.py +68 -1
- {svg_ultralight-0.33.0 → svg_ultralight-0.34.0}/tests/test_layout.py +21 -0
- {svg_ultralight-0.33.0 → svg_ultralight-0.34.0}/.gitignore +0 -0
- {svg_ultralight-0.33.0 → svg_ultralight-0.34.0}/.pre-commit-config.yaml +0 -0
- {svg_ultralight-0.33.0 → svg_ultralight-0.34.0}/README.md +0 -0
- {svg_ultralight-0.33.0 → svg_ultralight-0.34.0}/setup.cfg +0 -0
- {svg_ultralight-0.33.0 → svg_ultralight-0.34.0}/src/svg_ultralight/animate.py +0 -0
- {svg_ultralight-0.33.0 → svg_ultralight-0.34.0}/src/svg_ultralight/bounding_boxes/__init__.py +0 -0
- {svg_ultralight-0.33.0 → svg_ultralight-0.34.0}/src/svg_ultralight/bounding_boxes/supports_bounds.py +0 -0
- {svg_ultralight-0.33.0 → svg_ultralight-0.34.0}/src/svg_ultralight/bounding_boxes/type_bound_collection.py +0 -0
- {svg_ultralight-0.33.0 → svg_ultralight-0.34.0}/src/svg_ultralight/bounding_boxes/type_bound_element.py +0 -0
- {svg_ultralight-0.33.0 → svg_ultralight-0.34.0}/src/svg_ultralight/bounding_boxes/type_bounding_box.py +0 -0
- {svg_ultralight-0.33.0 → svg_ultralight-0.34.0}/src/svg_ultralight/bounding_boxes/type_padded_text.py +0 -0
- {svg_ultralight-0.33.0 → svg_ultralight-0.34.0}/src/svg_ultralight/constructors/__init__.py +0 -0
- {svg_ultralight-0.33.0 → svg_ultralight-0.34.0}/src/svg_ultralight/constructors/new_element.py +0 -0
- {svg_ultralight-0.33.0 → svg_ultralight-0.34.0}/src/svg_ultralight/inkscape.py +0 -0
- {svg_ultralight-0.33.0 → svg_ultralight-0.34.0}/src/svg_ultralight/main.py +0 -0
- {svg_ultralight-0.33.0 → svg_ultralight-0.34.0}/src/svg_ultralight/metadata.py +0 -0
- {svg_ultralight-0.33.0 → svg_ultralight-0.34.0}/src/svg_ultralight/nsmap.py +0 -0
- {svg_ultralight-0.33.0 → svg_ultralight-0.34.0}/src/svg_ultralight/py.typed +0 -0
- {svg_ultralight-0.33.0 → svg_ultralight-0.34.0}/src/svg_ultralight/query.py +0 -0
- {svg_ultralight-0.33.0 → svg_ultralight-0.34.0}/src/svg_ultralight/root_elements.py +0 -0
- {svg_ultralight-0.33.0 → svg_ultralight-0.34.0}/src/svg_ultralight/string_conversion.py +0 -0
- {svg_ultralight-0.33.0 → svg_ultralight-0.34.0}/src/svg_ultralight/strings/__init__.py +0 -0
- {svg_ultralight-0.33.0 → svg_ultralight-0.34.0}/src/svg_ultralight/strings/svg_strings.py +0 -0
- {svg_ultralight-0.33.0 → svg_ultralight-0.34.0}/src/svg_ultralight/transformations.py +0 -0
- {svg_ultralight-0.33.0 → svg_ultralight-0.34.0}/src/svg_ultralight/unit_conversion.py +0 -0
- {svg_ultralight-0.33.0 → svg_ultralight-0.34.0}/src/svg_ultralight.egg-info/SOURCES.txt +0 -0
- {svg_ultralight-0.33.0 → svg_ultralight-0.34.0}/src/svg_ultralight.egg-info/dependency_links.txt +0 -0
- {svg_ultralight-0.33.0 → svg_ultralight-0.34.0}/src/svg_ultralight.egg-info/requires.txt +0 -0
- {svg_ultralight-0.33.0 → svg_ultralight-0.34.0}/src/svg_ultralight.egg-info/top_level.txt +0 -0
- {svg_ultralight-0.33.0 → svg_ultralight-0.34.0}/tests/__init__.py +0 -0
- {svg_ultralight-0.33.0 → svg_ultralight-0.34.0}/tests/conftest.py +0 -0
- {svg_ultralight-0.33.0 → svg_ultralight-0.34.0}/tests/test_inkscape.py +0 -0
- {svg_ultralight-0.33.0 → svg_ultralight-0.34.0}/tests/test_matrices.py +0 -0
- {svg_ultralight-0.33.0 → svg_ultralight-0.34.0}/tests/test_metadata.py +0 -0
- {svg_ultralight-0.33.0 → svg_ultralight-0.34.0}/tests/test_new_element.py +0 -0
- {svg_ultralight-0.33.0 → svg_ultralight-0.34.0}/tests/test_queries.py +0 -0
- {svg_ultralight-0.33.0 → svg_ultralight-0.34.0}/tests/test_root_elements.py +0 -0
- {svg_ultralight-0.33.0 → svg_ultralight-0.34.0}/tests/test_string_conversion.py +0 -0
- {svg_ultralight-0.33.0 → svg_ultralight-0.34.0}/tests/test_svg_ultralight.py +0 -0
- {svg_ultralight-0.33.0 → svg_ultralight-0.34.0}/tox.ini +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "svg-ultralight"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.34.0"
|
|
4
4
|
description = "a sensible way to create svg files with Python"
|
|
5
5
|
authors = [{ name = "Shay Hill", email = "shay_public@hotmail.com" }]
|
|
6
6
|
license = { text = "MIT" }
|
|
@@ -37,7 +37,7 @@ legacy_tox_ini = """
|
|
|
37
37
|
|
|
38
38
|
[tool.commitizen]
|
|
39
39
|
name = "cz_conventional_commits"
|
|
40
|
-
version = "0.
|
|
40
|
+
version = "0.34.0"
|
|
41
41
|
tag_format = "$version"
|
|
42
42
|
version_files = ["pyproject.toml:^version"]
|
|
43
43
|
annotated_tag = true
|
|
@@ -8,6 +8,10 @@ from svg_ultralight.bounding_boxes.bound_helpers import (
|
|
|
8
8
|
new_bbox_union,
|
|
9
9
|
new_bound_union,
|
|
10
10
|
new_element_union,
|
|
11
|
+
cut_bbox,
|
|
12
|
+
pad_bbox,
|
|
13
|
+
bbox_dict,
|
|
14
|
+
new_bbox_rect,
|
|
11
15
|
)
|
|
12
16
|
from svg_ultralight.bounding_boxes.supports_bounds import SupportsBounds
|
|
13
17
|
from svg_ultralight.bounding_boxes.type_bound_collection import BoundCollection
|
|
@@ -57,7 +61,9 @@ __all__ = [
|
|
|
57
61
|
"NSMAP",
|
|
58
62
|
"PaddedText",
|
|
59
63
|
"SupportsBounds",
|
|
64
|
+
"bbox_dict",
|
|
60
65
|
"clear_svg_ultralight_cache",
|
|
66
|
+
"cut_bbox",
|
|
61
67
|
"deepcopy_element",
|
|
62
68
|
"format_attr_dict",
|
|
63
69
|
"format_number",
|
|
@@ -68,6 +74,7 @@ __all__ = [
|
|
|
68
74
|
"mat_apply",
|
|
69
75
|
"mat_dot",
|
|
70
76
|
"mat_invert",
|
|
77
|
+
"new_bbox_rect",
|
|
71
78
|
"new_bbox_union",
|
|
72
79
|
"new_bound_union",
|
|
73
80
|
"new_element",
|
|
@@ -77,6 +84,7 @@ __all__ = [
|
|
|
77
84
|
"new_sub_element",
|
|
78
85
|
"new_svg_root",
|
|
79
86
|
"new_svg_root_around_bounds",
|
|
87
|
+
"pad_bbox",
|
|
80
88
|
"pad_text",
|
|
81
89
|
"transform_element",
|
|
82
90
|
"update_element",
|
{svg_ultralight-0.33.0 → svg_ultralight-0.34.0}/src/svg_ultralight/bounding_boxes/bound_helpers.py
RENAMED
|
@@ -95,3 +95,77 @@ def new_bound_union(*blems: SupportsBounds | EtreeElement) -> BoundElement:
|
|
|
95
95
|
group = new_element_union(*blems)
|
|
96
96
|
bbox = new_bbox_union(*blems)
|
|
97
97
|
return BoundElement(group, bbox)
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def _expand_pad(pad: float | tuple[float, ...]) -> tuple[float, float, float, float]:
|
|
101
|
+
"""Expand a float pad argument into a 4-tuple."""
|
|
102
|
+
if isinstance(pad, (int, float)):
|
|
103
|
+
return pad, pad, pad, pad
|
|
104
|
+
if len(pad) == 1:
|
|
105
|
+
return pad[0], pad[0], pad[0], pad[0]
|
|
106
|
+
if len(pad) == 2:
|
|
107
|
+
return pad[0], pad[1], pad[0], pad[1]
|
|
108
|
+
if len(pad) == 3:
|
|
109
|
+
return pad[0], pad[1], pad[2], pad[1]
|
|
110
|
+
return pad[0], pad[1], pad[2], pad[3]
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def cut_bbox(
|
|
114
|
+
bbox: SupportsBounds,
|
|
115
|
+
*,
|
|
116
|
+
x: float | None = None,
|
|
117
|
+
y: float | None = None,
|
|
118
|
+
x2: float | None = None,
|
|
119
|
+
y2: float | None = None,
|
|
120
|
+
) -> BoundingBox:
|
|
121
|
+
"""Return a new bounding box with updated limits.
|
|
122
|
+
|
|
123
|
+
:param bbox: the original bounding box or bounded element.
|
|
124
|
+
:param x: the new x-coordinate.
|
|
125
|
+
:param y: the new y-coordinate.
|
|
126
|
+
:param x2: the new x2-coordinate.
|
|
127
|
+
:param y2: the new y2-coordinate.
|
|
128
|
+
:return: a new bounding box with the updated limits.
|
|
129
|
+
"""
|
|
130
|
+
x = bbox.x if x is None else x
|
|
131
|
+
y = bbox.y if y is None else y
|
|
132
|
+
x2 = bbox.x2 if x2 is None else x2
|
|
133
|
+
y2 = bbox.y2 if y2 is None else y2
|
|
134
|
+
width = x2 - x
|
|
135
|
+
height = y2 - y
|
|
136
|
+
return BoundingBox(x, y, width, height)
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def pad_bbox(bbox: SupportsBounds, pad: float | tuple[float, ...]) -> BoundingBox:
|
|
140
|
+
"""Return a new bounding box with padding.
|
|
141
|
+
|
|
142
|
+
:param bbox: the original bounding box or bounded element.
|
|
143
|
+
:param pad: the padding to apply.
|
|
144
|
+
If a single number, the same padding will be applied to all sides.
|
|
145
|
+
If a tuple, will be applied per css rules.
|
|
146
|
+
len = 1 : 0, 0, 0, 0
|
|
147
|
+
len = 2 : 0, 1, 0, 1
|
|
148
|
+
len = 3 : 0, 1, 2, 1
|
|
149
|
+
len = 4 : 0, 1, 2, 3
|
|
150
|
+
:return: a new bounding box with padding applied.
|
|
151
|
+
"""
|
|
152
|
+
t, r, b, l = _expand_pad(pad)
|
|
153
|
+
return cut_bbox(bbox, x=bbox.x - l, y=bbox.y - t, x2=bbox.x2 + r, y2=bbox.y2 + b)
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
def bbox_dict(bbox: SupportsBounds) -> dict[str, float]:
|
|
157
|
+
"""Return a dictionary representation of a bounding box.
|
|
158
|
+
|
|
159
|
+
:param bbox: the bounding box or bound element from which to extract dimensions.
|
|
160
|
+
:return: a dictionary with keys x, y, width, and height.
|
|
161
|
+
"""
|
|
162
|
+
return {"x": bbox.x, "y": bbox.y, "width": bbox.width, "height": bbox.height}
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
def new_bbox_rect(bbox: BoundingBox, **kwargs: float | str) -> EtreeElement:
|
|
166
|
+
"""Return a new rect element with the same dimensions as the bounding box.
|
|
167
|
+
|
|
168
|
+
:param bbox: the bounding box or bound element from which to extract dimensions.
|
|
169
|
+
:param kwargs: additional attributes for the rect element.
|
|
170
|
+
"""
|
|
171
|
+
return new_element("rect", **bbox_dict(bbox), **kwargs)
|
|
@@ -43,7 +43,10 @@ def expand_pad_arg(pad: PadArg) -> tuple[float, float, float, float]:
|
|
|
43
43
|
return expand_pad_arg([pad])
|
|
44
44
|
as_ms = [m if isinstance(m, Measurement) else Measurement(m) for m in pad]
|
|
45
45
|
as_units = [m.value for m in as_ms]
|
|
46
|
-
|
|
46
|
+
if len(as_units) == 3:
|
|
47
|
+
as_units = [*as_units, as_units[1]]
|
|
48
|
+
else:
|
|
49
|
+
as_units = [as_units[i % len(as_units)] for i in range(4)]
|
|
47
50
|
return as_units[0], as_units[1], as_units[2], as_units[3]
|
|
48
51
|
|
|
49
52
|
|
|
@@ -10,9 +10,16 @@ from svg_ultralight.bounding_boxes.type_bound_element import BoundElement
|
|
|
10
10
|
from svg_ultralight.bounding_boxes.type_padded_text import PaddedText
|
|
11
11
|
from svg_ultralight.bounding_boxes.type_bounding_box import BoundingBox
|
|
12
12
|
from svg_ultralight.bounding_boxes.type_bound_collection import BoundCollection
|
|
13
|
+
from svg_ultralight.bounding_boxes.bound_helpers import (
|
|
14
|
+
pad_bbox,
|
|
15
|
+
cut_bbox,
|
|
16
|
+
bbox_dict,
|
|
17
|
+
new_bbox_rect,
|
|
18
|
+
)
|
|
13
19
|
import copy
|
|
14
20
|
from svg_ultralight.constructors import new_element
|
|
15
21
|
|
|
22
|
+
|
|
16
23
|
class TestBoundElement:
|
|
17
24
|
@pytest.fixture
|
|
18
25
|
def bound_element(self) -> BoundElement:
|
|
@@ -84,7 +91,6 @@ class TestBoundElement:
|
|
|
84
91
|
assert bound_element.y2 == 250.0
|
|
85
92
|
|
|
86
93
|
|
|
87
|
-
|
|
88
94
|
class TestPaddedText:
|
|
89
95
|
@pytest.fixture
|
|
90
96
|
def bound_element(self) -> PaddedText:
|
|
@@ -155,6 +161,7 @@ class TestPaddedText:
|
|
|
155
161
|
assert math.isclose(bound_element.height, 252.76)
|
|
156
162
|
assert bound_element.y2 == 203.0
|
|
157
163
|
|
|
164
|
+
|
|
158
165
|
class TestBoundCollection:
|
|
159
166
|
|
|
160
167
|
@pytest.fixture
|
|
@@ -178,3 +185,63 @@ class TestBoundCollection:
|
|
|
178
185
|
blem_trans = blem.elem.attrib["transform"]
|
|
179
186
|
elem_trans = elem.attrib["transform"]
|
|
180
187
|
assert blem_trans == elem_trans
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
class TestBoundHelpers:
|
|
191
|
+
def test_pad_bbox(self):
|
|
192
|
+
bbox = BoundingBox(0, 0, 4, 4)
|
|
193
|
+
padded = pad_bbox(bbox, 1)
|
|
194
|
+
assert padded.x == -1
|
|
195
|
+
assert padded.y == -1
|
|
196
|
+
assert padded.width == 6
|
|
197
|
+
assert padded.height == 6
|
|
198
|
+
|
|
199
|
+
def test_pad_bbox_t1(self):
|
|
200
|
+
bbox = BoundingBox(0, 0, 4, 4)
|
|
201
|
+
padded = pad_bbox(bbox, (1,))
|
|
202
|
+
assert padded.x == -1
|
|
203
|
+
assert padded.y == -1
|
|
204
|
+
assert padded.width == 6
|
|
205
|
+
assert padded.height == 6
|
|
206
|
+
|
|
207
|
+
def test_pad_bbox_t2(self):
|
|
208
|
+
bbox = BoundingBox(0, 0, 4, 4)
|
|
209
|
+
padded = pad_bbox(bbox, (1, 2))
|
|
210
|
+
assert padded.x == -2
|
|
211
|
+
assert padded.y == -1
|
|
212
|
+
assert padded.width == 8
|
|
213
|
+
assert padded.height == 6
|
|
214
|
+
|
|
215
|
+
def test_pad_bbox_t3(self):
|
|
216
|
+
bbox = BoundingBox(0, 0, 4, 4)
|
|
217
|
+
padded = pad_bbox(bbox, (1, 2, 3))
|
|
218
|
+
assert padded.x == -2
|
|
219
|
+
assert padded.y == -1
|
|
220
|
+
assert padded.width == 8
|
|
221
|
+
assert padded.height == 8
|
|
222
|
+
|
|
223
|
+
def test_pad_bbox_t4(self):
|
|
224
|
+
bbox = BoundingBox(0, 0, 4, 4)
|
|
225
|
+
padded = pad_bbox(bbox, (1, 2, 3, 4))
|
|
226
|
+
assert padded.x == -4
|
|
227
|
+
assert padded.y == -1
|
|
228
|
+
assert padded.width == 10
|
|
229
|
+
assert padded.height == 8
|
|
230
|
+
|
|
231
|
+
def test_cut_bbox(self):
|
|
232
|
+
bbox = BoundingBox(0, 0, 4, 4)
|
|
233
|
+
cut = cut_bbox(bbox, x=1)
|
|
234
|
+
assert cut.x == 1
|
|
235
|
+
assert cut.y == 0
|
|
236
|
+
assert cut.width == 3
|
|
237
|
+
assert cut.height == 4
|
|
238
|
+
|
|
239
|
+
def test_bbox_dict(self):
|
|
240
|
+
bbox = BoundingBox(0, 1, 2, 3)
|
|
241
|
+
assert bbox_dict(bbox) == {"x": 0, "y": 1, "width": 2, "height": 3}
|
|
242
|
+
|
|
243
|
+
def test_new_bbox_rect(self):
|
|
244
|
+
bbox = BoundingBox(0, 1, 2, 3)
|
|
245
|
+
elem = new_bbox_rect(bbox)
|
|
246
|
+
assert elem.attrib == {"x": "0", "y": "1", "width": "2", "height": "3"}
|
|
247
|
+
|
|
@@ -123,6 +123,27 @@ class TestMeasurement:
|
|
|
123
123
|
assert (Measurement((1, unit)) / 4).value == Measurement((1 / 4, unit)).value
|
|
124
124
|
|
|
125
125
|
|
|
126
|
+
class TestExpandPadArg:
|
|
127
|
+
def test_expand_val(self):
|
|
128
|
+
"""Test that a single value is expanded to a 4-tuple."""
|
|
129
|
+
assert layout.expand_pad_arg(1) == (1, 1, 1, 1)
|
|
130
|
+
|
|
131
|
+
def test_expand_1tuple(self):
|
|
132
|
+
"""Test that a single value is expanded to a 4-tuple."""
|
|
133
|
+
assert layout.expand_pad_arg(1) == (1, 1, 1, 1)
|
|
134
|
+
|
|
135
|
+
def test_expand_2tuple(self):
|
|
136
|
+
"""Test that a single value is expanded to a 4-tuple."""
|
|
137
|
+
assert layout.expand_pad_arg((1, 2)) == (1, 2, 1, 2)
|
|
138
|
+
|
|
139
|
+
def test_expand_3tuple(self):
|
|
140
|
+
"""Test that a single value is expanded to a 4-tuple per css rules."""
|
|
141
|
+
assert layout.expand_pad_arg((1, 2, 3)) == (1, 2, 3, 2)
|
|
142
|
+
|
|
143
|
+
def test_expand_4tuple(self):
|
|
144
|
+
"""Test that a single value is expanded to a 4-tuple per css rules."""
|
|
145
|
+
assert layout.expand_pad_arg((1, 2, 3, 4)) == (1, 2, 3, 4)
|
|
146
|
+
|
|
126
147
|
class TestLayout:
|
|
127
148
|
def test_standard(self):
|
|
128
149
|
"""No print dimensions give expanded pad argument
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{svg_ultralight-0.33.0 → svg_ultralight-0.34.0}/src/svg_ultralight/bounding_boxes/__init__.py
RENAMED
|
File without changes
|
{svg_ultralight-0.33.0 → svg_ultralight-0.34.0}/src/svg_ultralight/bounding_boxes/supports_bounds.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{svg_ultralight-0.33.0 → svg_ultralight-0.34.0}/src/svg_ultralight/constructors/new_element.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{svg_ultralight-0.33.0 → svg_ultralight-0.34.0}/src/svg_ultralight.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|