[Git][debian-gis-team/bpack][master] 5 commits: New upstream version 1.3.0

Antonio Valentino (@antonio.valentino) gitlab at salsa.debian.org
Thu Jan 9 06:31:12 GMT 2025



Antonio Valentino pushed to branch master at Debian GIS Project / bpack


Commits:
14062567 by Antonio Valentino at 2025-01-09T06:23:49+00:00
New upstream version 1.3.0
- - - - -
39790a21 by Antonio Valentino at 2025-01-09T06:23:50+00:00
Update upstream source from tag 'upstream/1.3.0'

Update to upstream version '1.3.0'
with Debian dir 47aa67356eb1dd22b8f857e047740a2917c96840
- - - - -
206ca39a by Antonio Valentino at 2025-01-09T06:24:49+00:00
New upstream release

- - - - -
8f9d68d5 by Antonio Valentino at 2025-01-09T06:25:52+00:00
Update dates in d/copyright

- - - - -
4c0cfb44 by Antonio Valentino at 2025-01-09T06:26:47+00:00
Set distribution to unstable

- - - - -


12 changed files:

- .flake8
- .pre-commit-config.yaml
- Makefile
- README.rst
- bpack/__init__.py
- bpack/descriptors.py
- bpack/tests/test_field_descriptor.py
- + bpack/tests/test_future_annotations.py
- debian/changelog
- debian/copyright
- docs/release_notes.rst
- tox.ini


Changes:

=====================================
.flake8
=====================================
@@ -8,17 +8,17 @@ extend-ignore = E203,E501,E701,W503,SC,CNL
 # extend-ignore = SC  # flake8-spellcheck: too aggressive
 # extend-ignore = CNL  # flake8-class-newline: incompatible with black
 # extend-ignore = A003,A005  # Python builtin is shadowed by class attribute / module
-extend-select = W504,B950
 # https://docs.astral.sh/ruff/rules/#pydocstyle-d
-# D105: undocumented-magic-method
-# D107: undocumented-public-init
-# extend-ignore = E203,W503,D105,D107  # D* are in pyproject.toml
+# extend-ignore = D105  # undocumented-magic-method
+# extend-ignore = D107  # undocumented-public-init
+extend-select = W504,B950
 per-file-ignores =
     */tests/test_*.py: D,T003
     */tests/data/*.py: D,T003,F821
     bpack/utils.py: D103
     bpack/codecs.py: A005
     bpack/typing.py: A005
+    bpack/tests/test_future_annotations.py: D,T003,NQA102
 statistics = True
 count = True
 extend-exclude = examples/*


=====================================
.pre-commit-config.yaml
=====================================
@@ -22,7 +22,7 @@ repos:
 #     -   id: ruff-format
 
 -   repo: https://github.com/asottile/pyupgrade
-    rev: v3.19.0
+    rev: v3.19.1
     hooks:
     -   id: pyupgrade
         args: [--py39-plus]
@@ -30,7 +30,8 @@ repos:
             (?x)^(
                 bpack/tests/test_field_descriptor.py|
                 bpack/tests/test_record_descriptor.py|
-                bpack/tests/test_utils.py
+                bpack/tests/test_utils.py|
+                bpack/tests/test_future_annotations.py
             )
 
 -   repo: https://github.com/pycqa/flake8
@@ -51,7 +52,7 @@ repos:
         name: isort (python)
 
 -   repo: https://github.com/psf/black-pre-commit-mirror
-    rev: 24.8.0
+    rev: 24.10.0
     hooks:
     -   id: black
         language_version: python3.9


=====================================
Makefile
=====================================
@@ -4,7 +4,8 @@ PYTHON=python3
 SPHINX_APIDOC=sphinx-apidoc
 TARGET=bpack
 
-.PHONY: default help dist check fullcheck coverage lint api docs clean cleaner distclean
+.PHONY: default help dist check fullcheck coverage clean cleaner distclean \
+        lint docs api
 
 default: help
 
@@ -16,12 +17,12 @@ help:
 	@echo "  check     - run a full test (using pytest)"
 	@echo "  fullcheck - run a full test (using tox)"
 	@echo "  coverage  - run tests and generate the coverage report"
-	@echo "  lint      - perform check with code linter (flake8, black)"
-	@echo "  api       - update the API source files in the documentation"
-	@echo "  docs      - generate the sphinx documentation"
 	@echo "  clean     - clean build artifacts"
 	@echo "  cleaner   - clean cache files and working directories of al tools"
 	@echo "  distclean - clean all the generated files"
+	@echo "  lint      - perform check with code linter (flake8, black)"
+	@echo "  docs      - generate the sphinx documentation"
+	@echo "  api       - update the API source files in the documentation"
 
 dist:
 	$(PYTHON) -m build
@@ -36,24 +37,6 @@ fullcheck:
 coverage:
 	$(PYTHON) -m pytest --doctest-modules --cov=$(TARGET) --cov-report=html --cov-report=term
 
-lint:
-	$(PYTHON) -m flake8 --count --statistics $(TARGET)
-	$(PYTHON) -m pydocstyle --count $(TARGET)
-	$(PYTHON) -m isort --check $(TARGET)
-	$(PYTHON) -m black --check $(TARGET)
-	# $(PYTHON) -m mypy --check-untyped-defs --ignore-missing-imports $(TARGET)
-	# ruff check $(TARGET)
-
-api:
-	$(RM) -r docs/api
-	$(SPHINX_APIDOC) --module-first --separate --no-toc -o docs/api \
-	  --doc-project "$(TARGET) API" --templatedir docs/_templates/apidoc \
-	  $(TARGET) $(TARGET)/tests
-
-docs:
-	mkdir -p docs/_static
-	$(MAKE) -C docs html
-
 clean:
 	$(RM) -r *.*-info build
 	find . -name __pycache__ -type d -exec $(RM) -r {} +
@@ -70,3 +53,21 @@ cleaner: clean
 
 distclean: cleaner
 	$(RM) -r dist
+
+lint:
+	$(PYTHON) -m flake8 --count --statistics $(TARGET)
+	$(PYTHON) -m pydocstyle --count $(TARGET)
+	$(PYTHON) -m isort --check $(TARGET)
+	$(PYTHON) -m black --check $(TARGET)
+	# $(PYTHON) -m mypy --check-untyped-defs --ignore-missing-imports $(TARGET)
+	# ruff check $(TARGET)
+
+docs:
+	mkdir -p docs/_static
+	$(MAKE) -C docs html
+
+api:
+	$(RM) -r docs/api
+	$(SPHINX_APIDOC) --module-first --separate --no-toc -o docs/api \
+	  --doc-project "$(TARGET) API" --templatedir docs/_templates/apidoc \
+	  $(TARGET) $(TARGET)/tests


=====================================
README.rst
=====================================
@@ -4,7 +4,7 @@ Binary data structures (un-)Packing library
 
 .. badges
 
-|PyPI Status| |GHA Status| |Documentation Status|
+|PyPI Status| |GHA Status| |Documentation Status| |Python Versions| |License|
 
 .. |PyPI Status| image:: https://img.shields.io/pypi/v/bpack.svg
     :target: https://pypi.org/project/bpack
@@ -15,6 +15,12 @@ Binary data structures (un-)Packing library
 .. |Documentation Status| image:: https://readthedocs.org/projects/bpack/badge/?version=latest
     :target: https://bpack.readthedocs.io/en/latest/?badge=latest
     :alt: Documentation Status
+.. |Python Versions| image:: https://img.shields.io/pypi/pyversions/bpack
+    :target: https://pypi.org/project/bpack
+    :alt: Supported Python versions
+.. |License| image:: https://img.shields.io/pypi/l/${packagename}
+    :target: https://pypi.org/project/${packagename}
+    :alt: License
 
 .. description
 
@@ -52,7 +58,7 @@ Encoders/decoders (*backends*) rely on well known Python packages like:
 License
 -------
 
-:Copyright: 2020-2024, Antonio Valentino <antonio.valentino at tiscali.it>
+:Copyright: 2020-2025, Antonio Valentino <antonio.valentino at tiscali.it>
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.


=====================================
bpack/__init__.py
=====================================
@@ -20,4 +20,4 @@ from .descriptors import (  # noqa: F401
     calcsize,
 )
 
-__version__ = "1.2.0"
+__version__ = "1.3.0"


=====================================
bpack/descriptors.py
=====================================
@@ -7,7 +7,7 @@ import types
 import builtins
 import warnings
 import dataclasses
-from typing import Optional, Union
+from typing import Optional, Union, get_type_hints
 from collections.abc import Iterator, Sequence
 
 import bpack.utils
@@ -62,6 +62,11 @@ def _resolve_type(type_):
     Replace :class:`typing.Annotated` types with the corresponding
     not-annotated ones.
     """
+    if isinstance(type_, str):
+        raise TypeError(
+            f"the 'type_' parameter cannot be a string (type_: {type_!r})"
+        )
+
     if bpack.utils.is_sequence_type(type_):
         etype = bpack.utils.effective_type(type_)
         try:
@@ -97,6 +102,10 @@ class BinFieldDescriptor:
     def _validate_type(self):
         if self.type is None:
             raise TypeError(f"invalid type '{self.type!r}'")
+        elif isinstance(self.type, str):
+            raise TypeError(
+                f"'{self.__class__.__name__}.type' cannot be a string"
+            )
 
     def _validate_size(self):
         msg = f"invalid size: {self.size!r} (must be a positive integer)"
@@ -133,6 +142,12 @@ class BinFieldDescriptor:
 
     def __post_init__(self):
         """Finalize BinFieldDescriptor instance initialization."""
+        if isinstance(self.type, str):
+            raise TypeError(
+                f"the 'type' parameter cannot be a string "
+                f"(type_: {self.type!r})"
+            )
+
         if self.offset is not None:
             self._validate_offset()
 
@@ -201,6 +216,11 @@ class BinFieldDescriptor:
         """Update the field descriptor according to the specified type."""
         if self.type is not None:
             raise TypeError("the type attribute is already set")
+        if isinstance(type_, str):
+            raise TypeError(
+                f"the 'type_' parameter cannot be a string (type_: {type_!r})"
+            )
+
         if bpack.typing.is_annotated(type_):
             _, params = bpack.typing.get_args(type_)
             valid = True
@@ -221,7 +241,11 @@ class BinFieldDescriptor:
                 self.size = params.size
         elif bpack.utils.is_sequence_type(type_):
             etype = bpack.utils.effective_type(type_, keep_annotations=True)
+
+            # this is needed to set "signed" and "size"
             self.update_from_type(etype)
+
+            # restore the proper sequence type
             self.type = _resolve_type(type_)
         else:
             self.type = type_
@@ -284,6 +308,12 @@ def is_field(obj) -> bool:
 
 
 def _update_field_metadata(field_, **kwargs):
+    type_ = kwargs.get("type")
+    if isinstance(type_, str):
+        raise TypeError(
+            f"the 'type' parameter cannot be a string (type_: {type_!r})"
+        )
+
     metadata = field_.metadata.copy() if field_.metadata is not None else {}
     metadata.update(**kwargs)
     field_.metadata = types.MappingProxyType(metadata)
@@ -444,6 +474,9 @@ def descriptor(  # noqa: CCR001
     else:
         cls = dataclasses.dataclass(cls, **kwargs)
 
+    # import inspect
+    # types_ = inspect.get_annotations(cls)
+    types_ = get_type_hints(cls, include_extras=True)
     fields_ = dataclasses.fields(cls)
 
     # Initialize to a dummy value with initial offset + size = 0
@@ -457,6 +490,10 @@ def descriptor(  # noqa: CCR001
         # NOTE: this is ensured by dataclasses but not by attr
         assert field_.type is not None
 
+        # resolve all types
+        if isinstance(field_.type, str):
+            field_.type = types_[field_.name]
+
         if bpack.typing.is_annotated(field_.type):
             # check byteorder
             _, params = bpack.typing.get_args(field_.type)
@@ -476,6 +513,7 @@ def descriptor(  # noqa: CCR001
         except NotFieldDescriptorError:
             field_descr = BinFieldDescriptor()
             if isinstance(field_, Field):
+                # set "type", "size" and "signed"
                 field_descr.update_from_type(field_.type)
 
         if field_descr.size is None:


=====================================
bpack/tests/test_field_descriptor.py
=====================================
@@ -156,7 +156,7 @@ class TestRecordFields:
 
     @staticmethod
     def test_invalid_field_type():
-        with pytest.raises(TypeError):
+        with pytest.raises((TypeError, NameError)):
 
             @bpack.descriptor
             class Record:


=====================================
bpack/tests/test_future_annotations.py
=====================================
@@ -0,0 +1,81 @@
+"""Tests bpack with "from __future__ import annotations"."""
+
+from __future__ import annotations
+
+import enum
+
+import pytest
+
+import bpack
+from bpack import T
+
+
+class EEnumType(enum.IntEnum):
+    A = 1
+    B = 2
+    C = 3
+
+
+ at bpack.descriptor
+class Record:
+    field_1: int = bpack.field(size=4, default=11)
+    field_2: float = bpack.field(size=4, default=22.22)
+    field_3: EEnumType = bpack.field(size=1, default=EEnumType.A)
+
+
+ at bpack.descriptor
+class NestedRecord:
+    field_1: str = bpack.field(size=10, default="0123456789")
+    field_2: Record = bpack.field(
+        size=bpack.calcsize(Record), default_factory=Record
+    )
+    field_3: int = bpack.field(size=4, default=3)
+    field_4: T["f8"] = 0.1  # noqa: F821
+
+
+def test_nested_records():
+    record = Record()
+    nested_record = NestedRecord()
+
+    assert nested_record.field_1 == "0123456789"
+    assert nested_record.field_2 == record
+    assert nested_record.field_2.field_1 == record.field_1
+    assert nested_record.field_2.field_2 == record.field_2
+    assert nested_record.field_2.field_3 is EEnumType.A
+    assert nested_record.field_3 == 3
+    assert nested_record.field_4 == 0.1
+
+
+def test_nested_records_consistency_error():
+    with pytest.raises(bpack.descriptors.DescriptorConsistencyError):
+
+        @bpack.descriptor
+        class NestedRecord:
+            field_1: str = bpack.field(size=10, default="0123456789")
+            field_2: Record = bpack.field(
+                size=bpack.calcsize(Record) + 1, default_factory=Record
+            )
+            field_3: int = bpack.field(size=4, default=3)
+
+
+def test_nested_records_autosize():
+    assert bpack.calcsize(NestedRecord) == 31
+
+
+def test_unexisting_field_type():
+    with pytest.raises((TypeError, NameError)):
+
+        @bpack.descriptor
+        class Record:
+            field_1: "unexisting" = bpack.field(size=4)  # noqa: F821
+
+
+invalid = True
+
+
+def test_invalid_field_type():
+    with pytest.raises((TypeError, NameError)):
+
+        @bpack.descriptor
+        class Record:
+            field_1: "invalid" = bpack.field(size=4)  # noqa: F821


=====================================
debian/changelog
=====================================
@@ -1,3 +1,10 @@
+bpack (1.3.0-1) unstable; urgency=medium
+
+  * New upstream version.
+  * Update dates in d/copyright.
+
+ -- Antonio Valentino <antonio.valentino at tiscali.it>  Thu, 09 Jan 2025 06:26:26 +0000
+
 bpack (1.2.0-1) unstable; urgency=medium
 
   [ Bas Couwenberg ]


=====================================
debian/copyright
=====================================
@@ -4,11 +4,11 @@ Upstream-Contact: Antonio Valentino <antonio.valentino at tiscali.it>
 Source: https://github.com/avalentino/bpack
 
 Files: *
-Copyright: 2023-2024, Antonio Valentino <antonio.valentino at tiscali.it>
+Copyright: 2023-2025, Antonio Valentino <antonio.valentino at tiscali.it>
 License: Apache-2.0
 
 Files: debian/*
-Copyright: 2023-2024, Antonio Valentino <antonio.valentino at tiscali.it>
+Copyright: 2023-2025, Antonio Valentino <antonio.valentino at tiscali.it>
 License: Apache-2.0
 
 License: Apache-2.0


=====================================
docs/release_notes.rst
=====================================
@@ -1,6 +1,24 @@
 Release Notes
 =============
 
+bpack v1.3.0 (06/01/2025)
+-------------------------
+
+* Support for annotations saved in string form (see also `PEP-563`_).
+  Is some circumstances Python typing annotations are stored
+  as strings. E.g. this happens when people uses::
+
+    from __future__ import annotations
+
+  Starting from v1.3.0, `bpack` is compatible with this way of storing
+  annotations.
+  Please note, anyway, that `bpack` still need to evaluate the annotations
+  at compile time so the "Postponed Evaluation of Annotations" described in
+  `PEP-563`_ is not really supported.
+
+.. _`PEP-563`: https://peps.python.org/pep-0563
+
+
 bpack v1.2.0 (26/11/2024)
 -------------------------
 


=====================================
tox.ini
=====================================
@@ -6,7 +6,6 @@ env_list =
     py311
     py312
     py313
-    pypy3
     strict
     coverage
     codestyle
@@ -22,14 +21,6 @@ extras = test
 commands =
     python3 -m pytest {tty:--color=yes} --doctest-modules {posargs}
 
-[testenv:pypy3]
-deps =
-    pytest>=6
-    typing-extensions
-extras = bs,np
-commands =
-    python3 -m pytest {tty:--color=yes} {posargs}
-
 [testenv:strict]
 commands =
     python3 -m pytest {tty:--color=yes} -W error {posargs}
@@ -54,7 +45,7 @@ deps =
 changedir = {toxinidir}
 commands =
     python3 -m flake8 --version
-    python3 -m flake8 --count --statistics --count bpack
+    python3 -m flake8 --count --statistics bpack
 	python3 -m pydocstyle --count bpack
 	python3 -m isort --check bpack
 	python3 -m black --check bpack



View it on GitLab: https://salsa.debian.org/debian-gis-team/bpack/-/compare/51dffb0109aa4911db8ee4a5cb679c3954a604fe...4c0cfb44062d848615aec22a2bede9e589184c21

-- 
View it on GitLab: https://salsa.debian.org/debian-gis-team/bpack/-/compare/51dffb0109aa4911db8ee4a5cb679c3954a604fe...4c0cfb44062d848615aec22a2bede9e589184c21
You're receiving this email because of your account on salsa.debian.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/pkg-grass-devel/attachments/20250109/92c61517/attachment-0001.htm>


More information about the Pkg-grass-devel mailing list