Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 372b1d9

Browse files
committedMay 16, 2025·
Migrate to a package, add type information
1 parent dd59aae commit 372b1d9

File tree

10 files changed

+51
-35
lines changed

10 files changed

+51
-35
lines changed
 

‎.bumpversion.cfg

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
[bumpversion]
2-
current_version = 3.0.1
2+
current_version = 3.1.0
33
commit = True
44
tag = True
55

66
[bumpversion:file:setup.py]
77

88
[bumpversion:file:docs/conf.py]
99

10-
[bumpversion:file:src/asn1.py]
10+
[bumpversion:file:src/asn1/core.py]
1111

‎CHANGELOG.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
Changelog
22
=========
33

4+
3.1.0 (2025-05-16)
5+
------------------
6+
7+
* #291 - Add support for mypy. As a consequence, the previous module has been migrated to a package.
8+
49
3.0.1 (2025-05-02)
510
------------------
611

‎MANIFEST.in

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ graft examples
33
graft src
44
graft ci
55
graft tests
6-
graft stubs
76

87
include .coveragerc
98
include .cookiecutterrc
@@ -23,5 +22,8 @@ include *.ini
2322
include *.yml
2423
include *.yaml
2524

25+
include src/asn1/core.pyi
26+
include src/asn1/py.typed
27+
2628
global-exclude *.py[cod] __pycache__ *.so *.dylib .DS_Store .mypy_cache
2729
exclude .python-version

‎docs/conf.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
year = '2007-2022'
2828
author = 'Sebastien Andrivet'
2929
copyright = '{0}, {1}'.format(year, author)
30-
version = release = '3.0.1'
30+
version = release = '3.1.0'
3131

3232
pygments_style = 'trac'
3333
templates_path = ['.']

‎docs/credits.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,4 @@ The following projects have provided inspiration for Python-ASN1:
88
building constructed types.
99

1010
.. _pyasn1: https://pyasn1.sourceforge.net/
11-
.. _Samba: https://www.samba.org
11+
.. _Samba: https://github.com/samba-team/samba/tree/master/source3/libads

‎setup.py

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ def read(*names, **kwargs):
2929

3030
setup(
3131
name='asn1',
32-
version='3.0.1',
32+
version='3.1.0',
3333
license='BSD',
3434
description='Python-ASN1 is a simple ASN.1 encoder and decoder for Python 2.7+ and 3.5+.',
3535
long_description='%s\n%s' % (
@@ -42,6 +42,7 @@ def read(*names, **kwargs):
4242
url='https://github.com/andrivet/python-asn1',
4343
packages=find_packages('src'),
4444
package_dir={'': 'src'},
45+
package_data={'asn1': ['py.typed', 'core.pyi']},
4546
py_modules=[splitext(basename(path))[0] for path in glob('src/*.py')],
4647
include_package_data=True,
4748
zip_safe=False,
@@ -72,9 +73,5 @@ def read(*names, **kwargs):
7273
# eg: 'keyword1', 'keyword2', 'keyword3',
7374
],
7475
install_requires=install_requires,
75-
extras_require={
76-
# eg:
77-
# 'rst': ['docutils>=0.11'],
78-
# ':python_version=="2.6"': ['argparse'],
79-
},
76+
extras_require={},
8077
)

‎src/asn1/__init__.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
from .core import Classes
2+
from .core import Decoder
3+
from .core import Encoder
4+
from .core import Encoding
5+
from .core import Error
6+
from .core import Numbers
7+
from .core import ReadFlags
8+
from .core import Tag
9+
from .core import Types
10+
11+
__all__ = ["Decoder", "Encoder", "Numbers", "Types", "Classes", "Encoding", "ReadFlags", "Tag", "Error"]

‎src/asn1.py renamed to ‎src/asn1/core.py

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
from enum import IntEnum
2929
from functools import reduce
3030

31-
__version__ = "3.0.1"
31+
__version__ = "3.1.0"
3232

3333
from typing import Any # noqa: F401
3434
from typing import Generator # noqa: F401
@@ -103,6 +103,7 @@ class Classes(Asn1Enum):
103103

104104

105105
class Encoding(Asn1Enum):
106+
"""ASN.1 encoding types."""
106107
DER = 1 # Distinguished Encoding Rules
107108
CER = 2 # Canonical Encoding Rules
108109

@@ -119,6 +120,12 @@ class ReadFlags(IntEnum):
119120
`Decoder.read()`.
120121
"""
121122

123+
EncoderStream = Union[io.RawIOBase, io.BufferedWriter, None]
124+
"""A stream that can be used for output."""
125+
126+
DecoderStream = Union[io.RawIOBase, io.BufferedIOBase, bytes]
127+
"""A stream that can be used for input."""
128+
122129

123130
def to_int_2c(values): # type: (bytes) -> int
124131
"""Bytes to integer conversion in two's complement."""
@@ -205,19 +212,19 @@ class Encoder(object):
205212

206213
def __init__(self): # type: () -> None
207214
"""Constructor."""
208-
self._stream = None # type: Union[io.RawIOBase, io.BufferedWriter, None] # Output stream
215+
self._stream = None # type: EncoderStream # Output stream
209216
self._encoding = None # type: Union[Encoding, None] # Encoding type (DER or CER)
210217
self._stack = None # type: List[List[bytes]] | None # Stack of encoded data
211218

212219
def start(self, stream=None, encoding=None):
213-
# type: (Union[io.RawIOBase, io.BufferedWriter, Encoding, None], Union[Encoding, None]) -> None
220+
# type: (EncoderStream, Union[Encoding, None]) -> None
214221
"""
215222
This method instructs the encoder to start encoding a new ASN.1
216223
output. This method may be called at any time to reset the encoder
217224
and reset the current output (if any).
218225
219226
Args:
220-
stream (io.RawIOBase or Encoding or None): The output stream or the encoding with no stream.
227+
stream (EncoderStream): The output stream or the encoding with no stream.
221228
encoding (Encoding or None): The encoding (DER or CER) to use.
222229
"""
223230
# stream is an Encoding, encoding is an Encoding: this not allowed
@@ -724,7 +731,7 @@ def __init__(self): # type: () -> None
724731
self._levels = 0 # type: int # Number of recursive calls
725732
self._ends = [] # type: List[int] # End of the current element (or INDEFINITE_FORM) for enter / leave
726733

727-
def start(self, stream): # type: (Union[io.RawIOBase, io.BufferedIOBase, bytes]) -> None
734+
def start(self, stream): # type: (DecoderStream) -> None
728735
"""
729736
This method instructs the decoder to start decoding an ASN.1 input.
730737
This method may be called at any time to start a new decoding job.
@@ -736,7 +743,7 @@ def start(self, stream): # type: (Union[io.RawIOBase, io.BufferedIOBase, bytes]
736743
assumes the input is in BER or DER format.
737744
738745
Args:
739-
stream (bytes or io.RawIOBase): ASN.1 input, in BER or DER format, to be decoded.
746+
stream (DecoderStream): ASN.1 input, in BER or DER format, to be decoded.
740747
741748
Returns:
742749
None
@@ -745,7 +752,7 @@ def start(self, stream): # type: (Union[io.RawIOBase, io.BufferedIOBase, bytes]
745752
`Error`
746753
"""
747754
if not isinstance(stream, bytes) and not isinstance(stream, io.RawIOBase) and not isinstance(stream, io.BufferedIOBase):
748-
raise Error('Expecting bytes or a subclass of io.RawIOBase. Get {} instead.'.format(type(stream)))
755+
raise Error('Expecting bytes or a subclass of io.RawIOBase or BufferedIOBase. Get {} instead.'.format(type(stream)))
749756

750757
self._stream = io.BytesIO(stream) if isinstance(stream, bytes) else stream # type: ignore
751758
self._tag = None

‎stubs/asn1.pyi renamed to ‎src/asn1/core.pyi

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,6 @@ from typing import Any
66
from typing import Generator
77
from typing import NamedTuple
88

9-
from _typeshed import Incomplete
10-
11-
INDEFINITE_FORM: int
12-
139
class Asn1Enum(IntEnum): ...
1410

1511
class Numbers(Asn1Enum):
@@ -59,29 +55,27 @@ class Classes(Asn1Enum):
5955
Context = 128
6056
Private = 192
6157

58+
class Encoding(Asn1Enum):
59+
DER = 1
60+
CER = 2
61+
6262
class ReadFlags(IntEnum):
6363
OnlyValue = 0
6464
WithUnused = 1
6565

6666
class Tag(NamedTuple):
67-
nr: Incomplete
68-
typ: Incomplete
69-
cls: Incomplete
67+
nr: int
68+
typ: int
69+
cls: int
7070

71-
def to_int_2c(values: bytes) -> int: ...
72-
def to_bytes_2c(value: int) -> bytes: ...
73-
def shift_bits_right(values, unused): ...
74-
def is_negative_zero(x): ...
75-
def is_positive_infinity(x): ...
76-
def is_negative_infinity(x): ...
77-
def is_nan(x): ...
78-
def is_iterable(value): ...
71+
EncoderStream: io.RawIOBase | io.BufferedWriter | None
72+
DecoderStream = io.RawIOBase | io.BufferedIOBase | bytes
7973

8074
class Error(Exception): ...
8175

8276
class Encoder:
8377
def __init__(self) -> None: ...
84-
def start(self, stream: io.RawIOBase | None = None) -> None: ...
78+
def start(self, stream: EncoderStream = None, encoding: Encoding | None = None) -> None: ...
8579
def enter(self, nr: int, cls: int | None = None) -> None: ...
8680
def leave(self) -> None: ...
8781
def construct(self, nr: int, cls: int | None = None) -> Generator[None, Any, None]: ...
@@ -90,7 +84,7 @@ class Encoder:
9084

9185
class Decoder:
9286
def __init__(self) -> None: ...
93-
def start(self, stream: io.RawIOBase | bytes) -> None: ...
87+
def start(self, stream: DecoderStream) -> None: ...
9488
def peek(self) -> Tag | None: ...
9589
def read(self, flags: ReadFlags = ...) -> tuple[Tag | None, Any]: ...
9690
def eof(self) -> bool: ...

‎src/asn1/py.typed

Whitespace-only changes.

0 commit comments

Comments
 (0)
Please sign in to comment.