weasyprint 66.0__py3-none-any.whl → 67.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. weasyprint/__init__.py +14 -7
  2. weasyprint/__main__.py +19 -10
  3. weasyprint/anchors.py +4 -4
  4. weasyprint/css/__init__.py +723 -66
  5. weasyprint/css/computed_values.py +64 -175
  6. weasyprint/css/counters.py +1 -1
  7. weasyprint/css/functions.py +206 -0
  8. weasyprint/css/html5_ua.css +1 -0
  9. weasyprint/css/html5_ua_form.css +1 -1
  10. weasyprint/css/media_queries.py +3 -1
  11. weasyprint/css/properties.py +6 -2
  12. weasyprint/css/{utils.py → tokens.py} +306 -397
  13. weasyprint/css/units.py +91 -0
  14. weasyprint/css/validation/__init__.py +1 -1
  15. weasyprint/css/validation/descriptors.py +47 -19
  16. weasyprint/css/validation/expanders.py +7 -8
  17. weasyprint/css/validation/properties.py +341 -357
  18. weasyprint/document.py +19 -10
  19. weasyprint/draw/__init__.py +6 -7
  20. weasyprint/draw/border.py +3 -5
  21. weasyprint/draw/color.py +1 -1
  22. weasyprint/draw/text.py +59 -39
  23. weasyprint/formatting_structure/boxes.py +21 -3
  24. weasyprint/formatting_structure/build.py +2 -4
  25. weasyprint/images.py +68 -47
  26. weasyprint/layout/__init__.py +27 -24
  27. weasyprint/layout/absolute.py +3 -5
  28. weasyprint/layout/background.py +7 -7
  29. weasyprint/layout/block.py +140 -128
  30. weasyprint/layout/column.py +18 -24
  31. weasyprint/layout/flex.py +13 -5
  32. weasyprint/layout/float.py +4 -6
  33. weasyprint/layout/grid.py +284 -90
  34. weasyprint/layout/inline.py +114 -60
  35. weasyprint/layout/page.py +23 -12
  36. weasyprint/layout/percent.py +14 -10
  37. weasyprint/layout/preferred.py +45 -30
  38. weasyprint/layout/replaced.py +9 -6
  39. weasyprint/layout/table.py +8 -5
  40. weasyprint/pdf/__init__.py +46 -13
  41. weasyprint/pdf/anchors.py +1 -2
  42. weasyprint/pdf/fonts.py +126 -69
  43. weasyprint/pdf/metadata.py +36 -4
  44. weasyprint/pdf/pdfa.py +19 -3
  45. weasyprint/pdf/pdfx.py +83 -0
  46. weasyprint/pdf/stream.py +18 -1
  47. weasyprint/pdf/tags.py +6 -4
  48. weasyprint/svg/__init__.py +37 -21
  49. weasyprint/svg/images.py +11 -3
  50. weasyprint/svg/text.py +11 -2
  51. weasyprint/svg/utils.py +6 -3
  52. weasyprint/text/constants.py +1 -1
  53. weasyprint/text/ffi.py +4 -3
  54. weasyprint/text/fonts.py +12 -4
  55. weasyprint/text/line_break.py +101 -17
  56. weasyprint/urls.py +21 -4
  57. {weasyprint-66.0.dist-info → weasyprint-67.0.dist-info}/METADATA +5 -6
  58. weasyprint-67.0.dist-info/RECORD +77 -0
  59. weasyprint-66.0.dist-info/RECORD +0 -74
  60. {weasyprint-66.0.dist-info → weasyprint-67.0.dist-info}/WHEEL +0 -0
  61. {weasyprint-66.0.dist-info → weasyprint-67.0.dist-info}/entry_points.txt +0 -0
  62. {weasyprint-66.0.dist-info → weasyprint-67.0.dist-info}/licenses/LICENSE +0 -0
weasyprint/__init__.py CHANGED
@@ -15,7 +15,7 @@ import cssselect2
15
15
  import tinycss2
16
16
  import tinyhtml5
17
17
 
18
- VERSION = __version__ = '66.0'
18
+ VERSION = __version__ = '67.0'
19
19
 
20
20
  #: Default values for command-line and Python API options. See
21
21
  #: :func:`__main__.main` to learn more about specific options for
@@ -198,7 +198,8 @@ class HTML:
198
198
  def _ph_stylesheets(self):
199
199
  return [HTML5_PH_STYLESHEET]
200
200
 
201
- def render(self, font_config=None, counter_style=None, **options):
201
+ def render(self, font_config=None, counter_style=None, color_profiles=None,
202
+ **options):
202
203
  """Lay out and paginate the document, but do not (yet) export it.
203
204
 
204
205
  This returns a :class:`document.Document` object which provides
@@ -222,10 +223,11 @@ class HTML:
222
223
  new_options = DEFAULT_OPTIONS.copy()
223
224
  new_options.update(options)
224
225
  options = new_options
225
- return Document._render(self, font_config, counter_style, options)
226
+ return Document._render(
227
+ self, font_config, counter_style, color_profiles, options)
226
228
 
227
229
  def write_pdf(self, target=None, zoom=1, finisher=None,
228
- font_config=None, counter_style=None, **options):
230
+ font_config=None, counter_style=None, color_profiles=None, **options):
229
231
  """Render the document to a PDF file.
230
232
 
231
233
  This is a shortcut for calling :meth:`render`, then
@@ -265,7 +267,7 @@ class HTML:
265
267
  new_options.update(options)
266
268
  options = new_options
267
269
  return (
268
- self.render(font_config, counter_style, **options)
270
+ self.render(font_config, counter_style, color_profiles, **options)
269
271
  .write_pdf(target, zoom, finisher, **options))
270
272
 
271
273
 
@@ -288,7 +290,8 @@ class CSS:
288
290
  string=None, encoding=None, base_url=None,
289
291
  url_fetcher=default_url_fetcher, _check_mime_type=False,
290
292
  media_type='print', font_config=None, counter_style=None,
291
- matcher=None, page_rules=None):
293
+ color_profiles=None, matcher=None, page_rules=None, layers=None,
294
+ layer=None):
292
295
  PROGRESS_LOGGER.info(
293
296
  'Step 2 - Fetching and parsing CSS - %s',
294
297
  filename or url or getattr(file_obj, 'name', 'CSS string'))
@@ -309,10 +312,13 @@ class CSS:
309
312
  self.base_url = base_url
310
313
  self.matcher = matcher or cssselect2.Matcher()
311
314
  self.page_rules = [] if page_rules is None else page_rules
315
+ self.layers = [] if layers is None else layers
312
316
  counter_style = {} if counter_style is None else counter_style
317
+ color_profiles = {} if color_profiles is None else color_profiles
313
318
  preprocess_stylesheet(
314
319
  media_type, base_url, stylesheet, url_fetcher, self.matcher,
315
- self.page_rules, font_config, counter_style)
320
+ self.page_rules, self.layers, font_config, counter_style, color_profiles,
321
+ layer=layer)
316
322
 
317
323
 
318
324
  class Attachment:
@@ -429,6 +435,7 @@ def _select_source(guess=None, filename=None, url=None, file_obj=None,
429
435
  assert string is not None
430
436
  yield 'string', string, base_url, None
431
437
 
438
+
432
439
  # Work around circular imports.
433
440
  from .css import preprocess_stylesheet # noqa: I001, E402
434
441
  from .html import ( # noqa: E402
weasyprint/__main__.py CHANGED
@@ -16,16 +16,18 @@ from .urls import default_url_fetcher
16
16
 
17
17
  class PrintInfo(argparse.Action):
18
18
  def __call__(*_, **__):
19
+ # TODO: ignore check at block-level when available.
20
+ # https://github.com/astral-sh/ruff/issues/3711
19
21
  uname = platform.uname()
20
- print('System:', uname.system)
21
- print('Machine:', uname.machine)
22
- print('Version:', uname.version)
23
- print('Release:', uname.release)
24
- print()
25
- print('WeasyPrint version:', __version__)
26
- print('Python version:', sys.version.split()[0])
27
- print('Pydyf version:', pydyf.__version__)
28
- print('Pango version:', pango.pango_version())
22
+ print('System:', uname.system) # noqa: T201
23
+ print('Machine:', uname.machine) # noqa: T201
24
+ print('Version:', uname.version) # noqa: T201
25
+ print('Release:', uname.release) # noqa: T201
26
+ print() # noqa: T201
27
+ print('WeasyPrint version:', __version__) # noqa: T201
28
+ print('Python version:', sys.version.split()[0]) # noqa: T201
29
+ print('Pydyf version:', pydyf.__version__) # noqa: T201
30
+ print('Pango version:', pango.pango_version()) # noqa: T201
29
31
  sys.exit()
30
32
 
31
33
 
@@ -138,7 +140,10 @@ PARSER.add_argument(
138
140
  help='print system information and exit')
139
141
  PARSER.add_argument(
140
142
  '-t', '--timeout', type=int,
141
- help='Set timeout in seconds for HTTP requests')
143
+ help='set timeout in seconds for HTTP requests')
144
+ PARSER.add_argument(
145
+ '--allowed-protocols', dest='allowed_protocols',
146
+ help='only authorize comma-separated list of protocols for fetching URLs')
142
147
  PARSER.set_defaults(**DEFAULT_OPTIONS)
143
148
 
144
149
 
@@ -169,6 +174,10 @@ def main(argv=None, stdout=None, stdin=None, HTML=HTML): # noqa: N803
169
174
  url_fetcher = default_url_fetcher
170
175
  if args.timeout is not None:
171
176
  url_fetcher = partial(default_url_fetcher, timeout=args.timeout)
177
+ if args.allowed_protocols is not None:
178
+ protocols = {
179
+ protocol.strip().lower() for protocol in args.allowed_protocols.split(',')}
180
+ url_fetcher = partial(url_fetcher, allowed_protocols=protocols)
172
181
 
173
182
  options = {
174
183
  key: value for key, value in vars(args).items() if key in DEFAULT_OPTIONS}
weasyprint/anchors.py CHANGED
@@ -43,8 +43,8 @@ def gather_anchors(box, anchors, links, bookmarks, forms, parent_matrix=None,
43
43
  border_width = box.border_width()
44
44
  border_height = box.border_height()
45
45
  origin_x, origin_y = box.style['transform_origin']
46
- offset_x = percentage(origin_x, border_width)
47
- offset_y = percentage(origin_y, border_height)
46
+ offset_x = percentage(origin_x, box.style, border_width)
47
+ offset_y = percentage(origin_y, box.style, border_height)
48
48
  origin_x = box.border_box_x() + offset_x
49
49
  origin_y = box.border_box_y() + offset_y
50
50
 
@@ -58,8 +58,8 @@ def gather_anchors(box, anchors, links, bookmarks, forms, parent_matrix=None,
58
58
  b = math.sin(args)
59
59
  c = -b
60
60
  elif name == 'translate':
61
- e = percentage(args[0], border_width)
62
- f = percentage(args[1], border_height)
61
+ e = percentage(args[0], box.style, border_width)
62
+ f = percentage(args[1], box.style, border_height)
63
63
  elif name == 'skew':
64
64
  b, c = math.tan(args[1]), math.tan(args[0])
65
65
  else: