Skip to content

Commit

Permalink
Updated CI and added ruff (#21)
Browse files Browse the repository at this point in the history
Updated CI and applied some fixes
  • Loading branch information
spacemanspiff2007 authored Apr 5, 2024
1 parent 068f2b6 commit 5f3b8f9
Show file tree
Hide file tree
Showing 36 changed files with 264 additions and 132 deletions.
10 changes: 5 additions & 5 deletions .github/workflows/publish-pypi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,16 @@ jobs:
build-n-publish:
name: Build and publish Python 🐍 distributions 📦 to PyPI and TestPyPI
runs-on: ubuntu-latest
environment: pypi
permissions:
id-token: write # IMPORTANT: this permission is mandatory for trusted publishing

steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
ref: master
- name: Set up Python 3.10
uses: actions/setup-python@v4
uses: actions/setup-python@v5
with:
python-version: '3.10'

Expand All @@ -28,6 +31,3 @@ jobs:
- name: Publish distribution to PyPI
uses: pypa/gh-action-pypi-publish@master
with:
user: __token__
password: ${{ secrets.pypi_api_key }}
8 changes: 4 additions & 4 deletions .github/workflows/run_tox.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ jobs:
name: pre-commit
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.10'
- uses: pre-commit/[email protected]
Expand All @@ -23,9 +23,9 @@ jobs:
python-version: ['3.8', '3.9', '3.10', '3.11', '3.12']

steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
Expand Down
18 changes: 5 additions & 13 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,18 @@ repos:
- id: check-builtin-literals
- id: check-docstring-first
- id: check-merge-conflict
# - id: check-toml
- id: check-toml
- id: check-yaml
- id: debug-statements
- id: end-of-file-fixer
- id: trailing-whitespace

- repo: https://github.com/pycqa/isort
rev: 5.12.0
hooks:
- id: isort
name: isort (python)

- repo: https://github.com/PyCQA/flake8
rev: '6.1.0'
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.3.5
hooks:
- id: flake8
additional_dependencies:
- flake8-bugbear==23.9.16
- flake8-comprehensions==3.14
- flake8-noqa==1.3
- id: ruff


- repo: meta
hooks:
Expand Down
66 changes: 66 additions & 0 deletions .ruff.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@

line-length = 120
indent-width = 4

target-version = "py38"
src = ["src", "test"]

[lint]

# https://docs.astral.sh/ruff/settings/#ignore-init-module-imports
ignore-init-module-imports = true

select = [
"E", "W", # https://docs.astral.sh/ruff/rules/#pycodestyle-e-w
"I", # https://docs.astral.sh/ruff/rules/#isort-i
"UP", # https://docs.astral.sh/ruff/rules/#pyupgrade-up

"A", # https://docs.astral.sh/ruff/rules/#flake8-builtins-a
"ASYNC", # https://docs.astral.sh/ruff/rules/#flake8-async-async
"C4", # https://docs.astral.sh/ruff/rules/#flake8-comprehensions-c4
"EM", # https://docs.astral.sh/ruff/rules/#flake8-errmsg-em
"FIX", # https://docs.astral.sh/ruff/rules/#flake8-fixme-fix
"INP", # https://docs.astral.sh/ruff/rules/#flake8-no-pep420-inp
"ISC", # https://docs.astral.sh/ruff/rules/#flake8-implicit-str-concat-isc
"PIE", # https://docs.astral.sh/ruff/rules/#flake8-pie-pie
"PT", # https://docs.astral.sh/ruff/rules/#flake8-pytest-style-pt
"PTH", # https://docs.astral.sh/ruff/rules/#flake8-use-pathlib-pth
"RET", # https://docs.astral.sh/ruff/rules/#flake8-return-ret
"SIM", # https://docs.astral.sh/ruff/rules/#flake8-simplify-sim
"SLOT", # https://docs.astral.sh/ruff/rules/#flake8-slots-slot
"T10", # https://docs.astral.sh/ruff/rules/#flake8-debugger-t10
"TCH", # https://docs.astral.sh/ruff/rules/#flake8-type-checking-tch
"TD", # https://docs.astral.sh/ruff/rules/#flake8-todos-td

"TRY", # https://docs.astral.sh/ruff/rules/#tryceratops-try
"FLY", # https://docs.astral.sh/ruff/rules/#flynt-fly
"PERF", # https://docs.astral.sh/ruff/rules/#perflint-perf
"RUF", # https://docs.astral.sh/ruff/rules/#ruff-specific-rules-ruf

# "PL", # https://docs.astral.sh/ruff/rules/#pylint-pl
# "FURB", # https://docs.astral.sh/ruff/rules/#refurb-furb
]

ignore = [
"PT007" # Wrong values type in `@pytest.mark.parametrize` expected `list` of `tuple`
]


[format]
# Use single quotes for non-triple-quoted strings.
quote-style = "single"


# [lint.flake8-builtins]
# builtins-ignorelist = ["id", "input"]


[lint.per-file-ignores]
"src/smllib/errors.py" = ["A002"] # Argument `type` is shadowing a Python builtin
"src/smllib/sml/_field_info.py" = ["A002"] # Argument `type` is shadowing a Python builtin
"tests/*" = ["INP001"] # INP001 File `PATH` is part of an implicit namespace package. Add an `__init__.py`.


[lint.isort]
# https://docs.astral.sh/ruff/settings/#lint_isort_lines-after-imports
lines-after-imports = 2
17 changes: 15 additions & 2 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,15 @@
pytest == 7.4.2
pre-commit == 3.5.0
# -----------------------------------------------------------------------------
# Packages required for testing
# -----------------------------------------------------------------------------
-r requirements_tests.txt

# -----------------------------------------------------------------------------
# Packages for source formatting
# -----------------------------------------------------------------------------
ruff == 0.3.4
pre-commit == 3.7.0

# -----------------------------------------------------------------------------
# Packages for other developement tasks
# -----------------------------------------------------------------------------
pur == 7.3.1 # Update requirements.txt
1 change: 1 addition & 0 deletions requirements_tests.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pytest == 8.1.1
4 changes: 2 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import typing
from pathlib import Path

import setuptools # type: ignore
import setuptools


def load_version() -> str:
version: typing.Dict[str, str] = {}
with open("src/smllib/__version__.py") as fp:
with (Path(__file__).parent / "src/smllib/__version__.py").open() as fp:
exec(fp.read(), version)
assert version['__version__'], version
return version['__version__']
Expand Down
1 change: 1 addition & 0 deletions src/smllib/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from smllib import errors
from smllib.__version__ import __version__


# isort: split

import smllib.reader
Expand Down
2 changes: 1 addition & 1 deletion src/smllib/__version__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = '1.3'
__version__ = '1.4'
8 changes: 6 additions & 2 deletions src/smllib/builder/__init__.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
from ._builder import SmlObjBuilder, T_SML_BUILDER
from ._builder import T_SML_BUILDER, SmlObjBuilder


# isort: split


from .list_entry import SmlListEntryBuilder
from .message import SmlMessageBuilder
from .response_get_list import SmlGetListResponseBuilder
from .response_open_close import SmlCloseResponseBuilder, SmlOpenResponseBuilder


# isort: split

from .default_context import create_context, CTX_HINT

from .default_context import CTX_HINT, create_context
5 changes: 3 additions & 2 deletions src/smllib/builder/_builder.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from typing import Dict, Generic, Type, TypeVar

from smllib.errors import WrongArgCount, WrongValueType
from smllib.sml import inspect_obj, SmlBaseObj, SmlObjFieldInfo, T_SML_OBJ
from smllib.sml import T_SML_OBJ, SmlBaseObj, SmlObjFieldInfo, inspect_obj
from smllib.sml_frame_snippet import SmlFrameSnippet


Expand Down Expand Up @@ -37,7 +37,8 @@ def build(self, obj: SmlFrameSnippet, classes: Dict[Type[SmlBaseObj], 'SmlObjBui
value = tuple([cls_builder.build(v, classes) for v in value])
else:
if not isinstance(value, field.type):
raise WrongValueType(f'{value} ({type(value)}) != {field.type}')
msg = f'{value} ({type(value)}) != {field.type}'
raise WrongValueType(msg)

setattr(out, name, value)
return out
Expand Down
11 changes: 9 additions & 2 deletions src/smllib/builder/default_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,15 @@

from smllib.sml import SmlBaseObj, SmlCloseResponse, SmlGetListResponse, SmlListEntry, SmlMessage, SmlOpenResponse

from . import SmlCloseResponseBuilder, SmlGetListResponseBuilder, \
SmlListEntryBuilder, SmlMessageBuilder, SmlOpenResponseBuilder, T_SML_BUILDER
from . import (
T_SML_BUILDER,
SmlCloseResponseBuilder,
SmlGetListResponseBuilder,
SmlListEntryBuilder,
SmlMessageBuilder,
SmlOpenResponseBuilder,
)


CTX_HINT = Dict[Type[SmlBaseObj], T_SML_BUILDER]

Expand Down
3 changes: 2 additions & 1 deletion src/smllib/builder/list_entry.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ def build(self, obj: SmlFrameSnippet, classes: Dict[Type[SmlBaseObj], 'SmlObjBui

value = ret.value
if value is None:
raise ValueError('value is required!')
msg = 'value is required!'
raise ValueError(msg)

# Maybe it's ascii so we try to decode it
if isinstance(value, str):
Expand Down
1 change: 1 addition & 0 deletions src/smllib/crc.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from typing import Union


CRC16_X25_TABLE = (
0x0000, 0x1189, 0x2312, 0x329B, 0x4624, 0x57AD, 0x6536, 0x74BF,
0x8C48, 0x9DC1, 0xAF5A, 0xBED3, 0xCA6C, 0xDBE5, 0xE97E, 0xF8F7,
Expand Down
2 changes: 1 addition & 1 deletion src/smllib/reader.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from typing import Optional

from smllib.builder import create_context, CTX_HINT
from smllib.builder import CTX_HINT, create_context
from smllib.crc import get_crc
from smllib.errors import CrcError
from smllib.sml_frame import SmlFrame
Expand Down
14 changes: 12 additions & 2 deletions src/smllib/sml/__init__.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,29 @@
from smllib.sml._base_obj import SmlBaseObj, T_SML_OBJ
from smllib.sml._base_obj import T_SML_OBJ, SmlBaseObj
from smllib.sml.sml_eom import EndOfSmlMsg


# isort: split


from smllib.sml.sml_choice import SmlChoice


# isort: split
from smllib.sml._field_info import inspect_obj, SmlObjFieldInfo


from smllib.sml._field_info import SmlObjFieldInfo, inspect_obj


# isort: split


from smllib.sml.list_entry import SmlListEntry
from smllib.sml.response_get_list import SmlGetListResponse
from smllib.sml.response_open_close import SmlCloseResponse, SmlOpenResponse
from smllib.sml.sml_obis import ObisCode


# isort: split


from smllib.sml.message import SmlMessage
10 changes: 6 additions & 4 deletions src/smllib/sml/_base_obj.py
Original file line number Diff line number Diff line change
@@ -1,24 +1,26 @@
import typing
from typing import Final, TypeVar


INDENT: Final = ' '


class SmlBaseObj:
__sml__: dict
__sml__: typing.ClassVar[dict]

def format_msg(self, indent: int = 0):
indent += 1
r = f'<{self.__class__.__name__}>\n'
w = max(map(len, self.__dict__), default=0)
for k, v in self.__dict__.items():
if isinstance(v, SmlBaseObj):
r += f'{INDENT * indent}{str(k):s} {v.format_msg(indent)}'
r += f'{INDENT * indent}{k!s:s} {v.format_msg(indent)}'
elif isinstance(v, (tuple, list)):
r += f'{INDENT * indent}{str(k):s}:\n'
r += f'{INDENT * indent}{k!s:s}:\n'
for e in v:
r += f'{INDENT * (indent + 1)}{e.format_msg(indent + 1)}'
else:
r += f'{INDENT * indent}{str(k):{w}s}: {v}\n'
r += f'{INDENT * indent}{k!s:{w}s}: {v}\n'
return r


Expand Down
5 changes: 3 additions & 2 deletions src/smllib/sml/_field_info.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Any, Callable, Dict, Final, get_args, get_origin, get_type_hints, Optional, Type, Union
from typing import Any, Callable, Dict, Final, Optional, Type, Union, get_args, get_origin, get_type_hints

from smllib.sml import SmlBaseObj, SmlChoice

Expand Down Expand Up @@ -64,6 +64,7 @@ def inspect_obj(cls: Type['SmlBaseObj']) -> Dict[str, SmlObjFieldInfo]:
info.type = args[0]
continue

raise ValueError(f'Unknown hint: {origin} for {name}')
msg = f'Unknown hint: {origin} for {name}'
raise ValueError(msg)

return fields
10 changes: 5 additions & 5 deletions src/smllib/sml/list_entry.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
from typing import Dict, Optional, Union
from typing import ClassVar, Dict, Optional, Union

from smllib.const import OBIS_NAMES, UNITS
from smllib.sml import SmlObjFieldInfo
from smllib.sml._base_obj import INDENT, SmlBaseObj

from .sml_obis import build_obis, ObisCode
from .sml_time import build_time, TIME_HINT
from .sml_obis import ObisCode, build_obis
from .sml_time import TIME_HINT, build_time


class SmlListEntry(SmlBaseObj):
__sml__: Dict[str, SmlObjFieldInfo] = {
__sml__: ClassVar[Dict[str, SmlObjFieldInfo]] = {
'val_time': SmlObjFieldInfo(func=build_time),
'obis': SmlObjFieldInfo(func=build_obis)
}
Expand All @@ -35,7 +35,7 @@ def format_msg(self, indent: int = 0):
w = max(map(len, self.__dict__), default=0)

for k, v in self.__dict__.items():
r += f'{INDENT*indent}{str(k):{w}s}: {v}{f" ({self.obis.obis_code})" if k == "obis" else ""}\n'
r += f'{INDENT*indent}{k!s:{w}s}: {v}{f" ({self.obis.obis_code})" if k == "obis" else ""}\n'

summary = ''
if self.unit:
Expand Down
Loading

0 comments on commit 5f3b8f9

Please sign in to comment.