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
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ jobs:
compat-test-python3-ubuntu:
strategy:
matrix:
python3-version: ['8', '9', '10', '11', '12', '13']
python3-version: ['10', '11', '12', '13']
runs-on: ubuntu-latest
container: ghcr.io/opencyphal/toxic:tx22.4.3
needs: test
Expand Down
4 changes: 1 addition & 3 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@ classifiers =
License :: OSI Approved :: MIT License
Programming Language :: Python
Programming Language :: Python :: 3
Programming Language :: Python :: 3.8
Programming Language :: Python :: 3.9
Programming Language :: Python :: 3.10
Programming Language :: Python :: 3.11
Programming Language :: Python :: 3.12
Expand Down Expand Up @@ -46,7 +44,7 @@ config =

zip_safe = False

python_requires >= 3.8
python_requires >= 3.10

[options.entry_points]
console_scripts =
Expand Down
20 changes: 5 additions & 15 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,18 +33,8 @@
pydsdl_version_specifier = f"pydsdl {match.group(1)} {match.group(2)}"
package_data = {"": ["*.j2", "**/*.css", "**/*.js", "*.ini", "*.json", "*.hpp", "*.h"]}

if sys.version_info < (3, 9):
# For version 3.8 we need to add importlib_resources as a dependency. This seems to blow away the values
# in setup.cfg so we need to specify them here.
setuptools.setup(
version=version["__version__"],
package_data=package_data,
install_requires=["importlib_resources", pydsdl_version_specifier],
)
else:
# For version 3.9 and later we don't need to add importlib_resources as a dependency.
setuptools.setup(
version=version["__version__"],
package_data=package_data,
install_requires=[pydsdl_version_specifier],
)
setuptools.setup(
version=version["__version__"],
package_data=package_data,
install_requires=[pydsdl_version_specifier],
)
40 changes: 15 additions & 25 deletions src/nunavut/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,36 +15,26 @@
invoking the ``nunavut.generate_all`` method.

"""

import sys as _sys

from ._generators import AbstractGenerator
from ._generators import generate_all
from ._generators import generate_all_for_language
from ._generators import generate_all_from_namespace
from ._generators import generate_all_from_namespace_with_generators
from ._generators import basic_language_context_builder_from_args
from ._generators import (
AbstractGenerator,
basic_language_context_builder_from_args,
generate_all,
generate_all_for_language,
generate_all_from_namespace,
generate_all_from_namespace_with_generators,
)
from ._namespace import Namespace
from ._utilities import TEMPLATE_SUFFIX
from ._utilities import DefaultValue
from ._utilities import ResourceType
from ._utilities import ResourceSearchPolicy
from ._utilities import YesNoDefault
from ._version import __author__
from ._version import __copyright__
from ._version import __email__
from ._version import __license__
from ._version import __version__
from .jinja import CodeGenerator
from .jinja import DSDLCodeGenerator
from .jinja import SupportGenerator
from .lang import Language
from .lang import LanguageContext
from .lang import LanguageContextBuilder
from .lang import UnsupportedLanguageError
from ._utilities import TEMPLATE_SUFFIX, DefaultValue, ResourceSearchPolicy, ResourceType, YesNoDefault
from ._version import __author__, __copyright__, __email__, __license__, __version__
from .jinja import CodeGenerator, DSDLCodeGenerator, SupportGenerator
from .lang import Language, LanguageContext, LanguageContextBuilder, UnsupportedLanguageError
from .lang._config import LanguageConfig

if _sys.version_info[:2] < (3, 8): # pragma: no cover
print("A newer version of Python is required", file=_sys.stderr)
if _sys.version_info[:2] < (3, 10): # pragma: no cover
print("Python 3.10 or newer is required", file=_sys.stderr)
_sys.exit(1)

__version_info__ = tuple(map(int, __version__.split(".")[:3]))
Expand Down
1 change: 0 additions & 1 deletion src/nunavut/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,4 @@

from .cli.runners import main as cli_main


sys.exit(cli_main())
87 changes: 38 additions & 49 deletions src/nunavut/_namespace.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,9 @@
Iterator,
KeysView,
List,
Optional,
Protocol,
Tuple,
TypeVar,
Union,
cast,
)

Expand All @@ -79,15 +77,6 @@
from .lang import Language, LanguageContext
from .lang._common import IncludeGenerator

if sys.version_info < (3, 9):
# Python 3.8 has a bug. This is a workaround per https://stackoverflow.com/a/66518591/310659
def _register(self, cls, method=None): # type: ignore
if hasattr(cls, "__func__"):
setattr(cls, "__annotations__", cls.__func__.__annotations__)
return self.dispatcher.register(cls, func=method)

singledispatchmethod.register = _register # type: ignore

# +--------------------------------------------------------------------------------------------------------------------+


Expand All @@ -96,7 +85,7 @@ class AsyncResultProtocol(Protocol):
Defines the protocol for a duck-type compatible with multiprocessing.pool.AsyncResult.
"""

def get(self, timeout: Optional[Any] = None) -> Any:
def get(self, timeout: Any | None = None) -> Any:
"""
See multiprocessing.pool.AsyncResult.get
"""
Expand All @@ -113,7 +102,7 @@ def __init__(self, read_method: Callable[..., Any], args: Tuple[Any, ...]) -> No
self.args = args
self._logger = logging.getLogger(NotAsyncResult.__name__)

def get(self, timeout: Optional[Any] = None) -> Any:
def get(self, timeout: Any | None = None) -> Any:
"""
Perform the work synchronously.
"""
Expand All @@ -130,7 +119,7 @@ def get(self, timeout: Optional[Any] = None) -> Any:
def _read_files_strategy(
index: "Namespace",
apply_method: ApplyMethodT,
dsdl_files: Union[Path, str, Iterable[Union[Path, str]]],
dsdl_files: Path | str | Iterable[Path | str],
job_timeout_seconds: float,
omit_dependencies: bool,
args: Iterable[Any],
Expand Down Expand Up @@ -274,7 +263,7 @@ def wrap(
"""
return Generatable(definition, input_types, path)

def with_segments(self, *pathsegments: Union[str, PathLike]) -> Path:
def with_segments(self, *pathsegments: str | PathLike) -> Path:
"""
Path override: Construct a new path object from any number of path-like objects.
We discard the Generatable type here and continue on with a default Path object.
Expand Down Expand Up @@ -380,11 +369,11 @@ def strop_namespace(cls, full_namespace: str, language_context: LanguageContext)
def add_types(
cls,
index: "Namespace",
types: Union[
Tuple[pydsdl.CompositeType, List[pydsdl.CompositeType]],
List[Tuple[pydsdl.CompositeType, List[pydsdl.CompositeType]]],
],
extension: Optional[str] = None,
types: (
Tuple[pydsdl.CompositeType, List[pydsdl.CompositeType]]
| List[Tuple[pydsdl.CompositeType, List[pydsdl.CompositeType]]]
),
extension: str | None = None,
) -> None:
"""
Add a set of types to a namespace tree building new nodes as needed.
Expand Down Expand Up @@ -441,9 +430,9 @@ def Identity(cls, output_path: Path, lctx: LanguageContext) -> "Namespace":
def read_namespace(
cls,
index: "Namespace",
root_namespace_directory: Union[Path, str],
lookup_directories: Optional[Union[Path, str, Iterable[Union[Path, str]]]] = None,
print_output_handler: Optional[Callable[[Path, int, str], None]] = None,
root_namespace_directory: Path | str,
lookup_directories: Path | str | Iterable[Path | str] | None = None,
print_output_handler: Callable[[Path, int, str], None] | None = None,
allow_unregulated_fixed_port_id: bool = False,
allow_root_namespace_name_collision: bool = True,
) -> "Namespace":
Expand Down Expand Up @@ -477,9 +466,9 @@ def _(
cls,
output_path: str,
lctx: LanguageContext,
root_namespace_directory: Union[Path, str],
lookup_directories: Optional[Union[Path, str, Iterable[Union[Path, str]]]] = None,
print_output_handler: Optional[Callable[[Path, int, str], None]] = None,
root_namespace_directory: Path | str,
lookup_directories: Path | str | Iterable[Path | str] | None = None,
print_output_handler: Callable[[Path, int, str], None] | None = None,
allow_unregulated_fixed_port_id: bool = False,
allow_root_namespace_name_collision: bool = True,
) -> pydsdl.Any:
Expand Down Expand Up @@ -510,9 +499,9 @@ def _(
cls,
output_path: Path,
lctx: LanguageContext,
root_namespace_directory: Union[Path, str],
lookup_directories: Optional[Union[Path, str, Iterable[Union[Path, str]]]] = None,
print_output_handler: Optional[Callable[[Path, int, str], None]] = None,
root_namespace_directory: Path | str,
lookup_directories: Path | str | Iterable[Path | str] | None = None,
print_output_handler: Callable[[Path, int, str], None] | None = None,
allow_unregulated_fixed_port_id: bool = False,
allow_root_namespace_name_collision: bool = True,
) -> pydsdl.Any:
Expand Down Expand Up @@ -542,12 +531,12 @@ def _(
def read_files(
cls,
index: "Namespace",
dsdl_files: Union[Path, str, Iterable[Union[Path, str]]],
root_namespace_directories_or_names: Optional[Union[Path, str, Iterable[Union[Path, str]]]],
dsdl_files: Path | str | Iterable[Path | str],
root_namespace_directories_or_names: Path | str | Iterable[Path | str] | None,
jobs: int = 0,
job_timeout_seconds: float = 0,
lookup_directories: Optional[Union[Path, str, Iterable[Union[Path, str]]]] = None,
print_output_handler: Optional[Callable[[Path, int, str], None]] = None,
lookup_directories: Path | str | Iterable[Path | str] | None = None,
print_output_handler: Callable[[Path, int, str], None] | None = None,
allow_unregulated_fixed_port_id: bool = False,
omit_dependencies: bool = False,
) -> "Namespace":
Expand Down Expand Up @@ -590,12 +579,12 @@ def _(
cls,
output_path: Path,
lctx: LanguageContext,
dsdl_files: Optional[Union[Path, str, Iterable[Union[Path, str]]]],
root_namespace_directories_or_names: Optional[Union[Path, str, Iterable[Union[Path, str]]]],
dsdl_files: Path | str | Iterable[Path | str] | None,
root_namespace_directories_or_names: Path | str | Iterable[Path | str] | None,
jobs: int = 0,
job_timeout_seconds: float = 0,
lookup_directories: Optional[Union[Path, str, Iterable[Union[Path, str]]]] = None,
print_output_handler: Optional[Callable[[Path, int, str], None]] = None,
lookup_directories: Path | str | Iterable[Path | str] | None = None,
print_output_handler: Callable[[Path, int, str], None] | None = None,
allow_unregulated_fixed_port_id: bool = False,
omit_dependencies: bool = False,
) -> pydsdl.Any:
Expand Down Expand Up @@ -633,12 +622,12 @@ def _(
cls,
output_path: str,
lctx: LanguageContext,
dsdl_files: Optional[Union[Path, str, Iterable[Union[Path, str]]]],
root_namespace_directories_or_names: Optional[Union[Path, str, Iterable[Union[Path, str]]]],
dsdl_files: Path | str | Iterable[Path | str] | None,
root_namespace_directories_or_names: Path | str | Iterable[Path | str] | None,
jobs: int = 0,
job_timeout_seconds: float = 0,
lookup_directories: Optional[Union[Path, str, Iterable[Union[Path, str]]]] = None,
print_output_handler: Optional[Callable[[Path, int, str], None]] = None,
lookup_directories: Path | str | Iterable[Path | str] | None = None,
print_output_handler: Callable[[Path, int, str], None] | None = None,
allow_unregulated_fixed_port_id: bool = False,
omit_dependencies: bool = False,
) -> pydsdl.Any:
Expand Down Expand Up @@ -677,7 +666,7 @@ def __init__(
full_namespace: str,
namespace_dir: Path,
language_context: LanguageContext,
parent: Optional["Namespace"] = None,
parent: "Namespace | None" = None,
):
if full_namespace.startswith("."):
full_namespace = full_namespace[1:]
Expand Down Expand Up @@ -741,7 +730,7 @@ def output_path(self) -> Path:
return self._output_path

@property
def parent(self) -> Optional["Namespace"]:
def parent(self) -> "Namespace | None":
"""
The parent namespace of this namespace or None if this is a root namespace.
"""
Expand Down Expand Up @@ -934,14 +923,14 @@ def get_all_namespaces(self) -> Generator[Tuple["Namespace", Path], None, None]:
"""
yield from self._recursive_namespace_generator(self)

def get_all_types(self) -> Generator[Tuple[pydsdl.Any, Union[Generatable, Path]], None, None]:
def get_all_types(self) -> Generator[Tuple[pydsdl.Any, Generatable | Path], None, None]:
"""
Generates tuples relating datatypes and nested namespaces at and below this
namespace to the path for each type's generated output.
"""
yield from self._recursive_data_type_and_namespace_generator(self)

def find_output_path_for_type(self, compound_type: Union["Namespace", pydsdl.CompositeType]) -> Path:
def find_output_path_for_type(self, compound_type: "Namespace | pydsdl.CompositeType") -> Path:
"""
Searches the entire namespace tree to find a mapping of the type to an
output file path.
Expand All @@ -958,7 +947,7 @@ def find_output_path_for_type(self, compound_type: Union["Namespace", pydsdl.Com
return root_namespace._bfs_search_for_output_path(compound_type) # pylint: disable=protected-access

def add_data_type(
self, dsdl_type: pydsdl.CompositeType, input_types: List[pydsdl.CompositeType], extension: Optional[str]
self, dsdl_type: pydsdl.CompositeType, input_types: List[pydsdl.CompositeType], extension: str | None
) -> Generatable:
"""
Add a datatype to this namespace.
Expand Down Expand Up @@ -1098,7 +1087,7 @@ def _recursive_namespace_generator(cls, namespace: "Namespace") -> Generator[Tup
@classmethod
def _recursive_data_type_and_namespace_generator(
cls, namespace: "Namespace"
) -> Generator[Tuple[pydsdl.Any, Union[Path, Generatable]], None, None]:
) -> Generator[Tuple[pydsdl.Any, Path | Generatable], None, None]:
yield (namespace, namespace.output_path)

for data_type, output_path in namespace.get_nested_types():
Expand All @@ -1113,8 +1102,8 @@ def _recursive_data_type_and_namespace_generator(

def build_namespace_tree(
types: List[pydsdl.CompositeType],
root_namespace_dir: Union[str, Path],
output_dir: Union[str, Path],
root_namespace_dir: str | Path,
output_dir: str | Path,
language_context: LanguageContext,
) -> Namespace:
"""
Expand Down
3 changes: 2 additions & 1 deletion src/nunavut/_postprocessors.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@
"""
Module containing post processing logic to run on generated files.
"""

import abc
import pathlib
import typing
import re
import sys
import typing
from subprocess import run as subprocess_run # nosec

# +---------------------------------------------------------------------------+
Expand Down
1 change: 1 addition & 0 deletions src/nunavut/_templates.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"""
Abstractions around template engine internals.
"""

import functools
import inspect
import types
Expand Down
Loading
Loading