Skip to content

Commit

Permalink
Add support for Python 3.13 and drop support for Python 3.10 (#784)
Browse files Browse the repository at this point in the history
* Update to python 3.13 + updated pyproject.toml format

* Update foramtting (safe fixes)

* Update foramtting (less safe fixes)

* Updated changelog
  • Loading branch information
abey79 authored Feb 16, 2025
1 parent f7a141d commit 3dbc352
Show file tree
Hide file tree
Showing 20 changed files with 86 additions and 104 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/benchmarks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,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
2 changes: 1 addition & 1 deletion .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.10', '3.11', '3.12']
python-version: ['3.11', '3.11', '3.13']
os: [ubuntu-latest, macos-latest, windows-latest]
defaults:
run:
Expand Down
2 changes: 1 addition & 1 deletion .readthedocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ sphinx:
build:
os: ubuntu-22.04
tools:
python: "3.11"
python: "3.13"
jobs:
pre_create_environment:
- pip install poetry
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ Release date: UNRELEASED

### New features and improvements

* Added support for Python 3.13 and dropped support for Python 3.10 (#784)
* Added a `--orientation` option to the `pagerotate` command to conditionally rotate the page to a target orientation (thanks to @gatesphere) (#705)
* Added a `lineshuffle` command to randomize the plotting order of lines in the current geometry (thanks to @gatesphere) (#715)

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ curvy (circles, bezier curves, etc.) to lines made of small segments. _vpype_ do
Detailed installation instructions are available in the [latest documentation](https://vpype.readthedocs.io/en/latest/install.html).

TL;DR:
- Python 3.12 is recommended, but *vpype* is also compatible with Python 3.10 and 3.11.
- Python 3.13 is recommended, but *vpype* is also compatible with Python 3.11 and 3.12.
- *vpype* is published on the [Python Package Index](https://pypi.org) and can be installed using [pipx](https://pypa.github.io/pipx/):
```bash
pipx install "vpype[all]"
Expand Down
4 changes: 2 additions & 2 deletions docs/install.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ This page explain how to install *vpype* for end-users. If you intend to develop

.. note::

The recommended Python version is 3.12.1 or later. *vpype* is also compatible with Python 3.10 and 3.11.
The recommended Python version is 3.13. *vpype* is also compatible with Python 3.11 and 3.12.

.. warning::

Expand Down Expand Up @@ -38,7 +38,7 @@ You can ensure that the installed Python interpreter is properly installed by r

It should produce an output similar to::

Python 3.12.1
Python 3.13.2

The version number should match the installer you used.

Expand Down
31 changes: 3 additions & 28 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

88 changes: 48 additions & 40 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,18 +1,49 @@
[tool.poetry]
[project]
name = "vpype"
version = "1.15.0a0"
description = "The Swiss Army knife of vector graphics for pen plotters"
authors = ["Antoine Beyeler <[email protected]>"]
authors = [
{ name = "Antoine Beyeler", email = "[email protected]>" }
]
license = "MIT"
readme = "README.md"
homepage = "https://github.com/abey79/vpype"
documentation = "https://vpype.readthedocs.io/en/latest/"
classifiers = [
"Development Status :: 5 - Production/Stable",
"Environment :: Console",
"Topic :: Artistic Software",
"Topic :: Multimedia :: Graphics",
requires-python = ">=3.11, <3.14"
dynamic = ["classifiers"]

dependencies = [
"asteval>=0.9.26",
"cachetools>=4.2.2",
"click>=8.0.1,<8.2.0",
"multiprocess>=0.70.11",
"numpy>=1.25,<3",
"pnoise>=0.2.0",
"pyphen>=0.14,<0.16",
"scipy>=1.6",
"Shapely>=1.8.2",
"svgelements>=1.6.10",
"svgwrite~=1.4",
"tomli>=2.0.0",
]

[project.optional-dependencies]
all = [
"matplotlib>=3.3.2",
"glcontext>=2.3.2", # 2.3.2 needed to fix #200
"moderngl>=5.6.2,!=5.7.1,!=5.7.2", # see moderngl/moderngl#525
"Pillow>=9.0.1",
"PySide6>=6.4.0.1,!=6.6.2",
]


[project.urls]
documentation = "https://vpype.readthedocs.io/en/latest/"
repository = "https://github.com/abey79/vpype"

[project.scripts]
vpype = "vpype_cli.cli:cli"


[tool.poetry]
packages = [
{ include = "vpype" },
{ include = "vpype_cli" },
Expand All @@ -29,31 +60,14 @@ include = [
"vpype_viewer/qtviewer/resources/*",
]

[tool.poetry.scripts]
vpype = "vpype_cli.cli:cli"
# Poetry autofills license and Python version related items.
classifiers = [
"Development Status :: 5 - Production/Stable",
"Environment :: Console",
"Topic :: Artistic Software",
"Topic :: Multimedia :: Graphics",
]

[tool.poetry.dependencies]
python = ">=3.10, <3.13"

asteval = ">=0.9.26"
cachetools = ">=4.2.2"
click = ">=8.0.1,<8.2.0"
multiprocess = ">=0.70.11"
numpy = ">=1.25,<3"
pnoise = ">=0.2.0"
pyphen = ">=0.14,<0.16"
scipy = ">=1.6"
Shapely = ">=1.8.2"
svgelements = ">=1.6.10"
svgwrite = "~1.4"
tomli = ">=2.0.0"

# additional dependencies for the viewer and the `show` command
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.4.0.1,!=6.6.2", optional = true }

[tool.poetry.group.dev.dependencies]
coverage = {extras = ["toml"], version = ">=5.4"}
Expand Down Expand Up @@ -83,9 +97,6 @@ sphinx-click = ">=4.3.0"
sphinx-copybutton = ">=0.5.0"


[tool.poetry.extras]
all = ["matplotlib", "glcontext", "moderngl", "Pillow", "PySide6"]

[build-system]
requires = ["poetry-core>=1.0.8"]
build-backend = "poetry.core.masonry.api"
Expand Down Expand Up @@ -129,13 +140,10 @@ exclude_lines = [
'@(abc\.)?abstractmethod',
]

[tool.black]
line-length = 95
target-version = ["py39", "py310", "py311"]

[tool.ruff]
line-length = 95
target-version = "py39"
target-version = "py311"
exclude = ["examples", "scripts"]

[tool.ruff.lint]
Expand Down
3 changes: 2 additions & 1 deletion tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
import pathlib
import random
import string
from typing import Callable, Protocol
from collections.abc import Callable
from typing import Protocol
from xml.dom import minidom
from xml.etree import ElementTree

Expand Down
10 changes: 5 additions & 5 deletions vpype/io.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,11 +84,11 @@ def get(self) -> np.ndarray:
return self._stack


_PathType = Union[
_PathType = Union[ # noqa: UP007
# for actual paths and shapes transformed into paths
svgelements.Path,
# for the special case of Polygon and Polylines
list[Union[svgelements.PathSegment, svgelements.Polygon, svgelements.Polyline]],
list[svgelements.PathSegment | svgelements.Polygon | svgelements.Polyline],
]
_PathListType = list[_PathType]

Expand Down Expand Up @@ -178,7 +178,7 @@ def _element_to_paths(elem: svgelements.SVGElement) -> _PathType | None:
if isinstance(elem, svgelements.Path):
if len(elem) != 0:
return elem
elif isinstance(elem, (svgelements.Polyline, svgelements.Polygon)):
elif isinstance(elem, svgelements.Polyline | svgelements.Polygon):
# Here we add a "fake" path containing just the Polyline/Polygon,
# to be treated specifically by _convert_flattened_paths.
path = [svgelements.Move(elem.points[0]), elem]
Expand Down Expand Up @@ -316,14 +316,14 @@ def _process_path(path):
point_stack = _ComplexStack()

point_stack.append(complex(seg.end))
elif isinstance(seg, (svgelements.Line, svgelements.Close)):
elif isinstance(seg, svgelements.Line | svgelements.Close):
start = complex(seg.start)
end = complex(seg.end)
if not point_stack.ends_with(start):
point_stack.append(start)
if end != start:
point_stack.append(end)
elif isinstance(seg, (svgelements.Polygon, svgelements.Polyline)):
elif isinstance(seg, svgelements.Polygon | svgelements.Polyline):
line = np.array(seg.points, dtype=float)
line = line.view(dtype=complex).reshape(len(line))
if point_stack.ends_with(line[0]):
Expand Down
2 changes: 1 addition & 1 deletion vpype/metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ def __init__(
alpha: int | None = None,
):
svgc = None
if isinstance(red, (svgelements.Color, Color)):
if isinstance(red, svgelements.Color | Color):
svgc = red
elif isinstance(red, str):
svgc = svgelements.Color(red)
Expand Down
12 changes: 6 additions & 6 deletions vpype/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@

import math
import pathlib
from collections.abc import Iterable, Iterator
from typing import Any, Callable, Optional, Union, cast
from collections.abc import Callable, Iterable, Iterator
from typing import Any, Union, cast

import numpy as np
from shapely.geometry import LinearRing, LineString, MultiLineString
Expand All @@ -28,7 +28,7 @@
"_MetadataMixin", # for documentation
]

LineLike = Union[LineString, LinearRing, Iterable[complex]]
LineLike = Union[LineString, LinearRing, Iterable[complex]] # noqa: UP007

# We accept LineString and LinearRing as line collection because MultiLineString are regularly
# converted to LineString/LinearRing when operation reduce them to single-line construct.
Expand Down Expand Up @@ -193,7 +193,7 @@ def append(self, line: LineLike) -> None:
Args:
line (LineLike): line to append
"""
if isinstance(line, (LineString, LinearRing)):
if isinstance(line, LineString | LinearRing):
# noinspection PyTypeChecker
self._lines.append(np.array(line.coords).view(dtype=complex).reshape(-1))
else:
Expand Down Expand Up @@ -222,7 +222,7 @@ def extend(self, lines: LineCollectionLike) -> None:
# handle shapely objects
if isinstance(lines, MultiLineString):
lines = lines.geoms
elif isinstance(lines, (LineString, LinearRing)):
elif isinstance(lines, LineString | LinearRing):
lines = [lines]

for line in lines:
Expand Down Expand Up @@ -623,7 +623,7 @@ def page_size(self) -> tuple[float, float] | None:
return self.property(METADATA_FIELD_PAGE_SIZE)

@page_size.setter
def page_size(self, page_size=Optional[tuple[float, float]]) -> None:
def page_size(self, page_size=tuple[float, float] | None) -> None:
"""Sets the page size to a new value."""
self.set_property(METADATA_FIELD_PAGE_SIZE, page_size)

Expand Down
2 changes: 1 addition & 1 deletion vpype/text.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@

import itertools
import pickle
from collections.abc import Callable
from dataclasses import dataclass
from pathlib import Path
from typing import Callable

import pyphen

Expand Down
Loading

0 comments on commit 3dbc352

Please sign in to comment.