* :py:class:`pyderasn.BitString` (that is multiple of 8 bits)
* :py:class:`pyderasn.OctetString`
* :py:class:`pyderasn.SequenceOf`/:py:class:`pyderasn.SetOf`
- ``Any``/``OctetString``-s
+ ``Any``/``BitString``/``OctetString``-s
When any of those fields is automatically decoded, then ``.defined``
attribute contains ``(OID, value)`` tuple. ``OID`` tells by which OID it
(
(
"content",
- decode_path_defby(id_signedData),
+ DecodePathDefBy(id_signedData),
"encapContentInfo",
"eContentType",
),
(
(
"content",
- decode_path_defby(id_signedData),
+ DecodePathDefBy(id_signedData),
"encapContentInfo",
"eContent",
- decode_path_defby(id_cct_PKIResponse),
+ DecodePathDefBy(id_cct_PKIResponse),
"controlSequence",
any,
"attrType",
),
))
-Pay attention for :py:func:`pyderasn.decode_path_defby` and ``any``.
+Pay attention for :py:class:`pyderasn.DecodePathDefBy` and ``any``.
First function is useful for path construction when some automatic
decoding is already done. ``any`` means literally any value it meet --
useful for SEQUENCE/SET OF-s.
from collections import OrderedDict
from datetime import datetime
from math import ceil
+from os import environ
from six import add_metaclass
from six import binary_type
from six.moves import xrange as six_xrange
+try:
+ from termcolor import colored
+except ImportError:
+ def colored(what, *args):
+ return what
+
+
__all__ = (
"Any",
"BitString",
"Boolean",
"BoundsError",
"Choice",
- "decode_path_defby",
"DecodeError",
+ "DecodePathDefBy",
"Enumerated",
"GeneralizedTime",
"GeneralString",
c for c in (
"" if self.klass is None else self.klass.__name__,
(
- ("(%s)" % ".".join(self.decode_path))
+ ("(%s)" % ".".join(str(dp) for dp in self.decode_path))
if len(self.decode_path) > 0 else ""
),
("(at %d)" % self.offset) if self.offset > 0 else "",
return self.expl_tlen + self.expl_llen + self.expl_vlen
-def decode_path_defby(defined_by):
+class DecodePathDefBy(object):
"""DEFINED BY representation inside decode path
"""
- return "DEFINED BY (%s)" % defined_by
+ __slots__ = ('defined_by',)
+
+ def __init__(self, defined_by):
+ self.defined_by = defined_by
+
+ def __eq__(self, their):
+ if not isinstance(their, self.__class__):
+ return False
+ return self.defined_by == their.defined_by
+
+ def __str__(self):
+ return "DEFINED BY " + str(self.defined_by)
+
+ def __repr__(self):
+ return "<%s: %s>" % (self.__class__.__name__, self.defined_by)
########################################################################
)
-def pp_console_row(pp, oids=None, with_offsets=False, with_blob=True):
+def _colorize(what, colour, with_colours, attrs=("bold",)):
+ return colored(what, colour, attrs=attrs) if with_colours else what
+
+
+def pp_console_row(
+ pp,
+ oids=None,
+ with_offsets=False,
+ with_blob=True,
+ with_colours=False,
+):
cols = []
if with_offsets:
- cols.append("%5d%s [%d,%d,%4d]" % (
+ col = "%5d%s" % (
pp.offset,
(
" " if pp.expl_offset is None else
("-%d" % (pp.offset - pp.expl_offset))
),
- pp.tlen,
- pp.llen,
- pp.vlen,
- ))
+ )
+ cols.append(_colorize(col, "red", with_colours, ()))
+ col = "[%d,%d,%4d]" % (pp.tlen, pp.llen, pp.vlen)
+ cols.append(_colorize(col, "green", with_colours, ()))
if len(pp.decode_path) > 0:
cols.append(" ." * (len(pp.decode_path)))
- cols.append("%s:" % pp.decode_path[-1])
+ ent = pp.decode_path[-1]
+ if isinstance(ent, DecodePathDefBy):
+ cols.append(_colorize("DEFINED BY", "red", with_colours, ("reverse",)))
+ value = str(ent.defined_by)
+ if (
+ oids is not None and
+ ent.defined_by.asn1_type_name ==
+ ObjectIdentifier.asn1_type_name and
+ value in oids
+ ):
+ cols.append(_colorize("%s:" % oids[value], "green", with_colours))
+ else:
+ cols.append(_colorize("%s:" % value, "white", with_colours, ("reverse",)))
+ else:
+ cols.append(_colorize("%s:" % ent, "yellow", with_colours, ("reverse",)))
if pp.expl is not None:
klass, _, num = pp.expl
- cols.append("[%s%d] EXPLICIT" % (TagClassReprs[klass], num))
+ col = "[%s%d] EXPLICIT" % (TagClassReprs[klass], num)
+ cols.append(_colorize(col, "blue", with_colours))
if pp.impl is not None:
klass, _, num = pp.impl
- cols.append("[%s%d]" % (TagClassReprs[klass], num))
+ col = "[%s%d]" % (TagClassReprs[klass], num)
+ cols.append(_colorize(col, "blue", with_colours))
if pp.asn1_type_name.replace(" ", "") != pp.obj_name.upper():
- cols.append(pp.obj_name)
- cols.append(pp.asn1_type_name)
+ cols.append(_colorize(pp.obj_name, "magenta", with_colours))
+ cols.append(_colorize(pp.asn1_type_name, "cyan", with_colours))
if pp.value is not None:
value = pp.value
+ cols.append(_colorize(value, "white", with_colours, ("reverse",)))
if (
oids is not None and
pp.asn1_type_name == ObjectIdentifier.asn1_type_name and
value in oids
):
- value = "%s (%s)" % (oids[value], pp.value)
- cols.append(value)
+ cols.append(_colorize("(%s)" % oids[value], "green", with_colours))
if with_blob:
if isinstance(pp.blob, binary_type):
cols.append(hexenc(pp.blob))
elif isinstance(pp.blob, tuple):
cols.append(", ".join(pp.blob))
if pp.optional:
- cols.append("OPTIONAL")
+ cols.append(_colorize("OPTIONAL", "red", with_colours))
if pp.default:
- cols.append("DEFAULT")
+ cols.append(_colorize("DEFAULT", "red", with_colours))
return " ".join(cols)
yield " ".join(cols + [", ".join(pp.blob)])
-def pprint(obj, oids=None, big_blobs=False):
+def pprint(obj, oids=None, big_blobs=False, with_colours=False):
"""Pretty print object
:param Obj obj: object you want to pretty print
:param big_blobs: if large binary objects are met (like OctetString
values), do we need to print them too, on separate
lines
+ :param with_colours: colourize output, if ``termcolor`` library
+ is available
"""
def _pprint_pps(pps):
for pp in pps:
oids=oids,
with_offsets=True,
with_blob=False,
+ with_colours=with_colours,
)
for row in pp_console_blob(pp):
yield row
else:
- yield pp_console_row(pp, oids=oids, with_offsets=True)
+ yield pp_console_row(
+ pp,
+ oids=oids,
+ with_offsets=True,
+ with_blob=True,
+ with_colours=with_colours,
+ )
else:
for row in _pprint_pps(pp):
yield row
defined_by, defined = self.defined or (None, None)
if defined_by is not None:
yield defined.pps(
- decode_path=decode_path + (decode_path_defby(defined_by),)
+ decode_path=decode_path + (DecodePathDefBy(defined_by),)
)
defined_by, defined = self.defined or (None, None)
if defined_by is not None:
yield defined.pps(
- decode_path=decode_path + (decode_path_defby(defined_by),)
+ decode_path=decode_path + (DecodePathDefBy(defined_by),)
)
defined_by, defined = self.defined or (None, None)
if defined_by is not None:
yield defined.pps(
- decode_path=decode_path + (decode_path_defby(defined_by),)
+ decode_path=decode_path + (DecodePathDefBy(defined_by),)
)
for i, _value in enumerate(value):
sub_sub_decode_path = sub_decode_path + (
str(i),
- decode_path_defby(defined_by),
+ DecodePathDefBy(defined_by),
)
defined_value, defined_tail = defined_spec.decode(
memoryview(bytes(_value)),
- sub_offset + value.tlen + value.llen,
+ sub_offset + (
+ (value.tlen + value.llen + value.expl_tlen + value.expl_llen)
+ if value.expled else (value.tlen + value.llen)
+ ),
leavemm=True,
decode_path=sub_sub_decode_path,
ctx=ctx,
else:
defined_value, defined_tail = defined_spec.decode(
memoryview(bytes(value)),
- sub_offset + value.tlen + value.llen,
+ sub_offset + (
+ (value.tlen + value.llen + value.expl_tlen + value.expl_llen)
+ if value.expled else (value.tlen + value.llen)
+ ),
leavemm=True,
- decode_path=sub_decode_path + (decode_path_defby(defined_by),),
+ decode_path=sub_decode_path + (DecodePathDefBy(defined_by),),
ctx=ctx,
)
if len(defined_tail) > 0:
raise DecodeError(
"remaining data",
klass=self.__class__,
- decode_path=sub_decode_path + (decode_path_defby(defined_by),),
+ decode_path=sub_decode_path + (DecodePathDefBy(defined_by),),
offset=offset,
)
value.defined = (defined_by, defined_value)
__slots__ = ()
schema = choice
- def pprint_any(obj, oids=None):
+ def pprint_any(obj, oids=None, with_colours=False):
def _pprint_pps(pps):
for pp in pps:
if hasattr(pp, "_fields"):
oids=oids,
with_offsets=True,
with_blob=False,
+ with_colours=with_colours,
)
for row in pp_console_blob(pp):
yield row
{"defines_by_path": obj_by_path(args.defines_by_path)}
),
)
- print(pprinter(obj, oids=oids))
+ print(pprinter(
+ obj,
+ oids=oids,
+ with_colours=True if environ.get("NO_COLOR") is None else False,
+ ))
if tail != b"":
print("\nTrailing data: %s" % hexenc(tail))