Skip to content

Commit

Permalink
Cleanup (OpenCyphal#93)
Browse files Browse the repository at this point in the history
- Update the development-related dependencies.

- Demote Python v3.6 and v3.7 to minimally supported versions (no
linting, no coverage).

- Fix OpenCyphal#84. `os.path` is no
longer used, and dependency on the text representations of paths is
minimized.

- Refactor the test suite to eliminate the global state and simplify the
internal APIs.

- The library now logs a warning when it encounters a `*.uavcan` file,
suggesting renaming it to `*.dsdl`. See
https://forum.opencyphal.org/t/uavcan-file-extension/438/8. There are no
plans to remove support for `*.uavcan` but it is desirable to push users
towards consistency.

- Bump the minor version.
  • Loading branch information
pavel-kirienko authored Apr 26, 2023
1 parent fc0715c commit 7f0270c
Show file tree
Hide file tree
Showing 11 changed files with 569 additions and 553 deletions.
3 changes: 2 additions & 1 deletion .idea/dictionaries/pavel.xml

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

4 changes: 2 additions & 2 deletions appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,11 @@ for:
- python --version
test_script:
# GNU/Linux test.
- sh: nox --non-interactive --error-on-missing-interpreters --session test lint --python $PYTHON
- sh: nox --non-interactive --error-on-missing-interpreters --session test test_eol pristine lint --python $PYTHON
# skip macOS docs build
- sh: 'if [ "$APPVEYOR_BUILD_WORKER_IMAGE" != "macos" ]; then nox --non-interactive --session docs; fi'
# MS Windows test.
- cmd: nox --forcecolor --non-interactive --error-on-missing-interpreters --session test lint
- cmd: nox --forcecolor --non-interactive --error-on-missing-interpreters --session test test_eol pristine lint
# Shared test for all platforms.
- git clone https://github.com/OpenCyphal/public_regulated_data_types .dsdl-test
- python -c "import pydsdl; pydsdl.read_namespace('.dsdl-test/uavcan', [])"
Expand Down
35 changes: 28 additions & 7 deletions noxfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@
import os
import shutil
from pathlib import Path
from functools import partial
import nox


PYTHONS = ["3.6", "3.7", "3.8", "3.9", "3.10", "3.11"]
PYTHONS = ["3.8", "3.9", "3.10", "3.11"]
"""The newest supported Python shall be listed LAST."""

nox.options.error_on_external_run = True
Expand Down Expand Up @@ -48,9 +49,9 @@ def test(session):
session.log("Using the newest supported Python: %s", is_latest_python(session))
session.install("-e", ".")
session.install(
"pytest ~= 7.0",
"pytest-randomly ~= 3.10",
"coverage ~= 6.2",
"pytest ~= 7.3",
"pytest-randomly ~= 3.12",
"coverage ~= 7.2",
)
session.run("coverage", "run", "-m", "pytest")
session.run("coverage", "report", "--fail-under=95")
Expand All @@ -60,12 +61,32 @@ def test(session):
session.log(f"OPEN IN WEB BROWSER: file://{report_file}")


@nox.session(python=["3.6", "3.7"])
def test_eol(session):
"""This is a minimal test session for those old Pythons that have EOLed."""
session.install("-e", ".")
session.install("pytest")
session.run("pytest")


@nox.session(python=PYTHONS)
def pristine(session):
"""
Install the library into a pristine environment and ensure that it is importable.
This is needed to catch errors caused by accidental reliance on test dependencies in the main codebase.
"""
exe = partial(session.run, "python", "-c", silent=True)
session.cd(session.create_tmp()) # Change the directory to reveal spurious dependencies from the project root.
session.install(f"{ROOT_DIR}") # Testing bare installation first.
exe("import pydsdl")


@nox.session(python=PYTHONS, reuse_venv=True)
def lint(session):
session.log("Using the newest supported Python: %s", is_latest_python(session))
session.install(
"mypy == 0.942",
"pylint == 2.13.*",
"mypy ~= 1.2.0",
"pylint ~= 2.17.2",
)
session.run(
"mypy",
Expand All @@ -84,7 +105,7 @@ def lint(session):
},
)
if is_latest_python(session):
session.install("black == 22.*")
session.install("black ~= 23.3")
session.run("black", "--check", ".")


Expand Down
6 changes: 3 additions & 3 deletions pydsdl/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@

# pylint: disable=wrong-import-position

import os as _os
import sys as _sys
from pathlib import Path as _Path

__version__ = "1.18.0"
__version__ = "1.19.0"
__version_info__ = tuple(map(int, __version__.split(".")[:3]))
__license__ = "MIT"
__author__ = "OpenCyphal"
Expand All @@ -22,7 +22,7 @@
# to import stuff dynamically after the initialization is finished (e.g., function-local imports won't be
# able to reach the third-party stuff), but we don't care.
_original_sys_path = _sys.path
_sys.path = [_os.path.join(_os.path.dirname(__file__), "third_party")] + _sys.path
_sys.path = [str(_Path(__file__).parent / "third_party")] + _sys.path

# Never import anything that is not available here - API stability guarantees are only provided for the exposed items.
from ._namespace import read_namespace as read_namespace
Expand Down
2 changes: 1 addition & 1 deletion pydsdl/_bit_length_set/_symbolic.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ def modulo(self, divisor: int) -> typing.Set[int]:
mods = [ch.modulo(divisor) for ch in self._children]
prod = itertools.product(*mods)
sums = set(map(sum, prod))
return {typing.cast(int, x) % divisor for x in sums}
return {x % divisor for x in sums}

@property
def min(self) -> int:
Expand Down
17 changes: 4 additions & 13 deletions pydsdl/_dsdl_definition.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
# This software is distributed under the terms of the MIT License.
# Author: Pavel Kirienko <[email protected]>

import os
import time
from typing import Iterable, Callable, Optional, List
import logging
Expand Down Expand Up @@ -41,21 +40,14 @@ def __init__(self, file_path: Path, root_namespace_path: Path):
self._text = str(f.read())

# Checking the sanity of the root directory path - can't contain separators
if CompositeType.NAME_COMPONENT_SEPARATOR in os.path.split(self._root_namespace_path)[-1]:
if CompositeType.NAME_COMPONENT_SEPARATOR in self._root_namespace_path.name:
raise FileNameFormatError("Invalid namespace name", path=self._root_namespace_path)

# Determining the relative path within the root namespace directory
relative_path = str(
os.path.join(
os.path.split(self._root_namespace_path)[-1],
self._file_path.relative_to(self._root_namespace_path),
)
)

relative_directory, basename = [str(x) for x in os.path.split(relative_path)] # type: str, str
relative_path = self._root_namespace_path.name / self._file_path.relative_to(self._root_namespace_path)

# Parsing the basename, e.g., 434.GetTransportStatistics.0.1.dsdl
basename_components = basename.split(".")[:-1]
basename_components = relative_path.name.split(".")[:-1]
str_fixed_port_id: Optional[str] = None
if len(basename_components) == 4:
str_fixed_port_id, short_name, str_major_version, str_minor_version = basename_components
Expand Down Expand Up @@ -86,11 +78,10 @@ def __init__(self, file_path: Path, root_namespace_path: Path):
raise FileNameFormatError("Could not parse the version numbers", path=self._file_path) from None

# Finally, constructing the name
namespace_components = list(relative_directory.strip(os.sep).split(os.sep))
namespace_components = list(relative_path.parent.parts)
for nc in namespace_components:
if CompositeType.NAME_COMPONENT_SEPARATOR in nc:
raise FileNameFormatError(f"Invalid name for namespace component: {nc!r}", path=self._file_path)

self._name: str = CompositeType.NAME_COMPONENT_SEPARATOR.join(namespace_components + [str(short_name)])

self._cached_type: Optional[CompositeType] = None
Expand Down
Loading

0 comments on commit 7f0270c

Please sign in to comment.