Skip to content

Commit

Permalink
ruff and linter update
Browse files Browse the repository at this point in the history
  • Loading branch information
robamu committed Nov 27, 2024
1 parent 78ccc7e commit 87a2f4d
Show file tree
Hide file tree
Showing 86 changed files with 768 additions and 1,187 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
python-version: ['3.8', '3.9', '3.10', '3.11']

steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
Expand All @@ -31,15 +31,15 @@ jobs:
sphinx-build -b doctest docs docs/_build
- name: Lint with Ruff
uses: chartboost/ruff-action@v1
uses: astral-sh/ruff-action@v1

- name: Run tests and generate coverage data
run: |
python3 -m pip install coverage pytest
coverage run -m pytest
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v3
uses: codecov/codecov-action@v5
with:
token: ${{ secrets.CODECOV_TOKEN }}
flags: unittests
Expand Down
72 changes: 69 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ name = "spacepackets"
description = "Various CCSDS and ECSS packet implementations"
readme = "README.md"
version = "0.25.0"
requires-python = ">=3.8"
requires-python = ">=3.9"
license = {text = "Apache-2.0"}
authors = [
{name = "Robin Mueller", email = "[email protected]"}
Expand Down Expand Up @@ -38,7 +38,73 @@ dependencies = [
[tool.setuptools.packages]
find = {}

[tool.ruff]
exclude = [
".git",
"venv",
"docs"
]
line-length = 100

[tool.ruff.lint]
ignore = ["E501"]
select = [
# See https://docs.astral.sh/ruff/rules/
"F", # pyflakes
"E", # pycodestyle
"W", # pycodestyle
"I", # isort
"N", # pep8-naming
# "D", # pydocstyle (documentation!)
"ANN", # flake8-annotations
"UP", # pyupgrade
"ASYNC", # flake8-async
"S", # flake8-bandit
"B", # flake8-bugbear
"A", # flake8-builtins
"C4", # flake8-comprehensions
"DTZ", # flake8-datetimez
"ICN", # flake8-import-conventions
"INP", # flake8-no-pep420
"PIE", # flake8-pie
"PYI", # flake8-pyi
"RSE", # flake8-raise
"RET", # flake8-return
"SIM", # flake8-simplify
"TID", # flake8-tidy
"TCH", # flake8-type-checking
"PERF", # Performance
"FURB", # Refurb rules
"PL", # Pylint
"RUF" # ruff specific
]
ignore = [
"N818", # Exception names should end in "Error", requires API change
"S101", # Use of assert, should be changed in the future
"ANN204", # Do not use return typing on __init__, __new__ and __call__ methods
"E111", # Recommended to be disabled when using the ruff formatter
"E114" # Recommended to be disabled when using the ruff formatter
]

[tool.ruff.lint.extend-per-file-ignores]
"__init__.py" = ["F401"]
"tests/*" = [
"INP001", # Tests are implicit namespace packets
"S101", # Tests use assert
"S105", # Tests use hardcoded test credentials
"S108", # Tests use temporary files names
"S311", # Tests use random without cryptographic security requirements
"ANN", # Type hints in test are not required
"PLR0912", # Too many branches
"PLR0915", # Too many statements
"PLR2004", # Magic values in comparison are common in tests
"D" # No documentation rules in tests
]
"examples/*" = [
"INP001", # Examples are implicit namespace packets
"S101", # Examples use assert
"S104", # Possible binding to all interfaces
"S108", # Temp files
"PLR0915" # Too many statements
]

[tool.ruff.lint.pylint]
max-args = 10
2 changes: 1 addition & 1 deletion release-checklist.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ The steps shown here are for Ubuntu/MacOS.
3. Update `CHANGELOG.md`: Convert `unreleased` section into version section
with date and new `unreleased`section.
4. Run tests with `pytest .`
5. Run auto-formatter with `black .`
5. Run auto-formatter with `ruff format .`
6. Run linter with `ruff check .`
7. Wait for CI/CD results. This also runs the tests on different operating systems

Expand Down
9 changes: 4 additions & 5 deletions spacepackets/__init__.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
import logging

from spacepackets.ccsds import (
SpacePacketHeader,
SpHeader,
SpacePacket,
PacketType,
SequenceFlags,
SpacePacket,
SpacePacketHeader,
SpHeader,
)

from spacepackets.exceptions import BytesTooShortError


__LIB_LOGGER = logging.getLogger(__name__)


Expand Down
14 changes: 7 additions & 7 deletions spacepackets/ccsds/__init__.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
"""This package contains all CCSDS related components"""

from .spacepacket import (
SpHeader,
SpacePacketHeader,
SpacePacket,
PacketType,
SequenceFlags,
SPACE_PACKET_HEADER_SIZE,
AbstractSpacePacket,
PacketId,
PacketSeqCtrl,
AbstractSpacePacket,
SPACE_PACKET_HEADER_SIZE,
PacketType,
SequenceFlags,
SpacePacket,
SpacePacketHeader,
SpHeader,
get_total_space_packet_len_from_len_field,
)
from .time import * # noqa: F403 # re-export
40 changes: 12 additions & 28 deletions spacepackets/ccsds/spacepacket.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@

from __future__ import annotations

from abc import abstractmethod, ABC
import enum
import struct

from typing import Tuple, Deque, List, Final, Optional, Sequence
from abc import ABC, abstractmethod
from collections.abc import Sequence
from typing import Deque, Final, List, Optional, Tuple

from spacepackets.exceptions import BytesTooShortError

Expand Down Expand Up @@ -39,9 +39,7 @@ class PacketSeqCtrl:

def __init__(self, seq_flags: SequenceFlags, seq_count: int):
if seq_count > MAX_SEQ_COUNT or seq_count < 0:
raise ValueError(
f"Sequence count larger than allowed {pow(2, 14) - 1} or negative"
)
raise ValueError(f"Sequence count larger than allowed {pow(2, 14) - 1} or negative")
self.seq_flags = seq_flags
self.seq_count = seq_count

Expand Down Expand Up @@ -78,9 +76,7 @@ def __eq__(self, other: object) -> bool:

@classmethod
def from_raw(cls, raw: int):
return cls(
seq_flags=SequenceFlags((raw >> 14) & 0b11), seq_count=raw & ~SEQ_FLAG_MASK
)
return cls(seq_flags=SequenceFlags((raw >> 14) & 0b11), seq_count=raw & ~SEQ_FLAG_MASK)


class PacketId:
Expand All @@ -89,9 +85,7 @@ class PacketId:

def __init__(self, ptype: PacketType, sec_header_flag: bool, apid: int):
if apid > pow(2, 11) - 1 or apid < 0:
raise ValueError(
f"Invalid APID, exceeds maximum value {pow(2, 11) - 1} or negative"
)
raise ValueError(f"Invalid APID, exceeds maximum value {pow(2, 11) - 1} or negative")
self.ptype = ptype
self.sec_header_flag = sec_header_flag
self.apid = apid
Expand Down Expand Up @@ -233,9 +227,7 @@ def __init__(
f" {pow(2, 16) - 1} or negative"
)
self._ccsds_version = ccsds_version
self._packet_id = PacketId(
ptype=packet_type, sec_header_flag=sec_header_flag, apid=apid
)
self._packet_id = PacketId(ptype=packet_type, sec_header_flag=sec_header_flag, apid=apid)
self._psc = PacketSeqCtrl(seq_flags=seq_flags, seq_count=seq_count)
self.data_len = data_len

Expand Down Expand Up @@ -476,11 +468,8 @@ def pack(self) -> bytearray:
"Secondary header flag is set but no secondary header was supplied"
)
packet.extend(self.sec_header)
else:
if self.user_data is None:
raise ValueError(
"Secondary header not present but no user data supplied"
)
elif self.user_data is None:
raise ValueError("Secondary header not present but no user data supplied")
if self.user_data is not None:
packet.extend(self.user_data)
return packet
Expand Down Expand Up @@ -532,9 +521,7 @@ def get_space_packet_id_bytes(
return byte_one, byte_two


def get_sp_packet_id_raw(
packet_type: PacketType, secondary_header_flag: bool, apid: int
) -> int:
def get_sp_packet_id_raw(packet_type: PacketType, secondary_header_flag: bool, apid: int) -> int:
"""Get packet identification segment of packet primary header in integer format"""
return PacketId(packet_type, secondary_header_flag, apid).raw()

Expand Down Expand Up @@ -624,9 +611,6 @@ def __handle_packet_id_match(
analysis_queue.clear()
analysis_queue.append(concatenated_packets[current_idx:])
return -1, current_idx
else:
tm_list.append(
concatenated_packets[current_idx : current_idx + total_packet_len]
)
current_idx += total_packet_len
tm_list.append(concatenated_packets[current_idx : current_idx + total_packet_len])
current_idx += total_packet_len
return 0, current_idx
2 changes: 1 addition & 1 deletion spacepackets/ccsds/time/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""This module contains the CCSDS specific time code implementations."""

from .common import CcsdsTimeProvider, CcsdsTimeCodeId, SECONDS_PER_DAY, MS_PER_DAY
from .cds import CdsShortTimestamp
from .common import MS_PER_DAY, SECONDS_PER_DAY, CcsdsTimeCodeId, CcsdsTimeProvider
31 changes: 11 additions & 20 deletions spacepackets/ccsds/time/cds.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from __future__ import annotations

import datetime
import enum
import math
Expand All @@ -8,16 +9,16 @@

import deprecation

from spacepackets.version import get_version
from spacepackets.exceptions import BytesTooShortError
from spacepackets.ccsds.time.common import (
MS_PER_DAY,
SECONDS_PER_DAY,
CcsdsTimeCodeId,
CcsdsTimeProvider,
convert_ccsds_days_to_unix_days,
SECONDS_PER_DAY,
convert_unix_days_to_ccsds_days,
CcsdsTimeCodeId,
MS_PER_DAY,
)
from spacepackets.exceptions import BytesTooShortError
from spacepackets.version import get_version


class LenOfDaysSegment(enum.IntEnum):
Expand Down Expand Up @@ -45,9 +46,7 @@ class CdsShortTimestamp(CcsdsTimeProvider):
CDS_SHORT_ID = 0b100
TIMESTAMP_SIZE = 7

def __init__(
self, ccsds_days: int, ms_of_day: int, init_dt_unix_stamp: bool = True
):
def __init__(self, ccsds_days: int, ms_of_day: int, init_dt_unix_stamp: bool = True):
"""Create a stamp from the contained values directly.
>>> zero_stamp = CdsShortTimestamp(ccsds_days=0, ms_of_day=0)
Expand Down Expand Up @@ -150,14 +149,10 @@ def unpack_from_raw(data: bytes) -> Tuple[int, int]:
raise BytesTooShortError(CdsShortTimestamp.TIMESTAMP_SIZE, len(data))
p_field = data[0]
if (p_field >> 4) & 0b111 != CcsdsTimeCodeId.CDS:
raise ValueError(
f"invalid CCSDS Time Code {p_field}, expected {CcsdsTimeCodeId.CDS}"
)
raise ValueError(f"invalid CCSDS Time Code {p_field}, expected {CcsdsTimeCodeId.CDS}")
len_of_day = len_of_day_seg_from_pfield(p_field)
if len_of_day != LenOfDaysSegment.DAYS_16_BITS:
raise ValueError(
f"invalid length of days field {len_of_day} for CDS short timestamp"
)
raise ValueError(f"invalid length of days field {len_of_day} for CDS short timestamp")
ccsds_days = struct.unpack("!H", data[1:3])[0]
ms_of_day = struct.unpack("!I", data[3:7])[0]
return ccsds_days, ms_of_day
Expand All @@ -173,9 +168,7 @@ def __str__(self):

def __eq__(self, other: object):
if isinstance(other, CdsShortTimestamp):
return (self.ccsds_days == other.ccsds_days) and (
self.ms_of_day == other.ms_of_day
)
return (self.ccsds_days == other.ccsds_days) and (self.ms_of_day == other.ms_of_day)
return False

def __add__(self, timedelta: datetime.timedelta):
Expand Down Expand Up @@ -252,9 +245,7 @@ def ms_of_today(seconds_since_epoch: Optional[float] = None):
if seconds_since_epoch is None:
seconds_since_epoch = time.time()
fraction_ms = seconds_since_epoch - math.floor(seconds_since_epoch)
return int(
math.floor((seconds_since_epoch % SECONDS_PER_DAY) * 1000 + fraction_ms)
)
return int(math.floor((seconds_since_epoch % SECONDS_PER_DAY) * 1000 + fraction_ms))

def as_unix_seconds(self) -> float:
return self._unix_seconds
Expand Down
9 changes: 5 additions & 4 deletions spacepackets/ccsds/time/common.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
from __future__ import annotations

import datetime
import enum
from abc import abstractmethod, ABC
from spacepackets.version import get_version
from abc import ABC, abstractmethod

import deprecation

from spacepackets.version import get_version

#: The day offset to convert from CCSDS days to UNIX days.
DAYS_CCSDS_TO_UNIX = -4383
#: Seconds per days as integer
Expand Down Expand Up @@ -96,13 +98,12 @@ def as_date_time(self) -> datetime.datetime:
"""Retrieve a :py:class:`datetime.datetime` with the :py:class:`datetime.timezone` set to
utc.
"""
pass

def as_time_string(self) -> str:
return self.as_date_time().strftime("%Y-%m-%d %H:%M:%S.%f")

def ccsds_time_code(self) -> int:
if self.pfield == bytes():
if self.pfield == b"":
return 0
return (self.pfield[0] >> 4) & 0b111

Expand Down
Loading

0 comments on commit 87a2f4d

Please sign in to comment.