foundrytools-cli 2.0.4__tar.gz → 2.1.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.
- {foundrytools_cli-2.0.4 → foundrytools_cli-2.1.0}/PKG-INFO +9 -9
- {foundrytools_cli-2.0.4 → foundrytools_cli-2.1.0}/README.md +2 -2
- {foundrytools_cli-2.0.4 → foundrytools_cli-2.1.0}/pyproject.toml +18 -30
- foundrytools_cli-2.1.0/src/foundrytools_cli/__init__.py +3 -0
- {foundrytools_cli-2.0.4 → foundrytools_cli-2.1.0}/src/foundrytools_cli/commands/cff.py +2 -1
- {foundrytools_cli-2.0.4 → foundrytools_cli-2.1.0}/src/foundrytools_cli/commands/converter/cli.py +8 -8
- {foundrytools_cli-2.0.4 → foundrytools_cli-2.1.0}/src/foundrytools_cli/commands/converter/ttf_to_otf.py +5 -6
- {foundrytools_cli-2.0.4 → foundrytools_cli-2.1.0}/src/foundrytools_cli/commands/fix/cli.py +33 -0
- {foundrytools_cli-2.0.4 → foundrytools_cli-2.1.0}/src/foundrytools_cli/commands/font.py +3 -3
- {foundrytools_cli-2.0.4 → foundrytools_cli-2.1.0}/src/foundrytools_cli/commands/hhea.py +3 -1
- {foundrytools_cli-2.0.4 → foundrytools_cli-2.1.0}/src/foundrytools_cli/commands/name.py +10 -10
- {foundrytools_cli-2.0.4 → foundrytools_cli-2.1.0}/src/foundrytools_cli/commands/os_2.py +4 -4
- {foundrytools_cli-2.0.4 → foundrytools_cli-2.1.0}/src/foundrytools_cli/commands/otf.py +14 -6
- {foundrytools_cli-2.0.4 → foundrytools_cli-2.1.0}/src/foundrytools_cli/commands/post.py +5 -5
- {foundrytools_cli-2.0.4 → foundrytools_cli-2.1.0}/src/foundrytools_cli/commands/print/cli.py +1 -2
- {foundrytools_cli-2.0.4 → foundrytools_cli-2.1.0}/src/foundrytools_cli/commands/print/font_names.py +4 -5
- {foundrytools_cli-2.0.4 → foundrytools_cli-2.1.0}/src/foundrytools_cli/commands/utils/cli.py +4 -2
- {foundrytools_cli-2.0.4 → foundrytools_cli-2.1.0}/src/foundrytools_cli/commands/utils/font_renamer.py +62 -0
- {foundrytools_cli-2.0.4 → foundrytools_cli-2.1.0}/src/foundrytools_cli/utils/__init__.py +10 -11
- {foundrytools_cli-2.0.4 → foundrytools_cli-2.1.0}/src/foundrytools_cli/utils/task_runner.py +5 -4
- {foundrytools_cli-2.0.4 → foundrytools_cli-2.1.0}/src/foundrytools_cli/utils/timer.py +5 -4
- foundrytools_cli-2.0.4/src/foundrytools_cli/__init__.py +0 -3
- {foundrytools_cli-2.0.4 → foundrytools_cli-2.1.0}/src/foundrytools_cli/__main__.py +0 -0
- {foundrytools_cli-2.0.4 → foundrytools_cli-2.1.0}/src/foundrytools_cli/commands/__init__.py +0 -0
- {foundrytools_cli-2.0.4 → foundrytools_cli-2.1.0}/src/foundrytools_cli/commands/cmap.py +0 -0
- {foundrytools_cli-2.0.4 → foundrytools_cli-2.1.0}/src/foundrytools_cli/commands/converter/__init__.py +0 -0
- {foundrytools_cli-2.0.4 → foundrytools_cli-2.1.0}/src/foundrytools_cli/commands/fix/__init__.py +0 -0
- {foundrytools_cli-2.0.4 → foundrytools_cli-2.1.0}/src/foundrytools_cli/commands/fix/legacy_accents.py +0 -0
- {foundrytools_cli-2.0.4 → foundrytools_cli-2.1.0}/src/foundrytools_cli/commands/fix/vertical_metrics.py +0 -0
- {foundrytools_cli-2.0.4 → foundrytools_cli-2.1.0}/src/foundrytools_cli/commands/gsub.py +0 -0
- {foundrytools_cli-2.0.4 → foundrytools_cli-2.1.0}/src/foundrytools_cli/commands/print/__init__.py +0 -0
- {foundrytools_cli-2.0.4 → foundrytools_cli-2.1.0}/src/foundrytools_cli/commands/print/font_info.py +0 -0
- {foundrytools_cli-2.0.4 → foundrytools_cli-2.1.0}/src/foundrytools_cli/commands/print/vf_instances.py +0 -0
- {foundrytools_cli-2.0.4 → foundrytools_cli-2.1.0}/src/foundrytools_cli/commands/ttf.py +0 -0
- {foundrytools_cli-2.0.4 → foundrytools_cli-2.1.0}/src/foundrytools_cli/commands/utils/__init__.py +0 -0
- {foundrytools_cli-2.0.4 → foundrytools_cli-2.1.0}/src/foundrytools_cli/commands/utils/font_organizer.py +0 -0
- {foundrytools_cli-2.0.4 → foundrytools_cli-2.1.0}/src/foundrytools_cli/commands/utils/sync_timestamps.py +0 -0
- {foundrytools_cli-2.0.4 → foundrytools_cli-2.1.0}/src/foundrytools_cli/utils/logger.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: foundrytools-cli
|
|
3
|
-
Version: 2.0
|
|
3
|
+
Version: 2.1.0
|
|
4
4
|
Summary: A set of command line tools to inspect, manipulate and convert font files
|
|
5
5
|
Author: Cesare Gilento
|
|
6
6
|
Author-email: Cesare Gilento <ftcli@proton.me>
|
|
@@ -11,22 +11,22 @@ Classifier: Intended Audience :: End Users/Desktop
|
|
|
11
11
|
Classifier: Natural Language :: English
|
|
12
12
|
Classifier: Operating System :: OS Independent
|
|
13
13
|
Classifier: Programming Language :: Python :: 3
|
|
14
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
15
14
|
Classifier: Programming Language :: Python :: 3.10
|
|
16
15
|
Classifier: Programming Language :: Python :: 3.11
|
|
17
16
|
Classifier: Programming Language :: Python :: 3.12
|
|
18
17
|
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
19
19
|
Classifier: License :: OSI Approved :: MIT License
|
|
20
20
|
Classifier: Topic :: Text Processing :: Fonts
|
|
21
|
-
Requires-Dist: afdko>=4.0.
|
|
22
|
-
Requires-Dist: click>=8.1
|
|
23
|
-
Requires-Dist: foundrytools>=0.1.
|
|
21
|
+
Requires-Dist: afdko>=4.0.3
|
|
22
|
+
Requires-Dist: click>=8.3.1
|
|
23
|
+
Requires-Dist: foundrytools>=0.1.6
|
|
24
24
|
Requires-Dist: loguru>=0.7.3
|
|
25
25
|
Requires-Dist: pathvalidate>=3.3.1
|
|
26
|
-
Requires-Dist: rich>=14.
|
|
26
|
+
Requires-Dist: rich>=14.3.0
|
|
27
27
|
Requires-Dist: ufolib2>=0.18.1
|
|
28
28
|
Requires-Dist: win32-setctime>=1.2.0 ; sys_platform >= 'win32'
|
|
29
|
-
Requires-Python: >=3.
|
|
29
|
+
Requires-Python: >=3.10
|
|
30
30
|
Project-URL: Homepage, https://github.com/ftCLI/FoundryTools-CLI
|
|
31
31
|
Description-Content-Type: text/markdown
|
|
32
32
|
|
|
@@ -54,7 +54,7 @@ rendered by [rich](https://github.com/Textualize/rich).
|
|
|
54
54
|
|
|
55
55
|
## Installation
|
|
56
56
|
|
|
57
|
-
FoundryTools-CLI requires Python 3.
|
|
57
|
+
FoundryTools-CLI requires Python 3.10 or later.
|
|
58
58
|
|
|
59
59
|
**IMPORTANT**: If you have Python 2.x installed in your system, you may have to use `python3`
|
|
60
60
|
(instead of `python`) in the commands below.
|
|
@@ -96,7 +96,7 @@ python -m pip install -e .
|
|
|
96
96
|
|
|
97
97
|
FoundryTools-CLI is a Terminal app where commands are logically organized into subcommands.
|
|
98
98
|
|
|
99
|
-
Please refer to the [user documentation](https://foundrytools-cli.readthedocs.io/).
|
|
99
|
+
Please refer to the [user documentation](https://foundrytools-cli.readthedocs.io/en/stable/).
|
|
100
100
|
|
|
101
101
|
## License
|
|
102
102
|
|
|
@@ -22,7 +22,7 @@ rendered by [rich](https://github.com/Textualize/rich).
|
|
|
22
22
|
|
|
23
23
|
## Installation
|
|
24
24
|
|
|
25
|
-
FoundryTools-CLI requires Python 3.
|
|
25
|
+
FoundryTools-CLI requires Python 3.10 or later.
|
|
26
26
|
|
|
27
27
|
**IMPORTANT**: If you have Python 2.x installed in your system, you may have to use `python3`
|
|
28
28
|
(instead of `python`) in the commands below.
|
|
@@ -64,7 +64,7 @@ python -m pip install -e .
|
|
|
64
64
|
|
|
65
65
|
FoundryTools-CLI is a Terminal app where commands are logically organized into subcommands.
|
|
66
66
|
|
|
67
|
-
Please refer to the [user documentation](https://foundrytools-cli.readthedocs.io/).
|
|
67
|
+
Please refer to the [user documentation](https://foundrytools-cli.readthedocs.io/en/stable/).
|
|
68
68
|
|
|
69
69
|
## License
|
|
70
70
|
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
[build-system]
|
|
2
|
-
requires = ["uv_build>=0.
|
|
2
|
+
requires = ["uv_build>=0.9.17"]
|
|
3
3
|
build-backend = "uv_build"
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "foundrytools-cli"
|
|
7
|
-
version = "2.0
|
|
7
|
+
version = "2.1.0"
|
|
8
8
|
description = "A set of command line tools to inspect, manipulate and convert font files"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "MIT"
|
|
11
|
-
requires-python = ">=3.
|
|
11
|
+
requires-python = ">=3.10"
|
|
12
12
|
authors = [
|
|
13
13
|
{ name = "Cesare Gilento", email = "ftcli@proton.me" },
|
|
14
14
|
]
|
|
@@ -20,36 +20,36 @@ classifiers = [
|
|
|
20
20
|
"Natural Language :: English",
|
|
21
21
|
"Operating System :: OS Independent",
|
|
22
22
|
"Programming Language :: Python :: 3",
|
|
23
|
-
"Programming Language :: Python :: 3.9",
|
|
24
23
|
"Programming Language :: Python :: 3.10",
|
|
25
24
|
"Programming Language :: Python :: 3.11",
|
|
26
25
|
"Programming Language :: Python :: 3.12",
|
|
27
26
|
"Programming Language :: Python :: 3.13",
|
|
27
|
+
"Programming Language :: Python :: 3.14",
|
|
28
28
|
"License :: OSI Approved :: MIT License",
|
|
29
29
|
"Topic :: Text Processing :: Fonts",
|
|
30
30
|
]
|
|
31
31
|
|
|
32
32
|
dependencies = [
|
|
33
|
-
"afdko>=4.0.
|
|
34
|
-
"click>=8.1
|
|
35
|
-
"foundrytools>=0.1.
|
|
33
|
+
"afdko>=4.0.3",
|
|
34
|
+
"click>=8.3.1",
|
|
35
|
+
"foundrytools>=0.1.6",
|
|
36
36
|
"loguru>=0.7.3",
|
|
37
37
|
"pathvalidate>=3.3.1",
|
|
38
|
-
"rich>=14.
|
|
38
|
+
"rich>=14.3.0",
|
|
39
39
|
"ufolib2>=0.18.1",
|
|
40
40
|
"win32-setctime>=1.2.0; sys_platform >= 'win32'",
|
|
41
41
|
]
|
|
42
42
|
|
|
43
|
-
[
|
|
43
|
+
[dependency-groups]
|
|
44
44
|
dev = [
|
|
45
|
-
"bump-my-version>=1.2.
|
|
46
|
-
"mypy>=1.
|
|
47
|
-
"pre-commit>=4.
|
|
48
|
-
"pylint>=
|
|
45
|
+
"bump-my-version>=1.2.6",
|
|
46
|
+
"mypy>=1.19.1",
|
|
47
|
+
"pre-commit>=4.5.1",
|
|
48
|
+
"pylint>=4.0.4",
|
|
49
49
|
]
|
|
50
50
|
docs = [
|
|
51
|
-
"sphinx-click>=6.
|
|
52
|
-
"sphinx-rtd-theme>=3.0
|
|
51
|
+
"sphinx-click>=6.2.0",
|
|
52
|
+
"sphinx-rtd-theme>=3.1.0",
|
|
53
53
|
]
|
|
54
54
|
|
|
55
55
|
[project.scripts]
|
|
@@ -58,22 +58,10 @@ ftcli = "foundrytools_cli.__main__:cli"
|
|
|
58
58
|
[project.urls]
|
|
59
59
|
Homepage = "https://github.com/ftCLI/FoundryTools-CLI"
|
|
60
60
|
|
|
61
|
-
[tool.hatch.version]
|
|
62
|
-
path = "src/foundrytools_cli/__init__.py"
|
|
63
|
-
pattern = 'VERSION = __version__ = "(?P<version>[^"]+)"'
|
|
64
|
-
|
|
65
|
-
[tool.hatch.build.targets.sdist]
|
|
66
|
-
include = [
|
|
67
|
-
"/src",
|
|
68
|
-
]
|
|
69
|
-
exclude = [
|
|
70
|
-
"/.gitignore",
|
|
71
|
-
]
|
|
72
|
-
|
|
73
61
|
[tool.bumpversion]
|
|
74
|
-
current_version = "2.0
|
|
75
|
-
commit =
|
|
76
|
-
tag =
|
|
62
|
+
current_version = "2.1.0"
|
|
63
|
+
commit = false
|
|
64
|
+
tag = false
|
|
77
65
|
|
|
78
66
|
[[tool.bumpversion.files]]
|
|
79
67
|
filename = "src/foundrytools_cli/__init__.py"
|
{foundrytools_cli-2.0.4 → foundrytools_cli-2.1.0}/src/foundrytools_cli/commands/converter/cli.py
RENAMED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from pathlib import Path
|
|
2
|
-
from typing import Any, Literal
|
|
2
|
+
from typing import Any, Literal
|
|
3
3
|
|
|
4
4
|
import click
|
|
5
5
|
from fontTools.misc.cliTools import makeOutputFileName
|
|
@@ -74,8 +74,8 @@ def otf_to_ttf(input_path: Path, **options: dict[str, Any]) -> None:
|
|
|
74
74
|
def task(
|
|
75
75
|
font: Font,
|
|
76
76
|
tolerance: float = 1.0,
|
|
77
|
-
target_upm:
|
|
78
|
-
output_dir:
|
|
77
|
+
target_upm: int | None = None,
|
|
78
|
+
output_dir: Path | None = None,
|
|
79
79
|
overwrite: bool = True,
|
|
80
80
|
) -> None:
|
|
81
81
|
flavor = font.ttfont.flavor
|
|
@@ -142,7 +142,7 @@ def otf_to_ttf(input_path: Path, **options: dict[str, Any]) -> None:
|
|
|
142
142
|
""",
|
|
143
143
|
)
|
|
144
144
|
@click.option(
|
|
145
|
-
"-cc
|
|
145
|
+
"-cc/-no-cc",
|
|
146
146
|
"--correct-contours/--no-correct-contours",
|
|
147
147
|
is_flag=True,
|
|
148
148
|
default=True,
|
|
@@ -201,7 +201,7 @@ def ttf_to_otf(input_path: Path, **options: dict[str, Any]) -> None:
|
|
|
201
201
|
)
|
|
202
202
|
def web_to_sfnt(
|
|
203
203
|
input_path: Path,
|
|
204
|
-
in_format:
|
|
204
|
+
in_format: Literal["woff", "woff2"] | None,
|
|
205
205
|
**options: dict[str, Any],
|
|
206
206
|
) -> None:
|
|
207
207
|
"""
|
|
@@ -236,8 +236,8 @@ def sfnt_to_web(input_path: Path, **options: dict[str, Any]) -> None:
|
|
|
236
236
|
|
|
237
237
|
def task(
|
|
238
238
|
font: Font,
|
|
239
|
-
output_dir:
|
|
240
|
-
out_format:
|
|
239
|
+
output_dir: Path | None = None,
|
|
240
|
+
out_format: Literal["woff", "woff2"] | None = None,
|
|
241
241
|
overwrite: bool = True,
|
|
242
242
|
reorder_tables: bool = False,
|
|
243
243
|
) -> None:
|
|
@@ -302,7 +302,7 @@ def variable_to_static(input_path: Path, **options: dict[str, Any]) -> None:
|
|
|
302
302
|
var_font: Font,
|
|
303
303
|
select_instance: bool = False,
|
|
304
304
|
overlap: int = 1,
|
|
305
|
-
output_dir:
|
|
305
|
+
output_dir: Path | None = None,
|
|
306
306
|
overwrite: bool = True,
|
|
307
307
|
) -> None:
|
|
308
308
|
if select_instance:
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
from pathlib import Path
|
|
2
|
-
from typing import Optional
|
|
3
2
|
|
|
4
3
|
from afdko.fdkutils import run_shell_command
|
|
5
4
|
from foundrytools import Font
|
|
@@ -10,7 +9,7 @@ from foundrytools.lib.qu2cu import quadratics_to_cubics_2
|
|
|
10
9
|
from foundrytools_cli.utils.logger import logger
|
|
11
10
|
|
|
12
11
|
|
|
13
|
-
def _build_out_file_name(font: Font, output_dir:
|
|
12
|
+
def _build_out_file_name(font: Font, output_dir: Path | None, overwrite: bool = True) -> Path:
|
|
14
13
|
"""
|
|
15
14
|
When converting a TrueType flavored web font to PS flavored web font, we need to add a suffix to
|
|
16
15
|
the output file name to avoid overwriting the input file. This function builds the output file
|
|
@@ -39,11 +38,11 @@ def _build_out_file_name(font: Font, output_dir: Optional[Path], overwrite: bool
|
|
|
39
38
|
def ttf2otf(
|
|
40
39
|
font: Font,
|
|
41
40
|
tolerance: float = 1.0,
|
|
42
|
-
target_upm:
|
|
41
|
+
target_upm: int | None = None,
|
|
43
42
|
correct_contours: bool = True,
|
|
44
43
|
check_outlines: bool = False,
|
|
45
44
|
subroutinize: bool = True,
|
|
46
|
-
output_dir:
|
|
45
|
+
output_dir: Path | None = None,
|
|
47
46
|
overwrite: bool = True,
|
|
48
47
|
) -> None:
|
|
49
48
|
"""
|
|
@@ -104,11 +103,11 @@ def ttf2otf(
|
|
|
104
103
|
|
|
105
104
|
def ttf2otf_with_tx(
|
|
106
105
|
font: Font,
|
|
107
|
-
target_upm:
|
|
106
|
+
target_upm: int | None = None,
|
|
108
107
|
correct_contours: bool = True,
|
|
109
108
|
check_outlines: bool = False,
|
|
110
109
|
subroutinize: bool = True,
|
|
111
|
-
output_dir:
|
|
110
|
+
output_dir: Path | None = None,
|
|
112
111
|
recalc_timestamp: bool = False,
|
|
113
112
|
overwrite: bool = True,
|
|
114
113
|
) -> None:
|
|
@@ -344,6 +344,39 @@ def fix_monospace(input_path: Path, **options: dict[str, Any]) -> None:
|
|
|
344
344
|
runner.run()
|
|
345
345
|
|
|
346
346
|
|
|
347
|
+
@cli.command("integer-ppem-if-hinted", cls=BaseCommand)
|
|
348
|
+
def fix_integer_ppm_if_hinted(input_path: Path, **options: dict[str, Any]) -> None:
|
|
349
|
+
"""
|
|
350
|
+
Sets the ``head.flags`` bit 3 to force integer ppem for hinted fonts.
|
|
351
|
+
|
|
352
|
+
fontbakery check id: com.google.fonts/check/integer_ppem_if_hinted
|
|
353
|
+
|
|
354
|
+
Rationale:
|
|
355
|
+
|
|
356
|
+
Hinted fonts must have head table flag bit 3 set.
|
|
357
|
+
|
|
358
|
+
Per https://docs.microsoft.com/en-us/typography/opentype/spec/head, bit 3 of Head::flags decides
|
|
359
|
+
whether PPEM should be rounded. This bit should always be set for hinted fonts.
|
|
360
|
+
|
|
361
|
+
Note:
|
|
362
|
+
Bit 3 = Force ppem to integer values for all internal scaler math;
|
|
363
|
+
|
|
364
|
+
Fixing procedure:
|
|
365
|
+
|
|
366
|
+
* Check if the font is hinted by looking for the presence of the ``fpgm`` table.
|
|
367
|
+
* Set the ``head.flags`` bit 3 to force integer ppem for hinted fonts.
|
|
368
|
+
"""
|
|
369
|
+
|
|
370
|
+
def task(font: Font) -> bool:
|
|
371
|
+
if font.ttfont.get("fpgm"):
|
|
372
|
+
font.t_head.set_bit("flags", 3, True)
|
|
373
|
+
return font.t_head.is_modified
|
|
374
|
+
|
|
375
|
+
runner = TaskRunner(input_path=input_path, task=task, **options)
|
|
376
|
+
runner.filter.filter_out_ps = True
|
|
377
|
+
runner.run()
|
|
378
|
+
|
|
379
|
+
|
|
347
380
|
@cli.command("transformed-components", cls=BaseCommand)
|
|
348
381
|
def fix_transformed_components(input_path: Path, **options: dict[str, Any]) -> None:
|
|
349
382
|
"""
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from pathlib import Path
|
|
2
|
-
from typing import Any, Literal
|
|
2
|
+
from typing import Any, Literal
|
|
3
3
|
|
|
4
4
|
import click
|
|
5
5
|
from foundrytools.core.font import Font
|
|
@@ -150,8 +150,8 @@ def remove_glyphs(input_path: Path, **options: dict[str, Any]) -> None:
|
|
|
150
150
|
|
|
151
151
|
def task(
|
|
152
152
|
font: Font,
|
|
153
|
-
glyph_names_to_remove:
|
|
154
|
-
glyph_ids_to_remove:
|
|
153
|
+
glyph_names_to_remove: set[str] | None,
|
|
154
|
+
glyph_ids_to_remove: set[int] | None,
|
|
155
155
|
) -> bool:
|
|
156
156
|
removed_glyphs = font.remove_glyphs(
|
|
157
157
|
glyph_names_to_remove=glyph_names_to_remove,
|
|
@@ -50,7 +50,9 @@ def recalc_caret_offset(input_path: Path, **options: dict[str, Any]) -> None:
|
|
|
50
50
|
source_file = font.file
|
|
51
51
|
else:
|
|
52
52
|
font.ttfont.flavor = None
|
|
53
|
-
|
|
53
|
+
temp_file = get_temp_file_path()
|
|
54
|
+
font.save(temp_file)
|
|
55
|
+
source_file = temp_file
|
|
54
56
|
font.save(source_file)
|
|
55
57
|
|
|
56
58
|
command_1 = ["tx", "-t1", source_file, temp_t1_file]
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from pathlib import Path
|
|
2
|
-
from typing import Any
|
|
2
|
+
from typing import Any
|
|
3
3
|
|
|
4
4
|
import click
|
|
5
5
|
from foundrytools import Font
|
|
@@ -55,8 +55,8 @@ def del_names(input_path: Path, **options: dict[str, Any]) -> None:
|
|
|
55
55
|
def task(
|
|
56
56
|
font: Font,
|
|
57
57
|
name_ids_to_process: tuple[int],
|
|
58
|
-
platform_id:
|
|
59
|
-
language_string:
|
|
58
|
+
platform_id: int | None = None,
|
|
59
|
+
language_string: str | None = None,
|
|
60
60
|
) -> bool:
|
|
61
61
|
font.t_name.remove_names(
|
|
62
62
|
name_ids=name_ids_to_process, platform_id=platform_id, language_string=language_string
|
|
@@ -171,8 +171,8 @@ def find_replace(input_path: Path, **options: dict[str, Any]) -> None:
|
|
|
171
171
|
font: Font,
|
|
172
172
|
old_string: str,
|
|
173
173
|
new_string: str,
|
|
174
|
-
name_ids_to_process:
|
|
175
|
-
name_ids_to_skip:
|
|
174
|
+
name_ids_to_process: tuple[int] | None = None,
|
|
175
|
+
name_ids_to_skip: tuple[int] | None = None,
|
|
176
176
|
) -> bool:
|
|
177
177
|
font.t_name.find_replace(
|
|
178
178
|
old_string=old_string,
|
|
@@ -227,7 +227,7 @@ def set_name(input_path: Path, **options: dict[str, Any]) -> None:
|
|
|
227
227
|
font: Font,
|
|
228
228
|
name_id: int,
|
|
229
229
|
name_string: str,
|
|
230
|
-
platform_id:
|
|
230
|
+
platform_id: int | None = None,
|
|
231
231
|
language_string: str = "en",
|
|
232
232
|
) -> bool:
|
|
233
233
|
font.t_name.set_name(
|
|
@@ -289,7 +289,7 @@ def build_unique_id(input_path: Path, **options: dict[str, Any]) -> None:
|
|
|
289
289
|
``Font Revision;Vendor ID;PostScript Name``
|
|
290
290
|
"""
|
|
291
291
|
|
|
292
|
-
def task(font: Font, platform_id:
|
|
292
|
+
def task(font: Font, platform_id: int | None = None, alternate: bool = False) -> bool:
|
|
293
293
|
font.t_name.build_unique_identifier(platform_id=platform_id, alternate=alternate)
|
|
294
294
|
return font.t_name.is_modified
|
|
295
295
|
|
|
@@ -313,7 +313,7 @@ def build_full_name(input_path: Path, **options: dict[str, Any]) -> None:
|
|
|
313
313
|
Builds the NameID 4 (Full Font Name).
|
|
314
314
|
"""
|
|
315
315
|
|
|
316
|
-
def task(font: Font, platform_id:
|
|
316
|
+
def task(font: Font, platform_id: int | None = None) -> bool:
|
|
317
317
|
font.t_name.build_full_font_name(platform_id=platform_id)
|
|
318
318
|
return font.t_name.is_modified
|
|
319
319
|
|
|
@@ -337,7 +337,7 @@ def build_version_string(input_path: Path, **options: dict[str, Any]) -> None:
|
|
|
337
337
|
Builds the NameID 5 (Version String).
|
|
338
338
|
"""
|
|
339
339
|
|
|
340
|
-
def task(font: Font, platform_id:
|
|
340
|
+
def task(font: Font, platform_id: int | None = None) -> bool:
|
|
341
341
|
font.t_name.build_version_string(platform_id=platform_id)
|
|
342
342
|
return font.t_name.is_modified
|
|
343
343
|
|
|
@@ -361,7 +361,7 @@ def build_postscript_name(input_path: Path, **options: dict[str, Any]) -> None:
|
|
|
361
361
|
Builds the NameID 6 (PostScript Name).
|
|
362
362
|
"""
|
|
363
363
|
|
|
364
|
-
def task(font: Font, platform_id:
|
|
364
|
+
def task(font: Font, platform_id: int | None = None) -> bool:
|
|
365
365
|
font.t_name.build_postscript_name(platform_id=platform_id)
|
|
366
366
|
return font.t_name.is_modified
|
|
367
367
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from pathlib import Path
|
|
2
|
-
from typing import Any
|
|
2
|
+
from typing import Any
|
|
3
3
|
|
|
4
4
|
import click
|
|
5
5
|
from fontTools.misc.roundTools import otRound
|
|
@@ -257,7 +257,7 @@ def set_attrs(input_path: Path, **options: dict[str, Any]) -> None:
|
|
|
257
257
|
"""
|
|
258
258
|
ensure_at_least_one_param(click.get_current_context())
|
|
259
259
|
|
|
260
|
-
def task(font: Font, **kwargs: dict[str,
|
|
260
|
+
def task(font: Font, **kwargs: dict[str, int | float | str | bool | None]) -> bool:
|
|
261
261
|
for attr, value in kwargs.items():
|
|
262
262
|
if value is not None:
|
|
263
263
|
try:
|
|
@@ -417,7 +417,7 @@ def set_fs_selection(input_path: Path, **options: dict[str, Any]) -> None:
|
|
|
417
417
|
"""
|
|
418
418
|
ensure_at_least_one_param(click.get_current_context())
|
|
419
419
|
|
|
420
|
-
def task(font: Font, **kwargs: dict[str,
|
|
420
|
+
def task(font: Font, **kwargs: dict[str, bool | None]) -> bool:
|
|
421
421
|
for attr, value in kwargs.items():
|
|
422
422
|
if value is not None:
|
|
423
423
|
if hasattr(font.flags, attr):
|
|
@@ -497,7 +497,7 @@ def set_fs_type(input_path: Path, **options: dict[str, Any]) -> None:
|
|
|
497
497
|
"""
|
|
498
498
|
ensure_at_least_one_param(click.get_current_context())
|
|
499
499
|
|
|
500
|
-
def task(font: Font, **kwargs: dict[str,
|
|
500
|
+
def task(font: Font, **kwargs: dict[str, bool | None]) -> bool:
|
|
501
501
|
for attr, value in kwargs.items():
|
|
502
502
|
if hasattr(font.t_os_2, attr) and value is not None:
|
|
503
503
|
setattr(font.t_os_2, attr, value)
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
from collections.abc import Callable
|
|
1
2
|
from pathlib import Path
|
|
2
|
-
from typing import Any,
|
|
3
|
+
from typing import Any, cast
|
|
3
4
|
|
|
4
5
|
import click
|
|
5
6
|
from foundrytools import Font
|
|
7
|
+
from foundrytools.app.otf_autohint import OTFAutohintError
|
|
6
8
|
from foundrytools.app.otf_autohint import run as otf_autohint
|
|
7
9
|
from foundrytools.app.otf_check_outlines import run as otf_check_outlines
|
|
8
10
|
from foundrytools.app.otf_dehint import run as otf_dehint
|
|
@@ -57,8 +59,8 @@ def subroutinize_flag() -> Callable:
|
|
|
57
59
|
""",
|
|
58
60
|
)
|
|
59
61
|
@click.option(
|
|
60
|
-
"-d",
|
|
61
|
-
"--decimal",
|
|
62
|
+
"-d/-no-d",
|
|
63
|
+
"--decimal/--no-decimal",
|
|
62
64
|
"roundCoords",
|
|
63
65
|
is_flag=True,
|
|
64
66
|
default=True,
|
|
@@ -94,7 +96,12 @@ def autohint(input_path: Path, **options: dict[str, Any]) -> None:
|
|
|
94
96
|
|
|
95
97
|
def task(font: Font, subroutinize: bool = True, **kwargs: dict[str, Any]) -> bool:
|
|
96
98
|
logger.info("Autohinting...")
|
|
97
|
-
|
|
99
|
+
|
|
100
|
+
try:
|
|
101
|
+
otf_autohint(font, **kwargs)
|
|
102
|
+
except OTFAutohintError as e:
|
|
103
|
+
logger.error(f"Autohinting failed: {e}")
|
|
104
|
+
return False
|
|
98
105
|
|
|
99
106
|
if subroutinize:
|
|
100
107
|
font.reload() # DO NOT REMOVE
|
|
@@ -269,8 +276,9 @@ def recalc_stems(input_path: Path, **options: dict[str, Any]) -> None:
|
|
|
269
276
|
temp_file = get_temp_file_path()
|
|
270
277
|
if flavor is not None:
|
|
271
278
|
font.ttfont.flavor = None
|
|
272
|
-
|
|
273
|
-
|
|
279
|
+
temp_file = get_temp_file_path()
|
|
280
|
+
font.save(temp_file)
|
|
281
|
+
input_file = temp_file
|
|
274
282
|
else:
|
|
275
283
|
input_file = font.file
|
|
276
284
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from pathlib import Path
|
|
2
|
-
from typing import Any
|
|
2
|
+
from typing import Any
|
|
3
3
|
|
|
4
4
|
import click
|
|
5
5
|
from foundrytools import Font
|
|
@@ -43,10 +43,10 @@ def cli(input_path: Path, **options: dict[str, Any]) -> None:
|
|
|
43
43
|
|
|
44
44
|
def task(
|
|
45
45
|
font: Font,
|
|
46
|
-
italic_angle:
|
|
47
|
-
underline_position:
|
|
48
|
-
underline_thickness:
|
|
49
|
-
fixed_pitch:
|
|
46
|
+
italic_angle: float | None = None,
|
|
47
|
+
underline_position: int | None = None,
|
|
48
|
+
underline_thickness: int | None = None,
|
|
49
|
+
fixed_pitch: bool | None = None,
|
|
50
50
|
) -> bool:
|
|
51
51
|
attrs = {
|
|
52
52
|
"italic_angle": italic_angle,
|
{foundrytools_cli-2.0.4 → foundrytools_cli-2.1.0}/src/foundrytools_cli/commands/print/cli.py
RENAMED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
from pathlib import Path
|
|
2
|
-
from typing import Optional
|
|
3
2
|
|
|
4
3
|
import click
|
|
5
4
|
from foundrytools import FontFinder
|
|
@@ -53,7 +52,7 @@ def font_info(input_path: Path) -> None:
|
|
|
53
52
|
Prints a minimal set of NameRecords, omitting the ones with nameID not in 1, 2, 3, 4, 5, 6, 16,
|
|
54
53
|
17, 18, 21, 22, 25""",
|
|
55
54
|
)
|
|
56
|
-
def font_names(input_path: Path, max_lines:
|
|
55
|
+
def font_names(input_path: Path, max_lines: int | None = None, minimal: bool = False) -> None:
|
|
57
56
|
"""
|
|
58
57
|
Prints the name table.
|
|
59
58
|
"""
|
{foundrytools_cli-2.0.4 → foundrytools_cli-2.1.0}/src/foundrytools_cli/commands/print/font_names.py
RENAMED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
from shutil import get_terminal_size
|
|
2
|
-
from typing import Optional
|
|
3
2
|
|
|
4
3
|
from fontTools.ttLib.tables._n_a_m_e import _MAC_LANGUAGES, _WINDOWS_LANGUAGES, NameRecord
|
|
5
4
|
from foundrytools import Font
|
|
@@ -42,7 +41,7 @@ JUSTIFY = 22
|
|
|
42
41
|
|
|
43
42
|
|
|
44
43
|
def _process_name_table(
|
|
45
|
-
font: Font, table: Table, terminal_width: int, max_lines:
|
|
44
|
+
font: Font, table: Table, terminal_width: int, max_lines: int | None, minimal: bool
|
|
46
45
|
) -> None:
|
|
47
46
|
name_table = NameTable(font.ttfont)
|
|
48
47
|
names = name_table.table.names
|
|
@@ -63,7 +62,7 @@ def _process_name_table(
|
|
|
63
62
|
|
|
64
63
|
|
|
65
64
|
def _add_name_row_to_table(
|
|
66
|
-
table: Table, name: NameRecord, terminal_width: int, max_lines:
|
|
65
|
+
table: Table, name: NameRecord, terminal_width: int, max_lines: int | None
|
|
67
66
|
) -> None:
|
|
68
67
|
row_string = _get_name_row(name)
|
|
69
68
|
row_string = wrap_string(
|
|
@@ -77,7 +76,7 @@ def _add_name_row_to_table(
|
|
|
77
76
|
|
|
78
77
|
|
|
79
78
|
def _process_cff_table(
|
|
80
|
-
font: Font, table: Table, terminal_width: int, max_lines:
|
|
79
|
+
font: Font, table: Table, terminal_width: int, max_lines: int | None, minimal: bool
|
|
81
80
|
) -> None:
|
|
82
81
|
if not font.is_ps:
|
|
83
82
|
return
|
|
@@ -133,7 +132,7 @@ def _get_name_row(name: NameRecord) -> str:
|
|
|
133
132
|
)
|
|
134
133
|
|
|
135
134
|
|
|
136
|
-
def main(font: Font, max_lines:
|
|
135
|
+
def main(font: Font, max_lines: int | None = None, minimal: bool = False) -> None:
|
|
137
136
|
"""
|
|
138
137
|
Prints the names of the font.
|
|
139
138
|
"""
|
{foundrytools_cli-2.0.4 → foundrytools_cli-2.1.0}/src/foundrytools_cli/commands/utils/cli.py
RENAMED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# pylint: disable=import-outside-toplevel
|
|
2
|
+
from collections.abc import Callable
|
|
2
3
|
from pathlib import Path
|
|
3
|
-
from typing import Any,
|
|
4
|
+
from typing import Any, cast
|
|
4
5
|
|
|
5
6
|
import click
|
|
6
7
|
|
|
@@ -38,7 +39,7 @@ cli = click.Group(help="Miscellaneous utilities.")
|
|
|
38
39
|
@click.option(
|
|
39
40
|
"-s",
|
|
40
41
|
"--source",
|
|
41
|
-
type=click.Choice(choices=["1", "2", "3", "4", "5"]),
|
|
42
|
+
type=click.Choice(choices=["1", "2", "3", "4", "5", "6"]),
|
|
42
43
|
default="1",
|
|
43
44
|
callback=choice_to_int_callback,
|
|
44
45
|
help="""
|
|
@@ -52,6 +53,7 @@ cli = click.Group(help="Miscellaneous utilities.")
|
|
|
52
53
|
3: Full Font Name
|
|
53
54
|
4: CFF fontNames (CFF fonts only)
|
|
54
55
|
5: CFF TopDict FullName (CFF fonts only)
|
|
56
|
+
6: Macintosh LWFN (LaserWriter Font Naming) using 5:3:3 rule
|
|
55
57
|
""",
|
|
56
58
|
)
|
|
57
59
|
@click.option(
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# ruff: noqa: C901
|
|
2
|
+
import re
|
|
1
3
|
from pathlib import Path
|
|
2
4
|
|
|
3
5
|
from foundrytools import Font
|
|
@@ -6,6 +8,59 @@ from pathvalidate import sanitize_filename
|
|
|
6
8
|
from foundrytools_cli.utils.logger import logger
|
|
7
9
|
|
|
8
10
|
|
|
11
|
+
def _apply_533_rule(postscript_name: str) -> str:
|
|
12
|
+
"""
|
|
13
|
+
Apply the Macintosh LaserWriter Font Naming (LWFN) 5:3:3 rule.
|
|
14
|
+
|
|
15
|
+
The rule divides the font name into "words" where each uppercase letter begins
|
|
16
|
+
a new word. The file name is derived by:
|
|
17
|
+
- Taking the initial uppercase letter and up to 4 lowercase letters in the first word
|
|
18
|
+
- Taking the initial uppercase letter and up to 2 lowercase letters for subsequent words
|
|
19
|
+
- Dropping hyphens between family and style portions
|
|
20
|
+
|
|
21
|
+
Args:
|
|
22
|
+
postscript_name: The PostScript name (e.g., "Helvetica-BoldOblique")
|
|
23
|
+
|
|
24
|
+
Returns:
|
|
25
|
+
The abbreviated filename following the 5:3:3 rule (e.g., "HelveBolObl")
|
|
26
|
+
|
|
27
|
+
Examples:
|
|
28
|
+
>>> _apply_533_rule("Helvetica-BoldOblique")
|
|
29
|
+
'HelveBolObl'
|
|
30
|
+
>>> _apply_533_rule("AGaramond-Bold")
|
|
31
|
+
'AGarBol'
|
|
32
|
+
>>> _apply_533_rule("Palatino-Roman")
|
|
33
|
+
'PalatRom'
|
|
34
|
+
>>> _apply_533_rule("Optima")
|
|
35
|
+
'Optim'
|
|
36
|
+
"""
|
|
37
|
+
# Remove hyphens to get a continuous string
|
|
38
|
+
name_without_hyphens = postscript_name.replace("-", "")
|
|
39
|
+
|
|
40
|
+
# Split into words where each uppercase letter begins a new word
|
|
41
|
+
# This regex finds: uppercase letter followed by any number of lowercase letters
|
|
42
|
+
words = re.findall(r"[A-Z][a-z]*", name_without_hyphens)
|
|
43
|
+
|
|
44
|
+
if not words:
|
|
45
|
+
# Fallback for invalid/unusual PostScript names without uppercase letters.
|
|
46
|
+
# PostScript font names should start with uppercase per Adobe spec, but we handle
|
|
47
|
+
# the edge case gracefully. The 11-char limit approximates typical LWFN length
|
|
48
|
+
# (5+3+3 for a three-word name like FamilyStyleVariant).
|
|
49
|
+
MAX_FALLBACK_LENGTH = 11
|
|
50
|
+
return name_without_hyphens[:MAX_FALLBACK_LENGTH]
|
|
51
|
+
|
|
52
|
+
result = []
|
|
53
|
+
for i, word in enumerate(words):
|
|
54
|
+
if i == 0:
|
|
55
|
+
# First word: take up to 5 characters (1 uppercase + 4 lowercase)
|
|
56
|
+
result.append(word[:5])
|
|
57
|
+
else:
|
|
58
|
+
# Subsequent words: take up to 3 characters (1 uppercase + 2 lowercase)
|
|
59
|
+
result.append(word[:3])
|
|
60
|
+
|
|
61
|
+
return "".join(result)
|
|
62
|
+
|
|
63
|
+
|
|
9
64
|
def _get_file_stem(font: Font, source: int = 1) -> str:
|
|
10
65
|
"""
|
|
11
66
|
Get the best file name for a font.
|
|
@@ -20,6 +75,7 @@ def _get_file_stem(font: Font, source: int = 1) -> str:
|
|
|
20
75
|
3: Full Font Name
|
|
21
76
|
4: CFF fontNames (CFF fonts only)
|
|
22
77
|
5: CFF TopDict FullName (CFF fonts only)
|
|
78
|
+
6: Macintosh LWFN (LaserWriter Font Naming) using 5:3:3 rule
|
|
23
79
|
|
|
24
80
|
Returns:
|
|
25
81
|
A sanitized file name for the font.
|
|
@@ -49,6 +105,12 @@ def _get_file_stem(font: Font, source: int = 1) -> str:
|
|
|
49
105
|
file_name = font.t_cff_.table.cff.fontNames[0]
|
|
50
106
|
elif source == 5 and font.is_ps:
|
|
51
107
|
file_name = font.t_cff_.top_dict.FullName
|
|
108
|
+
elif source == 6:
|
|
109
|
+
# Build name from family and subfamily for LWFN 5:3:3 rule
|
|
110
|
+
family_name = str(font.t_name.table.getBestFamilyName())
|
|
111
|
+
subfamily_name = str(font.t_name.table.getBestSubFamilyName())
|
|
112
|
+
font_name = f"{family_name}-{subfamily_name}".replace(" ", "").replace(".", "")
|
|
113
|
+
file_name = _apply_533_rule(font_name)
|
|
52
114
|
else:
|
|
53
115
|
raise ValueError("Invalid source value.")
|
|
54
116
|
return sanitize_filename(file_name, platform="auto")
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import os
|
|
2
|
+
from collections.abc import Callable
|
|
2
3
|
from pathlib import Path
|
|
3
4
|
from textwrap import TextWrapper
|
|
4
|
-
from typing import Any
|
|
5
|
+
from typing import Any
|
|
5
6
|
|
|
6
7
|
import click
|
|
7
8
|
|
|
@@ -41,7 +42,7 @@ class BaseCommand(click.Command):
|
|
|
41
42
|
""",
|
|
42
43
|
),
|
|
43
44
|
click.Option(
|
|
44
|
-
["-no-ow", "--no-overwrite"
|
|
45
|
+
["-ow/-no-ow", "--overwrite/--no-overwrite"],
|
|
45
46
|
is_flag=True,
|
|
46
47
|
default=True,
|
|
47
48
|
help="""
|
|
@@ -54,7 +55,7 @@ class BaseCommand(click.Command):
|
|
|
54
55
|
""",
|
|
55
56
|
),
|
|
56
57
|
click.Option(
|
|
57
|
-
["-no-rbb", "--no-recalc-bboxes"
|
|
58
|
+
["-rbb/-no-rbb", "--recalc-bboxes/--no-recalc-bboxes"],
|
|
58
59
|
is_flag=True,
|
|
59
60
|
default=True,
|
|
60
61
|
help="""
|
|
@@ -66,7 +67,7 @@ class BaseCommand(click.Command):
|
|
|
66
67
|
""",
|
|
67
68
|
),
|
|
68
69
|
click.Option(
|
|
69
|
-
["-rtb", "--reorder-tables"
|
|
70
|
+
["-rtb", "--reorder-tables"],
|
|
70
71
|
is_flag=True,
|
|
71
72
|
default=False,
|
|
72
73
|
help="""
|
|
@@ -112,8 +113,8 @@ def make_options(options: list[Callable]) -> Callable:
|
|
|
112
113
|
|
|
113
114
|
|
|
114
115
|
def choice_to_int_callback(
|
|
115
|
-
ctx: click.Context, _: click.Parameter, value:
|
|
116
|
-
) ->
|
|
116
|
+
ctx: click.Context, _: click.Parameter, value: str | tuple[str, ...]
|
|
117
|
+
) -> int | tuple[int, ...] | None:
|
|
117
118
|
"""
|
|
118
119
|
Callback for click options that accept a choice. Converts the choice to an integer or a tuple
|
|
119
120
|
of integers.
|
|
@@ -129,7 +130,7 @@ def choice_to_int_callback(
|
|
|
129
130
|
:param value: The value to convert
|
|
130
131
|
:type value: Union[str, tuple[str, ...]]
|
|
131
132
|
:return: The converted value
|
|
132
|
-
:rtype:
|
|
133
|
+
:rtype: int | tuple[int, ...] | None
|
|
133
134
|
"""
|
|
134
135
|
|
|
135
136
|
# we do not check if the values can be converted to integers here because the click.Choice
|
|
@@ -169,9 +170,7 @@ def tuple_to_set_callback(
|
|
|
169
170
|
return set(value)
|
|
170
171
|
|
|
171
172
|
|
|
172
|
-
def output_dir_callback(
|
|
173
|
-
ctx: click.Context, _: click.Parameter, value: Optional[Path]
|
|
174
|
-
) -> Optional[Path]:
|
|
173
|
+
def output_dir_callback(ctx: click.Context, _: click.Parameter, value: Path | None) -> Path | None:
|
|
175
174
|
"""
|
|
176
175
|
Callback for ``--output-dir option``.
|
|
177
176
|
|
|
@@ -227,7 +226,7 @@ def ensure_at_least_one_param(ctx: click.Context) -> None:
|
|
|
227
226
|
|
|
228
227
|
|
|
229
228
|
def wrap_string(
|
|
230
|
-
string: str, width: int, initial_indent: int, indent: int, max_lines:
|
|
229
|
+
string: str, width: int, initial_indent: int, indent: int, max_lines: int | None = None
|
|
231
230
|
) -> str:
|
|
232
231
|
"""
|
|
233
232
|
Wraps a string to a specified width.
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
from collections.abc import Callable
|
|
1
2
|
from dataclasses import dataclass
|
|
2
3
|
from pathlib import Path
|
|
3
|
-
from typing import Any,
|
|
4
|
+
from typing import Any, get_type_hints
|
|
4
5
|
|
|
5
6
|
from foundrytools import Font
|
|
6
7
|
from foundrytools.lib.font_finder import (
|
|
@@ -28,9 +29,9 @@ class SaveOptions:
|
|
|
28
29
|
A class that specifies how to save the font.
|
|
29
30
|
"""
|
|
30
31
|
|
|
31
|
-
reorder_tables:
|
|
32
|
+
reorder_tables: bool | None = True
|
|
32
33
|
suffix: str = ""
|
|
33
|
-
output_dir:
|
|
34
|
+
output_dir: Path | None = None
|
|
34
35
|
overwrite: bool = False
|
|
35
36
|
|
|
36
37
|
|
|
@@ -74,7 +75,7 @@ class TaskRunnerConfig: # pylint: disable=too-few-public-methods
|
|
|
74
75
|
|
|
75
76
|
@staticmethod
|
|
76
77
|
def _set_options(
|
|
77
|
-
options_group:
|
|
78
|
+
options_group: dict | FinderOptions | SaveOptions, options: dict[str, Any]
|
|
78
79
|
) -> None:
|
|
79
80
|
"""
|
|
80
81
|
Update attributes of an options_group with provided options if the attribute exists.
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
# https://realpython.com/python-timer/#the-python-timer-code
|
|
2
2
|
|
|
3
3
|
import time
|
|
4
|
+
from collections.abc import Callable
|
|
4
5
|
from contextlib import ContextDecorator
|
|
5
6
|
from dataclasses import dataclass, field
|
|
6
|
-
from typing import Any,
|
|
7
|
+
from typing import Any, ClassVar
|
|
7
8
|
|
|
8
9
|
|
|
9
10
|
class TimerError(Exception):
|
|
@@ -15,10 +16,10 @@ class Timer(ContextDecorator):
|
|
|
15
16
|
"""Time your code using a class, context manager, or decorator"""
|
|
16
17
|
|
|
17
18
|
timers: ClassVar[dict[str, float]] = {}
|
|
18
|
-
name:
|
|
19
|
+
name: str | None = None
|
|
19
20
|
text: str = "Elapsed time: {:0.4f} seconds"
|
|
20
|
-
logger:
|
|
21
|
-
_start_time:
|
|
21
|
+
logger: Callable[[str], None] | None = print
|
|
22
|
+
_start_time: float | None = field(default=None, init=False, repr=False)
|
|
22
23
|
|
|
23
24
|
def __post_init__(self) -> None:
|
|
24
25
|
"""Initialization: add timer to dict of timers"""
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{foundrytools_cli-2.0.4 → foundrytools_cli-2.1.0}/src/foundrytools_cli/commands/fix/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{foundrytools_cli-2.0.4 → foundrytools_cli-2.1.0}/src/foundrytools_cli/commands/print/__init__.py
RENAMED
|
File without changes
|
{foundrytools_cli-2.0.4 → foundrytools_cli-2.1.0}/src/foundrytools_cli/commands/print/font_info.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{foundrytools_cli-2.0.4 → foundrytools_cli-2.1.0}/src/foundrytools_cli/commands/utils/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|