svg-ultralight 0.47.0__tar.gz → 0.50.1__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.

Files changed (63) hide show
  1. {svg_ultralight-0.47.0/src/svg_ultralight.egg-info → svg_ultralight-0.50.1}/PKG-INFO +208 -214
  2. {svg_ultralight-0.47.0 → svg_ultralight-0.50.1}/README.md +190 -190
  3. {svg_ultralight-0.47.0 → svg_ultralight-0.50.1}/pyproject.toml +75 -81
  4. {svg_ultralight-0.47.0 → svg_ultralight-0.50.1}/src/svg_ultralight/__init__.py +108 -105
  5. {svg_ultralight-0.47.0 → svg_ultralight-0.50.1}/src/svg_ultralight/animate.py +40 -40
  6. {svg_ultralight-0.47.0 → svg_ultralight-0.50.1}/src/svg_ultralight/attrib_hints.py +13 -14
  7. {svg_ultralight-0.47.0 → svg_ultralight-0.50.1}/src/svg_ultralight/bounding_boxes/__init__.py +5 -5
  8. {svg_ultralight-0.47.0 → svg_ultralight-0.50.1}/src/svg_ultralight/bounding_boxes/bound_helpers.py +189 -201
  9. {svg_ultralight-0.47.0 → svg_ultralight-0.50.1}/src/svg_ultralight/bounding_boxes/padded_text_initializers.py +207 -206
  10. {svg_ultralight-0.47.0 → svg_ultralight-0.50.1}/src/svg_ultralight/bounding_boxes/supports_bounds.py +166 -166
  11. {svg_ultralight-0.47.0 → svg_ultralight-0.50.1}/src/svg_ultralight/bounding_boxes/type_bound_collection.py +71 -71
  12. {svg_ultralight-0.47.0 → svg_ultralight-0.50.1}/src/svg_ultralight/bounding_boxes/type_bound_element.py +65 -65
  13. {svg_ultralight-0.47.0 → svg_ultralight-0.50.1}/src/svg_ultralight/bounding_boxes/type_bounding_box.py +396 -396
  14. {svg_ultralight-0.47.0 → svg_ultralight-0.50.1}/src/svg_ultralight/bounding_boxes/type_padded_text.py +411 -411
  15. {svg_ultralight-0.47.0 → svg_ultralight-0.50.1}/src/svg_ultralight/constructors/__init__.py +14 -14
  16. {svg_ultralight-0.47.0 → svg_ultralight-0.50.1}/src/svg_ultralight/constructors/new_element.py +115 -115
  17. {svg_ultralight-0.47.0 → svg_ultralight-0.50.1}/src/svg_ultralight/font_tools/__init__.py +5 -5
  18. {svg_ultralight-0.47.0 → svg_ultralight-0.50.1}/src/svg_ultralight/font_tools/comp_results.py +295 -293
  19. {svg_ultralight-0.47.0 → svg_ultralight-0.50.1}/src/svg_ultralight/font_tools/font_info.py +793 -784
  20. {svg_ultralight-0.47.0 → svg_ultralight-0.50.1}/src/svg_ultralight/image_ops.py +156 -156
  21. {svg_ultralight-0.47.0 → svg_ultralight-0.50.1}/src/svg_ultralight/inkscape.py +261 -261
  22. {svg_ultralight-0.47.0 → svg_ultralight-0.50.1}/src/svg_ultralight/layout.py +290 -291
  23. {svg_ultralight-0.47.0 → svg_ultralight-0.50.1}/src/svg_ultralight/main.py +183 -198
  24. {svg_ultralight-0.47.0 → svg_ultralight-0.50.1}/src/svg_ultralight/metadata.py +122 -122
  25. {svg_ultralight-0.47.0 → svg_ultralight-0.50.1}/src/svg_ultralight/nsmap.py +36 -36
  26. svg_ultralight-0.50.1/src/svg_ultralight/py.typed +5 -0
  27. {svg_ultralight-0.47.0 → svg_ultralight-0.50.1}/src/svg_ultralight/query.py +254 -249
  28. svg_ultralight-0.50.1/src/svg_ultralight/read_svg.py +58 -0
  29. {svg_ultralight-0.47.0 → svg_ultralight-0.50.1}/src/svg_ultralight/root_elements.py +87 -87
  30. {svg_ultralight-0.47.0 → svg_ultralight-0.50.1}/src/svg_ultralight/string_conversion.py +244 -244
  31. {svg_ultralight-0.47.0 → svg_ultralight-0.50.1}/src/svg_ultralight/strings/__init__.py +21 -13
  32. {svg_ultralight-0.47.0 → svg_ultralight-0.50.1}/src/svg_ultralight/strings/svg_strings.py +106 -67
  33. {svg_ultralight-0.47.0 → svg_ultralight-0.50.1}/src/svg_ultralight/transformations.py +140 -141
  34. {svg_ultralight-0.47.0 → svg_ultralight-0.50.1}/src/svg_ultralight/unit_conversion.py +247 -248
  35. svg_ultralight-0.47.0/.gitignore +0 -3
  36. svg_ultralight-0.47.0/.pre-commit-config.yaml +0 -118
  37. svg_ultralight-0.47.0/PKG-INFO +0 -214
  38. svg_ultralight-0.47.0/dev-requirements.txt +0 -118
  39. svg_ultralight-0.47.0/experiments/encode_fonts3.txt +0 -248
  40. svg_ultralight-0.47.0/experiments/font_css.py +0 -82
  41. svg_ultralight-0.47.0/setup.cfg +0 -4
  42. svg_ultralight-0.47.0/src/svg_ultralight/py.typed +0 -0
  43. svg_ultralight-0.47.0/src/svg_ultralight.egg-info/SOURCES.txt +0 -59
  44. svg_ultralight-0.47.0/src/svg_ultralight.egg-info/dependency_links.txt +0 -1
  45. svg_ultralight-0.47.0/src/svg_ultralight.egg-info/requires.txt +0 -17
  46. svg_ultralight-0.47.0/src/svg_ultralight.egg-info/top_level.txt +0 -1
  47. svg_ultralight-0.47.0/tests/__init__.py +0 -0
  48. svg_ultralight-0.47.0/tests/conftest.py +0 -37
  49. svg_ultralight-0.47.0/tests/resources/arrow.svg +0 -3
  50. svg_ultralight-0.47.0/tests/test_bound_element.py +0 -84
  51. svg_ultralight-0.47.0/tests/test_bounding.py +0 -284
  52. svg_ultralight-0.47.0/tests/test_inkscape.py +0 -48
  53. svg_ultralight-0.47.0/tests/test_layout.py +0 -250
  54. svg_ultralight-0.47.0/tests/test_matrices.py +0 -37
  55. svg_ultralight-0.47.0/tests/test_metadata.py +0 -89
  56. svg_ultralight-0.47.0/tests/test_new_element.py +0 -60
  57. svg_ultralight-0.47.0/tests/test_padded_text_initializers.py +0 -78
  58. svg_ultralight-0.47.0/tests/test_padding.py +0 -56
  59. svg_ultralight-0.47.0/tests/test_queries.py +0 -233
  60. svg_ultralight-0.47.0/tests/test_root_elements.py +0 -78
  61. svg_ultralight-0.47.0/tests/test_string_conversion.py +0 -137
  62. svg_ultralight-0.47.0/tests/test_svg_ultralight.py +0 -192
  63. svg_ultralight-0.47.0/tox.ini +0 -6
@@ -1,214 +1,208 @@
1
- Metadata-Version: 2.4
2
- Name: svg-ultralight
3
- Version: 0.47.0
4
- Summary: a sensible way to create svg files with Python
5
- Author-email: Shay Hill <shay_public@hotmail.com>
6
- License: MIT
7
- Requires-Python: >=3.9
8
- Description-Content-Type: text/markdown
9
- Requires-Dist: cssutils
10
- Requires-Dist: fonttools
11
- Requires-Dist: lxml
12
- Requires-Dist: paragraphs
13
- Requires-Dist: pillow
14
- Requires-Dist: svg-path-data
15
- Requires-Dist: types-lxml
16
- Requires-Dist: typing-extensions
17
- Provides-Extra: dev
18
- Requires-Dist: pytest; extra == "dev"
19
- Requires-Dist: commitizen; extra == "dev"
20
- Requires-Dist: pre-commit; extra == "dev"
21
- Requires-Dist: tox; extra == "dev"
22
- Provides-Extra: images
23
- Requires-Dist: pillow; extra == "images"
24
-
25
- # svg_ultralight
26
-
27
- The most straightforward way to create SVG files with Python.
28
-
29
- ## Four principal functions:
30
-
31
- from svg_ultralight import new_svg_root, write_svg, write_png_from_svg, write_png
32
-
33
- ## One convenience:
34
-
35
- from svg_ultralight import NSMAP
36
-
37
- ### new_svg_root
38
- x_: Optional[float],
39
- y_: Optional[float],
40
- width_: Optional[float],
41
- height_: Optional[float],
42
- pad_: float = 0
43
- dpu_: float = 1
44
- nsmap: Optional[Dict[str, str]] = None (svg_ultralight.NSMAP if None)
45
- **attributes: Union[float, str],
46
- -> etree.Element
47
-
48
- Create an svg root element from viewBox style arguments and provide the necessary svg-specific attributes and namespaces. This is your window onto the scene.
49
-
50
- Three ways to call:
51
-
52
- 1. The trailing-underscore arguments are the same you'd use to create a `rect` element (plus `pad_` and `dpu_`). `new_svg_root` will infer `viewBox`, `width`, and `height` svg attributes from these values.
53
- 2. Use the svg attributes you already know: `viewBox`, `width`, `height`, etc. These will be written to the xml file.
54
- 3. Of course, you can combine 1. and 2. if you know what you're doing.
55
-
56
- See `namespaces` below.
57
-
58
- * `x_`: x value in upper-left corner
59
- * `y_`: y value in upper-left corner
60
- * `width_`: width of viewBox
61
- * `height_`: height of viewBox
62
- * `pad_`: the one small convenience I've provided. Optionally increase viewBox by `pad` in all directions.
63
- * `dpu_`: pixels per viewBox unit for output png images.
64
- * `nsmap`: namespaces. (defaults to svg_ultralight.NSMAP). Available as an argument should you wish to add additional namespaces. To do this, add items to NSMAP then call with `nsmap=NSMAP`.
65
- * `**attributes`: the trailing-underscore arguments are an *optional* shortcut for creating a scene. The entire svg interface is available to you through kwargs. See `A few helpers` below for details on attribute-name translation between Python and xml (the short version: `this_name` becomes `this-name` and `this_` becomes `this`)
66
-
67
- ### namespaces (svg_ultralight.NSMAP)
68
-
69
- `new_svg_root` will create a root with several available namespaces.
70
-
71
- * `"dc": "http://purl.org/dc/elements/1.1/"`
72
- * `"cc": "http://creativecommons.org/ns#"`
73
- * `"rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#"`
74
- * `"svg": "http://www.w3.org/2000/svg"`
75
- * `"xlink": "http://www.w3.org/1999/xlink"`
76
- * `"sodipodi": "http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"`
77
- * `"inkscape": "http://www.inkscape.org/namespaces/inkscape"`
78
-
79
- I have made these available to you as `svg_ultralight.NSMAP`
80
-
81
- ### write_svg
82
- svg: str,
83
- xml: etree.Element,
84
- stylesheet: Optional[str] = None,
85
- do_link_css: bool = False,
86
- **tostring_kwargs,
87
- -> str:
88
-
89
- Write an xml element as an svg file. This will link or inline your css code and insert the necessary declaration, doctype, and processing instructions.
90
-
91
- * `svg`: path to output file (include extension .svg)
92
- * `param xml`: root node of your svg geometry (created by `new_svg_root`)
93
- * `stylesheet`: optional path to a css stylesheet
94
- * `do_link_css`: link to stylesheet, else (default) write contents of stylesheet into svg (ignored if `stylesheet` is None). If you have a stylesheet somewhere, the default action is to dump the entire contents into your svg file. Linking to the stylesheet is more elegant, but inlining *always* works.
95
- * `**tostring_kwargs`: optional kwarg arguments for `lxml.etree.tostring`. Passing `xml_declaration=True` by itself will create an xml declaration with encoding set to UTF-8 and an svg DOCTYPE. These defaults can be overridden with keyword arguments `encoding` and `doctype`. If you don't know what this is, you can probably get away without it.
96
- * `returns`: for convenience, returns svg filename (`svg`)
97
- * `effects`: creates svg file at `svg`
98
-
99
- ### write_png_from_svg
100
-
101
- inkscape_exe: str,
102
- svg: str
103
- png: Optional[str]
104
- -> str
105
-
106
- Convert an svg file to a png. Python does not have a library for this. That has an upside, as any library would be one more set of svg implementation idiosyncrasies we'd have to deal with. Inkscape will convert the file. This function provides the necessary command-line arguments.
107
-
108
- * `inkscape_exe`: path to inkscape.exe
109
- * `svg`: path to svg file
110
- * `png`: optional path to png output (if not given, png name will be inferred from `svg`: `'name.svg'` becomes `'name.png'`)
111
- * `return`: png filename
112
- * `effects`: creates png file at `png` (or infers png path and filename from `svg`)
113
-
114
- ### write_png
115
-
116
- inkscape_exe: str,
117
- png: str,
118
- xml: etree.Element,
119
- stylesheet: Optional[str] = None
120
- -> str
121
-
122
- Create a png without writing an initial svg to your filesystem. This is not faster (it may be slightly slower), but it may be important when writing many images (animation frames) to your filesystem.
123
-
124
- * `inkscape_exe`: path to inkscape.exe
125
- * `png`: path to output file (include extension .png)
126
- * `param xml`: root node of your svg geometry (created by `new_svg_root`)
127
- * `stylesheet`: optional path to a css stylesheet
128
- * `returns`: for convenience, returns png filename (`png`)
129
- * `effects`: creates png file at `png`
130
-
131
- ## A few helpers:
132
-
133
- from svg_ultralight.constructors import new_element, new_sub_element
134
-
135
- I do want to keep this ultralight and avoid creating some pseudo scripting language between Python and lxml, but here are two very simple, very optional functions to save your having to `str()` every argument to `etree.Element`.
136
-
137
- ### constructors.new_element
138
-
139
- tag: str
140
- **params: Union[str, float]
141
- -> etree.Element
142
-
143
- Python allows underscores in variable names; xml uses dashes.
144
-
145
- Python understands numbers; xml wants strings.
146
-
147
- This is a convenience function to swap `"_"` for `"-"` and `10.2` for `"10.2"` before creating an xml element.
148
-
149
- Translates numbers to strings
150
-
151
- >>> elem = new_element('line', x1=0, y1=0, x2=5, y2=5)
152
- >>> etree.tostring(elem)
153
- b'<line x1="0" y1="0" x2="5" y2="5"/>'
154
-
155
- Translates underscores to hyphens
156
-
157
- >>> elem = new_element('line', stroke_width=1)
158
- >>> etree.tostring(elem)
159
- b'<line stroke-width="1"/>'
160
-
161
- Removes trailing underscores. You'll almost certainly want to use reserved names like ``class`` as svg parameters. This
162
- can be done by passing the name with a trailing underscore.
163
-
164
- >>> elem = new_element('line', class_='thick_line')
165
- >>> etree.tostring(elem)
166
- b'<line class="thick_line"/>'
167
-
168
- Special handling for a 'text' argument. Places value between element tags.
169
-
170
- >>> elem = new_element('text', text='please star my project')
171
- >>> etree.tostring(elem)
172
- b'<text>please star my project</text>'
173
-
174
- ### constructors.new_sub_element
175
-
176
- parent: etree.Element
177
- tag: str
178
- **params: Union[str, float]
179
- -> etree.Element
180
-
181
- As above, but creates a subelement.
182
-
183
- >>> parent = etree.Element('g')
184
- >>> _ = new_sub_element('rect')
185
- >>> etree.tostring(parent)
186
- b'<g><rect/></g>'
187
-
188
- ### update_element
189
-
190
- Another way to add params through the new_element name / float translator. Again unnecessary, but potentially helpful. Easily understood from the code or docstrings.
191
-
192
- ## Extras:
193
-
194
- ### query.map_elems_to_bounding_boxes
195
-
196
- Python cannot parse an svg file. Python can *create* an svg file, and Inkscape can parse (and inspect) it. Inkscape has a command-line interface capable of reading an svg file and returning some limited information. This is the only way I know for a Python program to:
197
-
198
- 1. create an svg file (optionally without writing to filesystem)
199
- 2. query the svg file for bounding-box information
200
- 3. create an adjusted svg file.
201
-
202
- This would be necessary for, e.g., algorithmically fitting text in a box.
203
-
204
- from svg_ultralight.queries import map_elems_to_bounding_boxes
205
-
206
- You can get a tiny bit more sophisticated with Inkscape bounding-box queries, but not much. This will give you pretty much all you can get out of it.
207
-
208
- ### animate.write_gif
209
-
210
- Create an animated gif from a sequence of png filenames. This is a Pillow one-liner, but it's convenient for me to have it, so it might be convenient for you. Requires pillow, which is not a project dependency.
211
-
212
- from svg_ultralight.animate import write_gif
213
-
214
- [Full Documentation and Tutorial](https://shayallenhill.com/svg-with-css-in-python/)
1
+ Metadata-Version: 2.4
2
+ Name: svg-ultralight
3
+ Version: 0.50.1
4
+ Summary: a sensible way to create svg files with Python
5
+ Author: Shay Hill
6
+ Author-email: Shay Hill <shay_public@hotmail.com>
7
+ License-Expression: MIT
8
+ Requires-Dist: cssutils>=2.11.1
9
+ Requires-Dist: fonttools>=4.60.1
10
+ Requires-Dist: lxml>=6.0.2
11
+ Requires-Dist: paragraphs>=1.0.1
12
+ Requires-Dist: pillow>=11.3.0
13
+ Requires-Dist: svg-path-data>=0.5.3
14
+ Requires-Dist: types-lxml>=2025.8.25
15
+ Requires-Dist: typing-extensions>=4.15.0
16
+ Requires-Python: >=3.10
17
+ Description-Content-Type: text/markdown
18
+
19
+ # svg_ultralight
20
+
21
+ The most straightforward way to create SVG files with Python.
22
+
23
+ ## Four principal functions:
24
+
25
+ from svg_ultralight import new_svg_root, write_svg, write_png_from_svg, write_png
26
+
27
+ ## One convenience:
28
+
29
+ from svg_ultralight import NSMAP
30
+
31
+ ### new_svg_root
32
+ x_: Optional[float],
33
+ y_: Optional[float],
34
+ width_: Optional[float],
35
+ height_: Optional[float],
36
+ pad_: float = 0
37
+ dpu_: float = 1
38
+ nsmap: Optional[Dict[str, str]] = None (svg_ultralight.NSMAP if None)
39
+ **attributes: Union[float, str],
40
+ -> etree.Element
41
+
42
+ Create an svg root element from viewBox style arguments and provide the necessary svg-specific attributes and namespaces. This is your window onto the scene.
43
+
44
+ Three ways to call:
45
+
46
+ 1. The trailing-underscore arguments are the same you'd use to create a `rect` element (plus `pad_` and `dpu_`). `new_svg_root` will infer `viewBox`, `width`, and `height` svg attributes from these values.
47
+ 2. Use the svg attributes you already know: `viewBox`, `width`, `height`, etc. These will be written to the xml file.
48
+ 3. Of course, you can combine 1. and 2. if you know what you're doing.
49
+
50
+ See `namespaces` below.
51
+
52
+ * `x_`: x value in upper-left corner
53
+ * `y_`: y value in upper-left corner
54
+ * `width_`: width of viewBox
55
+ * `height_`: height of viewBox
56
+ * `pad_`: the one small convenience I've provided. Optionally increase viewBox by `pad` in all directions.
57
+ * `dpu_`: pixels per viewBox unit for output png images.
58
+ * `nsmap`: namespaces. (defaults to svg_ultralight.NSMAP). Available as an argument should you wish to add additional namespaces. To do this, add items to NSMAP then call with `nsmap=NSMAP`.
59
+ * `**attributes`: the trailing-underscore arguments are an *optional* shortcut for creating a scene. The entire svg interface is available to you through kwargs. See `A few helpers` below for details on attribute-name translation between Python and xml (the short version: `this_name` becomes `this-name` and `this_` becomes `this`)
60
+
61
+ ### namespaces (svg_ultralight.NSMAP)
62
+
63
+ `new_svg_root` will create a root with several available namespaces.
64
+
65
+ * `"dc": "http://purl.org/dc/elements/1.1/"`
66
+ * `"cc": "http://creativecommons.org/ns#"`
67
+ * `"rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#"`
68
+ * `"svg": "http://www.w3.org/2000/svg"`
69
+ * `"xlink": "http://www.w3.org/1999/xlink"`
70
+ * `"sodipodi": "http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"`
71
+ * `"inkscape": "http://www.inkscape.org/namespaces/inkscape"`
72
+
73
+ I have made these available to you as `svg_ultralight.NSMAP`
74
+
75
+ ### write_svg
76
+ svg: str,
77
+ xml: etree.Element,
78
+ stylesheet: Optional[str] = None,
79
+ do_link_css: bool = False,
80
+ **tostring_kwargs,
81
+ -> str:
82
+
83
+ Write an xml element as an svg file. This will link or inline your css code and insert the necessary declaration, doctype, and processing instructions.
84
+
85
+ * `svg`: path to output file (include extension .svg)
86
+ * `param xml`: root node of your svg geometry (created by `new_svg_root`)
87
+ * `stylesheet`: optional path to a css stylesheet
88
+ * `do_link_css`: link to stylesheet, else (default) write contents of stylesheet into svg (ignored if `stylesheet` is None). If you have a stylesheet somewhere, the default action is to dump the entire contents into your svg file. Linking to the stylesheet is more elegant, but inlining *always* works.
89
+ * `**tostring_kwargs`: optional kwarg arguments for `lxml.etree.tostring`. Passing `xml_declaration=True` by itself will create an xml declaration with encoding set to UTF-8 and an svg DOCTYPE. These defaults can be overridden with keyword arguments `encoding` and `doctype`. If you don't know what this is, you can probably get away without it.
90
+ * `returns`: for convenience, returns svg filename (`svg`)
91
+ * `effects`: creates svg file at `svg`
92
+
93
+ ### write_png_from_svg
94
+
95
+ inkscape_exe: str,
96
+ svg: str
97
+ png: Optional[str]
98
+ -> str
99
+
100
+ Convert an svg file to a png. Python does not have a library for this. That has an upside, as any library would be one more set of svg implementation idiosyncrasies we'd have to deal with. Inkscape will convert the file. This function provides the necessary command-line arguments.
101
+
102
+ * `inkscape_exe`: path to inkscape.exe
103
+ * `svg`: path to svg file
104
+ * `png`: optional path to png output (if not given, png name will be inferred from `svg`: `'name.svg'` becomes `'name.png'`)
105
+ * `return`: png filename
106
+ * `effects`: creates png file at `png` (or infers png path and filename from `svg`)
107
+
108
+ ### write_png
109
+
110
+ inkscape_exe: str,
111
+ png: str,
112
+ xml: etree.Element,
113
+ stylesheet: Optional[str] = None
114
+ -> str
115
+
116
+ Create a png without writing an initial svg to your filesystem. This is not faster (it may be slightly slower), but it may be important when writing many images (animation frames) to your filesystem.
117
+
118
+ * `inkscape_exe`: path to inkscape.exe
119
+ * `png`: path to output file (include extension .png)
120
+ * `param xml`: root node of your svg geometry (created by `new_svg_root`)
121
+ * `stylesheet`: optional path to a css stylesheet
122
+ * `returns`: for convenience, returns png filename (`png`)
123
+ * `effects`: creates png file at `png`
124
+
125
+ ## A few helpers:
126
+
127
+ from svg_ultralight.constructors import new_element, new_sub_element
128
+
129
+ I do want to keep this ultralight and avoid creating some pseudo scripting language between Python and lxml, but here are two very simple, very optional functions to save your having to `str()` every argument to `etree.Element`.
130
+
131
+ ### constructors.new_element
132
+
133
+ tag: str
134
+ **params: Union[str, float]
135
+ -> etree.Element
136
+
137
+ Python allows underscores in variable names; xml uses dashes.
138
+
139
+ Python understands numbers; xml wants strings.
140
+
141
+ This is a convenience function to swap `"_"` for `"-"` and `10.2` for `"10.2"` before creating an xml element.
142
+
143
+ Translates numbers to strings
144
+
145
+ >>> elem = new_element('line', x1=0, y1=0, x2=5, y2=5)
146
+ >>> etree.tostring(elem)
147
+ b'<line x1="0" y1="0" x2="5" y2="5"/>'
148
+
149
+ Translates underscores to hyphens
150
+
151
+ >>> elem = new_element('line', stroke_width=1)
152
+ >>> etree.tostring(elem)
153
+ b'<line stroke-width="1"/>'
154
+
155
+ Removes trailing underscores. You'll almost certainly want to use reserved names like ``class`` as svg parameters. This
156
+ can be done by passing the name with a trailing underscore.
157
+
158
+ >>> elem = new_element('line', class_='thick_line')
159
+ >>> etree.tostring(elem)
160
+ b'<line class="thick_line"/>'
161
+
162
+ Special handling for a 'text' argument. Places value between element tags.
163
+
164
+ >>> elem = new_element('text', text='please star my project')
165
+ >>> etree.tostring(elem)
166
+ b'<text>please star my project</text>'
167
+
168
+ ### constructors.new_sub_element
169
+
170
+ parent: etree.Element
171
+ tag: str
172
+ **params: Union[str, float]
173
+ -> etree.Element
174
+
175
+ As above, but creates a subelement.
176
+
177
+ >>> parent = etree.Element('g')
178
+ >>> _ = new_sub_element('rect')
179
+ >>> etree.tostring(parent)
180
+ b'<g><rect/></g>'
181
+
182
+ ### update_element
183
+
184
+ Another way to add params through the new_element name / float translator. Again unnecessary, but potentially helpful. Easily understood from the code or docstrings.
185
+
186
+ ## Extras:
187
+
188
+ ### query.map_elems_to_bounding_boxes
189
+
190
+ Python cannot parse an svg file. Python can *create* an svg file, and Inkscape can parse (and inspect) it. Inkscape has a command-line interface capable of reading an svg file and returning some limited information. This is the only way I know for a Python program to:
191
+
192
+ 1. create an svg file (optionally without writing to filesystem)
193
+ 2. query the svg file for bounding-box information
194
+ 3. create an adjusted svg file.
195
+
196
+ This would be necessary for, e.g., algorithmically fitting text in a box.
197
+
198
+ from svg_ultralight.queries import map_elems_to_bounding_boxes
199
+
200
+ You can get a tiny bit more sophisticated with Inkscape bounding-box queries, but not much. This will give you pretty much all you can get out of it.
201
+
202
+ ### animate.write_gif
203
+
204
+ Create an animated gif from a sequence of png filenames. This is a Pillow one-liner, but it's convenient for me to have it, so it might be convenient for you. Requires pillow, which is not a project dependency.
205
+
206
+ from svg_ultralight.animate import write_gif
207
+
208
+ [Full Documentation and Tutorial](https://shayallenhill.com/svg-with-css-in-python/)