foundrytools-cli 2.0.3__tar.gz → 2.0.5__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.3 → foundrytools_cli-2.0.5}/PKG-INFO +13 -13
- {foundrytools_cli-2.0.3 → foundrytools_cli-2.0.5}/README.md +2 -2
- {foundrytools_cli-2.0.3 → foundrytools_cli-2.0.5}/pyproject.toml +23 -23
- foundrytools_cli-2.0.5/src/foundrytools_cli/__init__.py +3 -0
- {foundrytools_cli-2.0.3 → foundrytools_cli-2.0.5}/src/foundrytools_cli/commands/cff.py +2 -1
- {foundrytools_cli-2.0.3 → foundrytools_cli-2.0.5}/src/foundrytools_cli/commands/converter/cli.py +7 -7
- {foundrytools_cli-2.0.3 → foundrytools_cli-2.0.5}/src/foundrytools_cli/commands/converter/ttf_to_otf.py +5 -6
- {foundrytools_cli-2.0.3 → foundrytools_cli-2.0.5}/src/foundrytools_cli/commands/fix/cli.py +33 -0
- {foundrytools_cli-2.0.3 → foundrytools_cli-2.0.5}/src/foundrytools_cli/commands/font.py +3 -3
- {foundrytools_cli-2.0.3 → foundrytools_cli-2.0.5}/src/foundrytools_cli/commands/name.py +10 -10
- {foundrytools_cli-2.0.3 → foundrytools_cli-2.0.5}/src/foundrytools_cli/commands/os_2.py +4 -4
- {foundrytools_cli-2.0.3 → foundrytools_cli-2.0.5}/src/foundrytools_cli/commands/otf.py +2 -1
- {foundrytools_cli-2.0.3 → foundrytools_cli-2.0.5}/src/foundrytools_cli/commands/post.py +5 -5
- {foundrytools_cli-2.0.3 → foundrytools_cli-2.0.5}/src/foundrytools_cli/commands/print/cli.py +1 -2
- {foundrytools_cli-2.0.3 → foundrytools_cli-2.0.5}/src/foundrytools_cli/commands/print/font_names.py +4 -5
- {foundrytools_cli-2.0.3 → foundrytools_cli-2.0.5}/src/foundrytools_cli/commands/utils/cli.py +2 -1
- {foundrytools_cli-2.0.3 → foundrytools_cli-2.0.5}/src/foundrytools_cli/utils/__init__.py +7 -8
- {foundrytools_cli-2.0.3 → foundrytools_cli-2.0.5}/src/foundrytools_cli/utils/task_runner.py +5 -4
- {foundrytools_cli-2.0.3 → foundrytools_cli-2.0.5}/src/foundrytools_cli/utils/timer.py +5 -4
- foundrytools_cli-2.0.3/.gitignore +0 -161
- foundrytools_cli-2.0.3/LICENSE +0 -21
- foundrytools_cli-2.0.3/src/foundrytools_cli/__init__.py +0 -3
- {foundrytools_cli-2.0.3 → foundrytools_cli-2.0.5}/src/foundrytools_cli/__main__.py +0 -0
- {foundrytools_cli-2.0.3 → foundrytools_cli-2.0.5}/src/foundrytools_cli/commands/__init__.py +0 -0
- {foundrytools_cli-2.0.3 → foundrytools_cli-2.0.5}/src/foundrytools_cli/commands/cmap.py +0 -0
- {foundrytools_cli-2.0.3 → foundrytools_cli-2.0.5}/src/foundrytools_cli/commands/converter/__init__.py +0 -0
- {foundrytools_cli-2.0.3 → foundrytools_cli-2.0.5}/src/foundrytools_cli/commands/fix/__init__.py +0 -0
- {foundrytools_cli-2.0.3 → foundrytools_cli-2.0.5}/src/foundrytools_cli/commands/fix/legacy_accents.py +0 -0
- {foundrytools_cli-2.0.3 → foundrytools_cli-2.0.5}/src/foundrytools_cli/commands/fix/vertical_metrics.py +0 -0
- {foundrytools_cli-2.0.3 → foundrytools_cli-2.0.5}/src/foundrytools_cli/commands/gsub.py +0 -0
- {foundrytools_cli-2.0.3 → foundrytools_cli-2.0.5}/src/foundrytools_cli/commands/hhea.py +0 -0
- {foundrytools_cli-2.0.3 → foundrytools_cli-2.0.5}/src/foundrytools_cli/commands/print/__init__.py +0 -0
- {foundrytools_cli-2.0.3 → foundrytools_cli-2.0.5}/src/foundrytools_cli/commands/print/font_info.py +0 -0
- {foundrytools_cli-2.0.3 → foundrytools_cli-2.0.5}/src/foundrytools_cli/commands/print/vf_instances.py +0 -0
- {foundrytools_cli-2.0.3 → foundrytools_cli-2.0.5}/src/foundrytools_cli/commands/ttf.py +0 -0
- {foundrytools_cli-2.0.3 → foundrytools_cli-2.0.5}/src/foundrytools_cli/commands/utils/__init__.py +0 -0
- {foundrytools_cli-2.0.3 → foundrytools_cli-2.0.5}/src/foundrytools_cli/commands/utils/font_organizer.py +0 -0
- {foundrytools_cli-2.0.3 → foundrytools_cli-2.0.5}/src/foundrytools_cli/commands/utils/font_renamer.py +0 -0
- {foundrytools_cli-2.0.3 → foundrytools_cli-2.0.5}/src/foundrytools_cli/commands/utils/sync_timestamps.py +0 -0
- {foundrytools_cli-2.0.3 → foundrytools_cli-2.0.5}/src/foundrytools_cli/utils/logger.py +0 -0
|
@@ -1,32 +1,32 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: foundrytools-cli
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.5
|
|
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>
|
|
7
7
|
License-Expression: MIT
|
|
8
|
-
License-File: LICENSE
|
|
9
8
|
Classifier: Development Status :: 5 - Production/Stable
|
|
10
9
|
Classifier: Intended Audience :: Developers
|
|
11
10
|
Classifier: Intended Audience :: End Users/Desktop
|
|
12
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
13
11
|
Classifier: Natural Language :: English
|
|
14
12
|
Classifier: Operating System :: OS Independent
|
|
15
13
|
Classifier: Programming Language :: Python :: 3
|
|
16
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
17
14
|
Classifier: Programming Language :: Python :: 3.10
|
|
18
15
|
Classifier: Programming Language :: Python :: 3.11
|
|
19
16
|
Classifier: Programming Language :: Python :: 3.12
|
|
20
17
|
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
21
19
|
Classifier: Topic :: Text Processing :: Fonts
|
|
22
|
-
Requires-
|
|
23
|
-
Requires-Dist:
|
|
24
|
-
Requires-Dist:
|
|
25
|
-
Requires-Dist: foundrytools>=0.1.4
|
|
20
|
+
Requires-Dist: afdko>=4.0.3
|
|
21
|
+
Requires-Dist: click>=8.3.1
|
|
22
|
+
Requires-Dist: foundrytools>=0.1.5
|
|
26
23
|
Requires-Dist: loguru>=0.7.3
|
|
27
24
|
Requires-Dist: pathvalidate>=3.3.1
|
|
28
|
-
Requires-Dist: rich>=14.
|
|
29
|
-
Requires-Dist:
|
|
25
|
+
Requires-Dist: rich>=14.2.0
|
|
26
|
+
Requires-Dist: ufolib2>=0.18.1
|
|
27
|
+
Requires-Dist: win32-setctime>=1.2.0 ; sys_platform >= 'win32'
|
|
28
|
+
Requires-Python: >=3.10
|
|
29
|
+
Project-URL: Homepage, https://github.com/ftCLI/FoundryTools-CLI
|
|
30
30
|
Description-Content-Type: text/markdown
|
|
31
31
|
|
|
32
32
|
# FoundryTools-CLI
|
|
@@ -53,7 +53,7 @@ rendered by [rich](https://github.com/Textualize/rich).
|
|
|
53
53
|
|
|
54
54
|
## Installation
|
|
55
55
|
|
|
56
|
-
FoundryTools-CLI requires Python 3.
|
|
56
|
+
FoundryTools-CLI requires Python 3.10 or later.
|
|
57
57
|
|
|
58
58
|
**IMPORTANT**: If you have Python 2.x installed in your system, you may have to use `python3`
|
|
59
59
|
(instead of `python`) in the commands below.
|
|
@@ -95,7 +95,7 @@ python -m pip install -e .
|
|
|
95
95
|
|
|
96
96
|
FoundryTools-CLI is a Terminal app where commands are logically organized into subcommands.
|
|
97
97
|
|
|
98
|
-
Please refer to the [user documentation](https://foundrytools-cli.readthedocs.io/).
|
|
98
|
+
Please refer to the [user documentation](https://foundrytools-cli.readthedocs.io/en/stable/).
|
|
99
99
|
|
|
100
100
|
## License
|
|
101
101
|
|
|
@@ -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 = ["
|
|
3
|
-
build-backend = "
|
|
2
|
+
requires = ["uv_build>=0.9.17"]
|
|
3
|
+
build-backend = "uv_build"
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "foundrytools-cli"
|
|
7
|
-
|
|
7
|
+
version = "2.0.5"
|
|
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,7 +20,6 @@ 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",
|
|
@@ -30,36 +29,37 @@ classifiers = [
|
|
|
30
29
|
]
|
|
31
30
|
|
|
32
31
|
dependencies = [
|
|
33
|
-
"afdko>=4.0.
|
|
34
|
-
"click>=8.1
|
|
35
|
-
"foundrytools>=0.1.
|
|
32
|
+
"afdko>=4.0.3",
|
|
33
|
+
"click>=8.3.1",
|
|
34
|
+
"foundrytools>=0.1.5",
|
|
36
35
|
"loguru>=0.7.3",
|
|
37
36
|
"pathvalidate>=3.3.1",
|
|
38
|
-
"rich>=14.
|
|
37
|
+
"rich>=14.2.0",
|
|
38
|
+
"ufolib2>=0.18.1",
|
|
39
39
|
"win32-setctime>=1.2.0; sys_platform >= 'win32'",
|
|
40
40
|
]
|
|
41
41
|
|
|
42
|
+
[dependency-groups]
|
|
43
|
+
dev = [
|
|
44
|
+
"bump-my-version>=1.2.6",
|
|
45
|
+
"mypy>=1.19.1",
|
|
46
|
+
"pre-commit>=4.5.1",
|
|
47
|
+
"pylint>=4.0.4",
|
|
48
|
+
]
|
|
49
|
+
docs = [
|
|
50
|
+
"sphinx-click>=6.2.0",
|
|
51
|
+
"sphinx-rtd-theme>=3.0.2",
|
|
52
|
+
]
|
|
53
|
+
|
|
42
54
|
[project.scripts]
|
|
43
55
|
ftcli = "foundrytools_cli.__main__:cli"
|
|
44
56
|
|
|
45
57
|
[project.urls]
|
|
46
58
|
Homepage = "https://github.com/ftCLI/FoundryTools-CLI"
|
|
47
59
|
|
|
48
|
-
[tool.hatch.version]
|
|
49
|
-
path = "src/foundrytools_cli/__init__.py"
|
|
50
|
-
pattern = 'VERSION = __version__ = "(?P<version>[^"]+)"'
|
|
51
|
-
|
|
52
|
-
[tool.hatch.build.targets.sdist]
|
|
53
|
-
include = [
|
|
54
|
-
"/src",
|
|
55
|
-
]
|
|
56
|
-
exclude = [
|
|
57
|
-
"/.gitignore",
|
|
58
|
-
]
|
|
59
|
-
|
|
60
60
|
[tool.bumpversion]
|
|
61
|
-
current_version = "2.0.
|
|
62
|
-
commit =
|
|
61
|
+
current_version = "2.0.5"
|
|
62
|
+
commit = false
|
|
63
63
|
tag = true
|
|
64
64
|
|
|
65
65
|
[[tool.bumpversion.files]]
|
{foundrytools_cli-2.0.3 → foundrytools_cli-2.0.5}/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
|
|
@@ -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,
|
|
@@ -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,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.3 → foundrytools_cli-2.0.5}/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.3 → foundrytools_cli-2.0.5}/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
|
"""
|
|
@@ -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
|
|
|
@@ -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"""
|
|
@@ -1,161 +0,0 @@
|
|
|
1
|
-
# Byte-compiled / optimized / DLL files
|
|
2
|
-
__pycache__/
|
|
3
|
-
*.py[cod]
|
|
4
|
-
*$py.class
|
|
5
|
-
|
|
6
|
-
# C extensions
|
|
7
|
-
*.so
|
|
8
|
-
|
|
9
|
-
# Distribution / packaging
|
|
10
|
-
.Python
|
|
11
|
-
build/
|
|
12
|
-
develop-eggs/
|
|
13
|
-
dist/
|
|
14
|
-
downloads/
|
|
15
|
-
eggs/
|
|
16
|
-
.eggs/
|
|
17
|
-
foundryToolsCLI_2/lib/
|
|
18
|
-
lib64/
|
|
19
|
-
parts/
|
|
20
|
-
sdist/
|
|
21
|
-
var/
|
|
22
|
-
wheels/
|
|
23
|
-
share/python-wheels/
|
|
24
|
-
*.egg-info/
|
|
25
|
-
.installed.cfg
|
|
26
|
-
*.egg
|
|
27
|
-
MANIFEST
|
|
28
|
-
|
|
29
|
-
# PyInstaller
|
|
30
|
-
# Usually these files are written by a python script from a template
|
|
31
|
-
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
32
|
-
*.manifest
|
|
33
|
-
*.spec
|
|
34
|
-
|
|
35
|
-
# Installer logs
|
|
36
|
-
pip-log.txt
|
|
37
|
-
pip-delete-this-directory.txt
|
|
38
|
-
|
|
39
|
-
# Unit test / coverage reports
|
|
40
|
-
htmlcov/
|
|
41
|
-
.tox/
|
|
42
|
-
.nox/
|
|
43
|
-
.coverage
|
|
44
|
-
.coverage.*
|
|
45
|
-
.cache
|
|
46
|
-
nosetests.xml
|
|
47
|
-
coverage.xml
|
|
48
|
-
*.cover
|
|
49
|
-
*.py,cover
|
|
50
|
-
.hypothesis/
|
|
51
|
-
.pytest_cache/
|
|
52
|
-
cover/
|
|
53
|
-
|
|
54
|
-
# Translations
|
|
55
|
-
*.mo
|
|
56
|
-
*.pot
|
|
57
|
-
|
|
58
|
-
# Django stuff:
|
|
59
|
-
*.log
|
|
60
|
-
local_settings.py
|
|
61
|
-
db.sqlite3
|
|
62
|
-
db.sqlite3-journal
|
|
63
|
-
|
|
64
|
-
# Flask stuff:
|
|
65
|
-
instance/
|
|
66
|
-
.webassets-cache
|
|
67
|
-
|
|
68
|
-
# Scrapy stuff:
|
|
69
|
-
.scrapy
|
|
70
|
-
|
|
71
|
-
# Sphinx documentation
|
|
72
|
-
docs/_build/
|
|
73
|
-
|
|
74
|
-
# PyBuilder
|
|
75
|
-
.pybuilder/
|
|
76
|
-
target/
|
|
77
|
-
|
|
78
|
-
# Jupyter Notebook
|
|
79
|
-
.ipynb_checkpoints
|
|
80
|
-
|
|
81
|
-
# IPython
|
|
82
|
-
profile_default/
|
|
83
|
-
ipython_config.py
|
|
84
|
-
|
|
85
|
-
# pyenv
|
|
86
|
-
# For a library or package, you might want to ignore these files since the code is
|
|
87
|
-
# intended to run in multiple environments; otherwise, check them in:
|
|
88
|
-
# .python-version
|
|
89
|
-
|
|
90
|
-
# pipenv
|
|
91
|
-
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
|
92
|
-
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
|
93
|
-
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
|
94
|
-
# install all needed dependencies.
|
|
95
|
-
#Pipfile.lock
|
|
96
|
-
|
|
97
|
-
# poetry
|
|
98
|
-
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
|
99
|
-
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
100
|
-
# commonly ignored for libraries.
|
|
101
|
-
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
|
102
|
-
#poetry.lock
|
|
103
|
-
|
|
104
|
-
# pdm
|
|
105
|
-
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
|
106
|
-
#pdm.lock
|
|
107
|
-
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
|
108
|
-
# in version control.
|
|
109
|
-
# https://pdm.fming.dev/#use-with-ide
|
|
110
|
-
.pdm.toml
|
|
111
|
-
|
|
112
|
-
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
|
113
|
-
__pypackages__/
|
|
114
|
-
|
|
115
|
-
# Celery stuff
|
|
116
|
-
celerybeat-schedule
|
|
117
|
-
celerybeat.pid
|
|
118
|
-
|
|
119
|
-
# SageMath parsed files
|
|
120
|
-
*.sage.py
|
|
121
|
-
|
|
122
|
-
# Environments
|
|
123
|
-
.env
|
|
124
|
-
.venv
|
|
125
|
-
env/
|
|
126
|
-
venv/
|
|
127
|
-
ENV/
|
|
128
|
-
env.bak/
|
|
129
|
-
venv.bak/
|
|
130
|
-
|
|
131
|
-
# Spyder project settings
|
|
132
|
-
.spyderproject
|
|
133
|
-
.spyproject
|
|
134
|
-
|
|
135
|
-
# Rope project settings
|
|
136
|
-
.ropeproject
|
|
137
|
-
|
|
138
|
-
# mkdocs documentation
|
|
139
|
-
/site
|
|
140
|
-
|
|
141
|
-
# mypy
|
|
142
|
-
.mypy_cache/
|
|
143
|
-
.dmypy.json
|
|
144
|
-
dmypy.json
|
|
145
|
-
|
|
146
|
-
# Pyre type checker
|
|
147
|
-
.pyre/
|
|
148
|
-
|
|
149
|
-
# pytype static type analyzer
|
|
150
|
-
.pytype/
|
|
151
|
-
|
|
152
|
-
# Cython debug symbols
|
|
153
|
-
cython_debug/
|
|
154
|
-
|
|
155
|
-
# PyCharm
|
|
156
|
-
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
|
157
|
-
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
|
158
|
-
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
|
159
|
-
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
|
160
|
-
#.idea/
|
|
161
|
-
.qodo
|
foundrytools_cli-2.0.3/LICENSE
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2023 ftCLI
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{foundrytools_cli-2.0.3 → foundrytools_cli-2.0.5}/src/foundrytools_cli/commands/fix/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{foundrytools_cli-2.0.3 → foundrytools_cli-2.0.5}/src/foundrytools_cli/commands/print/__init__.py
RENAMED
|
File without changes
|
{foundrytools_cli-2.0.3 → foundrytools_cli-2.0.5}/src/foundrytools_cli/commands/print/font_info.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{foundrytools_cli-2.0.3 → foundrytools_cli-2.0.5}/src/foundrytools_cli/commands/utils/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|