diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 91ef1f3c..96486d1e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,66 +12,66 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v2 - with: - python-version: '3.x' - - name: Lint - run: | - pip install tox - tox -e lint + - uses: actions/checkout@v4 + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: "3.x" + - name: Lint + run: | + pip install tox + tox -e lint - docs: # To see if they build. + docs: # To see if they build. runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v2 - with: - python-version: '3.x' - - name: Lint - run: | - pip install tox - tox -e docs + - uses: actions/checkout@v4 + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: "3.x" + - name: Lint + run: | + pip install tox + tox -e docs test: runs-on: ${{ matrix.platform }} strategy: matrix: - python-version: ['3.8', '3.11'] + python-version: ["3.8", "3.13"] platform: [ubuntu-latest, windows-latest] steps: - - uses: actions/checkout@v2 - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 - with: - python-version: ${{ matrix.python-version }} - - name: Install packages - run: pip install tox coverage - - name: Run Tox - run: tox -e py-cov - - name: Re-run Tox without cattrs - if: startsWith(matrix.platform, 'ubuntu-latest') && startsWith(matrix.python-version, '3.11') - run: | - tox -e py-nocattrs - - name: Re-run Tox without msgpack - if: startsWith(matrix.platform, 'ubuntu-latest') && startsWith(matrix.python-version, '3.10') - run: | - tox -e py-nomsgpack - - name: Produce coverage files - run: | - coverage combine - coverage xml - - name: Upload coverage to Codecov - uses: codecov/codecov-action@v1 - with: - file: coverage.xml - flags: unittests - name: codecov-umbrella - fail_ci_if_error: false + - uses: actions/checkout@v4 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python-version }} + - name: Install packages + run: pip install tox coverage + - name: Run Tox + run: tox -e py-cov + - name: Re-run Tox without cattrs + if: startsWith(matrix.platform, 'ubuntu-latest') && startsWith(matrix.python-version, '3.13') + run: | + tox -e py-nocattrs + - name: Re-run Tox without msgpack + if: startsWith(matrix.platform, 'ubuntu-latest') && startsWith(matrix.python-version, '3.13') + run: | + tox -e py-nomsgpack + - name: Produce coverage files + run: | + coverage combine + coverage xml + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v1 + with: + file: coverage.xml + flags: unittests + name: codecov-umbrella + fail_ci_if_error: false deploy: # only run if the commit is tagged... @@ -84,19 +84,19 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v2 - with: - python-version: '3.x' - - name: Install dependencies - run: | - pip install build twine - - name: Build and publish - env: - TWINE_USERNAME: __token__ - TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }} - run: | - python -m build - twine check dist/* - twine upload dist/* + - uses: actions/checkout@v4 + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: "3.x" + - name: Install dependencies + run: | + pip install build twine + - name: Build and publish + env: + TWINE_USERNAME: __token__ + TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }} + run: | + python -m build + twine check dist/* + twine upload dist/* diff --git a/mypy.ini b/mypy.ini deleted file mode 100644 index 70696d15..00000000 --- a/mypy.ini +++ /dev/null @@ -1,36 +0,0 @@ -[mypy] -python_version = 3.8 - -# Untyped definitions and calls -disallow_incomplete_defs = True - -# None and Optional handling -no_implicit_optional = True -strict_optional = True - -# Configuring warnings -warn_no_return = True -warn_redundant_casts = True -warn_unreachable = True - -# Miscellaneous strictness flags -strict_equality = True - -[mypy-ufoLib2.*] -disallow_untyped_defs = True - -[mypy-ufoLib2._version] -# Unavailable until package installation. -ignore_missing_imports = True - -[mypy-fontTools.*] -ignore_missing_imports = True - -[mypy-pytest] -ignore_missing_imports = True - -[mypy-py] -ignore_missing_imports = True - -[mypy-setuptools] -ignore_missing_imports = True diff --git a/pyproject.toml b/pyproject.toml index 92df10e4..386baa01 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,9 +1,54 @@ [build-system] -requires = ["setuptools>=45", "wheel", "setuptools_scm>=6.2"] +requires = ["setuptools>=61.2", "wheel", "setuptools_scm>=6.2"] build-backend = "setuptools.build_meta" +[project] +name = "ufoLib2" +description = "ufoLib2 is a UFO font processing library." +authors = [{ name = "Adrien Tétar", email = "adri-from-59@hotmail.fr" }] +license = { text = "Apache 2.0" } +classifiers = [ + "Development Status :: 4 - Beta", + "Operating System :: OS Independent", + "Programming Language :: Python :: 3", + "Intended Audience :: Developers", + "Intended Audience :: End Users/Desktop", + "Topic :: Text Processing :: Fonts", + "License :: OSI Approved :: Apache Software License", +] +urls = { Homepage = "https://github.com/fonttools/ufoLib2" } +requires-python = ">=3.8" +dependencies = ["attrs >= 22.1.0", "fonttools[ufo] >= 4.0.0"] +dynamic = ["version"] + +[project.readme] +file = "README.md" +content-type = "text/markdown" + +[project.optional-dependencies] +lxml = ["lxml"] +converters = ["cattrs >= 22.2.0"] +json = ["cattrs >= 22.2.0", "orjson ; platform_python_implementation != 'PyPy'"] +msgpack = ["cattrs >= 22.2.0", "msgpack"] + +[tool.setuptools] +package-dir = { "" = "src" } +license-files = ["LICENSE"] +include-package-data = false + +# https://www.python.org/dev/peps/pep-0561 +[tool.setuptools.package-data] +"*" = ["py.typed"] + +[tool.setuptools.packages.find] +where = ["src"] +namespaces = false + +[tool.setuptools_scm] +write_to = "src/ufoLib2/_version.py" + [tool.black] -target-version = ["py37"] +target-version = ["py38"] [tool.isort] multi_line_output = 3 @@ -11,5 +56,30 @@ profile = "black" float_to_top = true known_first_party = "ufoLib2" -[tool.setuptools_scm] -write_to = "src/ufoLib2/_version.py" +[tool.pytest.ini_options] +minversion = "6.0" +testpaths = ["tests", "ufoLib2"] +addopts = "-ra --doctest-modules --doctest-ignore-import-errors --pyargs" +doctest_optionflags = ["ALLOW_UNICODE", "ELLIPSIS"] +filterwarnings = [ + "ignore::DeprecationWarning:fs", + "ignore::DeprecationWarning:pkg_resources", +] + +[tool.mypy] +python_version = "3.8" +disallow_incomplete_defs = true +no_implicit_optional = true +strict_optional = true +warn_no_return = true +warn_redundant_casts = true +warn_unreachable = true +strict_equality = true + +[[tool.mypy.overrides]] +module = "ufoLib2.*" +disallow_untyped_defs = true + +[[tool.mypy.overrides]] +module = ["fontTools.*", "ufoLib2._version"] +ignore_missing_imports = true diff --git a/requirements-dev.txt b/requirements-dev.txt index 726f2b77..dd39f345 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,44 +1,52 @@ -# -# This file is autogenerated by pip-compile with Python 3.11 -# by the following command: -# -# pip-compile --output-file=requirements-dev.txt requirements-dev.in -# -black==23.11.0 +# This file was autogenerated by uv via the following command: +# uv pip compile --python 3.8 requirements-dev.in +black==24.8.0 # via -r requirements-dev.in click==8.1.7 # via black -coverage==7.3.2 +coverage==7.6.1 # via -r requirements-dev.in -flake8==6.1.0 +exceptiongroup==1.2.2 + # via + # -c requirements.txt + # pytest +flake8==7.1.1 # via -r requirements-dev.in iniconfig==2.0.0 # via pytest -isort==5.12.0 +isort==5.13.2 # via -r requirements-dev.in mccabe==0.7.0 # via flake8 -mypy==1.7.1 +mypy==1.12.1 # via -r requirements-dev.in mypy-extensions==1.0.0 # via # black # mypy -packaging==23.2 +packaging==24.1 # via # black # pytest -pathspec==0.11.2 +pathspec==0.12.1 # via black -platformdirs==4.0.0 +platformdirs==4.3.6 # via black -pluggy==1.3.0 +pluggy==1.5.0 # via pytest -pycodestyle==2.11.1 +pycodestyle==2.12.1 # via flake8 -pyflakes==3.1.0 +pyflakes==3.2.0 # via flake8 -pytest==7.4.3 +pytest==8.3.3 # via -r requirements-dev.in -typing-extensions==4.8.0 - # via mypy +tomli==2.0.2 + # via + # black + # mypy + # pytest +typing-extensions==4.12.2 + # via + # -c requirements.txt + # black + # mypy diff --git a/requirements.txt b/requirements.txt index a12368c7..b39d0eb6 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,31 +1,28 @@ -# -# This file is autogenerated by pip-compile with Python 3.11 -# by the following command: -# -# pip-compile --extra=converters --extra=json --extra=lxml --extra=msgpack setup.cfg -# +# This file was autogenerated by uv via the following command: +# uv pip compile pyproject.toml --python 3.8 --extra=converters --extra=json --extra=lxml --extra=msgpack appdirs==1.4.4 # via fs -attrs==23.1.0 +attrs==24.2.0 # via + # ufolib2 (pyproject.toml) # cattrs - # ufoLib2 (setup.cfg) -cattrs==23.2.3 - # via ufoLib2 (setup.cfg) -fonttools[ufo]==4.46.0 - # via - # fonttools - # ufoLib2 (setup.cfg) +cattrs==24.1.2 + # via ufolib2 (pyproject.toml) +exceptiongroup==1.2.2 + # via cattrs +fonttools==4.54.1 + # via ufolib2 (pyproject.toml) fs==2.4.16 # via fonttools -lxml==4.9.3 - # via ufoLib2 (setup.cfg) -msgpack==1.0.7 - # via ufoLib2 (setup.cfg) -orjson==3.9.15 ; platform_python_implementation != "PyPy" - # via ufoLib2 (setup.cfg) +lxml==5.3.0 + # via ufolib2 (pyproject.toml) +msgpack==1.1.0 + # via ufolib2 (pyproject.toml) +orjson==3.10.9 + # via ufolib2 (pyproject.toml) +setuptools==75.2.0 + # via fs six==1.16.0 # via fs - -# The following packages are considered to be unsafe in a requirements file: -# setuptools +typing-extensions==4.12.2 + # via cattrs diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index 8bfc0840..00000000 --- a/setup.cfg +++ /dev/null @@ -1,46 +0,0 @@ -[metadata] -name = ufoLib2 -description = ufoLib2 is a UFO font processing library. -long_description = file: README.md -long_description_content_type = text/markdown -url = https://github.com/fonttools/ufoLib2 -author = Adrien Tétar -author_email = adri-from-59@hotmail.fr -license = Apache 2.0 -license_files = LICENSE -classifiers = - Development Status :: 4 - Beta - Operating System :: OS Independent - Programming Language :: Python :: 3 - Intended Audience :: Developers - Intended Audience :: End Users/Desktop - Topic :: Text Processing :: Fonts - License :: OSI Approved :: Apache Software License - -[options] -package_dir = =src -packages = find: -python_requires = >=3.8 -install_requires = - attrs >= 22.1.0 - fonttools[ufo] >= 4.0.0 - -# https://www.python.org/dev/peps/pep-0561 -[options.package_data] -* = py.typed - -[options.extras_require] -lxml = lxml -converters = cattrs >= 22.2.0 -json = - cattrs >= 22.2.0 - orjson ; platform_python_implementation != 'PyPy' -msgpack = - cattrs >= 22.2.0 - msgpack - -[options.packages.find] -where = src - -[bdist_wheel] -universal = 0 diff --git a/src/ufoLib2/objects/contour.py b/src/ufoLib2/objects/contour.py index 32b7cdaf..764ab056 100644 --- a/src/ufoLib2/objects/contour.py +++ b/src/ufoLib2/objects/contour.py @@ -54,8 +54,7 @@ def __delitem__(self, index: int | slice) -> None: del self.points[index] @overload - def __getitem__(self, index: int) -> Point: - ... + def __getitem__(self, index: int) -> Point: ... @overload def __getitem__(self, index: slice) -> list[Point]: # noqa: F811 diff --git a/src/ufoLib2/objects/info/woff.py b/src/ufoLib2/objects/info/woff.py index ac40e37a..aa328b70 100644 --- a/src/ufoLib2/objects/info/woff.py +++ b/src/ufoLib2/objects/info/woff.py @@ -2,6 +2,7 @@ https://unifiedfontobject.org/versions/ufo3/fontinfo.plist/#woff-data """ + from __future__ import annotations from typing import Any, List, Mapping, Optional, Sequence, Type, TypeVar diff --git a/src/ufoLib2/objects/layer.py b/src/ufoLib2/objects/layer.py index 35febb8d..faf227ae 100644 --- a/src/ufoLib2/objects/layer.py +++ b/src/ufoLib2/objects/layer.py @@ -228,12 +228,10 @@ def keys(self) -> KeysView[str]: return self._glyphs.keys() @overload - def pop(self, key: str) -> Glyph: - ... + def pop(self, key: str) -> Glyph: ... @overload - def pop(self, key: str, default: Glyph | T = ...) -> Glyph | T: - ... + def pop(self, key: str, default: Glyph | T = ...) -> Glyph | T: ... def pop(self, key: str, default: Glyph | T = KeyError) -> Glyph | T: # type: ignore """Remove and return glyph from layer. diff --git a/src/ufoLib2/typing.py b/src/ufoLib2/typing.py index 2747ba7c..242e1719 100644 --- a/src/ufoLib2/typing.py +++ b/src/ufoLib2/typing.py @@ -19,8 +19,7 @@ class Drawable(Protocol): See :mod:`fontTools.pens.basePen` for an introduction to pens. """ - def draw(self, pen: AbstractPen) -> None: - ... + def draw(self, pen: AbstractPen) -> None: ... class DrawablePoints(Protocol): @@ -29,8 +28,7 @@ class DrawablePoints(Protocol): See :mod:`fontTools.pens.pointPen` for an introduction to point pens. """ - def drawPoints(self, pen: AbstractPointPen) -> None: - ... + def drawPoints(self, pen: AbstractPointPen) -> None: ... class HasIdentifier(Protocol): @@ -54,8 +52,6 @@ class GlyphSet(Protocol): """ # "object" instead of "str" because that's what typeshed says a Mapping should have. - def __contains__(self, name: object) -> bool: - ... + def __contains__(self, name: object) -> bool: ... - def __getitem__(self, name: str) -> Drawable | DrawablePoints: - ... + def __getitem__(self, name: str) -> Drawable | DrawablePoints: ... diff --git a/tox.ini b/tox.ini index fa61302d..992e489f 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = lint, py3{8,9,10,11}-cov, htmlcov +envlist = lint, py3{8,9,10,11,12,13}-cov, htmlcov isolated_build = true [testenv] @@ -41,22 +41,8 @@ skip_install = true commands = sphinx-build -W -j auto docs/source docs/build -[pytest] -minversion = 3.0 -testpaths = - tests - ufoLib2 -addopts = - -r a - --doctest-modules - --doctest-ignore-import-errors - --pyargs -doctest_optionflags = - ALLOW_UNICODE - ELLIPSIS - [flake8] select = C, E, F, W, B, B9 -ignore = E203, E266, E501, W503 -max-line-length = 80 +ignore = E203, E266, E501, W503, E701, E704 +max-line-length = 88 exclude = .git, __pycache__, build, dist, .eggs, .tox, venv, venv*, .venv, .venv*