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

test-pyproject-toml #47

Closed
wants to merge 15 commits into from
Closed
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
18 changes: 7 additions & 11 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,7 @@ jobs:
- name: Install Python dependencies
run: |
python -m pip install --upgrade pip
pip install coverage
pip install -r requirements.txt
pip install .[dev,test]
- name: Setup test config and CouchDB database server
run: |
python test/_helper/setup_testdb.py -u "admin" -p "$COUCHDB_ADMIN_PASSWORD"
Expand All @@ -62,11 +61,10 @@ jobs:
- name: Install Python dependencies
run: |
python -m pip install --upgrade pip
pip install pycodestyle mypy
pip install -r requirements.txt
pip install .[dev]
- name: Check typing with MyPy
run: |
mypy basyx test
mypy --install-types --non-interactive basyx test
- name: Check code style with PyCodestyle
run: |
pycodestyle --count --max-line-length 120 basyx test
Expand All @@ -83,8 +81,7 @@ jobs:
- name: Install Python dependencies
run: |
python -m pip install --upgrade pip
pip install pycodestyle mypy codeblocks
pip install -r requirements.txt
pip install .[dev]
- name: Check typing with MyPy
run: |
mypy <(codeblocks python README.md)
Expand All @@ -107,8 +104,7 @@ jobs:
- name: Install Python dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
pip install -r docs/add-requirements.txt
pip install .[docs]
- name: Check documentation for errors
run: |
SPHINXOPTS="-a -E -n -W --keep-going" make -C docs html
Expand All @@ -125,7 +121,7 @@ jobs:
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install setuptools wheel
pip install build
- name: Create source and wheel dist
run: |
python setup.py sdist bdist_wheel
python -m build
26 changes: 24 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,29 @@
/htmlcov/
/docs/build/

# customized config files
/test/test_config.ini

# Schema files needed for testing
/test/adapter/schemas


# Python build artifacts
__pycache__/
*.py[cod]
*$py.class
*.so
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
9 changes: 9 additions & 0 deletions basyx/aas/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,12 @@
"""

__version__ = "1.0.0"

from dateutil.relativedelta import relativedelta as Duration

# If you're using TYPE_CHECKING elsewhere, you might want to do this instead:
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from dateutil.relativedelta import relativedelta as Duration
else:
from dateutil.relativedelta import relativedelta as Duration
3 changes: 3 additions & 0 deletions basyx/aas/model/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@
if TYPE_CHECKING:
from . import provider

if TYPE_CHECKING:
from dateutil.relativedelta import relativedelta as Duration

DataTypeDefXsd = Type[datatypes.AnyXSDType]
ValueDataType = datatypes.AnyXSDType # any xsd atomic type (from .datatypes)
ValueList = Set["ValueReferencePair"]
Expand Down
15 changes: 9 additions & 6 deletions basyx/aas/model/datatypes.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,12 @@
import re
from typing import Type, Union, Dict, Optional

import dateutil.relativedelta
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from dateutil.relativedelta import relativedelta as Duration
else:
from dateutil.relativedelta import relativedelta as Duration

Duration = dateutil.relativedelta.relativedelta
DateTime = datetime.datetime
Time = datetime.time
Boolean = bool
Expand Down Expand Up @@ -354,13 +357,13 @@ def from_string(cls, value: str) -> "NormalizedString":


AnyXSDType = Union[
Duration, DateTime, Date, Time, GYearMonth, GYear, GMonthDay, GMonth, GDay, Boolean, Base64Binary,
'Duration', DateTime, Date, Time, GYearMonth, GYear, GMonthDay, GMonth, GDay, Boolean, Base64Binary,
HexBinary, Float, Double, Decimal, Integer, Long, Int, Short, Byte, NonPositiveInteger, NegativeInteger,
NonNegativeInteger, PositiveInteger, UnsignedLong, UnsignedInt, UnsignedShort, UnsignedByte, AnyURI, String,
NormalizedString]


XSD_TYPE_NAMES: Dict[Type[AnyXSDType], str] = {k: "xs:" + v for k, v in {
XSD_TYPE_NAMES: Dict[Union[Type[AnyXSDType], Type['Duration']], str] = {k: "xs:" + v for k, v in {
Duration: "duration",
DateTime: "dateTime",
Date: "date",
Expand Down Expand Up @@ -478,7 +481,7 @@ def _serialize_date_tzinfo(date: Union[Date, GYear, GMonth, GDay, GYearMonth, GM
return ""


def _serialize_duration(value: Duration) -> str:
def _serialize_duration(value: 'Duration') -> str:
value = value.normalized()
signs = set(val < 0
for val in (value.years, value.months, value.days, value.hours, value.minutes, value.seconds,
Expand Down Expand Up @@ -563,7 +566,7 @@ def from_xsd(value: str, type_: Type[AnyXSDType]) -> AnyXSDType: # workaround.
DATE_RE = re.compile(r'^(-?)(\d\d\d\d)-(\d\d)-(\d\d)([+\-](\d\d):(\d\d)|Z)?$')


def _parse_xsd_duration(value: str) -> Duration:
def _parse_xsd_duration(value: str) -> 'Duration':
match = DURATION_RE.match(value)
if not match:
raise ValueError("Value is not a valid XSD duration string")
Expand Down
26 changes: 18 additions & 8 deletions basyx/aas/model/submodel.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,24 @@
# SPDX-License-Identifier: MIT
"""
This module contains everything needed to model Submodels and define Events according to the AAS metamodel.

.. data:: Duration

An alias for :class:`dateutil.relativedelta.relativedelta`, used to represent time durations.
"""

import abc
import uuid
from typing import Optional, Set, Iterable, TYPE_CHECKING, List, Type, TypeVar, Generic, Union
from typing import Optional, Set, Iterable, TYPE_CHECKING, List, Type, TypeVar, Generic, Union, NewType

from . import base, datatypes, _string_constraints
if TYPE_CHECKING:
from . import aas

from dateutil.relativedelta import relativedelta
Duration = NewType('Duration', relativedelta)



class SubmodelElement(base.Referable, base.Qualifiable, base.HasSemantics,
base.HasDataSpecification, metaclass=abc.ABCMeta):
Expand Down Expand Up @@ -1255,9 +1263,11 @@ class BasicEventElement(EventElement):
:ivar min_interval: For input direction, reports on the maximum frequency, the software entity behind the respective
Referable can handle input events. For output events, specifies the maximum frequency of
outputting this event to an outer infrastructure.
:type min_interval: Optional[Duration]
:ivar max_interval: For input direction: not applicable.
For output direction: maximum interval in time, the respective Referable shall send an update of
the status of the event, even if no other trigger condition for the event was not met.
:type max_interval: Optional[Duration]
:ivar display_name: Can be provided in several languages. (inherited from :class:`~basyx.aas.model.base.Referable`)
:ivar category: The category is a value that gives further meta information w.r.t. to the class of the element.
It affects the expected existence of attributes and the applicability of constraints.
Expand Down Expand Up @@ -1287,8 +1297,8 @@ def __init__(self,
message_broker: Optional[base.ModelReference[Union[Submodel, SubmodelElementList,
SubmodelElementCollection, Entity]]] = None,
last_update: Optional[datatypes.DateTime] = None,
min_interval: Optional[datatypes.Duration] = None,
max_interval: Optional[datatypes.Duration] = None,
min_interval: Optional[Duration] = None,
max_interval: Optional[Duration] = None,
display_name: Optional[base.MultiLanguageNameType] = None,
category: Optional[base.NameType] = None,
description: Optional[base.MultiLanguageTextType] = None,
Expand All @@ -1313,8 +1323,8 @@ def __init__(self,
self.message_broker: Optional[base.ModelReference[Union[Submodel, SubmodelElementList,
SubmodelElementCollection, Entity]]] = message_broker
self.last_update: Optional[datatypes.DateTime] = last_update
self.min_interval: Optional[datatypes.Duration] = min_interval
self.max_interval: Optional[datatypes.Duration] = max_interval
self.min_interval: Optional[Duration] = min_interval
self.max_interval: Optional[Duration] = max_interval

@property
def direction(self) -> base.Direction:
Expand All @@ -1337,11 +1347,11 @@ def last_update(self, last_update: Optional[datatypes.DateTime]) -> None:
self._last_update: Optional[datatypes.DateTime] = last_update

@property
def max_interval(self) -> Optional[datatypes.Duration]:
def max_interval(self) -> Optional[Duration]:
return self._max_interval

@max_interval.setter
def max_interval(self, max_interval: Optional[datatypes.Duration]) -> None:
def max_interval(self, max_interval: Optional[Duration]) -> None:
if max_interval is not None and self.direction is base.Direction.INPUT:
raise ValueError("max_interval is not applicable if direction = input!")
self._max_interval: Optional[datatypes.Duration] = max_interval
self._max_interval: Optional['Duration'] = max_interval
2 changes: 2 additions & 0 deletions basyx/aas/version.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# basyx/aas/version.py
__version__ = '0.1.0'
24 changes: 19 additions & 5 deletions docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,28 @@
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#
import os
import sys
import datetime

from typing import Dict, Any
from unittest.mock import MagicMock

sys.path.insert(0, os.path.abspath('../..'))
from basyx.aas import __version__


class Mock(MagicMock):
@classmethod
def __getattr__(cls, name):
return MagicMock()


MOCK_MODULES = ['dateutil', 'dateutil.relativedelta']
sys.modules.update((mod_name, Mock()) for mod_name in MOCK_MODULES)

autodoc_mock_imports = ['dateutil']


# -- Project information -----------------------------------------------------

project = 'Eclipse BaSyx Python SDK'
Expand All @@ -28,13 +40,11 @@
# The full version, including alpha/beta/rc tags
release = __version__


# -- General configuration ---------------------------------------------------

# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.

extensions = [
'sphinx.ext.autodoc',
'sphinx.ext.coverage',
Expand Down Expand Up @@ -67,6 +77,11 @@
'lxml': ('https://lxml.de/apidoc/', None)
}

# Add a new configuration for type aliases
autodoc_type_aliases: Dict[str, str] = {
'Duration': 'dateutil.relativedelta.relativedelta',
}


def on_missing_reference(app, env, node, contnode):
path = node["reftarget"].split(".")
Expand All @@ -85,7 +100,6 @@ def setup(app):

# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
html_theme = 'sphinx_rtd_theme'

# Add any paths that contain custom static files (such as style sheets) here,
Expand Down
Loading
Loading