LENINDEF = b"\x80" # length indefinite mark
LENINDEF_PP_CHAR = "I" if PY2 else "∞"
NAMEDTUPLE_KWARGS = {} if PY2 else {"module": __name__}
+SET01 = frozenset(("0", "1"))
+DECIMAL_SIGNS = ".,"
+
+
+def pureint(value):
+ i = int(value)
+ if (value[0] in "+- ") or (value[-1] == " "):
+ raise ValueError("non-pure integer")
+ return i
+
+def fractions2float(fractions_raw):
+ pureint(fractions_raw)
+ return float("0." + fractions_raw)
########################################################################
with_colours,
))
if with_blob:
- if isinstance(pp.blob, binary_type):
+ if pp.blob.__class__ == binary_type:
cols.append(hexenc(pp.blob))
- elif isinstance(pp.blob, tuple):
+ elif pp.blob.__class__ == tuple:
cols.append(", ".join(pp.blob))
if pp.optional:
cols.append(_colourize("OPTIONAL", "red", with_colours))
decode_path_len = len(pp.decode_path) - decode_path_len_decrease
if decode_path_len > 0:
cols.append(" ." * (decode_path_len + 1))
- if isinstance(pp.blob, binary_type):
+ if pp.blob.__class__ == binary_type:
blob = hexenc(pp.blob).upper()
for i in six_xrange(0, len(blob), 32):
chunk = blob[i:i + 32]
yield " ".join(cols + [colonize_hex(chunk)])
- elif isinstance(pp.blob, tuple):
+ elif pp.blob.__class__ == tuple:
yield " ".join(cols + [", ".join(pp.blob)])
self._value = default
def _value_sanitize(self, value):
- if isinstance(value, bool):
+ if value.__class__ == bool:
return value
if issubclass(value.__class__, Boolean):
return value._value
return self._value
def __eq__(self, their):
- if isinstance(their, bool):
+ if their.__class__ == bool:
return self._value == their
if not issubclass(their.__class__, Boolean):
return False
super(Integer, self).__init__(impl, expl, default, optional, _decoded)
self._value = value
specs = getattr(self, "schema", {}) if _specs is None else _specs
- self.specs = specs if isinstance(specs, dict) else dict(specs)
+ self.specs = specs if specs.__class__ == dict else dict(specs)
self._bound_min, self._bound_max = getattr(
self,
"bounds",
pass
elif issubclass(value.__class__, Integer):
value = value._value
- elif isinstance(value, str):
+ elif value.__class__ == str:
value = self.specs.get(value)
if value is None:
raise ObjUnknown("integer value: %s" % value)
yield pp
-SET01 = frozenset(("0", "1"))
BitStringState = namedtuple("BitStringState", (
"version",
"specs",
"""
super(BitString, self).__init__(impl, expl, default, optional, _decoded)
specs = getattr(self, "schema", {}) if _specs is None else _specs
- self.specs = specs if isinstance(specs, dict) else dict(specs)
+ self.specs = specs if specs.__class__ == dict else dict(specs)
self._value = None if value is None else self._value_sanitize(value)
if default is not None:
default = self._value_sanitize(default)
len(value) * 4,
hexdec(value + ("" if len(value) % 2 == 0 else "0")),
)
- if isinstance(value, binary_type):
+ if value.__class__ == binary_type:
return (len(value) * 8, value)
raise InvalidValueType((self.__class__, string_types, binary_type))
- if isinstance(value, tuple):
+ if value.__class__ == tuple:
if (
len(value) == 2 and
isinstance(value[0], integer_types) and
- isinstance(value[1], binary_type)
+ value[1].__class__ == binary_type
):
return value
bits = []
return self._value[1]
def __eq__(self, their):
- if isinstance(their, bytes):
+ if their.__class__ == bytes:
return self._value[1] == their
if not issubclass(their.__class__, BitString):
return False
)
def __getitem__(self, key):
- if isinstance(key, int):
+ if key.__class__ == int:
bit_len, octets = self._value
if key >= bit_len:
return False
)
def _value_sanitize(self, value):
- if isinstance(value, binary_type):
+ if value.__class__ == binary_type:
pass
elif issubclass(value.__class__, OctetString):
value = value._value
return self._value
def __eq__(self, their):
- if isinstance(their, binary_type):
+ if their.__class__ == binary_type:
return self._value == their
if not issubclass(their.__class__, OctetString):
return False
), **NAMEDTUPLE_KWARGS)
-def pureint(value):
- i = int(value)
- if (value[0] in "+- ") or (value[-1] == " "):
- raise ValueError("non-pure integer")
- return i
-
-
class ObjectIdentifier(Obj):
"""``OBJECT IDENTIFIER`` OID type
self.defines = defines
def __add__(self, their):
+ if their.__class__ == tuple:
+ return self.__class__(self._value + their)
if isinstance(their, self.__class__):
return self.__class__(self._value + their._value)
- if isinstance(their, tuple):
- return self.__class__(self._value + their)
raise InvalidValueType((self.__class__, tuple))
def _value_sanitize(self, value):
value = tuple(pureint(arc) for arc in value.split("."))
except ValueError:
raise InvalidOID("unacceptable arcs values")
- if isinstance(value, tuple):
+ if value.__class__ == tuple:
if len(value) < 2:
raise InvalidOID("less than 2 arcs")
first_arc = value[0]
)
def __eq__(self, their):
- if isinstance(their, tuple):
+ if their.__class__ == tuple:
return self._value == their
if not issubclass(their.__class__, ObjectIdentifier):
return False
def escape_control_unicode(c):
- if unicat(c).startswith("C"):
+ if unicat(c)[0] == "C":
c = repr(c).lstrip("u").strip("'")
return c
value_decoded = None
if isinstance(value, self.__class__):
value_raw = value._value
- elif isinstance(value, text_type):
+ elif value.__class__ == text_type:
value_decoded = value
- elif isinstance(value, binary_type):
+ elif value.__class__ == binary_type:
value_raw = value
else:
raise InvalidValueType((self.__class__, text_type, binary_type))
return value_raw
def __eq__(self, their):
- if isinstance(their, binary_type):
+ if their.__class__ == binary_type:
return self._value == their
- if isinstance(their, text_type):
+ if their.__class__ == text_type:
return self._value == their.encode(self.encoding)
if not isinstance(their, self.__class__):
return False
LEN_YYYYMMDDHHMMSSZ = len("YYYYMMDDHHMMSSZ")
-def fractions2float(fractions_raw):
- pureint(fractions_raw)
- return float("0." + fractions_raw)
-
-
class VisibleString(CommonString):
__slots__ = ()
tag_default = tag_encode(26)
)
+def str_to_time_fractions(value):
+ v = pureint(value)
+ year, v = (v // 10**10), (v % 10**10)
+ month, v = (v // 10**8), (v % 10**8)
+ day, v = (v // 10**6), (v % 10**6)
+ hour, v = (v // 10**4), (v % 10**4)
+ minute, second = (v // 100), (v % 100)
+ return year, month, day, hour, minute, second
+
+
class UTCTime(VisibleString):
"""``UTCTime`` datetime type
>>> UTCTime(datetime(2057, 9, 30, 22, 7, 50)).todatetime()
datetime.datetime(1957, 9, 30, 22, 7, 50)
+ If BER encoded value was met, then ``ber_raw`` attribute will hold
+ its raw representation.
+
.. warning::
Pay attention that UTCTime can not hold full year, so all years
* minutes are not exceeding 60
* offset value is not exceeding 14 hours
"""
- __slots__ = ("_ber_raw",)
+ __slots__ = ("ber_raw",)
tag_default = tag_encode(23)
encoding = "ascii"
asn1_type_name = "UTCTime"
None, None, impl, expl, None, optional, _decoded, ctx,
)
self._value = value
- self._ber_raw = None
+ self.ber_raw = None
if value is not None:
- self._value, self._ber_raw = self._value_sanitize(value, ctx)
- self.ber_encoded = self._ber_raw is not None
+ self._value, self.ber_raw = self._value_sanitize(value, ctx)
+ self.ber_encoded = self.ber_raw is not None
if default is not None:
default, _ = self._value_sanitize(default)
self.default = self.__class__(
self.optional = optional
def _strptime_bered(self, value):
- year = pureint(value[:2])
- year += 2000 if year < 50 else 1900
- decoded = datetime(
- year, # %Y
- pureint(value[2:4]), # %m
- pureint(value[4:6]), # %d
- pureint(value[6:8]), # %H
- pureint(value[8:10]), # %M
- )
+ year, month, day, hour, minute, _ = str_to_time_fractions(value[:10] + "00")
value = value[10:]
if len(value) == 0:
raise ValueError("no timezone")
+ year += 2000 if year < 50 else 1900
+ decoded = datetime(year, month, day, hour, minute)
offset = 0
if value[-1] == "Z":
value = value[:-1]
sign = 1
else:
raise ValueError("invalid UTC offset")
- offset = 60 * pureint(value[-2:])
+ v = pureint(value[-4:])
+ offset, v = (60 * (v % 100)), v // 100
if offset >= 3600:
raise ValueError("invalid UTC offset minutes")
- offset += 3600 * pureint(value[-4:-2])
+ offset += 3600 * v
if offset > 14 * 3600:
raise ValueError("too big UTC offset")
offset *= sign
seconds = pureint(value)
if seconds >= 60:
raise ValueError("invalid seconds value")
- decoded += timedelta(seconds=seconds)
- return offset, decoded
+ return offset, decoded + timedelta(seconds=seconds)
def _strptime(self, value):
# datetime.strptime's format: %y%m%d%H%M%SZ
raise ValueError("invalid UTCTime length")
if value[-1] != "Z":
raise ValueError("non UTC timezone")
- year = pureint(value[:2])
+ year, month, day, hour, minute, second = str_to_time_fractions(value[:-1])
year += 2000 if year < 50 else 1900
- return datetime(
- year, # %y
- pureint(value[2:4]), # %m
- pureint(value[4:6]), # %d
- pureint(value[6:8]), # %H
- pureint(value[8:10]), # %M
- pureint(value[10:12]), # %S
- )
+ return datetime(year, month, day, hour, minute, second)
def _dt_sanitize(self, value):
if value.year < 1950 or value.year > 2049:
return value.replace(microsecond=0)
def _value_sanitize(self, value, ctx=None):
- if isinstance(value, binary_type):
+ if value.__class__ == binary_type:
try:
value_decoded = value.decode("ascii")
except (UnicodeEncodeError, UnicodeDecodeError) as err:
try:
offset, _value = self._strptime_bered(value_decoded)
_value = _value - timedelta(seconds=offset)
- return self._dt_sanitize(_value), value_decoded
+ return self._dt_sanitize(_value), value
except (TypeError, ValueError, OverflowError) as _err:
err = _err
raise DecodeError(
)
if isinstance(value, self.__class__):
return value._value, None
- if isinstance(value, datetime):
+ if value.__class__ == datetime:
return self._dt_sanitize(value), None
raise InvalidValueType((self.__class__, datetime))
if self.ready:
value = self._value.isoformat()
if self.ber_encoded:
- value += " (%s)" % self._ber_raw
+ value += " (%s)" % self.ber_raw
return value
def __unicode__(self):
if self.ready:
value = self._value.isoformat()
if self.ber_encoded:
- value += " (%s)" % self._ber_raw
+ value += " (%s)" % self.ber_raw
return value
return text_type(self._pp_value())
def __getstate__(self):
return UTCTimeState(
*super(UTCTime, self).__getstate__(),
- **{"ber_raw": self._ber_raw}
+ **{"ber_raw": self.ber_raw}
)
def __setstate__(self, state):
super(UTCTime, self).__setstate__(state)
- self._ber_raw = state.ber_raw
+ self.ber_raw = state.ber_raw
def __bytes__(self):
self._assert_ready()
return self._encode_time()
def __eq__(self, their):
- if isinstance(their, binary_type):
+ if their.__class__ == binary_type:
return self._encode_time() == their
- if isinstance(their, datetime):
+ if their.__class__ == datetime:
return self.todatetime() == their
if not isinstance(their, self.__class__):
return False
def _strptime_bered(self, value):
if len(value) < 4 + 3 * 2:
raise ValueError("invalid GeneralizedTime")
- decoded = datetime(
- pureint(value[:4]), # %Y
- pureint(value[4:6]), # %m
- pureint(value[6:8]), # %d
- pureint(value[8:10]), # %H
- )
- value = value[10:]
- offset = 0
+ year, month, day, hour, _, _ = str_to_time_fractions(value[:10] + "0000")
+ decoded = datetime(year, month, day, hour)
+ offset, value = 0, value[10:]
if len(value) == 0:
return offset, decoded
if value[-1] == "Z":
idx = value.rfind(char)
if idx == -1:
continue
- offset_raw = value[idx + 1:].replace(":", "")
- if len(offset_raw) not in (2, 4):
+ offset_raw, value = value[idx + 1:].replace(":", ""), value[:idx]
+ v = pureint(offset_raw)
+ if len(offset_raw) == 4:
+ offset, v = (60 * (v % 100)), v // 100
+ if offset >= 3600:
+ raise ValueError("invalid UTC offset minutes")
+ elif len(offset_raw) == 2:
+ pass
+ else:
raise ValueError("invalid UTC offset")
- value = value[:idx]
- offset = 60 * pureint(offset_raw[2:] or "0")
- if offset >= 3600:
- raise ValueError("invalid UTC offset minutes")
- offset += 3600 * pureint(offset_raw[:2])
+ offset += 3600 * v
if offset > 14 * 3600:
raise ValueError("too big UTC offset")
offset *= sign
break
if len(value) == 0:
return offset, decoded
- decimal_signs = ".,"
- if value[0] in decimal_signs:
+ if value[0] in DECIMAL_SIGNS:
return offset, (
decoded + timedelta(seconds=3600 * fractions2float(value[1:]))
)
value = value[2:]
if len(value) == 0:
return offset, decoded
- if value[0] in decimal_signs:
+ if value[0] in DECIMAL_SIGNS:
return offset, (
decoded + timedelta(seconds=60 * fractions2float(value[1:]))
)
value = value[2:]
if len(value) == 0:
return offset, decoded
- if value[0] not in decimal_signs:
+ if value[0] not in DECIMAL_SIGNS:
raise ValueError("invalid format after seconds")
return offset, (
decoded + timedelta(microseconds=10**6 * fractions2float(value[1:]))
# datetime.strptime's format: %Y%m%d%H%M%SZ
if value[-1] != "Z":
raise ValueError("non UTC timezone")
- return datetime(
- pureint(value[:4]), # %Y
- pureint(value[4:6]), # %m
- pureint(value[6:8]), # %d
- pureint(value[8:10]), # %H
- pureint(value[10:12]), # %M
- pureint(value[12:14]), # %S
- )
+ return datetime(*str_to_time_fractions(value[:-1]))
if l >= LEN_YYYYMMDDHHMMSSDMZ:
# datetime.strptime's format: %Y%m%d%H%M%S.%fZ
if value[-1] != "Z":
if us_len > 6:
raise ValueError("only microsecond fractions are supported")
us = pureint(us + ("0" * (6 - us_len)))
- decoded = datetime(
- pureint(value[:4]), # %Y
- pureint(value[4:6]), # %m
- pureint(value[6:8]), # %d
- pureint(value[8:10]), # %H
- pureint(value[10:12]), # %M
- pureint(value[12:14]), # %S
- us, # %f
- )
- return decoded
+ year, month, day, hour, minute, second = str_to_time_fractions(value[:14])
+ return datetime(year, month, day, hour, minute, second, us)
raise ValueError("invalid GeneralizedTime length")
def _encode_time(self):
if len(schema) == 0:
raise ValueError("schema must be specified")
self.specs = (
- schema if isinstance(schema, OrderedDict) else OrderedDict(schema)
+ schema if schema.__class__ == OrderedDict else OrderedDict(schema)
)
self._value = None
if value is not None:
self._value = copy(default_obj._value)
def _value_sanitize(self, value):
- if isinstance(value, tuple) and len(value) == 2:
+ if (value.__class__ == tuple) and len(value) == 2:
choice, obj = value
spec = self.specs.get(choice)
if spec is None:
self.ber_encoded = state.ber_encoded
def __eq__(self, their):
- if isinstance(their, tuple) and len(their) == 2:
+ if (their.__class__ == tuple) and len(their) == 2:
return self._value == their
if not isinstance(their, self.__class__):
return False
self.defined = None
def _value_sanitize(self, value):
- if isinstance(value, binary_type):
+ if value.__class__ == binary_type:
return value
if isinstance(value, self.__class__):
return value._value
self.defined = state.defined
def __eq__(self, their):
- if isinstance(their, binary_type):
+ if their.__class__ == binary_type:
return self._value == their
if issubclass(their.__class__, Any):
return self._value == their._value
if schema is None:
schema = getattr(self, "schema", ())
self.specs = (
- schema if isinstance(schema, OrderedDict) else OrderedDict(schema)
+ schema if schema.__class__ == OrderedDict else OrderedDict(schema)
)
self._value = {}
if value is not None: