Skip to content

Commit

Permalink
chore: Adopt ruff for checks, linting, and formatting (#390)
Browse files Browse the repository at this point in the history
  • Loading branch information
hairmare authored Dec 21, 2024
1 parent 11cf9e6 commit c13b95d
Show file tree
Hide file tree
Showing 19 changed files with 177 additions and 189 deletions.
33 changes: 0 additions & 33 deletions .flake8

This file was deleted.

2 changes: 1 addition & 1 deletion .github/workflows/lint-and-test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: [ '3.x', '3.11' ]
python-version: [ '3.x', '3.12' ]
name: Test python ${{ matrix.python-version }}
steps:
- name: Checkout
Expand Down
7 changes: 0 additions & 7 deletions .isort.cfg

This file was deleted.

20 changes: 4 additions & 16 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,21 +1,9 @@
repos:
- repo: local
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: 'v0.8.4'
hooks:
- id: black
name: black
language: system
entry: black
types: [python]
- id: isort
name: isort
language: system
entry: isort
types: [python]
- id: flake8
name: flake8
language: system
entry: flake8
types: [python]
- id: ruff
- id: ruff-format
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.0.1
hooks:
Expand Down
10 changes: 0 additions & 10 deletions .pylintrc

This file was deleted.

1 change: 0 additions & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
#
# nowplaypadgen documentation build configuration file, created by
# sphinx-quickstart on Thu Aug 31 22:55:28 2017.
Expand Down
87 changes: 41 additions & 46 deletions nowplaypadgen/dlplus.py
Original file line number Diff line number Diff line change
Expand Up @@ -436,13 +436,12 @@ class DLPlusMessage:
<class 'nowplaypadgen.dlplus.DLPlusTag'>
"""

def __init__(self):
def __init__(self) -> None:
"""Create class:`DLPlusMessage` instance.
Creates a new :class:`DLPlusMessage` object which can be used to parse
or build a DL Plus message string.
"""

#: The format string from which the message will be built
self.format_string = ""
#: The formatted DL Plus message
Expand All @@ -456,7 +455,7 @@ def __init__(self):
#: Status if the message was successfully built
self._built = False

def add_dlp_object(self, dlp_object: DLPlusObject):
def add_dlp_object(self, dlp_object: DLPlusObject) -> None:
"""Add a :class:`DLPlusObject` to a message string.
This method is intended to be used before building a DL Plus Message.
Expand All @@ -472,16 +471,16 @@ def add_dlp_object(self, dlp_object: DLPlusObject):
maximum of four :class:`DLPlusObject`
objects where already added.
"""

if not isinstance(dlp_object, DLPlusObject):
raise DLPlusMessageError("dlp_object has to be a DLPlusObject object")
msg = "dlp_object has to be a DLPlusObject object"
raise DLPlusMessageError(msg)

# Up to four DL Plus objects can be created from each DL message
# according to ETSI TS 102 980, 5.1
if len(self._dlp_objects) >= 4:
raise DLPlusMessageError(
"Only a maximum of 4 DLPlusObject objects can be added"
)
_dlplus_max_objects = 4
if len(self._dlp_objects) >= _dlplus_max_objects:
msg = "Only a maximum of 4 DLPlusObject objects can be added"
raise DLPlusMessageError(msg)

# Use the content_type of the DL Plus object as the dictionary key
self._dlp_objects[dlp_object.content_type] = dlp_object
Expand All @@ -493,7 +492,7 @@ def get_dlp_objects(self) -> dict:
"""
return self._dlp_objects

def add_dlp_tag(self, dlp_tag: DLPlusTag):
def add_dlp_tag(self, dlp_tag: DLPlusTag) -> None:
"""Add a :class:`DLPlusTag` required for parsing the message.
This method is intended to be used before parsing a DL Plus Message.
Expand Down Expand Up @@ -524,16 +523,16 @@ def add_dlp_tag(self, dlp_tag: DLPlusTag):
of four :class:`DLPlusTag` objects where
already added.
"""

if not isinstance(dlp_tag, DLPlusTag):
raise DLPlusMessageError("dlp_tag has to be a DLPlusTag object")
msg = "dlp_tag has to be a DLPlusTag object"
raise DLPlusMessageError(msg)

# Up to four DL Plus tags can be created from each DL message
# according to ETSI TS 102 980, 5.1
if len(self._dlp_tags) >= 4:
raise DLPlusMessageError(
"Only a maximum of 4 DLPlusTag objects can be added"
)
_dlplus_max_objects = 4
if len(self._dlp_tags) >= _dlplus_max_objects:
msg = "Only a maximum of 4 DLPlusTag objects can be added"
raise DLPlusMessageError(msg)

self._dlp_tags[dlp_tag.content_type] = dlp_tag

Expand All @@ -544,7 +543,7 @@ def get_dlp_tags(self) -> dict:
"""
return self._dlp_tags

def parse(self, message: str):
def parse(self, message: str) -> None:
"""Parse a DL Plus `message` into DL Plus objects.
This method parses a given DL Plus `message` into zero or more DL Plus
Expand Down Expand Up @@ -575,13 +574,12 @@ def parse(self, message: str):
:param str message: The DL Plus message string which should be parsed
"""

# Reset the DLPlusObjects
self._dlp_objects = {}

# Extract sub strings from the message according to the DLPlusTag
# objects to create DLPLusObject objects
for _, dlp_tag in self._dlp_tags.items():
for dlp_tag in self._dlp_tags.values():
end = dlp_tag.start + dlp_tag.length

# Delete objects have their length marker set to 0 and the start
Expand All @@ -596,7 +594,7 @@ def parse(self, message: str):
self._message = message
self._parsed = True

def build(self, format_string: str):
def build(self, format_string: str) -> None:
"""Build a DL Plus message from a given format and DL Plus objects.
This method builds a DL Plus message string from a given
Expand Down Expand Up @@ -659,17 +657,16 @@ class TemplateWithDots(Template):
# Make sure that the byte length of the message doesn't exceed the
# maximum allowed limit.
if len(message.encode("utf-8")) > MAXIMUM_TEXT_LIMIT:
raise DLPlusMessageError(
f"Message is longer than {MAXIMUM_TEXT_LIMIT} bytes"
)
msg = f"Message is longer than {MAXIMUM_TEXT_LIMIT} bytes"
raise DLPlusMessageError(msg)

self._message = message

# Reset the DLPlusTags
self._dlp_tags = {}

# Create DLPlusTags from the message and DLPlusObjects
for _, dlp_object in self._dlp_objects.items():
for dlp_object in self._dlp_objects.values():
self._dlp_tags[dlp_object.content_type] = DLPlusTag.from_message(
self, dlp_object.content_type
)
Expand All @@ -689,14 +686,13 @@ def __str__(self) -> str:
:return: Formatted DL Plus Message
"""

return self.message


class DLPlusContentType:
"""Dynamic Label Plus content type."""

def __init__(self, content_type: str):
def __init__(self, content_type: str) -> None:
"""Create class:`DLPlusContentType` instance.
Creates a new :class:`DLPlusContentType` object with a specific content
Expand All @@ -712,9 +708,9 @@ def __init__(self, content_type: str):
A.1
:raises DLPlusContentTypeError: if an invalid content type was specified
"""

if content_type not in CONTENT_TYPES:
raise DLPlusContentTypeError(f"Invalid content_type: {content_type}")
msg = f"Invalid content_type: {content_type}"
raise DLPlusContentTypeError(msg)

#: The content type according to ETSI TS 102 980, Annex A, Table A.1
self.content_type = content_type
Expand Down Expand Up @@ -770,7 +766,7 @@ class DLPlusObject(DLPlusContentType):
DL Plus object which holds a text string with a defined content type.
"""

def __init__(self, content_type: str, text: str = "", delete: bool = False):
def __init__(self, content_type: str, text: str = "", delete: bool = False) -> None: # noqa: FBT001,FBT002
"""Create a class:`DLPlusObject` instance.
Creates a new :class:`DLPlusObject` object with a specific content type
Expand All @@ -790,15 +786,15 @@ def __init__(self, content_type: str, text: str = "", delete: bool = False):
:raises DLPlusMessageError: if the text exceeds the maximum allowed size
in bytes (:attr:`MAXIMUM_TEXT_LIMIT`).
"""

# Call the parent constructor which will assign self.content_type
super().__init__(content_type)

# Make sure that the byte length of the text doesn't exceed the maximum
# allowed limit.
# https://stackoverflow.com/a/4013418/8587602
if len(text.encode("utf-8")) > MAXIMUM_TEXT_LIMIT:
raise DLPlusObjectError(f"Text is longer than {MAXIMUM_TEXT_LIMIT} bytes")
msg = f"Text is longer than {MAXIMUM_TEXT_LIMIT} bytes"
raise DLPlusObjectError(msg)

# DL Plus dummy objects always have their text set to an empty string
if self.is_dummy():
Expand All @@ -814,20 +810,20 @@ def __init__(self, content_type: str, text: str = "", delete: bool = False):
self.is_delete = delete

#: The creation time stamp of the DL Plus object in UTC
self.creation_ts = datetime.datetime.utcnow().replace(tzinfo=pytz.utc)
self.creation_ts = datetime.datetime.utcnow().replace(tzinfo=pytz.utc) # noqa: DTZ003

#: The expiration (deletion) time stamp of the DL Plus object in UTC
self.expiration_ts = None

def expire(self):
def expire(self) -> None:
"""Set the expiration (deletion) time stamp to the current time in UTC.
This method should be called if the current DL Plus object gets updated
by a new one or an explicit delete object has been received. It will set
:attr:`expiration_ts` to a TZ aware :class:`datetime.datetime` object
representing the current time in UTC.
"""
self.expiration_ts = datetime.datetime.utcnow().replace(tzinfo=pytz.utc)
self.expiration_ts = datetime.datetime.utcnow().replace(tzinfo=pytz.utc) # noqa: DTZ003

@classmethod
def create_dummy(cls) -> DLPlusObject:
Expand All @@ -838,7 +834,6 @@ def create_dummy(cls) -> DLPlusObject:
:return: Dummy DL Plus Object
"""

return cls("DUMMY", "")

def __str__(self) -> str:
Expand Down Expand Up @@ -872,7 +867,7 @@ class DLPlusTag(DLPlusContentType):
1
"""

def __init__(self, content_type: str, start: int, length: int):
def __init__(self, content_type: str, start: int, length: int) -> None:
"""Create a class:`DLPlusTag` instance.
Creates a new :class:`DLPlusTag` object with a specific content type
Expand All @@ -894,15 +889,16 @@ def __init__(self, content_type: str, start: int, length: int):
:raises DLPlusTagError: if either `start` or `length` are not a positive
integer.
"""

# Call the parent constructor which will assign self.content_type
super().__init__(content_type)

if not isinstance(start, int) or start < 0:
raise DLPlusTagError("start must be a positive integer")
msg = "start must be a positive integer"
raise DLPlusTagError(msg)

if not isinstance(length, int) or length < 0:
raise DLPlusTagError("length must be a positive integer")
msg = "length must be a positive integer"
raise DLPlusTagError(msg)

# Dummy objects always have their start and length marker set to 0
if self.is_dummy():
Expand Down Expand Up @@ -940,25 +936,25 @@ def from_message(cls, dlp_message: DLPlusMessage, content_type: str) -> DLPlusTa
:param DLPlusMessage dlp_message: The populated DL Plus message
:return: DL Plus Tag
"""

# Pythonic factory class method according to:
# * https://stackoverflow.com/a/14992545
# * https://stackoverflow.com/a/12179752

if not isinstance(dlp_message, DLPlusMessage):
raise DLPlusTagError("dlp_message has to be a DLPlusMessage")
msg = "dlp_message has to be a DLPlusMessage"
raise DLPlusTagError(msg)

if content_type not in CONTENT_TYPES:
raise DLPlusContentTypeError(f"Invalid content_type: {content_type}")
msg = f"Invalid content_type: {content_type}"
raise DLPlusContentTypeError(msg)

# Check that a DLPlusObject object for the requested content type
# was added and is available.
try:
dlp_object = dlp_message.get_dlp_objects()[content_type]
except KeyError as key_error:
raise DLPlusTagError(
f"No DLPlusObject for content type {content_type} available"
) from key_error
msg = f"No DLPlusObject for content type {content_type} available"
raise DLPlusTagError(msg) from key_error

# Get the start marker (index) of the DL Plus object's text
start = dlp_message.message.find(dlp_object.text)
Expand All @@ -980,5 +976,4 @@ def create_dummy(cls) -> DLPlusTag:
:return: Dummy DL Plus Tag
"""

return cls("DUMMY", 0, 0)
Loading

0 comments on commit c13b95d

Please sign in to comment.