Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Python 3.11 compatibility #581

Merged
merged 13 commits into from
Mar 10, 2023
14 changes: 7 additions & 7 deletions .github/workflows/python-lint-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
strategy:
fail-fast: true
matrix:
python-version: [3.8, 3.9, '3.10']
python-version: [3.9, '3.10', '3.11']
os: [ubuntu-latest, macos-latest, windows-latest]
defaults:
run:
Expand All @@ -36,7 +36,7 @@ jobs:
- name: Install project
run: poetry install -E all
- name: Lint and static analysis
if: matrix.os == 'ubuntu-latest' && matrix.python-version == '3.10' # no need to run that 9x
if: matrix.os == 'ubuntu-latest' && matrix.python-version == '3.11' # no need to run that 9x
run: |
poetry run isort --check --diff vpype vpype_cli vpype_viewer tests
poetry run black --check --diff vpype vpype_cli vpype_viewer tests
Expand All @@ -49,15 +49,15 @@ jobs:
sudo apt-get install -y -qq libegl1-mesa libegl1-mesa-dev
# PYTEST STRATEGY
# macOS is the only runner who has working ModernGL behaviour
# macOS + 3.10 is used for code coverage
# macOS + 3.11 is used for code coverage
- name: Pytest (code coverage)
run: |
poetry run pytest --cov=./ --cov-report=xml
if: matrix.os == 'macos-latest' && matrix.python-version == '3.10'
if: matrix.os == 'macos-latest' && matrix.python-version == '3.11'
- name: Pytest
run: |
poetry run pytest
if: matrix.os == 'macos-latest' && matrix.python-version != '3.10'
if: matrix.os == 'macos-latest' && matrix.python-version != '3.11'
- name: Pytest (no image similarity check)
run: |
poetry run pytest --skip-image-similarity
Expand All @@ -76,7 +76,7 @@ jobs:
with:
token: ${{ secrets.CODECOV_TOKEN }}
file: ./coverage.xml
if: matrix.os == 'macos-latest' && matrix.python-version == '3.10'
if: matrix.os == 'macos-latest' && matrix.python-version == '3.11'


# ----------------------------------------
Expand All @@ -93,7 +93,7 @@ jobs:
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.10'
python-version: '3.11'
cache: 'poetry'
- name: Install project
run: poetry install -E all
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jobs:
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.10'
python-version: '3.11'
# no caching!
- name: Install project
run: poetry install -E all
Expand Down Expand Up @@ -53,7 +53,7 @@ jobs:
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.10'
python-version: '3.11'
- name: Build artifacts
run: poetry build
- name: Publish to PyPI
Expand Down
9 changes: 8 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Release date: UNRELEASED

### New features and improvements

* ...
* Added support for Python 3.11 and dropped support for Python 3.8 (#581)

### Bug fixes

Expand All @@ -16,10 +16,17 @@ Release date: UNRELEASED

* ...

### Known issue

* As of PySide 6.4.2, a refresh issue arises on macOS when the viewer window is resized by a window manager (#603)


## 1.12.1

Release date: 2022-11-12

**Note**: This is the last version of *vpype* to support Python 3.7.

### Bug fixes

* Pinned ModernGL to 5.7.0 or earlier to avoid an [issue](https://github.com/moderngl/moderngl/issues/525) introduced in 5.7.1 (2ce6aef780e8a280375cb230d732d092a0635ad3)
Expand Down
2,428 changes: 1,255 additions & 1,173 deletions poetry.lock

Large diffs are not rendered by default.

5 changes: 3 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ include = [
vpype = "vpype_cli.cli:cli"

[tool.poetry.dependencies]
python = ">=3.8, <3.11"
python = ">=3.9, <3.12"
cachetools = ">=4.2.2"
click = ">=8.0.1,<8.2.0"
multiprocess = ">=0.70.11"
Expand All @@ -51,7 +51,7 @@ matplotlib = { version = ">=3.3.2", optional = true }
glcontext = { version = ">=2.3.2", optional = true } # 2.3.2 needed to fix #200
moderngl = { version = ">=5.6.2,!=5.7.1,!=5.7.2", optional = true } # see moderngl/moderngl#525
Pillow = { version = ">=9.0.1", optional = true }
PySide6 = { version = ">=6.3.2,<6.4.0", optional = true } # 6.4.0 incompatible with matplotlib
PySide6 = { version = ">=6.4.0.1", optional = true }


[tool.poetry.group.dev.dependencies]
Expand All @@ -68,6 +68,7 @@ pytest-mpl = ">=0.12"
mypy = ">=0.901"
types-cachetools = ">=4.2.4"
types-setuptools = ">=57.4.17"
types-pillow = "^9.4.0.17"

[tool.poetry.group.docs]
optional = true
Expand Down
6 changes: 3 additions & 3 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,8 +141,8 @@ def pytest_addoption(parser):


def write_image_similarity_fail_report(
image: Image,
reference_image: Image,
image: Image.Image,
reference_image: Image.Image,
image_array: np.ndarray,
reference_image_array: np.ndarray,
test_id: str,
Expand Down Expand Up @@ -171,7 +171,7 @@ def assert_image_similarity(request) -> Callable:
test_id = test_id.replace("[", "-").replace("]", "-").replace("/", "_").rstrip("-")
path = REFERENCE_IMAGES_DIR + os.path.sep + test_id + ".png"

def _assert_image_similarity(img: Image) -> None:
def _assert_image_similarity(img: Image.Image) -> None:
nonlocal store_ref_image, test_id, path

if store_ref_image: # pragma: no cover
Expand Down
24 changes: 16 additions & 8 deletions vpype_cli/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -193,13 +193,21 @@ def cli(
logging.getLogger().setLevel(logging.DEBUG)

# Plug-in loading logic. This approach is preferred because:
# 1) Deferred plug-in loading avoid circular import between vpype and vpype_cli when plug-
# in uses deprecated APIs.
# 1) Deferred plugin loading avoid circular import between vpype and vpype_cli when plugin
# uses deprecated APIs.
# 2) Avoids the PyCharm type error with CliRunner.invoke()
global _PLUGINS_LOADED
if not _PLUGINS_LOADED:
_PLUGINS_LOADED = True
for entry_point in importlib.metadata.entry_points().get("vpype.plugins", []):

# since python 3.10, a new "selectable" API is used for entry points, see:
# https://docs.python.org/3/library/importlib.metadata.html#entry-points
# Not using it yields a deprecation warning in some circumstances.
if sys.version_info >= (3, 10):
entry_points = importlib.metadata.entry_points().select(group="vpype.plugins")
else: # pragma: no cover
entry_points = importlib.metadata.entry_points().get("vpype.plugins", [])
for entry_point in entry_points:
# noinspection PyBroadException
try:
cast(click.Group, ctx.command).add_command(entry_point.load())
Expand All @@ -210,8 +218,8 @@ def cli(
cast(click.Group, ctx.command).add_command(_BrokenCommand(entry_point.name))

# Manual handling of the help to work around circular import issues.
# Background: when importing plug-ins in the style of `click-plugin` (decorator, so plug-
# ins are loaded during the loading of `cli` itself), plug-in may not import things from
# Background: when importing plug-ins in the style of `click-plugin` (decorator, so plugins
# are loaded during the loading of `cli` itself), plug-in may not import things from
# `vpype_cli` since it is still partially loaded. Plug-ins are thus loaded when `cli` is
# actually executed (see previous lines). As a result, the Click's default behaviour for
# handling `--help` (i.e. print and exit *before* even executing `cli`) is unable to list
Expand Down Expand Up @@ -344,7 +352,7 @@ class BeginBlock:
def begin():
"""Marks the start of a block.

A `begin` command must be followed by a block processor command (eg. `grid` or `repeat`),
A `begin` command must be followed by a block processor command (e.g. `grid` or `repeat`),
which indicates how the block is processed. Blocks must be ended by a `end` command.

Blocks can be nested.
Expand Down Expand Up @@ -431,15 +439,15 @@ def execute(

This function serves as a Python API to vpype's pipeline. It can be used from a regular
Python script (as opposed to the ``vpype`` CLI which must be used from a console or via
:func:`os.system`.
:func:`os.system`).

If a :class:`vpype.Document` instance is provided, it will be preloaded in the pipeline
before the first command executes. The pipeline's content after the last command is
returned as a :class:`vpype.Document` instance.

Examples:

Read a SVG file, optimize it and return the result as a :class:`vpype.Document`
Read an SVG file, optimize it and return the result as a :class:`vpype.Document`
instance::

>>> doc = execute("read input.svg linemerge linesimplify linesort")
Expand Down
3 changes: 1 addition & 2 deletions vpype_cli/metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ def propset(
vpype [...] propset --global --type int my_prop 10 [...]

Set the layer property of type `float` (this is equivalent to using the `penwidth`
command:
command):

vpype [...] propset --layer 1 --type float vp_pen_width 0.5mm [...]

Expand Down Expand Up @@ -399,7 +399,6 @@ def name(layer: vp.LineCollection, name: str) -> vp.LineCollection:
@click.argument("pen_config", metavar="CONF", type=TextType())
@global_processor
def pens(document: vp.Document, pen_config: str) -> vp.Document:

# the CONF parameter must be checked explicitly (instead of using click.Choice()) because
# additional config file (potentially containing pen configs) may be added at runtime
config = vp.config_manager.config.get("pen_config", {})
Expand Down
Loading