X-Git-Url: http://www.git.cypherpunks.ru/?a=blobdiff_plain;f=pyderasn.py;h=ced46ddeb0f4fde4ca6f9be75120e9d1d421e1c2;hb=287f77ca2cf0b62db54e199ca1b5c16c93c3624e;hp=ea1b0b926ca295cea669fedaa2ed7d2c279f7f98;hpb=a5f63bdd812919be17945607d974825895448804;p=pyderasn.git diff --git a/pyderasn.py b/pyderasn.py index ea1b0b9..ced46dd 100755 --- a/pyderasn.py +++ b/pyderasn.py @@ -75,9 +75,17 @@ tags simultaneously. There are :py:func:`pyderasn.tag_ctxp` and :py:func:`pyderasn.tag_ctxc` functions, allowing you to easily create ``CONTEXT`` ``PRIMITIVE``/``CONSTRUCTED`` tags, by specifying only the required tag -number. Pay attention that explicit tags always have *constructed* tag -(``tag_ctxc``), but implicit tags for primitive types are primitive -(``tag_ctxp``). +number. + +.. note:: + + EXPLICIT tags always have **constructed** tag. PyDERASN does not + explicitly check correctness of schema input here. + +.. note:: + + Implicit tags have **primitive** (``tag_ctxp``) encoding for + primitive values. :: @@ -420,7 +428,7 @@ defines_by_path context option ______________________________ Sometimes you either can not or do not want to explicitly set *defines* -in the scheme. You can dynamically apply those definitions when calling +in the schema. You can dynamically apply those definitions when calling ``.decode()`` method. Specify ``defines_by_path`` key in the :ref:`decode context `. Its @@ -663,9 +671,9 @@ from copy import copy from datetime import datetime from datetime import timedelta from math import ceil -from os import environ from string import ascii_letters from string import digits +from sys import version_info from unicodedata import category as unicat from six import add_metaclass @@ -690,7 +698,7 @@ except ImportError: # pragma: no cover def colored(what, *args, **kwargs): return what -__version__ = "6.2" +__version__ = "6.3" __all__ = ( "Any", @@ -764,7 +772,7 @@ EOC = b"\x00\x00" EOC_LEN = len(EOC) LENINDEF = b"\x80" # length indefinite mark LENINDEF_PP_CHAR = "I" if PY2 else "∞" -NAMEDTUPLE_KWARGS = {} if PY2 else {"module": __name__} +NAMEDTUPLE_KWARGS = {} if version_info < (3, 6) else {"module": __name__} SET01 = frozenset("01") DECIMALS = frozenset(digits) DECIMAL_SIGNS = ".," @@ -1220,7 +1228,7 @@ class Obj(object): :param ctx: optional :ref:`context ` governing decoding process :param tag_only: decode only the tag, without length and contents (used only in Choice and Set structures, trying to - determine if tag satisfies the scheme) + determine if tag satisfies the schema) :param _ctx_immutable: do we need to ``copy.copy()`` ``ctx`` before using it? :returns: (Obj, remaining data) @@ -5133,7 +5141,7 @@ def get_def_by_path(defines_by_path, sub_decode_path): if len(path) != len(sub_decode_path): continue for p1, p2 in zip(path, sub_decode_path): - if (p1 != any) and (p1 != p2): + if (not p1 is any) and (p1 != p2): break else: return define @@ -5418,19 +5426,17 @@ class Sequence(Obj): return spec.default return None - def _encoded_values(self): - raws = [] + def _values_for_encoding(self): for name, spec in iteritems(self.specs): value = self._value.get(name) if value is None: if spec.optional: continue raise ObjNotReady(name) - raws.append(value.encode()) - return raws + yield value def _encode(self): - v = b"".join(self._encoded_values()) + v = b"".join(v.encode() for v in self._values_for_encoding()) return b"".join((self.tag, len_encode(len(v)), v)) def _decode(self, tlv, offset, decode_path, ctx, tag_only): @@ -5665,8 +5671,8 @@ class Set(Sequence): .. _allow_unordered_set_ctx: DER prohibits unordered values encoding and will raise an error - during decode. If If :ref:`bered ` context option is set, - then no error will occure. Also you can disable strict values + during decode. If :ref:`bered ` context option is set, + then no error will occur. Also you can disable strict values ordering check by setting ``"allow_unordered_set": True`` :ref:`context ` option. """ @@ -5675,7 +5681,7 @@ class Set(Sequence): asn1_type_name = "SET" def _encode(self): - raws = self._encoded_values() + raws = [v.encode() for v in self._values_for_encoding()] raws.sort() v = b"".join(raws) return b"".join((self.tag, len_encode(len(v)), v)) @@ -5816,13 +5822,14 @@ class Set(Sequence): tail = v[EOC_LEN:] obj.lenindef = True obj._value = values - if not obj.ready: - raise DecodeError( - "not all values are ready", - klass=self.__class__, - decode_path=decode_path, - offset=offset, - ) + for name, spec in iteritems(self.specs): + if name not in values and not spec.optional: + raise DecodeError( + "%s value is not ready" % name, + klass=self.__class__, + decode_path=decode_path, + offset=offset, + ) obj.ber_encoded = ber_encoded return obj, tail @@ -6041,11 +6048,11 @@ class SequenceOf(Obj): def __getitem__(self, key): return self._value[key] - def _encoded_values(self): - return [v.encode() for v in self._value] + def _values_for_encoding(self): + return iter(self._value) def _encode(self): - v = b"".join(self._encoded_values()) + v = b"".join(v.encode() for v in self._values_for_encoding()) return b"".join((self.tag, len_encode(len(v)), v)) def _decode(self, tlv, offset, decode_path, ctx, tag_only, ordering_check=False): @@ -6208,7 +6215,7 @@ class SetOf(SequenceOf): asn1_type_name = "SET OF" def _encode(self): - raws = self._encoded_values() + raws = [v.encode() for v in self._values_for_encoding()] raws.sort() v = b"".join(raws) return b"".join((self.tag, len_encode(len(v)), v)) @@ -6366,6 +6373,7 @@ def main(): # pragma: no cover if args.defines_by_path is not None: ctx["defines_by_path"] = obj_by_path(args.defines_by_path) obj, tail = schema().decode(der, ctx=ctx) + from os import environ print(pprinter( obj, oid_maps=oid_maps,