python-fontbro 0.32.0__tar.gz → 0.33.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.
Files changed (87) hide show
  1. {python_fontbro-0.32.0/python_fontbro.egg-info → python_fontbro-0.33.0}/PKG-INFO +2 -1
  2. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/fontbro/metadata.py +1 -1
  3. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/fontbro/variable.py +6 -2
  4. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/fontbro/version.py +27 -7
  5. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/pyproject.toml +2 -1
  6. {python_fontbro-0.32.0 → python_fontbro-0.33.0/python_fontbro.egg-info}/PKG-INFO +2 -1
  7. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/tests/test_instantiation.py +9 -0
  8. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/tests/test_variable.py +41 -0
  9. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/tests/test_version.py +18 -0
  10. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/LICENSE.txt +0 -0
  11. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/MANIFEST.in +0 -0
  12. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/README.md +0 -0
  13. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/fontbro/__init__.py +0 -0
  14. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/fontbro/bitmap.py +0 -0
  15. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/fontbro/color.py +0 -0
  16. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/fontbro/data/family-classifications.json +0 -0
  17. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/fontbro/data/features.json +0 -0
  18. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/fontbro/data/unicode-blocks.json +0 -0
  19. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/fontbro/data/unicode-scripts.json +0 -0
  20. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/fontbro/embedding_permissions.py +0 -0
  21. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/fontbro/exceptions.py +0 -0
  22. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/fontbro/family_classification.py +0 -0
  23. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/fontbro/features.py +0 -0
  24. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/fontbro/files.py +0 -0
  25. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/fontbro/fingerprint.py +0 -0
  26. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/fontbro/flags.py +0 -0
  27. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/fontbro/font.py +0 -0
  28. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/fontbro/glyphs.py +0 -0
  29. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/fontbro/math.py +0 -0
  30. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/fontbro/metrics.py +0 -0
  31. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/fontbro/monospace.py +0 -0
  32. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/fontbro/names.py +0 -0
  33. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/fontbro/pixel.py +0 -0
  34. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/fontbro/py.typed +0 -0
  35. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/fontbro/render.py +0 -0
  36. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/fontbro/sanitize.py +0 -0
  37. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/fontbro/style_flags.py +0 -0
  38. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/fontbro/subset.py +0 -0
  39. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/fontbro/support.py +0 -0
  40. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/fontbro/tables.py +0 -0
  41. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/fontbro/unicode.py +0 -0
  42. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/fontbro/utils.py +0 -0
  43. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/python_fontbro.egg-info/SOURCES.txt +0 -0
  44. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/python_fontbro.egg-info/dependency_links.txt +0 -0
  45. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/python_fontbro.egg-info/requires.txt +0 -0
  46. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/python_fontbro.egg-info/top_level.txt +0 -0
  47. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/setup.cfg +0 -0
  48. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/setup.py +0 -0
  49. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/tests/test_bitmap.py +0 -0
  50. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/tests/test_characters.py +0 -0
  51. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/tests/test_clone.py +0 -0
  52. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/tests/test_close.py +0 -0
  53. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/tests/test_collection.py +0 -0
  54. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/tests/test_color.py +0 -0
  55. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/tests/test_context_manager.py +0 -0
  56. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/tests/test_embedding_permissions.py +0 -0
  57. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/tests/test_exceptions.py +0 -0
  58. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/tests/test_family_classification.py +0 -0
  59. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/tests/test_family_name.py +0 -0
  60. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/tests/test_features.py +0 -0
  61. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/tests/test_filename.py +0 -0
  62. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/tests/test_fingerprint.py +0 -0
  63. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/tests/test_format.py +0 -0
  64. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/tests/test_glyphs.py +0 -0
  65. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/tests/test_image.py +0 -0
  66. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/tests/test_init.py +0 -0
  67. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/tests/test_issues.py +0 -0
  68. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/tests/test_italic_angle.py +0 -0
  69. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/tests/test_monospace.py +0 -0
  70. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/tests/test_names.py +0 -0
  71. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/tests/test_pixel.py +0 -0
  72. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/tests/test_rename.py +0 -0
  73. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/tests/test_sanitize.py +0 -0
  74. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/tests/test_save.py +0 -0
  75. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/tests/test_str.py +0 -0
  76. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/tests/test_style_flags.py +0 -0
  77. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/tests/test_style_name.py +0 -0
  78. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/tests/test_subset.py +0 -0
  79. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/tests/test_support.py +0 -0
  80. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/tests/test_svg.py +0 -0
  81. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/tests/test_tables.py +0 -0
  82. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/tests/test_unicode.py +0 -0
  83. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/tests/test_unicode_blocks_and_scripts.py +0 -0
  84. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/tests/test_update_unicode_data.py +0 -0
  85. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/tests/test_vertical_metrics.py +0 -0
  86. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/tests/test_weight.py +0 -0
  87. {python_fontbro-0.32.0 → python_fontbro-0.33.0}/tests/test_width.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-fontbro
3
- Version: 0.32.0
3
+ Version: 0.33.0
4
4
  Summary: friendly font operations on top of fontTools.
5
5
  Author-email: Fabio Caccamo <fabio.caccamo@gmail.com>
6
6
  Maintainer-email: Fabio Caccamo <fabio.caccamo@gmail.com>
@@ -47,6 +47,7 @@ Classifier: Programming Language :: Python :: 3.11
47
47
  Classifier: Programming Language :: Python :: 3.12
48
48
  Classifier: Programming Language :: Python :: 3.13
49
49
  Classifier: Programming Language :: Python :: 3.14
50
+ Classifier: Programming Language :: Python :: 3.15
50
51
  Classifier: Programming Language :: Python :: Implementation :: PyPy
51
52
  Classifier: Topic :: Text Processing :: Fonts
52
53
  Classifier: Topic :: Multimedia :: Graphics
@@ -4,4 +4,4 @@ __description__ = "friendly font operations on top of fontTools."
4
4
  __email__ = "fabio.caccamo@gmail.com"
5
5
  __license__ = "MIT"
6
6
  __title__ = "python-fontbro"
7
- __version__ = "0.32.0"
7
+ __version__ = "0.33.0"
@@ -175,11 +175,15 @@ def get_variable_instance_by_style_name(
175
175
  style_name: str,
176
176
  ) -> dict[str, Any] | None:
177
177
  """
178
- Gets the variable instance of the given font by style name.
178
+ Gets the variable instance of the given font by style name,
179
+ the instances without a name record (style name None) are skipped.
179
180
  """
181
+ if not style_name:
182
+ return None
180
183
  instances = get_variable_instances(ttfont) or []
181
184
  for instance in instances:
182
- if slugify(instance["style_name"]) == slugify(style_name):
185
+ instance_style_name = instance["style_name"]
186
+ if instance_style_name and slugify(instance_style_name) == slugify(style_name):
183
187
  return instance
184
188
  return None
185
189
 
@@ -1,7 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import re
4
- from typing import Any
4
+ from typing import Any, overload
5
5
 
6
6
  from fontTools.misc.fixedTools import fixedToStr, floatToFixed
7
7
  from fontTools.ttLib import TTFont
@@ -74,23 +74,43 @@ def format_version(
74
74
  return f"{prefix}{major}.{minor}"
75
75
 
76
76
 
77
+ @overload
77
78
  def parse_version(
78
79
  value: str | None,
79
- ) -> float:
80
+ *,
81
+ default: float = ...,
82
+ ) -> float: ...
83
+
84
+
85
+ @overload
86
+ def parse_version(
87
+ value: str | None,
88
+ *,
89
+ default: None,
90
+ ) -> float | None: ...
91
+
92
+
93
+ def parse_version(
94
+ value: str | None,
95
+ *,
96
+ default: float | None = 0.0,
97
+ ) -> float | None:
80
98
  """
81
99
  Parses the version value from the given version name record value,
82
100
  eg. "Version 1.015;git-0a5106e0b" -> 1.015.
83
101
  The value is matched from the beginning of the string to avoid reading
84
102
  unrelated numbers (eg. a date or a tool version).
85
- Returns 0.0 if the value cannot be parsed, or if it holds a value that
86
- cannot be stored as a font version.
103
+ Returns the default (0.0) if the value cannot be parsed, or if it holds
104
+ a value that cannot be stored as a font version. A zero version
105
+ (eg. "Version 0.000") is parsed as 0.0: with default=None it can be told
106
+ apart from a value that cannot be parsed.
87
107
  """
88
108
  match = _VERSION_PATTERN.match((value or "").strip())
89
109
  if not match:
90
- return 0.0
110
+ return default
91
111
  version = float(f"{match[1]}.{match[2]}")
92
- if not 0 < version <= _VERSION_MAX_VALUE:
93
- return 0.0
112
+ if not 0 <= version <= _VERSION_MAX_VALUE:
113
+ return default
94
114
  return normalize_version(version)
95
115
 
96
116
 
@@ -1,5 +1,5 @@
1
1
  [build-system]
2
- requires = ["setuptools"]
2
+ requires = ["setuptools>=61"]
3
3
  build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
@@ -44,6 +44,7 @@ classifiers = [
44
44
  "Programming Language :: Python :: 3.12",
45
45
  "Programming Language :: Python :: 3.13",
46
46
  "Programming Language :: Python :: 3.14",
47
+ "Programming Language :: Python :: 3.15",
47
48
  "Programming Language :: Python :: Implementation :: PyPy",
48
49
  "Topic :: Text Processing :: Fonts",
49
50
  "Topic :: Multimedia :: Graphics",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-fontbro
3
- Version: 0.32.0
3
+ Version: 0.33.0
4
4
  Summary: friendly font operations on top of fontTools.
5
5
  Author-email: Fabio Caccamo <fabio.caccamo@gmail.com>
6
6
  Maintainer-email: Fabio Caccamo <fabio.caccamo@gmail.com>
@@ -47,6 +47,7 @@ Classifier: Programming Language :: Python :: 3.11
47
47
  Classifier: Programming Language :: Python :: 3.12
48
48
  Classifier: Programming Language :: Python :: 3.13
49
49
  Classifier: Programming Language :: Python :: 3.14
50
+ Classifier: Programming Language :: Python :: 3.15
50
51
  Classifier: Programming Language :: Python :: Implementation :: PyPy
51
52
  Classifier: Topic :: Text Processing :: Fonts
52
53
  Classifier: Topic :: Multimedia :: Graphics
@@ -85,6 +85,15 @@ class InstantiationTestCase(AbstractTestCase):
85
85
  self.assertNotIn("STAT", ttfont)
86
86
  self.assertEqual(font.get_name(Font.NAME_POSTSCRIPT_NAME), "Tourney-Black")
87
87
 
88
+ def test_to_static_with_style_name_and_unnamed_instance(self):
89
+ font = self._get_variable_font()
90
+ ttfont = font.get_ttfont()
91
+ thin_instance = ttfont["fvar"].instances[0]
92
+ ttfont["name"].removeNames(nameID=thin_instance.subfamilyNameID)
93
+ font.to_static(style_name="Black")
94
+ self.assertTrue(font.is_static())
95
+ self.assertEqual(font.get_weight()["value"], 900)
96
+
88
97
  def test_to_static_with_style_name_invalid(self):
89
98
  font = self._get_variable_font()
90
99
  with self.assertRaises(ValueError):
@@ -85,6 +85,47 @@ class VariableTestCase(AbstractTestCase):
85
85
  instances = font.get_variable_instances()
86
86
  self.assertEqual(instances, None)
87
87
 
88
+ def test_get_variable_instance_by_style_name(self):
89
+ font = self._get_font("/Roboto_Mono/RobotoMono-VariableFont_wght.ttf")
90
+ instance = font.get_variable_instance_by_style_name("Bold")
91
+ self.assertEqual(
92
+ instance,
93
+ {
94
+ "coordinates": {"wght": 700.0},
95
+ "style_name": "Bold",
96
+ },
97
+ )
98
+ instance = font.get_variable_instance_by_style_name("Black")
99
+ self.assertEqual(instance, None)
100
+
101
+ def test_get_variable_instance_by_style_name_with_unnamed_instance(self):
102
+ font = self._get_font("/Roboto_Mono/RobotoMono-VariableFont_wght.ttf")
103
+ ttfont = font.get_ttfont()
104
+ thin_instance = ttfont["fvar"].instances[0]
105
+ ttfont["name"].removeNames(nameID=thin_instance.subfamilyNameID)
106
+ self.assertEqual(font.get_variable_instances()[0]["style_name"], None)
107
+ instance = font.get_variable_instance_by_style_name("Bold")
108
+ self.assertEqual(
109
+ instance,
110
+ {
111
+ "coordinates": {"wght": 700.0},
112
+ "style_name": "Bold",
113
+ },
114
+ )
115
+ instance = font.get_variable_instance_by_style_name("Thin")
116
+ self.assertEqual(instance, None)
117
+
118
+ def test_get_variable_instance_by_style_name_without_style_name(self):
119
+ font = self._get_font("/Roboto_Mono/RobotoMono-VariableFont_wght.ttf")
120
+ ttfont = font.get_ttfont()
121
+ # a style name without ascii characters has an empty slug
122
+ thin_instance = ttfont["fvar"].instances[0]
123
+ ttfont["name"].setName("太字", thin_instance.subfamilyNameID, 3, 1, 0x409)
124
+ instance = font.get_variable_instance_by_style_name("")
125
+ self.assertEqual(instance, None)
126
+ instance = font.get_variable_instance_by_style_name(None)
127
+ self.assertEqual(instance, None)
128
+
88
129
  def test_get_variable_instance_closest_to_coordinates(self):
89
130
  font = self._get_font("/Roboto_Mono/RobotoMono-VariableFont_wght.ttf")
90
131
  closest_instance = font.get_variable_instance_closest_to_coordinates(
@@ -76,6 +76,24 @@ class VersionTestCase(AbstractTestCase):
76
76
  with self.subTest(f"Test with value: {value!r}", value=value):
77
77
  self.assertEqual(parse_version(value), expected_value)
78
78
 
79
+ def test_parse_version_with_default(self):
80
+ values = [
81
+ ("Version 1.015", 1.015),
82
+ # a zero version is a version (eg. a font in development)
83
+ ("Version 0.000", 0.0),
84
+ ("0.000", 0.0),
85
+ # invalid values
86
+ (None, None),
87
+ ("", None),
88
+ ("Regular", None),
89
+ ("1", None),
90
+ ("Version 32768.0", None),
91
+ ]
92
+ for value, expected_value in values:
93
+ with self.subTest(f"Test with value: {value!r}", value=value):
94
+ self.assertEqual(parse_version(value, default=None), expected_value)
95
+ self.assertEqual(parse_version("Regular", default=1.0), 1.0)
96
+
79
97
  def test_normalize_version(self):
80
98
  values = [
81
99
  (1.0149993896484375, 1.015),