Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .github/workflows/pytest_linux.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,19 @@ on:
push:
branches:
- main
pull_request:
branches:
- main
# Only run on PRs from the same repository (not forks)
types: [opened, synchronize, reopened]
workflow_dispatch:

jobs:
build:
# Skip expensive tests for PRs from forks (unless manually triggered)
if:
github.event.pull_request.head.repo.full_name == github.repository ||
github.event_name == 'push' || github.event_name == 'workflow_dispatch'
runs-on: ubuntu-latest
strategy:
matrix:
Expand Down
12 changes: 11 additions & 1 deletion .github/workflows/pytest_windows.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,19 @@
name: Test on windows

on: workflow_dispatch
on:
workflow_dispatch:
pull_request:
branches:
- main
# Only run on PRs from the same repository (not forks)
types: [opened, synchronize, reopened]

jobs:
build:
# Skip expensive tests for PRs from forks
if:
github.event.pull_request.head.repo.full_name == github.repository ||
github.event_name == 'workflow_dispatch'
strategy:
matrix:
python-version: ["3.10"]
Expand Down
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ def readme():
"chardet>=4.0.0",
"networkx>=2.0.0",
"pydantic>=2.0.0",
"typing_extensions>=4.0.0; python_version<'3.12'", # For override (3.12+) and Self (3.11+)
],
conan_requirements=["fmt/[>=10.0.0]", "cgal/[>=6.0]"], # C++ Dependencies
conan_profile_settings={"compiler.cppstd": 17},
Expand Down
4 changes: 2 additions & 2 deletions src/cgshop2026_pyutils/geometry/_bindings.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
CGAL geometry bindings for CG:SHOP 2026
"""

from typing import overload, Sequence, Self, override

from typing import overload, Sequence
from typing_extensions import Self, override
class FieldNumber:
"""A container for exact numbers in CGAL."""

Expand Down
7 changes: 6 additions & 1 deletion src/cgshop2026_pyutils/geometry/flippable_triangulation.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
from typing import override
import sys

if sys.version_info >= (3, 12):
from typing import override
else:
from typing_extensions import override

from .flip_partner_map import FlipPartnerMap, normalize_edge
from ._bindings import is_triangulation, Point # pyright: ignore[reportMissingModuleSource]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import os
from typing import override
import sys

if sys.version_info >= (3, 12):
from typing import override
else:
from typing_extensions import override
from collections.abc import Iterator
from pathlib import Path
Comment on lines +3 to 9

Copilot AI Nov 21, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Import ordering violates PEP 8 conventions. The from collections.abc import Iterator import should come before the conditional typing_extensions import block. Standard library imports should be grouped together at the top, followed by third-party imports, then local imports.

Suggested order:

import os
import sys
from collections.abc import Iterator
from pathlib import Path

if sys.version_info >= (3, 12):
    from typing import override
else:
    from typing_extensions import override
Suggested change
if sys.version_info >= (3, 12):
from typing import override
else:
from typing_extensions import override
from collections.abc import Iterator
from pathlib import Path
from collections.abc import Iterator
from pathlib import Path
if sys.version_info >= (3, 12):
from typing import override
else:
from typing_extensions import override

Copilot uses AI. Check for mistakes.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@
import os
from pathlib import Path
from zipfile import ZipFile, ZipInfo
from typing import override
import sys

if sys.version_info >= (3, 12):
from typing import override
else:
from typing_extensions import override

from ..schemas.instance import CGSHOP2026Instance
from .instance_base_database import InstanceBaseDatabase
Expand Down
9 changes: 8 additions & 1 deletion src/cgshop2026_pyutils/zip/zip_processor.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,16 @@
in it. It is designed to be robust and include basic security features.
"""

import sys
from os import PathLike
from collections.abc import Iterator
from typing import BinaryIO, Any, Sequence, override
from typing import BinaryIO, Any, Sequence

if sys.version_info >= (3, 12):
from typing import override
else:
from typing_extensions import override

from zipfile import BadZipFile, ZipFile

from pydantic import ValidationError
Expand Down
4 changes: 1 addition & 3 deletions src/cgshop2026_pyutils/zip/zip_reader_errors.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
from pathlib import Path

from typing import TYPE_CHECKING

if TYPE_CHECKING:
from zipfile import ZipFile
from zipfile import ZipFile


class ZipReaderError(Exception):
Expand Down
144 changes: 144 additions & 0 deletions tests/test_imports.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
"""
Test that all modules can be imported successfully.
This catches compatibility issues with typing features across Python versions.
"""

import sys
import pytest


def test_python_version():
"""Verify we're running on supported Python version."""
assert sys.version_info >= (3, 10), "Python 3.10+ required"


def test_import_geometry_module():
"""Test that the main geometry module imports successfully."""
from cgshop2026_pyutils import geometry
assert geometry is not None


def test_import_geometry_classes():
"""Test that key geometry classes can be imported."""
from cgshop2026_pyutils.geometry import (
Point,
Segment,
FlippableTriangulation,
FlipPartnerMap,
is_triangulation,
compute_triangles,
do_cross,
)
assert Point is not None
assert Segment is not None
assert FlippableTriangulation is not None
assert FlipPartnerMap is not None
assert is_triangulation is not None
assert compute_triangles is not None
assert do_cross is not None


def test_import_schemas():
"""Test that schema classes can be imported."""
from cgshop2026_pyutils.schemas import (
CGSHOP2026Instance,
CGSHOP2026Solution,
)
assert CGSHOP2026Instance is not None
assert CGSHOP2026Solution is not None


def test_import_io():
"""Test that IO functions can be imported."""
from cgshop2026_pyutils.io import (
read_instance,
read_solution,
)
assert read_instance is not None
assert read_solution is not None


def test_import_verify():
"""Test that verification module can be imported."""
from cgshop2026_pyutils.verify import check_for_errors
assert check_for_errors is not None


def test_import_zip_utilities():
"""Test that ZIP utilities can be imported."""
from cgshop2026_pyutils.zip import (
ZipSolutionIterator,
ZipWriter,
)
assert ZipSolutionIterator is not None
assert ZipWriter is not None


def test_import_instance_database():
"""Test that instance database classes can be imported."""
from cgshop2026_pyutils.instance_database import InstanceDatabase
assert InstanceDatabase is not None


def test_typing_extensions_compatibility():
"""Test that typing features work correctly across Python versions."""
# This test ensures override and Self are available
if sys.version_info >= (3, 12):
from typing import override
else:
from typing_extensions import override

if sys.version_info >= (3, 11):
from typing import Self
else:
from typing_extensions import Self

assert override is not None
assert Self is not None


def test_override_decorator_usage():
"""Test that @override decorator works in actual classes."""
from cgshop2026_pyutils.geometry import FlippableTriangulation
from cgshop2026_pyutils.zip import ZipSolutionIterator

# Just verify these classes can be instantiated (basic smoke test)
# The fact they import successfully means @override is working
assert FlippableTriangulation is not None
assert ZipSolutionIterator is not None


def test_bindings_module_types():
"""Test that C++ binding types are available."""
from cgshop2026_pyutils.geometry._bindings import (
Point,
Segment,
FieldNumber,
)

# Test basic type instantiation
p = Point(0, 0)
assert p is not None

fn = FieldNumber(42)
assert fn is not None

s = Segment(Point(0, 0), Point(1, 1))
assert s is not None


def test_create_simple_triangulation():
"""Smoke test: create a simple triangulation to ensure everything works."""
from cgshop2026_pyutils.geometry import Point, is_triangulation

# Simple triangle
points = [Point(0, 0), Point(1, 0), Point(0, 1)]
edges = [(0, 1), (1, 2), (2, 0)]

result = is_triangulation(points, edges, verbose=False)
assert result is True


if __name__ == "__main__":
# Allow running this test file directly
pytest.main([__file__, "-v"])