Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Choise with callbacks #126

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 18 additions & 14 deletions asn1crypto/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ def load(encoded_data, strict=False):
- 5: Null
- 6: ObjectIdentifier
- 7: ObjectDescriptor
- 8: InstanceOf
- 8: InstanceOf, External
- 9: Real
- 10: Enumerated
- 11: EmbeddedPdv
Expand Down Expand Up @@ -584,10 +584,13 @@ def debug(self, nest_level=1):
elif hasattr(self, 'chosen'):
self.chosen.debug(nest_level + 2)
else:
if _PY2 and isinstance(self.native, byte_cls):
print('%s Native: b%s' % (prefix, repr(self.native)))
if hasattr(self, 'native'):
if _PY2 and isinstance(self.native, byte_cls):
print('%s Native: b%s' % (prefix, repr(self.native)))
else:
print('%s Native: %s' % (prefix, self.native))
else:
print('%s Native: %s' % (prefix, self.native))
print('%s No Native representation available' % (prefix,))

def dump(self, force=False):
"""
Expand Down Expand Up @@ -618,7 +621,6 @@ def dump(self, force=False):

return self._header + contents


class ValueMap():
"""
Basic functionality that allows for mapping values from ints or OIDs to
Expand Down Expand Up @@ -999,6 +1001,10 @@ class Choice(Asn1Value):
# A dict that maps alternative names to an index in _alternatives
_name_map = None

# A dict with keys being the name of a field and the value being a unicode
# string of the method name on self to call to get the spec for that field
_spec_callbacks = None

@classmethod
def load(cls, encoded_data, strict=False, **kwargs):
"""
Expand Down Expand Up @@ -1110,6 +1116,9 @@ def __init__(self, name=None, value=None, **kwargs):
self._choice = self._name_map[name]
_, spec, params = self._alternatives[self._choice]

if self._spec_callbacks and self.name in self._spec_callbacks:
spec = self._spec_callbacks[name]()

if not isinstance(value, spec):
value = spec(value, **params)
else:
Expand Down Expand Up @@ -1144,6 +1153,9 @@ def parse(self):

try:
_, spec, params = self._alternatives[self._choice]

if self._spec_callbacks and self.name in self._spec_callbacks:
spec = self._spec_callbacks[self.name](self)
self._parsed, _ = _parse_build(self.contents, spec=spec, spec_params=params)
except (ValueError, TypeError) as e:
args = e.args[1:]
Expand All @@ -1167,7 +1179,6 @@ def native(self):
:return:
The .native value from the contained value object
"""

return self.chosen.native

def validate(self, class_, tag, contents):
Expand Down Expand Up @@ -2952,7 +2963,6 @@ class InstanceOf(Primitive):

tag = 8


class Real(Primitive):
"""
Represents a real number from ASN.1 - no Python implementation
Expand Down Expand Up @@ -3212,7 +3222,6 @@ def _lazy_child(self, index):
"""
Builds a child object if the child has only been parsed into a tuple so far
"""

child = self.children[index]
if child.__class__ == tuple:
child = self.children[index] = _build(*child)
Expand Down Expand Up @@ -3469,7 +3478,6 @@ def _determine_spec(self, index):
name, field_spec, field_params = self._fields[index]
value_spec = field_spec
spec_override = None

if self._spec_callbacks is not None and name in self._spec_callbacks:
callback = self._spec_callbacks[name]
spec_override = callback(self)
Expand Down Expand Up @@ -4953,7 +4961,6 @@ def _build_id_tuple(params, spec):

return (required_class, required_tag)


_UNIVERSAL_SPECS = {
1: Boolean,
2: Integer,
Expand Down Expand Up @@ -5026,15 +5033,13 @@ def _build(class_, method, tag, header, contents, trailer, spec=None, spec_param
:return:
An object of the type spec, or if not specified, a child of Asn1Value
"""

if spec_params is not None:
_tag_type_to_explicit_implicit(spec_params)

if header is None:
return VOID

header_set = False

# If an explicit specification was passed in, make sure it matches
if spec is not None:
# If there is explicit tagging and contents, we have to split
Expand Down Expand Up @@ -5086,7 +5091,6 @@ def _build(class_, method, tag, header, contents, trailer, spec=None, spec_param
))
info, _ = _parse(to_parse, len(to_parse))
parsed_class, parsed_method, parsed_tag, parsed_header, to_parse, parsed_trailer = info

if not isinstance(value, Choice):
explicit_header += parsed_header
explicit_trailer = parsed_trailer + explicit_trailer
Expand All @@ -5102,7 +5106,7 @@ def _build(class_, method, tag, header, contents, trailer, spec=None, spec_param
else:
value = spec(contents=contents)

if spec is Any:
if issubclass(spec, Any) or isinstance(spec, Any):
pass

elif isinstance(value, Choice):
Expand Down