Atualiza a estrutura do projeto Evo AI, adicionando novos scripts de seeders para criar dados iniciais, incluindo usuários, agentes, clientes e ferramentas. Implementa rotas de autenticação e auditoria, além de configurar o middleware JWT. Atualiza as configurações de ambiente e o README para refletir as mudanças. Adiciona novas dependências para autenticação e envio de e-mails.

This commit is contained in:
Davidson Gomes
2025-04-28 15:33:48 -03:00
parent dbdb72ce0e
commit 84ea77c3f7
72 changed files with 5211 additions and 3083 deletions

View File

@@ -1,2 +1,7 @@
import sys
# https://www.python.org/dev/peps/pep-0396/
__version__ = '0.6.1'
__version__ = '0.4.8'
if sys.version_info[:2] < (2, 4):
raise RuntimeError('PyASN1 requires Python 2.4 or later')

File diff suppressed because it is too large Load Diff

View File

@@ -1,23 +1,23 @@
#
# This file is part of pyasn1 software.
#
# Copyright (c) 2005-2020, Ilya Etingof <etingof@gmail.com>
# License: https://pyasn1.readthedocs.io/en/latest/license.html
# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com>
# License: http://snmplabs.com/pyasn1/license.html
#
import sys
import warnings
from pyasn1 import debug
from pyasn1 import error
from pyasn1.codec.ber import eoo
from pyasn1.compat import _MISSING
from pyasn1.compat.integer import to_bytes
from pyasn1.compat.octets import (int2oct, oct2int, ints2octs, null,
str2octs, isOctetsType)
from pyasn1.type import char
from pyasn1.type import tag
from pyasn1.type import univ
from pyasn1.type import useful
__all__ = ['Encoder', 'encode']
__all__ = ['encode']
LOG = debug.registerLoggee(__name__, flags=debug.DEBUG_ENCODER)
@@ -27,7 +27,7 @@ class AbstractItemEncoder(object):
# An outcome of otherwise legit call `encodeFun(eoo.endOfOctets)`
eooIntegerSubstrate = (0, 0)
eooOctetsSubstrate = bytes(eooIntegerSubstrate)
eooOctetsSubstrate = ints2octs(eooIntegerSubstrate)
# noinspection PyMethodMayBeStatic
def encodeTag(self, singleTag, isConstructed):
@@ -89,7 +89,7 @@ class AbstractItemEncoder(object):
defMode = options.get('defMode', True)
substrate = b''
substrate = null
for idx, singleTag in enumerate(tagSet.superTags):
@@ -102,9 +102,10 @@ class AbstractItemEncoder(object):
value, asn1Spec, encodeFun, **options
)
except error.PyAsn1Error as exc:
except error.PyAsn1Error:
exc = sys.exc_info()
raise error.PyAsn1Error(
'Error encoding %r: %s' % (value, exc))
'Error encoding %r: %s' % (value, exc[1]))
if LOG:
LOG('encoded %svalue %s into %s' % (
@@ -125,16 +126,16 @@ class AbstractItemEncoder(object):
if LOG:
LOG('encoded %stag %s into %s' % (
isConstructed and 'constructed ' or '',
singleTag, debug.hexdump(bytes(header))))
singleTag, debug.hexdump(ints2octs(header))))
header += self.encodeLength(len(substrate), defModeOverride)
if LOG:
LOG('encoded %s octets (tag + payload) into %s' % (
len(substrate), debug.hexdump(bytes(header))))
len(substrate), debug.hexdump(ints2octs(header))))
if isOctets:
substrate = bytes(header) + substrate
substrate = ints2octs(header) + substrate
if not defModeOverride:
substrate += self.eooOctetsSubstrate
@@ -146,14 +147,14 @@ class AbstractItemEncoder(object):
substrate += self.eooIntegerSubstrate
if not isOctets:
substrate = bytes(substrate)
substrate = ints2octs(substrate)
return substrate
class EndOfOctetsEncoder(AbstractItemEncoder):
def encodeValue(self, value, asn1Spec, encodeFun, **options):
return b'', False, True
return null, False, True
class BooleanEncoder(AbstractItemEncoder):
@@ -198,7 +199,7 @@ class BitStringEncoder(AbstractItemEncoder):
maxChunkSize = options.get('maxChunkSize', 0)
if not maxChunkSize or len(alignedValue) <= maxChunkSize * 8:
substrate = alignedValue.asOctets()
return bytes((len(substrate) * 8 - valueLength,)) + substrate, False, True
return int2oct(len(substrate) * 8 - valueLength) + substrate, False, True
if LOG:
LOG('encoding into up to %s-octet chunks' % maxChunkSize)
@@ -215,7 +216,7 @@ class BitStringEncoder(AbstractItemEncoder):
alignedValue = alignedValue.clone(tagSet=tagSet)
stop = 0
substrate = b''
substrate = null
while stop < valueLength:
start = stop
stop = min(start + maxChunkSize * 8, valueLength)
@@ -231,7 +232,7 @@ class OctetStringEncoder(AbstractItemEncoder):
if asn1Spec is None:
substrate = value.asOctets()
elif not isinstance(value, bytes):
elif not isOctetsType(value):
substrate = asn1Spec.clone(value).asOctets()
else:
@@ -259,7 +260,7 @@ class OctetStringEncoder(AbstractItemEncoder):
asn1Spec = value.clone(tagSet=tagSet)
elif not isinstance(value, bytes):
elif not isOctetsType(value):
baseTag = asn1Spec.tagSet.baseTag
# strip off explicit tags
@@ -272,7 +273,7 @@ class OctetStringEncoder(AbstractItemEncoder):
asn1Spec = asn1Spec.clone(tagSet=tagSet)
pos = 0
substrate = b''
substrate = null
while True:
chunk = value[pos:pos + maxChunkSize]
@@ -289,7 +290,7 @@ class NullEncoder(AbstractItemEncoder):
supportIndefLenMode = False
def encodeValue(self, value, asn1Spec, encodeFun, **options):
return b'', False, True
return null, False, True
class ObjectIdentifierEncoder(AbstractItemEncoder):
@@ -351,41 +352,8 @@ class ObjectIdentifierEncoder(AbstractItemEncoder):
return octets, False, False
class RelativeOIDEncoder(AbstractItemEncoder):
supportIndefLenMode = False
def encodeValue(self, value, asn1Spec, encodeFun, **options):
if asn1Spec is not None:
value = asn1Spec.clone(value)
octets = ()
# Cycle through subIds
for subOid in value.asTuple():
if 0 <= subOid <= 127:
# Optimize for the common case
octets += (subOid,)
elif subOid > 127:
# Pack large Sub-Object IDs
res = (subOid & 0x7f,)
subOid >>= 7
while subOid:
res = (0x80 | (subOid & 0x7f),) + res
subOid >>= 7
# Add packed Sub-Object ID to resulted RELATIVE-OID
octets += res
else:
raise error.PyAsn1Error('Negative RELATIVE-OID arc %s at %s' % (subOid, value))
return octets, False, False
class RealEncoder(AbstractItemEncoder):
supportIndefLenMode = False
supportIndefLenMode = 0
binEncBase = 2 # set to None to choose encoding base automatically
@staticmethod
@@ -462,13 +430,13 @@ class RealEncoder(AbstractItemEncoder):
m, b, e = value
if not m:
return b'', False, True
return null, False, True
if b == 10:
if LOG:
LOG('encoding REAL into character form')
return b'\x03%dE%s%d' % (m, e == 0 and b'+' or b'', e), False, True
return str2octs('\x03%dE%s%d' % (m, e == 0 and '+' or '', e)), False, True
elif b == 2:
fo = 0x80 # binary encoding
@@ -505,20 +473,20 @@ class RealEncoder(AbstractItemEncoder):
raise error.PyAsn1Error('Scale factor overflow') # bug if raised
fo |= sf << 2
eo = b''
eo = null
if e == 0 or e == -1:
eo = bytes((e & 0xff,))
eo = int2oct(e & 0xff)
else:
while e not in (0, -1):
eo = bytes((e & 0xff,)) + eo
eo = int2oct(e & 0xff) + eo
e >>= 8
if e == 0 and eo and eo[0] & 0x80:
eo = bytes((0,)) + eo
if e == 0 and eo and oct2int(eo[0]) & 0x80:
eo = int2oct(0) + eo
if e == -1 and eo and not (eo[0] & 0x80):
eo = bytes((0xff,)) + eo
if e == -1 and eo and not (oct2int(eo[0]) & 0x80):
eo = int2oct(0xff) + eo
n = len(eo)
if n > 0xff:
@@ -535,15 +503,15 @@ class RealEncoder(AbstractItemEncoder):
else:
fo |= 3
eo = bytes((n & 0xff,)) + eo
eo = int2oct(n & 0xff) + eo
po = b''
po = null
while m:
po = bytes((m & 0xff,)) + po
po = int2oct(m & 0xff) + po
m >>= 8
substrate = bytes((fo,)) + eo + po
substrate = int2oct(fo) + eo + po
return substrate, False, True
@@ -558,7 +526,7 @@ class SequenceEncoder(AbstractItemEncoder):
def encodeValue(self, value, asn1Spec, encodeFun, **options):
substrate = b''
substrate = null
omitEmptyOptionals = options.get(
'omitEmptyOptionals', self.omitEmptyOptionals)
@@ -571,8 +539,7 @@ class SequenceEncoder(AbstractItemEncoder):
# instance of ASN.1 schema
inconsistency = value.isInconsistent
if inconsistency:
raise error.PyAsn1Error(
f"ASN.1 object {value.__class__.__name__} is inconsistent")
raise inconsistency
namedTypes = value.componentType
@@ -680,8 +647,7 @@ class SequenceOfEncoder(AbstractItemEncoder):
if asn1Spec is None:
inconsistency = value.isInconsistent
if inconsistency:
raise error.PyAsn1Error(
f"ASN.1 object {value.__class__.__name__} is inconsistent")
raise inconsistency
else:
asn1Spec = asn1Spec.componentType
@@ -709,7 +675,7 @@ class SequenceOfEncoder(AbstractItemEncoder):
chunks = self._encodeComponents(
value, asn1Spec, encodeFun, **options)
return b''.join(chunks), True, True
return null.join(chunks), True, True
class ChoiceEncoder(AbstractItemEncoder):
@@ -734,13 +700,13 @@ class AnyEncoder(OctetStringEncoder):
def encodeValue(self, value, asn1Spec, encodeFun, **options):
if asn1Spec is None:
value = value.asOctets()
elif not isinstance(value, bytes):
elif not isOctetsType(value):
value = asn1Spec.clone(value).asOctets()
return value, not options.get('defMode', True), True
TAG_MAP = {
tagMap = {
eoo.endOfOctets.tagSet: EndOfOctetsEncoder(),
univ.Boolean.tagSet: BooleanEncoder(),
univ.Integer.tagSet: IntegerEncoder(),
@@ -748,7 +714,6 @@ TAG_MAP = {
univ.OctetString.tagSet: OctetStringEncoder(),
univ.Null.tagSet: NullEncoder(),
univ.ObjectIdentifier.tagSet: ObjectIdentifierEncoder(),
univ.RelativeOID.tagSet: RelativeOIDEncoder(),
univ.Enumerated.tagSet: IntegerEncoder(),
univ.Real.tagSet: RealEncoder(),
# Sequence & Set have same tags as SequenceOf & SetOf
@@ -774,14 +739,13 @@ TAG_MAP = {
}
# Put in ambiguous & non-ambiguous types for faster codec lookup
TYPE_MAP = {
typeMap = {
univ.Boolean.typeId: BooleanEncoder(),
univ.Integer.typeId: IntegerEncoder(),
univ.BitString.typeId: BitStringEncoder(),
univ.OctetString.typeId: OctetStringEncoder(),
univ.Null.typeId: NullEncoder(),
univ.ObjectIdentifier.typeId: ObjectIdentifierEncoder(),
univ.RelativeOID.typeId: RelativeOIDEncoder(),
univ.Enumerated.typeId: IntegerEncoder(),
univ.Real.typeId: RealEncoder(),
# Sequence & Set have same tags as SequenceOf & SetOf
@@ -810,16 +774,14 @@ TYPE_MAP = {
}
class SingleItemEncoder(object):
class Encoder(object):
fixedDefLengthMode = None
fixedChunkSize = None
TAG_MAP = TAG_MAP
TYPE_MAP = TYPE_MAP
def __init__(self, tagMap=_MISSING, typeMap=_MISSING, **ignored):
self._tagMap = tagMap if tagMap is not _MISSING else self.TAG_MAP
self._typeMap = typeMap if typeMap is not _MISSING else self.TYPE_MAP
# noinspection PyDefaultArgument
def __init__(self, tagMap, typeMap={}):
self.__tagMap = tagMap
self.__typeMap = typeMap
def __call__(self, value, asn1Spec=None, **options):
try:
@@ -833,11 +795,8 @@ class SingleItemEncoder(object):
'and "asn1Spec" not given' % (value,))
if LOG:
LOG('encoder called in %sdef mode, chunk size %s for type %s, '
'value:\n%s' % (not options.get('defMode', True) and 'in' or '',
options.get('maxChunkSize', 0),
asn1Spec is None and value.prettyPrintType() or
asn1Spec.prettyPrintType(), value))
LOG('encoder called in %sdef mode, chunk size %s for '
'type %s, value:\n%s' % (not options.get('defMode', True) and 'in' or '', options.get('maxChunkSize', 0), asn1Spec is None and value.prettyPrintType() or asn1Spec.prettyPrintType(), value))
if self.fixedDefLengthMode is not None:
options.update(defMode=self.fixedDefLengthMode)
@@ -845,12 +804,12 @@ class SingleItemEncoder(object):
if self.fixedChunkSize is not None:
options.update(maxChunkSize=self.fixedChunkSize)
try:
concreteEncoder = self._typeMap[typeId]
concreteEncoder = self.__typeMap[typeId]
if LOG:
LOG('using value codec %s chosen by type ID '
'%s' % (concreteEncoder.__class__.__name__, typeId))
LOG('using value codec %s chosen by type ID %s' % (concreteEncoder.__class__.__name__, typeId))
except KeyError:
if asn1Spec is None:
@@ -862,38 +821,21 @@ class SingleItemEncoder(object):
baseTagSet = tag.TagSet(tagSet.baseTag, tagSet.baseTag)
try:
concreteEncoder = self._tagMap[baseTagSet]
concreteEncoder = self.__tagMap[baseTagSet]
except KeyError:
raise error.PyAsn1Error('No encoder for %r (%s)' % (value, tagSet))
if LOG:
LOG('using value codec %s chosen by tagSet '
'%s' % (concreteEncoder.__class__.__name__, tagSet))
LOG('using value codec %s chosen by tagSet %s' % (concreteEncoder.__class__.__name__, tagSet))
substrate = concreteEncoder.encode(value, asn1Spec, self, **options)
if LOG:
LOG('codec %s built %s octets of substrate: %s\nencoder '
'completed' % (concreteEncoder, len(substrate),
debug.hexdump(substrate)))
LOG('codec %s built %s octets of substrate: %s\nencoder completed' % (concreteEncoder, len(substrate), debug.hexdump(substrate)))
return substrate
class Encoder(object):
SINGLE_ITEM_ENCODER = SingleItemEncoder
def __init__(self, tagMap=_MISSING, typeMap=_MISSING, **options):
self._singleItemEncoder = self.SINGLE_ITEM_ENCODER(
tagMap=tagMap, typeMap=typeMap, **options
)
def __call__(self, pyObject, asn1Spec=None, **options):
return self._singleItemEncoder(
pyObject, asn1Spec=asn1Spec, **options)
#: Turns ASN.1 object into BER octet stream.
#:
#: Takes any ASN.1 object (e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative)
@@ -918,7 +860,7 @@ class Encoder(object):
#:
#: Returns
#: -------
#: : :py:class:`bytes`
#: : :py:class:`bytes` (Python 3) or :py:class:`str` (Python 2)
#: Given ASN.1 object encoded into BER octetstream
#:
#: Raises
@@ -945,10 +887,4 @@ class Encoder(object):
#: >>> encode(seq)
#: b'0\t\x02\x01\x01\x02\x01\x02\x02\x01\x03'
#:
encode = Encoder()
def __getattr__(attr: str):
if newAttr := {"tagMap": "TAG_MAP", "typeMap": "TYPE_MAP"}.get(attr):
warnings.warn(f"{attr} is deprecated. Please use {newAttr} instead.", DeprecationWarning)
return globals()[newAttr]
raise AttributeError(attr)
encode = Encoder(tagMap, typeMap)

View File

@@ -1,8 +1,8 @@
#
# This file is part of pyasn1 software.
#
# Copyright (c) 2005-2020, Ilya Etingof <etingof@gmail.com>
# License: https://pyasn1.readthedocs.io/en/latest/license.html
# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com>
# License: http://snmplabs.com/pyasn1/license.html
#
from pyasn1.type import base
from pyasn1.type import tag

View File

@@ -1,93 +1,64 @@
#
# This file is part of pyasn1 software.
#
# Copyright (c) 2005-2020, Ilya Etingof <etingof@gmail.com>
# License: https://pyasn1.readthedocs.io/en/latest/license.html
# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com>
# License: http://snmplabs.com/pyasn1/license.html
#
import warnings
from pyasn1 import error
from pyasn1.codec.streaming import readFromStream
from pyasn1.codec.ber import decoder
from pyasn1.compat.octets import oct2int
from pyasn1.type import univ
__all__ = ['decode', 'StreamingDecoder']
SubstrateUnderrunError = error.SubstrateUnderrunError
__all__ = ['decode']
class BooleanPayloadDecoder(decoder.AbstractSimplePayloadDecoder):
class BooleanDecoder(decoder.AbstractSimpleDecoder):
protoComponent = univ.Boolean(0)
def valueDecoder(self, substrate, asn1Spec,
tagSet=None, length=None, state=None,
decodeFun=None, substrateFun=None,
**options):
if length != 1:
head, tail = substrate[:length], substrate[length:]
if not head or length != 1:
raise error.PyAsn1Error('Not single-octet Boolean payload')
for chunk in readFromStream(substrate, length, options):
if isinstance(chunk, SubstrateUnderrunError):
yield chunk
byte = chunk[0]
byte = oct2int(head[0])
# CER/DER specifies encoding of TRUE as 0xFF and FALSE as 0x0, while
# BER allows any non-zero value as TRUE; cf. sections 8.2.2. and 11.1
# in https://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf
if byte == 0xff:
value = 1
elif byte == 0x00:
value = 0
else:
raise error.PyAsn1Error('Unexpected Boolean payload: %s' % byte)
yield self._createComponent(asn1Spec, tagSet, value, **options)
return self._createComponent(asn1Spec, tagSet, value, **options), tail
# TODO: prohibit non-canonical encoding
BitStringPayloadDecoder = decoder.BitStringPayloadDecoder
OctetStringPayloadDecoder = decoder.OctetStringPayloadDecoder
RealPayloadDecoder = decoder.RealPayloadDecoder
BitStringDecoder = decoder.BitStringDecoder
OctetStringDecoder = decoder.OctetStringDecoder
RealDecoder = decoder.RealDecoder
TAG_MAP = decoder.TAG_MAP.copy()
TAG_MAP.update(
{univ.Boolean.tagSet: BooleanPayloadDecoder(),
univ.BitString.tagSet: BitStringPayloadDecoder(),
univ.OctetString.tagSet: OctetStringPayloadDecoder(),
univ.Real.tagSet: RealPayloadDecoder()}
tagMap = decoder.tagMap.copy()
tagMap.update(
{univ.Boolean.tagSet: BooleanDecoder(),
univ.BitString.tagSet: BitStringDecoder(),
univ.OctetString.tagSet: OctetStringDecoder(),
univ.Real.tagSet: RealDecoder()}
)
TYPE_MAP = decoder.TYPE_MAP.copy()
typeMap = decoder.typeMap.copy()
# Put in non-ambiguous types for faster codec lookup
for typeDecoder in TAG_MAP.values():
for typeDecoder in tagMap.values():
if typeDecoder.protoComponent is not None:
typeId = typeDecoder.protoComponent.__class__.typeId
if typeId is not None and typeId not in TYPE_MAP:
TYPE_MAP[typeId] = typeDecoder
class SingleItemDecoder(decoder.SingleItemDecoder):
__doc__ = decoder.SingleItemDecoder.__doc__
TAG_MAP = TAG_MAP
TYPE_MAP = TYPE_MAP
class StreamingDecoder(decoder.StreamingDecoder):
__doc__ = decoder.StreamingDecoder.__doc__
SINGLE_ITEM_DECODER = SingleItemDecoder
if typeId is not None and typeId not in typeMap:
typeMap[typeId] = typeDecoder
class Decoder(decoder.Decoder):
__doc__ = decoder.Decoder.__doc__
STREAMING_DECODER = StreamingDecoder
pass
#: Turns CER octet stream into an ASN.1 object.
@@ -98,7 +69,7 @@ class Decoder(decoder.Decoder):
#:
#: Parameters
#: ----------
#: substrate: :py:class:`bytes`
#: substrate: :py:class:`bytes` (Python 3) or :py:class:`str` (Python 2)
#: CER octet-stream
#:
#: Keyword Args
@@ -140,10 +111,4 @@ class Decoder(decoder.Decoder):
#: SequenceOf:
#: 1 2 3
#:
decode = Decoder()
def __getattr__(attr: str):
if newAttr := {"tagMap": "TAG_MAP", "typeMap": "TYPE_MAP"}.get(attr):
warnings.warn(f"{attr} is deprecated. Please use {newAttr} instead.", DeprecationWarning)
return globals()[newAttr]
raise AttributeError(attr)
decode = Decoder(tagMap, decoder.typeMap)

View File

@@ -1,17 +1,16 @@
#
# This file is part of pyasn1 software.
#
# Copyright (c) 2005-2020, Ilya Etingof <etingof@gmail.com>
# License: https://pyasn1.readthedocs.io/en/latest/license.html
# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com>
# License: http://snmplabs.com/pyasn1/license.html
#
import warnings
from pyasn1 import error
from pyasn1.codec.ber import encoder
from pyasn1.compat.octets import str2octs, null
from pyasn1.type import univ
from pyasn1.type import useful
__all__ = ['Encoder', 'encode']
__all__ = ['encode']
class BooleanEncoder(encoder.IntegerEncoder):
@@ -117,7 +116,7 @@ class SetOfEncoder(encoder.SequenceOfEncoder):
# sort by serialised and padded components
if len(chunks) > 1:
zero = b'\x00'
zero = str2octs('\x00')
maxLen = max(map(len, chunks))
paddedChunks = [
(x.ljust(maxLen, zero), x) for x in chunks
@@ -126,19 +125,19 @@ class SetOfEncoder(encoder.SequenceOfEncoder):
chunks = [x[1] for x in paddedChunks]
return b''.join(chunks), True, True
return null.join(chunks), True, True
class SequenceOfEncoder(encoder.SequenceOfEncoder):
def encodeValue(self, value, asn1Spec, encodeFun, **options):
if options.get('ifNotEmpty', False) and not len(value):
return b'', True, True
return null, True, True
chunks = self._encodeComponents(
value, asn1Spec, encodeFun, **options)
return b''.join(chunks), True, True
return null.join(chunks), True, True
class SetEncoder(encoder.SequenceEncoder):
@@ -163,7 +162,7 @@ class SetEncoder(encoder.SequenceEncoder):
def encodeValue(self, value, asn1Spec, encodeFun, **options):
substrate = b''
substrate = null
comps = []
compsMap = {}
@@ -172,8 +171,7 @@ class SetEncoder(encoder.SequenceEncoder):
# instance of ASN.1 schema
inconsistency = value.isInconsistent
if inconsistency:
raise error.PyAsn1Error(
f"ASN.1 object {value.__class__.__name__} is inconsistent")
raise inconsistency
namedTypes = value.componentType
@@ -236,9 +234,8 @@ class SequenceEncoder(encoder.SequenceEncoder):
omitEmptyOptionals = True
TAG_MAP = encoder.TAG_MAP.copy()
TAG_MAP.update({
tagMap = encoder.tagMap.copy()
tagMap.update({
univ.Boolean.tagSet: BooleanEncoder(),
univ.Real.tagSet: RealEncoder(),
useful.GeneralizedTime.tagSet: GeneralizedTimeEncoder(),
@@ -248,9 +245,8 @@ TAG_MAP.update({
univ.Sequence.typeId: SequenceEncoder()
})
TYPE_MAP = encoder.TYPE_MAP.copy()
TYPE_MAP.update({
typeMap = encoder.typeMap.copy()
typeMap.update({
univ.Boolean.typeId: BooleanEncoder(),
univ.Real.typeId: RealEncoder(),
useful.GeneralizedTime.typeId: GeneralizedTimeEncoder(),
@@ -263,18 +259,10 @@ TYPE_MAP.update({
})
class SingleItemEncoder(encoder.SingleItemEncoder):
class Encoder(encoder.Encoder):
fixedDefLengthMode = False
fixedChunkSize = 1000
TAG_MAP = TAG_MAP
TYPE_MAP = TYPE_MAP
class Encoder(encoder.Encoder):
SINGLE_ITEM_ENCODER = SingleItemEncoder
#: Turns ASN.1 object into CER octet stream.
#:
#: Takes any ASN.1 object (e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative)
@@ -293,7 +281,7 @@ class Encoder(encoder.Encoder):
#:
#: Returns
#: -------
#: : :py:class:`bytes`
#: : :py:class:`bytes` (Python 3) or :py:class:`str` (Python 2)
#: Given ASN.1 object encoded into BER octet-stream
#:
#: Raises
@@ -320,12 +308,6 @@ class Encoder(encoder.Encoder):
#: >>> encode(seq)
#: b'0\x80\x02\x01\x01\x02\x01\x02\x02\x01\x03\x00\x00'
#:
encode = Encoder()
encode = Encoder(tagMap, typeMap)
# EncoderFactory queries class instance and builds a map of tags -> encoders
def __getattr__(attr: str):
if newAttr := {"tagMap": "TAG_MAP", "typeMap": "TYPE_MAP"}.get(attr):
warnings.warn(f"{attr} is deprecated. Please use {newAttr} instead.", DeprecationWarning)
return globals()[newAttr]
raise AttributeError(attr)

View File

@@ -1,64 +1,44 @@
#
# This file is part of pyasn1 software.
#
# Copyright (c) 2005-2020, Ilya Etingof <etingof@gmail.com>
# License: https://pyasn1.readthedocs.io/en/latest/license.html
# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com>
# License: http://snmplabs.com/pyasn1/license.html
#
import warnings
from pyasn1.codec.cer import decoder
from pyasn1.type import univ
__all__ = ['decode', 'StreamingDecoder']
__all__ = ['decode']
class BitStringPayloadDecoder(decoder.BitStringPayloadDecoder):
class BitStringDecoder(decoder.BitStringDecoder):
supportConstructedForm = False
class OctetStringPayloadDecoder(decoder.OctetStringPayloadDecoder):
class OctetStringDecoder(decoder.OctetStringDecoder):
supportConstructedForm = False
# TODO: prohibit non-canonical encoding
RealPayloadDecoder = decoder.RealPayloadDecoder
RealDecoder = decoder.RealDecoder
TAG_MAP = decoder.TAG_MAP.copy()
TAG_MAP.update(
{univ.BitString.tagSet: BitStringPayloadDecoder(),
univ.OctetString.tagSet: OctetStringPayloadDecoder(),
univ.Real.tagSet: RealPayloadDecoder()}
tagMap = decoder.tagMap.copy()
tagMap.update(
{univ.BitString.tagSet: BitStringDecoder(),
univ.OctetString.tagSet: OctetStringDecoder(),
univ.Real.tagSet: RealDecoder()}
)
TYPE_MAP = decoder.TYPE_MAP.copy()
typeMap = decoder.typeMap.copy()
# Put in non-ambiguous types for faster codec lookup
for typeDecoder in TAG_MAP.values():
for typeDecoder in tagMap.values():
if typeDecoder.protoComponent is not None:
typeId = typeDecoder.protoComponent.__class__.typeId
if typeId is not None and typeId not in TYPE_MAP:
TYPE_MAP[typeId] = typeDecoder
class SingleItemDecoder(decoder.SingleItemDecoder):
__doc__ = decoder.SingleItemDecoder.__doc__
TAG_MAP = TAG_MAP
TYPE_MAP = TYPE_MAP
supportIndefLength = False
class StreamingDecoder(decoder.StreamingDecoder):
__doc__ = decoder.StreamingDecoder.__doc__
SINGLE_ITEM_DECODER = SingleItemDecoder
if typeId is not None and typeId not in typeMap:
typeMap[typeId] = typeDecoder
class Decoder(decoder.Decoder):
__doc__ = decoder.Decoder.__doc__
STREAMING_DECODER = StreamingDecoder
supportIndefLength = False
#: Turns DER octet stream into an ASN.1 object.
@@ -69,7 +49,7 @@ class Decoder(decoder.Decoder):
#:
#: Parameters
#: ----------
#: substrate: :py:class:`bytes`
#: substrate: :py:class:`bytes` (Python 3) or :py:class:`str` (Python 2)
#: DER octet-stream
#:
#: Keyword Args
@@ -111,10 +91,4 @@ class Decoder(decoder.Decoder):
#: SequenceOf:
#: 1 2 3
#:
decode = Decoder()
def __getattr__(attr: str):
if newAttr := {"tagMap": "TAG_MAP", "typeMap": "TYPE_MAP"}.get(attr):
warnings.warn(f"{attr} is deprecated. Please use {newAttr} instead.", DeprecationWarning)
return globals()[newAttr]
raise AttributeError(attr)
decode = Decoder(tagMap, typeMap)

View File

@@ -1,16 +1,14 @@
#
# This file is part of pyasn1 software.
#
# Copyright (c) 2005-2020, Ilya Etingof <etingof@gmail.com>
# License: https://pyasn1.readthedocs.io/en/latest/license.html
# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com>
# License: http://snmplabs.com/pyasn1/license.html
#
import warnings
from pyasn1 import error
from pyasn1.codec.cer import encoder
from pyasn1.type import univ
__all__ = ['Encoder', 'encode']
__all__ = ['encode']
class SetEncoder(encoder.SetEncoder):
@@ -44,34 +42,23 @@ class SetEncoder(encoder.SetEncoder):
else:
return compType.tagSet
TAG_MAP = encoder.TAG_MAP.copy()
TAG_MAP.update({
tagMap = encoder.tagMap.copy()
tagMap.update({
# Set & SetOf have same tags
univ.Set.tagSet: SetEncoder()
})
TYPE_MAP = encoder.TYPE_MAP.copy()
TYPE_MAP.update({
typeMap = encoder.typeMap.copy()
typeMap.update({
# Set & SetOf have same tags
univ.Set.typeId: SetEncoder()
})
class SingleItemEncoder(encoder.SingleItemEncoder):
class Encoder(encoder.Encoder):
fixedDefLengthMode = True
fixedChunkSize = 0
TAG_MAP = TAG_MAP
TYPE_MAP = TYPE_MAP
class Encoder(encoder.Encoder):
SINGLE_ITEM_ENCODER = SingleItemEncoder
#: Turns ASN.1 object into DER octet stream.
#:
#: Takes any ASN.1 object (e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative)
@@ -90,7 +77,7 @@ class Encoder(encoder.Encoder):
#:
#: Returns
#: -------
#: : :py:class:`bytes`
#: : :py:class:`bytes` (Python 3) or :py:class:`str` (Python 2)
#: Given ASN.1 object encoded into BER octet-stream
#:
#: Raises
@@ -117,10 +104,4 @@ class Encoder(encoder.Encoder):
#: >>> encode(seq)
#: b'0\t\x02\x01\x01\x02\x01\x02\x02\x01\x03'
#:
encode = Encoder()
def __getattr__(attr: str):
if newAttr := {"tagMap": "TAG_MAP", "typeMap": "TYPE_MAP"}.get(attr):
warnings.warn(f"{attr} is deprecated. Please use {newAttr} instead.", DeprecationWarning)
return globals()[newAttr]
raise AttributeError(attr)
encode = Encoder(tagMap, typeMap)

View File

@@ -1,14 +1,11 @@
#
# This file is part of pyasn1 software.
#
# Copyright (c) 2005-2020, Ilya Etingof <etingof@gmail.com>
# License: https://pyasn1.readthedocs.io/en/latest/license.html
# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com>
# License: http://snmplabs.com/pyasn1/license.html
#
import warnings
from pyasn1 import debug
from pyasn1 import error
from pyasn1.compat import _MISSING
from pyasn1.type import base
from pyasn1.type import char
from pyasn1.type import tag
@@ -20,17 +17,17 @@ __all__ = ['decode']
LOG = debug.registerLoggee(__name__, flags=debug.DEBUG_DECODER)
class AbstractScalarPayloadDecoder(object):
class AbstractScalarDecoder(object):
def __call__(self, pyObject, asn1Spec, decodeFun=None, **options):
return asn1Spec.clone(pyObject)
class BitStringPayloadDecoder(AbstractScalarPayloadDecoder):
class BitStringDecoder(AbstractScalarDecoder):
def __call__(self, pyObject, asn1Spec, decodeFun=None, **options):
return asn1Spec.clone(univ.BitString.fromBinaryString(pyObject))
class SequenceOrSetPayloadDecoder(object):
class SequenceOrSetDecoder(object):
def __call__(self, pyObject, asn1Spec, decodeFun=None, **options):
asn1Value = asn1Spec.clone()
@@ -43,7 +40,7 @@ class SequenceOrSetPayloadDecoder(object):
return asn1Value
class SequenceOfOrSetOfPayloadDecoder(object):
class SequenceOfOrSetOfDecoder(object):
def __call__(self, pyObject, asn1Spec, decodeFun=None, **options):
asn1Value = asn1Spec.clone()
@@ -53,7 +50,7 @@ class SequenceOfOrSetOfPayloadDecoder(object):
return asn1Value
class ChoicePayloadDecoder(object):
class ChoiceDecoder(object):
def __call__(self, pyObject, asn1Spec, decodeFun=None, **options):
asn1Value = asn1Spec.clone()
@@ -67,134 +64,112 @@ class ChoicePayloadDecoder(object):
return asn1Value
TAG_MAP = {
univ.Integer.tagSet: AbstractScalarPayloadDecoder(),
univ.Boolean.tagSet: AbstractScalarPayloadDecoder(),
univ.BitString.tagSet: BitStringPayloadDecoder(),
univ.OctetString.tagSet: AbstractScalarPayloadDecoder(),
univ.Null.tagSet: AbstractScalarPayloadDecoder(),
univ.ObjectIdentifier.tagSet: AbstractScalarPayloadDecoder(),
univ.RelativeOID.tagSet: AbstractScalarPayloadDecoder(),
univ.Enumerated.tagSet: AbstractScalarPayloadDecoder(),
univ.Real.tagSet: AbstractScalarPayloadDecoder(),
univ.Sequence.tagSet: SequenceOrSetPayloadDecoder(), # conflicts with SequenceOf
univ.Set.tagSet: SequenceOrSetPayloadDecoder(), # conflicts with SetOf
univ.Choice.tagSet: ChoicePayloadDecoder(), # conflicts with Any
tagMap = {
univ.Integer.tagSet: AbstractScalarDecoder(),
univ.Boolean.tagSet: AbstractScalarDecoder(),
univ.BitString.tagSet: BitStringDecoder(),
univ.OctetString.tagSet: AbstractScalarDecoder(),
univ.Null.tagSet: AbstractScalarDecoder(),
univ.ObjectIdentifier.tagSet: AbstractScalarDecoder(),
univ.Enumerated.tagSet: AbstractScalarDecoder(),
univ.Real.tagSet: AbstractScalarDecoder(),
univ.Sequence.tagSet: SequenceOrSetDecoder(), # conflicts with SequenceOf
univ.Set.tagSet: SequenceOrSetDecoder(), # conflicts with SetOf
univ.Choice.tagSet: ChoiceDecoder(), # conflicts with Any
# character string types
char.UTF8String.tagSet: AbstractScalarPayloadDecoder(),
char.NumericString.tagSet: AbstractScalarPayloadDecoder(),
char.PrintableString.tagSet: AbstractScalarPayloadDecoder(),
char.TeletexString.tagSet: AbstractScalarPayloadDecoder(),
char.VideotexString.tagSet: AbstractScalarPayloadDecoder(),
char.IA5String.tagSet: AbstractScalarPayloadDecoder(),
char.GraphicString.tagSet: AbstractScalarPayloadDecoder(),
char.VisibleString.tagSet: AbstractScalarPayloadDecoder(),
char.GeneralString.tagSet: AbstractScalarPayloadDecoder(),
char.UniversalString.tagSet: AbstractScalarPayloadDecoder(),
char.BMPString.tagSet: AbstractScalarPayloadDecoder(),
char.UTF8String.tagSet: AbstractScalarDecoder(),
char.NumericString.tagSet: AbstractScalarDecoder(),
char.PrintableString.tagSet: AbstractScalarDecoder(),
char.TeletexString.tagSet: AbstractScalarDecoder(),
char.VideotexString.tagSet: AbstractScalarDecoder(),
char.IA5String.tagSet: AbstractScalarDecoder(),
char.GraphicString.tagSet: AbstractScalarDecoder(),
char.VisibleString.tagSet: AbstractScalarDecoder(),
char.GeneralString.tagSet: AbstractScalarDecoder(),
char.UniversalString.tagSet: AbstractScalarDecoder(),
char.BMPString.tagSet: AbstractScalarDecoder(),
# useful types
useful.ObjectDescriptor.tagSet: AbstractScalarPayloadDecoder(),
useful.GeneralizedTime.tagSet: AbstractScalarPayloadDecoder(),
useful.UTCTime.tagSet: AbstractScalarPayloadDecoder()
useful.ObjectDescriptor.tagSet: AbstractScalarDecoder(),
useful.GeneralizedTime.tagSet: AbstractScalarDecoder(),
useful.UTCTime.tagSet: AbstractScalarDecoder()
}
# Put in ambiguous & non-ambiguous types for faster codec lookup
TYPE_MAP = {
univ.Integer.typeId: AbstractScalarPayloadDecoder(),
univ.Boolean.typeId: AbstractScalarPayloadDecoder(),
univ.BitString.typeId: BitStringPayloadDecoder(),
univ.OctetString.typeId: AbstractScalarPayloadDecoder(),
univ.Null.typeId: AbstractScalarPayloadDecoder(),
univ.ObjectIdentifier.typeId: AbstractScalarPayloadDecoder(),
univ.RelativeOID.typeId: AbstractScalarPayloadDecoder(),
univ.Enumerated.typeId: AbstractScalarPayloadDecoder(),
univ.Real.typeId: AbstractScalarPayloadDecoder(),
typeMap = {
univ.Integer.typeId: AbstractScalarDecoder(),
univ.Boolean.typeId: AbstractScalarDecoder(),
univ.BitString.typeId: BitStringDecoder(),
univ.OctetString.typeId: AbstractScalarDecoder(),
univ.Null.typeId: AbstractScalarDecoder(),
univ.ObjectIdentifier.typeId: AbstractScalarDecoder(),
univ.Enumerated.typeId: AbstractScalarDecoder(),
univ.Real.typeId: AbstractScalarDecoder(),
# ambiguous base types
univ.Set.typeId: SequenceOrSetPayloadDecoder(),
univ.SetOf.typeId: SequenceOfOrSetOfPayloadDecoder(),
univ.Sequence.typeId: SequenceOrSetPayloadDecoder(),
univ.SequenceOf.typeId: SequenceOfOrSetOfPayloadDecoder(),
univ.Choice.typeId: ChoicePayloadDecoder(),
univ.Any.typeId: AbstractScalarPayloadDecoder(),
univ.Set.typeId: SequenceOrSetDecoder(),
univ.SetOf.typeId: SequenceOfOrSetOfDecoder(),
univ.Sequence.typeId: SequenceOrSetDecoder(),
univ.SequenceOf.typeId: SequenceOfOrSetOfDecoder(),
univ.Choice.typeId: ChoiceDecoder(),
univ.Any.typeId: AbstractScalarDecoder(),
# character string types
char.UTF8String.typeId: AbstractScalarPayloadDecoder(),
char.NumericString.typeId: AbstractScalarPayloadDecoder(),
char.PrintableString.typeId: AbstractScalarPayloadDecoder(),
char.TeletexString.typeId: AbstractScalarPayloadDecoder(),
char.VideotexString.typeId: AbstractScalarPayloadDecoder(),
char.IA5String.typeId: AbstractScalarPayloadDecoder(),
char.GraphicString.typeId: AbstractScalarPayloadDecoder(),
char.VisibleString.typeId: AbstractScalarPayloadDecoder(),
char.GeneralString.typeId: AbstractScalarPayloadDecoder(),
char.UniversalString.typeId: AbstractScalarPayloadDecoder(),
char.BMPString.typeId: AbstractScalarPayloadDecoder(),
char.UTF8String.typeId: AbstractScalarDecoder(),
char.NumericString.typeId: AbstractScalarDecoder(),
char.PrintableString.typeId: AbstractScalarDecoder(),
char.TeletexString.typeId: AbstractScalarDecoder(),
char.VideotexString.typeId: AbstractScalarDecoder(),
char.IA5String.typeId: AbstractScalarDecoder(),
char.GraphicString.typeId: AbstractScalarDecoder(),
char.VisibleString.typeId: AbstractScalarDecoder(),
char.GeneralString.typeId: AbstractScalarDecoder(),
char.UniversalString.typeId: AbstractScalarDecoder(),
char.BMPString.typeId: AbstractScalarDecoder(),
# useful types
useful.ObjectDescriptor.typeId: AbstractScalarPayloadDecoder(),
useful.GeneralizedTime.typeId: AbstractScalarPayloadDecoder(),
useful.UTCTime.typeId: AbstractScalarPayloadDecoder()
useful.ObjectDescriptor.typeId: AbstractScalarDecoder(),
useful.GeneralizedTime.typeId: AbstractScalarDecoder(),
useful.UTCTime.typeId: AbstractScalarDecoder()
}
class SingleItemDecoder(object):
class Decoder(object):
TAG_MAP = TAG_MAP
TYPE_MAP = TYPE_MAP
def __init__(self, tagMap=_MISSING, typeMap=_MISSING, **ignored):
self._tagMap = tagMap if tagMap is not _MISSING else self.TAG_MAP
self._typeMap = typeMap if typeMap is not _MISSING else self.TYPE_MAP
# noinspection PyDefaultArgument
def __init__(self, tagMap, typeMap):
self.__tagMap = tagMap
self.__typeMap = typeMap
def __call__(self, pyObject, asn1Spec, **options):
if LOG:
debug.scope.push(type(pyObject).__name__)
LOG('decoder called at scope %s, working with '
'type %s' % (debug.scope, type(pyObject).__name__))
LOG('decoder called at scope %s, working with type %s' % (debug.scope, type(pyObject).__name__))
if asn1Spec is None or not isinstance(asn1Spec, base.Asn1Item):
raise error.PyAsn1Error(
'asn1Spec is not valid (should be an instance of an ASN.1 '
'Item, not %s)' % asn1Spec.__class__.__name__)
raise error.PyAsn1Error('asn1Spec is not valid (should be an instance of an ASN.1 Item, not %s)' % asn1Spec.__class__.__name__)
try:
valueDecoder = self._typeMap[asn1Spec.typeId]
valueDecoder = self.__typeMap[asn1Spec.typeId]
except KeyError:
# use base type for codec lookup to recover untagged types
baseTagSet = tag.TagSet(asn1Spec.tagSet.baseTag, asn1Spec.tagSet.baseTag)
try:
valueDecoder = self._tagMap[baseTagSet]
valueDecoder = self.__tagMap[baseTagSet]
except KeyError:
raise error.PyAsn1Error('Unknown ASN.1 tag %s' % asn1Spec.tagSet)
if LOG:
LOG('calling decoder %s on Python type %s '
'<%s>' % (type(valueDecoder).__name__,
type(pyObject).__name__, repr(pyObject)))
LOG('calling decoder %s on Python type %s <%s>' % (type(valueDecoder).__name__, type(pyObject).__name__, repr(pyObject)))
value = valueDecoder(pyObject, asn1Spec, self, **options)
if LOG:
LOG('decoder %s produced ASN.1 type %s '
'<%s>' % (type(valueDecoder).__name__,
type(value).__name__, repr(value)))
LOG('decoder %s produced ASN.1 type %s <%s>' % (type(valueDecoder).__name__, type(value).__name__, repr(value)))
debug.scope.pop()
return value
class Decoder(object):
SINGLE_ITEM_DECODER = SingleItemDecoder
def __init__(self, **options):
self._singleItemDecoder = self.SINGLE_ITEM_DECODER(**options)
def __call__(self, pyObject, asn1Spec=None, **kwargs):
return self._singleItemDecoder(pyObject, asn1Spec=asn1Spec, **kwargs)
#: Turns Python objects of built-in types into ASN.1 objects.
#:
#: Takes Python objects of built-in types and turns them into a tree of
@@ -235,10 +210,4 @@ class Decoder(object):
#: SequenceOf:
#: 1 2 3
#:
decode = Decoder()
def __getattr__(attr: str):
if newAttr := {"tagMap": "TAG_MAP", "typeMap": "TYPE_MAP"}.get(attr):
warnings.warn(f"{attr} is deprecated. Please use {newAttr} instead.", DeprecationWarning)
return globals()[newAttr]
raise AttributeError(attr)
decode = Decoder(tagMap, typeMap)

View File

@@ -1,15 +1,17 @@
#
# This file is part of pyasn1 software.
#
# Copyright (c) 2005-2020, Ilya Etingof <etingof@gmail.com>
# License: https://pyasn1.readthedocs.io/en/latest/license.html
# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com>
# License: http://snmplabs.com/pyasn1/license.html
#
from collections import OrderedDict
import warnings
try:
from collections import OrderedDict
except ImportError:
OrderedDict = dict
from pyasn1 import debug
from pyasn1 import error
from pyasn1.compat import _MISSING
from pyasn1.type import base
from pyasn1.type import char
from pyasn1.type import tag
@@ -61,11 +63,6 @@ class ObjectIdentifierEncoder(AbstractItemEncoder):
return str(value)
class RelativeOIDEncoder(AbstractItemEncoder):
def encode(self, value, encodeFun, **options):
return str(value)
class RealEncoder(AbstractItemEncoder):
def encode(self, value, encodeFun, **options):
return float(value)
@@ -77,8 +74,7 @@ class SetEncoder(AbstractItemEncoder):
def encode(self, value, encodeFun, **options):
inconsistency = value.isInconsistent
if inconsistency:
raise error.PyAsn1Error(
f"ASN.1 object {value.__class__.__name__} is inconsistent")
raise inconsistency
namedTypes = value.componentType
substrate = self.protoDict()
@@ -98,8 +94,7 @@ class SequenceOfEncoder(AbstractItemEncoder):
def encode(self, value, encodeFun, **options):
inconsistency = value.isInconsistent
if inconsistency:
raise error.PyAsn1Error(
f"ASN.1 object {value.__class__.__name__} is inconsistent")
raise inconsistency
return [encodeFun(x, **options) for x in value]
@@ -112,14 +107,13 @@ class AnyEncoder(AbstractItemEncoder):
return value.asOctets()
TAG_MAP = {
tagMap = {
univ.Boolean.tagSet: BooleanEncoder(),
univ.Integer.tagSet: IntegerEncoder(),
univ.BitString.tagSet: BitStringEncoder(),
univ.OctetString.tagSet: OctetStringEncoder(),
univ.Null.tagSet: NullEncoder(),
univ.ObjectIdentifier.tagSet: ObjectIdentifierEncoder(),
univ.RelativeOID.tagSet: RelativeOIDEncoder(),
univ.Enumerated.tagSet: IntegerEncoder(),
univ.Real.tagSet: RealEncoder(),
# Sequence & Set have same tags as SequenceOf & SetOf
@@ -144,15 +138,15 @@ TAG_MAP = {
useful.UTCTime.tagSet: OctetStringEncoder()
}
# Put in ambiguous & non-ambiguous types for faster codec lookup
TYPE_MAP = {
typeMap = {
univ.Boolean.typeId: BooleanEncoder(),
univ.Integer.typeId: IntegerEncoder(),
univ.BitString.typeId: BitStringEncoder(),
univ.OctetString.typeId: OctetStringEncoder(),
univ.Null.typeId: NullEncoder(),
univ.ObjectIdentifier.typeId: ObjectIdentifierEncoder(),
univ.RelativeOID.typeId: RelativeOIDEncoder(),
univ.Enumerated.typeId: IntegerEncoder(),
univ.Real.typeId: RealEncoder(),
# Sequence & Set have same tags as SequenceOf & SetOf
@@ -181,66 +175,48 @@ TYPE_MAP = {
}
class SingleItemEncoder(object):
class Encoder(object):
TAG_MAP = TAG_MAP
TYPE_MAP = TYPE_MAP
def __init__(self, tagMap=_MISSING, typeMap=_MISSING, **ignored):
self._tagMap = tagMap if tagMap is not _MISSING else self.TAG_MAP
self._typeMap = typeMap if typeMap is not _MISSING else self.TYPE_MAP
# noinspection PyDefaultArgument
def __init__(self, tagMap, typeMap={}):
self.__tagMap = tagMap
self.__typeMap = typeMap
def __call__(self, value, **options):
if not isinstance(value, base.Asn1Item):
raise error.PyAsn1Error(
'value is not valid (should be an instance of an ASN.1 Item)')
raise error.PyAsn1Error('value is not valid (should be an instance of an ASN.1 Item)')
if LOG:
debug.scope.push(type(value).__name__)
LOG('encoder called for type %s '
'<%s>' % (type(value).__name__, value.prettyPrint()))
LOG('encoder called for type %s <%s>' % (type(value).__name__, value.prettyPrint()))
tagSet = value.tagSet
try:
concreteEncoder = self._typeMap[value.typeId]
concreteEncoder = self.__typeMap[value.typeId]
except KeyError:
# use base type for codec lookup to recover untagged types
baseTagSet = tag.TagSet(
value.tagSet.baseTag, value.tagSet.baseTag)
baseTagSet = tag.TagSet(value.tagSet.baseTag, value.tagSet.baseTag)
try:
concreteEncoder = self._tagMap[baseTagSet]
concreteEncoder = self.__tagMap[baseTagSet]
except KeyError:
raise error.PyAsn1Error('No encoder for %s' % (value,))
if LOG:
LOG('using value codec %s chosen by '
'%s' % (concreteEncoder.__class__.__name__, tagSet))
LOG('using value codec %s chosen by %s' % (concreteEncoder.__class__.__name__, tagSet))
pyObject = concreteEncoder.encode(value, self, **options)
if LOG:
LOG('encoder %s produced: '
'%s' % (type(concreteEncoder).__name__, repr(pyObject)))
LOG('encoder %s produced: %s' % (type(concreteEncoder).__name__, repr(pyObject)))
debug.scope.pop()
return pyObject
class Encoder(object):
SINGLE_ITEM_ENCODER = SingleItemEncoder
def __init__(self, **options):
self._singleItemEncoder = self.SINGLE_ITEM_ENCODER(**options)
def __call__(self, pyObject, asn1Spec=None, **options):
return self._singleItemEncoder(
pyObject, asn1Spec=asn1Spec, **options)
#: Turns ASN.1 object into a Python built-in type object(s).
#:
#: Takes any ASN.1 object (e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative)
@@ -248,7 +224,8 @@ class Encoder(object):
#: of those.
#:
#: One exception is that instead of :py:class:`dict`, the :py:class:`OrderedDict`
#: is used to preserve ordering of the components in ASN.1 SEQUENCE.
#: can be produced (whenever available) to preserve ordering of the components
#: in ASN.1 SEQUENCE.
#:
#: Parameters
#: ----------
@@ -276,10 +253,4 @@ class Encoder(object):
#: >>> encode(seq)
#: [1, 2, 3]
#:
encode = SingleItemEncoder()
def __getattr__(attr: str):
if newAttr := {"tagMap": "TAG_MAP", "typeMap": "TYPE_MAP"}.get(attr):
warnings.warn(f"{attr} is deprecated. Please use {newAttr} instead.", DeprecationWarning)
return globals()[newAttr]
raise AttributeError(attr)
encode = Encoder(tagMap, typeMap)

View File

@@ -1,234 +0,0 @@
#
# This file is part of pyasn1 software.
#
# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com>
# License: https://pyasn1.readthedocs.io/en/latest/license.html
#
import io
import os
from pyasn1 import error
from pyasn1.type import univ
class CachingStreamWrapper(io.IOBase):
"""Wrapper around non-seekable streams.
Note that the implementation is tied to the decoder,
not checking for dangerous arguments for the sake
of performance.
The read bytes are kept in an internal cache until
setting _markedPosition which may reset the cache.
"""
def __init__(self, raw):
self._raw = raw
self._cache = io.BytesIO()
self._markedPosition = 0
def peek(self, n):
result = self.read(n)
self._cache.seek(-len(result), os.SEEK_CUR)
return result
def seekable(self):
return True
def seek(self, n=-1, whence=os.SEEK_SET):
# Note that this not safe for seeking forward.
return self._cache.seek(n, whence)
def read(self, n=-1):
read_from_cache = self._cache.read(n)
if n != -1:
n -= len(read_from_cache)
if not n: # 0 bytes left to read
return read_from_cache
read_from_raw = self._raw.read(n)
self._cache.write(read_from_raw)
return read_from_cache + read_from_raw
@property
def markedPosition(self):
"""Position where the currently processed element starts.
This is used for back-tracking in SingleItemDecoder.__call__
and (indefLen)ValueDecoder and should not be used for other purposes.
The client is not supposed to ever seek before this position.
"""
return self._markedPosition
@markedPosition.setter
def markedPosition(self, value):
# By setting the value, we ensure we won't seek back before it.
# `value` should be the same as the current position
# We don't check for this for performance reasons.
self._markedPosition = value
# Whenever we set _marked_position, we know for sure
# that we will not return back, and thus it is
# safe to drop all cached data.
if self._cache.tell() > io.DEFAULT_BUFFER_SIZE:
self._cache = io.BytesIO(self._cache.read())
self._markedPosition = 0
def tell(self):
return self._cache.tell()
def asSeekableStream(substrate):
"""Convert object to seekable byte-stream.
Parameters
----------
substrate: :py:class:`bytes` or :py:class:`io.IOBase` or :py:class:`univ.OctetString`
Returns
-------
: :py:class:`io.IOBase`
Raises
------
: :py:class:`~pyasn1.error.PyAsn1Error`
If the supplied substrate cannot be converted to a seekable stream.
"""
if isinstance(substrate, io.BytesIO):
return substrate
elif isinstance(substrate, bytes):
return io.BytesIO(substrate)
elif isinstance(substrate, univ.OctetString):
return io.BytesIO(substrate.asOctets())
try:
if substrate.seekable(): # Will fail for most invalid types
return substrate
else:
return CachingStreamWrapper(substrate)
except AttributeError:
raise error.UnsupportedSubstrateError(
"Cannot convert " + substrate.__class__.__name__ +
" to a seekable bit stream.")
def isEndOfStream(substrate):
"""Check whether we have reached the end of a stream.
Although it is more effective to read and catch exceptions, this
function
Parameters
----------
substrate: :py:class:`IOBase`
Stream to check
Returns
-------
: :py:class:`bool`
"""
if isinstance(substrate, io.BytesIO):
cp = substrate.tell()
substrate.seek(0, os.SEEK_END)
result = substrate.tell() == cp
substrate.seek(cp, os.SEEK_SET)
yield result
else:
received = substrate.read(1)
if received is None:
yield
if received:
substrate.seek(-1, os.SEEK_CUR)
yield not received
def peekIntoStream(substrate, size=-1):
"""Peek into stream.
Parameters
----------
substrate: :py:class:`IOBase`
Stream to read from.
size: :py:class:`int`
How many bytes to peek (-1 = all available)
Returns
-------
: :py:class:`bytes` or :py:class:`str`
The return type depends on Python major version
"""
if hasattr(substrate, "peek"):
received = substrate.peek(size)
if received is None:
yield
while len(received) < size:
yield
yield received
else:
current_position = substrate.tell()
try:
for chunk in readFromStream(substrate, size):
yield chunk
finally:
substrate.seek(current_position)
def readFromStream(substrate, size=-1, context=None):
"""Read from the stream.
Parameters
----------
substrate: :py:class:`IOBase`
Stream to read from.
Keyword parameters
------------------
size: :py:class:`int`
How many bytes to read (-1 = all available)
context: :py:class:`dict`
Opaque caller context will be attached to exception objects created
by this function.
Yields
------
: :py:class:`bytes` or :py:class:`str` or :py:class:`SubstrateUnderrunError`
Read data or :py:class:`~pyasn1.error.SubstrateUnderrunError`
object if no `size` bytes is readily available in the stream. The
data type depends on Python major version
Raises
------
: :py:class:`~pyasn1.error.EndOfStreamError`
Input stream is exhausted
"""
while True:
# this will block unless stream is non-blocking
received = substrate.read(size)
if received is None: # non-blocking stream can do this
yield error.SubstrateUnderrunError(context=context)
elif not received and size != 0: # end-of-stream
raise error.EndOfStreamError(context=context)
elif len(received) < size:
substrate.seek(-len(received), os.SEEK_CUR)
# behave like a non-blocking stream
yield error.SubstrateUnderrunError(context=context)
else:
break
yield received

View File

@@ -1,4 +1 @@
# This file is necessary to make this directory a package.
# sentinal for missing argument
_MISSING = object()

View File

@@ -1,13 +1,110 @@
#
# This file is part of pyasn1 software.
#
# Copyright (c) 2005-2020, Ilya Etingof <etingof@gmail.com>
# License: https://pyasn1.readthedocs.io/en/latest/license.html
# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com>
# License: http://snmplabs.com/pyasn1/license.html
#
def to_bytes(value, signed=False, length=0):
length = max(value.bit_length(), length)
import sys
if signed and length % 8 == 0:
length += 1
try:
import platform
return value.to_bytes(length // 8 + (length % 8 and 1 or 0), 'big', signed=signed)
implementation = platform.python_implementation()
except (ImportError, AttributeError):
implementation = 'CPython'
from pyasn1.compat.octets import oct2int, null, ensureString
if sys.version_info[0:2] < (3, 2) or implementation != 'CPython':
from binascii import a2b_hex, b2a_hex
if sys.version_info[0] > 2:
long = int
def from_bytes(octets, signed=False):
if not octets:
return 0
value = long(b2a_hex(ensureString(octets)), 16)
if signed and oct2int(octets[0]) & 0x80:
return value - (1 << len(octets) * 8)
return value
def to_bytes(value, signed=False, length=0):
if value < 0:
if signed:
bits = bitLength(value)
# two's complement form
maxValue = 1 << bits
valueToEncode = (value + maxValue) % maxValue
else:
raise OverflowError('can\'t convert negative int to unsigned')
elif value == 0 and length == 0:
return null
else:
bits = 0
valueToEncode = value
hexValue = hex(valueToEncode)[2:]
if hexValue.endswith('L'):
hexValue = hexValue[:-1]
if len(hexValue) & 1:
hexValue = '0' + hexValue
# padding may be needed for two's complement encoding
if value != valueToEncode or length:
hexLength = len(hexValue) * 4
padLength = max(length, bits)
if padLength > hexLength:
hexValue = '00' * ((padLength - hexLength - 1) // 8 + 1) + hexValue
elif length and hexLength - length > 7:
raise OverflowError('int too big to convert')
firstOctet = int(hexValue[:2], 16)
if signed:
if firstOctet & 0x80:
if value >= 0:
hexValue = '00' + hexValue
elif value < 0:
hexValue = 'ff' + hexValue
octets_value = a2b_hex(hexValue)
return octets_value
def bitLength(number):
# bits in unsigned number
hexValue = hex(abs(number))
bits = len(hexValue) - 2
if hexValue.endswith('L'):
bits -= 1
if bits & 1:
bits += 1
bits *= 4
# TODO: strip lhs zeros
return bits
else:
def from_bytes(octets, signed=False):
return int.from_bytes(bytes(octets), 'big', signed=signed)
def to_bytes(value, signed=False, length=0):
length = max(value.bit_length(), length)
if signed and length % 8 == 0:
length += 1
return value.to_bytes(length // 8 + (length % 8 and 1 or 0), 'big', signed=signed)
def bitLength(number):
return int(number).bit_length()

View File

@@ -1,14 +1,15 @@
#
# This file is part of pyasn1 software.
#
# Copyright (c) 2005-2020, Ilya Etingof <etingof@gmail.com>
# License: https://pyasn1.readthedocs.io/en/latest/license.html
# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com>
# License: http://snmplabs.com/pyasn1/license.html
#
import logging
import sys
from pyasn1 import __version__
from pyasn1 import error
from pyasn1.compat.octets import octs2ints
__all__ = ['Debug', 'setLogger', 'hexdump']
@@ -54,6 +55,16 @@ class Printer(object):
return '<python logging>'
if hasattr(logging, 'NullHandler'):
NullHandler = logging.NullHandler
else:
# Python 2.6 and older
class NullHandler(logging.Handler):
def emit(self, record):
pass
class Debug(object):
defaultPrinter = Printer()
@@ -64,7 +75,7 @@ class Debug(object):
# route our logs to parent logger
self._printer = Printer(
logger=logging.getLogger(options['loggerName']),
handler=logging.NullHandler()
handler=NullHandler()
)
elif 'printer' in options:
@@ -126,7 +137,7 @@ def registerLoggee(module, name='LOG', flags=DEBUG_NONE):
def hexdump(octets):
return ' '.join(
['%s%.2X' % (n % 16 == 0 and ('\n%.5d: ' % n) or '', x)
for n, x in zip(range(len(octets)), octets)]
for n, x in zip(range(len(octets)), octs2ints(octets))]
)

View File

@@ -1,8 +1,8 @@
#
# This file is part of pyasn1 software.
#
# Copyright (c) 2005-2020, Ilya Etingof <etingof@gmail.com>
# License: https://pyasn1.readthedocs.io/en/latest/license.html
# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com>
# License: http://snmplabs.com/pyasn1/license.html
#
@@ -12,36 +12,7 @@ class PyAsn1Error(Exception):
`PyAsn1Error` is the base exception class (based on
:class:`Exception`) that represents all possible ASN.1 related
errors.
Parameters
----------
args:
Opaque positional parameters
Keyword Args
------------
kwargs:
Opaque keyword parameters
"""
def __init__(self, *args, **kwargs):
self._args = args
self._kwargs = kwargs
@property
def context(self):
"""Return exception context
When exception object is created, the caller can supply some opaque
context for the upper layers to better understand the cause of the
exception.
Returns
-------
: :py:class:`dict`
Dict holding context specific data
"""
return self._kwargs.get('context', {})
class ValueConstraintError(PyAsn1Error):
@@ -63,18 +34,6 @@ class SubstrateUnderrunError(PyAsn1Error):
"""
class EndOfStreamError(SubstrateUnderrunError):
"""ASN.1 data structure deserialization error
The `EndOfStreamError` exception indicates the condition of the input
stream has been closed.
"""
class UnsupportedSubstrateError(PyAsn1Error):
"""Unsupported substrate type to parse as ASN.1 data."""
class PyAsn1UnicodeError(PyAsn1Error, UnicodeError):
"""Unicode text processing error

View File

@@ -1,12 +1,13 @@
#
# This file is part of pyasn1 software.
#
# Copyright (c) 2005-2020, Ilya Etingof <etingof@gmail.com>
# License: https://pyasn1.readthedocs.io/en/latest/license.html
# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com>
# License: http://snmplabs.com/pyasn1/license.html
#
import sys
from pyasn1 import error
from pyasn1.compat import calling
from pyasn1.type import constraint
from pyasn1.type import tag
from pyasn1.type import tagmap
@@ -140,7 +141,7 @@ class Asn1Type(Asn1Item):
return True
def prettyPrint(self, scope=0):
raise NotImplementedError
raise NotImplementedError()
# backward compatibility
@@ -178,31 +179,31 @@ class NoValue(object):
Any operation attempted on the *noValue* object will raise the
*PyAsn1Error* exception.
"""
skipMethods = {
'__slots__',
# attributes
'__getattribute__',
'__getattr__',
'__setattr__',
'__delattr__',
# class instance
'__class__',
'__init__',
'__del__',
'__new__',
'__repr__',
'__qualname__',
'__objclass__',
'im_class',
'__sizeof__',
# pickle protocol
'__reduce__',
'__reduce_ex__',
'__getnewargs__',
'__getinitargs__',
'__getstate__',
'__setstate__',
}
skipMethods = set(
('__slots__',
# attributes
'__getattribute__',
'__getattr__',
'__setattr__',
'__delattr__',
# class instance
'__class__',
'__init__',
'__del__',
'__new__',
'__repr__',
'__qualname__',
'__objclass__',
'im_class',
'__sizeof__',
# pickle protocol
'__reduce__',
'__reduce_ex__',
'__getnewargs__',
'__getinitargs__',
'__getstate__',
'__setstate__')
)
_instance = None
@@ -219,7 +220,7 @@ class NoValue(object):
if (name not in cls.skipMethods and
name.startswith('__') and
name.endswith('__') and
callable(getattr(typ, name)))]
calling.callable(getattr(typ, name)))]
for name in set(op_names):
setattr(cls, name, getPlug(name))
@@ -267,8 +268,9 @@ class SimpleAsn1Type(Asn1Type):
try:
self.subtypeSpec(value)
except error.PyAsn1Error as exValue:
raise type(exValue)('%s at %s' % (exValue, self.__class__.__name__))
except error.PyAsn1Error:
exType, exValue, exTb = sys.exc_info()
raise exType('%s at %s' % (exValue, self.__class__.__name__))
self._value = value
@@ -289,9 +291,7 @@ class SimpleAsn1Type(Asn1Type):
return '<%s>' % representation
def __eq__(self, other):
if self is other:
return True
return self._value == other
return self is other and True or self._value == other
def __ne__(self, other):
return self._value != other
@@ -308,8 +308,12 @@ class SimpleAsn1Type(Asn1Type):
def __ge__(self, other):
return self._value >= other
def __bool__(self):
return bool(self._value)
if sys.version_info[0] <= 2:
def __nonzero__(self):
return self._value and True or False
else:
def __bool__(self):
return self._value and True or False
def __hash__(self):
return hash(self._value)
@@ -560,8 +564,12 @@ class ConstructedAsn1Type(Asn1Type):
def __ge__(self, other):
return self.components >= other
def __bool__(self):
return bool(self.components)
if sys.version_info[0] <= 2:
def __nonzero__(self):
return bool(self.components)
else:
def __bool__(self):
return bool(self.components)
@property
def components(self):

View File

@@ -1,8 +1,8 @@
#
# This file is part of pyasn1 software.
#
# Copyright (c) 2005-2020, Ilya Etingof <etingof@gmail.com>
# License: https://pyasn1.readthedocs.io/en/latest/license.html
# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com>
# License: http://snmplabs.com/pyasn1/license.html
#
import sys
@@ -22,14 +22,15 @@ class AbstractCharacterString(univ.OctetString):
"""Creates |ASN.1| schema or value object.
|ASN.1| class is based on :class:`~pyasn1.type.base.SimpleAsn1Type`,
its objects are immutable and duck-type :class:`bytes`.
When used in octet-stream context, |ASN.1| type assumes
its objects are immutable and duck-type Python 2 :class:`str` or Python 3
:class:`bytes`. When used in octet-stream context, |ASN.1| type assumes
"|encoding|" encoding.
Keyword Args
------------
value: :class:`str`, :class:`bytes` or |ASN.1| object
:class:`str`, alternatively :class:`bytes`
value: :class:`unicode`, :class:`str`, :class:`bytes` or |ASN.1| object
:class:`unicode` object (Python 2) or :class:`str` (Python 3),
alternatively :class:`str` (Python 2) or :class:`bytes` (Python 3)
representing octet-stream of serialised unicode string
(note `encoding` parameter) or |ASN.1| class instance.
If `value` is not given, schema object will be created.
@@ -43,8 +44,8 @@ class AbstractCharacterString(univ.OctetString):
instantiation.
encoding: :py:class:`str`
Unicode codec ID to encode/decode
:class:`str` the payload when |ASN.1| object is used
Unicode codec ID to encode/decode :class:`unicode` (Python 2) or
:class:`str` (Python 3) the payload when |ASN.1| object is used
in octet-stream context.
Raises
@@ -53,42 +54,88 @@ class AbstractCharacterString(univ.OctetString):
On constraint violation or bad initializer.
"""
def __str__(self):
return str(self._value)
if sys.version_info[0] <= 2:
def __str__(self):
try:
# `str` is Py2 text representation
return self._value.encode(self.encoding)
def __bytes__(self):
try:
return self._value.encode(self.encoding)
except UnicodeEncodeError as exc:
raise error.PyAsn1UnicodeEncodeError(
"Can't encode string '%s' with codec "
"%s" % (self._value, self.encoding), exc
)
except UnicodeEncodeError:
exc = sys.exc_info()[1]
raise error.PyAsn1UnicodeEncodeError(
"Can't encode string '%s' with codec "
"%s" % (self._value, self.encoding), exc
)
def prettyIn(self, value):
try:
if isinstance(value, str):
return value
elif isinstance(value, bytes):
return value.decode(self.encoding)
elif isinstance(value, (tuple, list)):
return self.prettyIn(bytes(value))
elif isinstance(value, univ.OctetString):
return value.asOctets().decode(self.encoding)
else:
return str(value)
def __unicode__(self):
return unicode(self._value)
except (UnicodeDecodeError, LookupError) as exc:
raise error.PyAsn1UnicodeDecodeError(
"Can't decode string '%s' with codec "
"%s" % (value, self.encoding), exc
)
def prettyIn(self, value):
try:
if isinstance(value, unicode):
return value
elif isinstance(value, str):
return value.decode(self.encoding)
elif isinstance(value, (tuple, list)):
return self.prettyIn(''.join([chr(x) for x in value]))
elif isinstance(value, univ.OctetString):
return value.asOctets().decode(self.encoding)
else:
return unicode(value)
def asOctets(self, padding=True):
return bytes(self)
except (UnicodeDecodeError, LookupError):
exc = sys.exc_info()[1]
raise error.PyAsn1UnicodeDecodeError(
"Can't decode string '%s' with codec "
"%s" % (value, self.encoding), exc
)
def asNumbers(self, padding=True):
return tuple(bytes(self))
def asOctets(self, padding=True):
return str(self)
def asNumbers(self, padding=True):
return tuple([ord(x) for x in str(self)])
else:
def __str__(self):
# `unicode` is Py3 text representation
return str(self._value)
def __bytes__(self):
try:
return self._value.encode(self.encoding)
except UnicodeEncodeError:
exc = sys.exc_info()[1]
raise error.PyAsn1UnicodeEncodeError(
"Can't encode string '%s' with codec "
"%s" % (self._value, self.encoding), exc
)
def prettyIn(self, value):
try:
if isinstance(value, str):
return value
elif isinstance(value, bytes):
return value.decode(self.encoding)
elif isinstance(value, (tuple, list)):
return self.prettyIn(bytes(value))
elif isinstance(value, univ.OctetString):
return value.asOctets().decode(self.encoding)
else:
return str(value)
except (UnicodeDecodeError, LookupError):
exc = sys.exc_info()[1]
raise error.PyAsn1UnicodeDecodeError(
"Can't decode string '%s' with codec "
"%s" % (value, self.encoding), exc
)
def asOctets(self, padding=True):
return bytes(self)
def asNumbers(self, padding=True):
return tuple(bytes(self))
#
# See OctetString.prettyPrint() for the explanation

View File

@@ -1,8 +1,8 @@
#
# This file is part of pyasn1 software.
#
# Copyright (c) 2005-2020, Ilya Etingof <etingof@gmail.com>
# License: https://pyasn1.readthedocs.io/en/latest/license.html
# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com>
# License: http://snmplabs.com/pyasn1/license.html
#
# Original concept and code by Mike C. Fletcher.
#
@@ -31,9 +31,9 @@ class AbstractConstraint(object):
try:
self._testValue(value, idx)
except error.ValueConstraintError as exc:
except error.ValueConstraintError:
raise error.ValueConstraintError(
'%s failed at: %r' % (self, exc)
'%s failed at: %r' % (self, sys.exc_info()[1])
)
def __repr__(self):
@@ -46,9 +46,7 @@ class AbstractConstraint(object):
return '<%s>' % representation
def __eq__(self, other):
if self is other:
return True
return self._values == other
return self is other and True or self._values == other
def __ne__(self, other):
return self._values != other
@@ -65,8 +63,12 @@ class AbstractConstraint(object):
def __ge__(self, other):
return self._values >= other
def __bool__(self):
return bool(self._values)
if sys.version_info[0] <= 2:
def __nonzero__(self):
return self._values and True or False
else:
def __bool__(self):
return self._values and True or False
def __hash__(self):
return self.__hash
@@ -148,6 +150,9 @@ class SingleValueConstraint(AbstractConstraint):
def __iter__(self):
return iter(self._set)
def __sub__(self, constraint):
return self.__class__(*(self._set.difference(constraint)))
def __add__(self, constraint):
return self.__class__(*(self._set.union(constraint)))

View File

@@ -1,8 +1,8 @@
#
# This file is part of pyasn1 software.
#
# Copyright (c) 2005-2020, Ilya Etingof <etingof@gmail.com>
# License: https://pyasn1.readthedocs.io/en/latest/license.html
# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com>
# License: http://snmplabs.com/pyasn1/license.html
#
from pyasn1.error import PyAsn1Error

View File

@@ -1,8 +1,8 @@
#
# This file is part of pyasn1 software.
#
# Copyright (c) 2005-2020, Ilya Etingof <etingof@gmail.com>
# License: https://pyasn1.readthedocs.io/en/latest/license.html
# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com>
# License: http://snmplabs.com/pyasn1/license.html
#
import sys
@@ -13,6 +13,13 @@ from pyasn1.type import tagmap
__all__ = ['NamedType', 'OptionalNamedType', 'DefaultedNamedType',
'NamedTypes']
try:
any
except NameError:
any = lambda x: bool(filter(bool, x))
class NamedType(object):
"""Create named field object for a constructed ASN.1 type.
@@ -204,8 +211,12 @@ class NamedTypes(object):
def __iter__(self):
return (x[0] for x in self.__namedTypes)
def __bool__(self):
return self.__namedTypesLen > 0
if sys.version_info[0] <= 2:
def __nonzero__(self):
return self.__namedTypesLen > 0
else:
def __bool__(self):
return self.__namedTypesLen > 0
def __len__(self):
return self.__namedTypesLen

View File

@@ -1,8 +1,8 @@
#
# This file is part of pyasn1 software.
#
# Copyright (c) 2005-2020, Ilya Etingof <etingof@gmail.com>
# License: https://pyasn1.readthedocs.io/en/latest/license.html
# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com>
# License: http://snmplabs.com/pyasn1/license.html
#
# ASN.1 named integers
#

View File

@@ -1,8 +1,8 @@
#
# This file is part of pyasn1 software.
#
# Copyright (c) 2005-2020, Ilya Etingof <etingof@gmail.com>
# License: https://pyasn1.readthedocs.io/en/latest/license.html
# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com>
# License: http://snmplabs.com/pyasn1/license.html
#
__all__ = ['OpenType']

View File

@@ -1,8 +1,8 @@
#
# This file is part of pyasn1 software.
#
# Copyright (c) 2005-2020, Ilya Etingof <etingof@gmail.com>
# License: https://pyasn1.readthedocs.io/en/latest/license.html
# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com>
# License: http://snmplabs.com/pyasn1/license.html
#
from pyasn1 import error
@@ -98,7 +98,7 @@ class Tag(object):
elif idx == 2:
return self.__tagId
else:
raise IndexError
raise IndexError()
def __iter__(self):
yield self.__tagClass

View File

@@ -1,8 +1,8 @@
#
# This file is part of pyasn1 software.
#
# Copyright (c) 2005-2020, Ilya Etingof <etingof@gmail.com>
# License: https://pyasn1.readthedocs.io/en/latest/license.html
# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com>
# License: http://snmplabs.com/pyasn1/license.html
#
from pyasn1 import error
@@ -46,7 +46,7 @@ class TagMap(object):
return self.__presentTypes[tagSet]
except KeyError:
if self.__defaultType is None:
raise
raise KeyError()
elif tagSet in self.__skipTypes:
raise error.PyAsn1Error('Key in negative map')
else:

View File

@@ -1,15 +1,17 @@
#
# This file is part of pyasn1 software.
#
# Copyright (c) 2005-2020, Ilya Etingof <etingof@gmail.com>
# License: https://pyasn1.readthedocs.io/en/latest/license.html
# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com>
# License: http://snmplabs.com/pyasn1/license.html
#
import math
import sys
from pyasn1 import error
from pyasn1.codec.ber import eoo
from pyasn1.compat import binary
from pyasn1.compat import integer
from pyasn1.compat import octets
from pyasn1.type import base
from pyasn1.type import constraint
from pyasn1.type import namedtype
@@ -164,23 +166,40 @@ class Integer(base.SimpleAsn1Type):
def __rfloordiv__(self, value):
return self.clone(value // self._value)
def __truediv__(self, value):
return Real(self._value / value)
if sys.version_info[0] <= 2:
def __div__(self, value):
if isinstance(value, float):
return Real(self._value / value)
else:
return self.clone(self._value / value)
def __rtruediv__(self, value):
return Real(value / self._value)
def __rdiv__(self, value):
if isinstance(value, float):
return Real(value / self._value)
else:
return self.clone(value / self._value)
else:
def __truediv__(self, value):
return Real(self._value / value)
def __divmod__(self, value):
return self.clone(divmod(self._value, value))
def __rtruediv__(self, value):
return Real(value / self._value)
def __rdivmod__(self, value):
return self.clone(divmod(value, self._value))
def __divmod__(self, value):
return self.clone(divmod(self._value, value))
__hash__ = base.SimpleAsn1Type.__hash__
def __rdivmod__(self, value):
return self.clone(divmod(value, self._value))
__hash__ = base.SimpleAsn1Type.__hash__
def __int__(self):
return int(self._value)
if sys.version_info[0] <= 2:
def __long__(self):
return long(self._value)
def __float__(self):
return float(self._value)
@@ -212,8 +231,9 @@ class Integer(base.SimpleAsn1Type):
def __ceil__(self):
return math.ceil(self._value)
def __trunc__(self):
return self.clone(math.trunc(self._value))
if sys.version_info[0:2] > (2, 5):
def __trunc__(self):
return self.clone(math.trunc(self._value))
def __lt__(self, value):
return self._value < value
@@ -241,9 +261,9 @@ class Integer(base.SimpleAsn1Type):
try:
return self.namedValues[value]
except KeyError as exc:
except KeyError:
raise error.PyAsn1Error(
'Can\'t coerce %r into integer: %s' % (value, exc)
'Can\'t coerce %r into integer: %s' % (value, sys.exc_info()[1])
)
def prettyOut(self, value):
@@ -322,18 +342,23 @@ class Boolean(Integer):
# Optimization for faster codec lookup
typeId = Integer.getTypeId()
if sys.version_info[0] < 3:
SizedIntegerBase = long
else:
SizedIntegerBase = int
class SizedInteger(int):
class SizedInteger(SizedIntegerBase):
bitLength = leadingZeroBits = None
def setBitLength(self, bitLength):
self.bitLength = bitLength
self.leadingZeroBits = max(bitLength - self.bit_length(), 0)
self.leadingZeroBits = max(bitLength - integer.bitLength(self), 0)
return self
def __len__(self):
if self.bitLength is None:
self.setBitLength(self.bit_length())
self.setBitLength(integer.bitLength(self))
return self.bitLength
@@ -528,18 +553,22 @@ class BitString(base.SimpleAsn1Type):
return self.clone(SizedInteger(self._value >> count).setBitLength(max(0, len(self._value) - count)))
def __int__(self):
return int(self._value)
return self._value
def __float__(self):
return float(self._value)
if sys.version_info[0] < 3:
def __long__(self):
return self._value
def asNumbers(self):
"""Get |ASN.1| value as a sequence of 8-bit integers.
If |ASN.1| object length is not a multiple of 8, result
will be left-padded with zeros.
"""
return tuple(self.asOctets())
return tuple(octets.octs2ints(self.asOctets()))
def asOctets(self):
"""Get |ASN.1| value as a sequence of octets.
@@ -557,7 +586,7 @@ class BitString(base.SimpleAsn1Type):
def asBinary(self):
"""Get |ASN.1| value as a text string of bits.
"""
binString = bin(self._value)[2:]
binString = binary.bin(self._value)[2:]
return '0' * (len(self._value) - len(binString)) + binString
@classmethod
@@ -572,8 +601,8 @@ class BitString(base.SimpleAsn1Type):
try:
value = SizedInteger(value, 16).setBitLength(len(value) * 4)
except ValueError as exc:
raise error.PyAsn1Error('%s.fromHexString() error: %s' % (cls.__name__, exc))
except ValueError:
raise error.PyAsn1Error('%s.fromHexString() error: %s' % (cls.__name__, sys.exc_info()[1]))
if prepend is not None:
value = SizedInteger(
@@ -597,8 +626,8 @@ class BitString(base.SimpleAsn1Type):
try:
value = SizedInteger(value or '0', 2).setBitLength(len(value))
except ValueError as exc:
raise error.PyAsn1Error('%s.fromBinaryString() error: %s' % (cls.__name__, exc))
except ValueError:
raise error.PyAsn1Error('%s.fromBinaryString() error: %s' % (cls.__name__, sys.exc_info()[1]))
if prepend is not None:
value = SizedInteger(
@@ -616,10 +645,10 @@ class BitString(base.SimpleAsn1Type):
Parameters
----------
value: :class:`bytes`
Text string like b'\\\\x01\\\\xff'
value: :class:`str` (Py2) or :class:`bytes` (Py3)
Text string like '\\\\x01\\\\xff' (Py2) or b'\\\\x01\\\\xff' (Py3)
"""
value = SizedInteger(int.from_bytes(bytes(value), 'big') >> padding).setBitLength(len(value) * 8 - padding)
value = SizedInteger(integer.from_bytes(value) >> padding).setBitLength(len(value) * 8 - padding)
if prepend is not None:
value = SizedInteger(
@@ -634,7 +663,7 @@ class BitString(base.SimpleAsn1Type):
def prettyIn(self, value):
if isinstance(value, SizedInteger):
return value
elif isinstance(value, str):
elif octets.isStringType(value):
if not value:
return SizedInteger(0).setBitLength(0)
@@ -681,7 +710,7 @@ class BitString(base.SimpleAsn1Type):
elif isinstance(value, BitString):
return SizedInteger(value).setBitLength(len(value))
elif isinstance(value, int):
elif isinstance(value, intTypes):
return SizedInteger(value)
else:
@@ -690,18 +719,32 @@ class BitString(base.SimpleAsn1Type):
)
try:
# noinspection PyStatementEffect
all
except NameError: # Python 2.4
# noinspection PyShadowingBuiltins
def all(iterable):
for element in iterable:
if not element:
return False
return True
class OctetString(base.SimpleAsn1Type):
"""Create |ASN.1| schema or value object.
|ASN.1| class is based on :class:`~pyasn1.type.base.SimpleAsn1Type`, its
objects are immutable and duck-type :class:`bytes`.
When used in Unicode context, |ASN.1| type
objects are immutable and duck-type Python 2 :class:`str` or
Python 3 :class:`bytes`. When used in Unicode context, |ASN.1| type
assumes "|encoding|" serialisation.
Keyword Args
------------
value: :class:`unicode`, :class:`str`, :class:`bytes` or |ASN.1| object
:class:`bytes`, alternatively :class:`str`
class:`str` (Python 2) or :class:`bytes` (Python 3), alternatively
class:`unicode` object (Python 2) or :class:`str` (Python 3)
representing character string to be serialised into octets
(note `encoding` parameter) or |ASN.1| object.
If `value` is not given, schema object will be created.
@@ -715,8 +758,8 @@ class OctetString(base.SimpleAsn1Type):
instantiation.
encoding: :py:class:`str`
Unicode codec ID to encode/decode
:class:`str` the payload when |ASN.1| object is used
Unicode codec ID to encode/decode :class:`unicode` (Python 2) or
:class:`str` (Python 3) the payload when |ASN.1| object is used
in text string context.
binValue: :py:class:`str`
@@ -793,50 +836,101 @@ class OctetString(base.SimpleAsn1Type):
base.SimpleAsn1Type.__init__(self, value, **kwargs)
def prettyIn(self, value):
if isinstance(value, bytes):
return value
if sys.version_info[0] <= 2:
def prettyIn(self, value):
if isinstance(value, str):
return value
elif isinstance(value, str):
elif isinstance(value, unicode):
try:
return value.encode(self.encoding)
except (LookupError, UnicodeEncodeError):
exc = sys.exc_info()[1]
raise error.PyAsn1UnicodeEncodeError(
"Can't encode string '%s' with codec "
"%s" % (value, self.encoding), exc
)
elif isinstance(value, (tuple, list)):
try:
return ''.join([chr(x) for x in value])
except ValueError:
raise error.PyAsn1Error(
"Bad %s initializer '%s'" % (self.__class__.__name__, value)
)
else:
return str(value)
def __str__(self):
return str(self._value)
def __unicode__(self):
try:
return value.encode(self.encoding)
return self._value.decode(self.encoding)
except UnicodeEncodeError as exc:
raise error.PyAsn1UnicodeEncodeError(
"Can't encode string '%s' with '%s' "
"codec" % (value, self.encoding), exc
except UnicodeDecodeError:
exc = sys.exc_info()[1]
raise error.PyAsn1UnicodeDecodeError(
"Can't decode string '%s' with codec "
"%s" % (self._value, self.encoding), exc
)
elif isinstance(value, OctetString): # a shortcut, bytes() would work the same way
return value.asOctets()
elif isinstance(value, base.SimpleAsn1Type): # this mostly targets Integer objects
return self.prettyIn(str(value))
def asOctets(self):
return str(self._value)
elif isinstance(value, (tuple, list)):
return self.prettyIn(bytes(value))
def asNumbers(self):
return tuple([ord(x) for x in self._value])
else:
return bytes(value)
else:
def prettyIn(self, value):
if isinstance(value, bytes):
return value
def __str__(self):
try:
return self._value.decode(self.encoding)
elif isinstance(value, str):
try:
return value.encode(self.encoding)
except UnicodeDecodeError as exc:
raise error.PyAsn1UnicodeDecodeError(
"Can't decode string '%s' with '%s' codec at "
"'%s'" % (self._value, self.encoding,
self.__class__.__name__), exc
)
except UnicodeEncodeError:
exc = sys.exc_info()[1]
raise error.PyAsn1UnicodeEncodeError(
"Can't encode string '%s' with '%s' "
"codec" % (value, self.encoding), exc
)
elif isinstance(value, OctetString): # a shortcut, bytes() would work the same way
return value.asOctets()
def __bytes__(self):
return bytes(self._value)
elif isinstance(value, base.SimpleAsn1Type): # this mostly targets Integer objects
return self.prettyIn(str(value))
def asOctets(self):
return bytes(self._value)
elif isinstance(value, (tuple, list)):
return self.prettyIn(bytes(value))
def asNumbers(self):
return tuple(self._value)
else:
return bytes(value)
def __str__(self):
try:
return self._value.decode(self.encoding)
except UnicodeDecodeError:
exc = sys.exc_info()[1]
raise error.PyAsn1UnicodeDecodeError(
"Can't decode string '%s' with '%s' codec at "
"'%s'" % (self._value, self.encoding,
self.__class__.__name__), exc
)
def __bytes__(self):
return bytes(self._value)
def asOctets(self):
return bytes(self._value)
def asNumbers(self):
return tuple(self._value)
#
# Normally, `.prettyPrint()` is called from `__str__()`. Historically,
@@ -905,7 +999,7 @@ class OctetString(base.SimpleAsn1Type):
r.append(byte)
return bytes(r)
return octets.ints2octs(r)
@staticmethod
def fromHexString(value):
@@ -927,7 +1021,7 @@ class OctetString(base.SimpleAsn1Type):
if p:
r.append(int(p + '0', 16))
return bytes(r)
return octets.ints2octs(r)
# Immutable sequence object protocol
@@ -1008,7 +1102,7 @@ class Null(OctetString):
tagSet = tag.initTagSet(
tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x05)
)
subtypeSpec = OctetString.subtypeSpec + constraint.SingleValueConstraint(b'')
subtypeSpec = OctetString.subtypeSpec + constraint.SingleValueConstraint(octets.str2octs(''))
# Optimization for faster codec lookup
typeId = OctetString.getTypeId()
@@ -1017,7 +1111,14 @@ class Null(OctetString):
if value:
return value
return b''
return octets.str2octs('')
if sys.version_info[0] <= 2:
intTypes = (int, long)
else:
intTypes = (int,)
numericTypes = intTypes + (float,)
class ObjectIdentifier(base.SimpleAsn1Type):
@@ -1129,25 +1230,24 @@ class ObjectIdentifier(base.SimpleAsn1Type):
def prettyIn(self, value):
if isinstance(value, ObjectIdentifier):
return tuple(value)
elif isinstance(value, str):
elif octets.isStringType(value):
if '-' in value:
raise error.PyAsn1Error(
# sys.exc_info in case prettyIn was called while handling an exception
'Malformed Object ID %s at %s: %s' % (value, self.__class__.__name__, sys.exc_info()[1])
)
try:
return tuple([int(subOid) for subOid in value.split('.') if subOid])
except ValueError as exc:
except ValueError:
raise error.PyAsn1Error(
'Malformed Object ID %s at %s: %s' % (value, self.__class__.__name__, exc)
'Malformed Object ID %s at %s: %s' % (value, self.__class__.__name__, sys.exc_info()[1])
)
try:
tupleOfInts = tuple([int(subOid) for subOid in value if subOid >= 0])
except (ValueError, TypeError) as exc:
except (ValueError, TypeError):
raise error.PyAsn1Error(
'Malformed Object ID %s at %s: %s' % (value, self.__class__.__name__, exc)
'Malformed Object ID %s at %s: %s' % (value, self.__class__.__name__, sys.exc_info()[1])
)
if len(tupleOfInts) == len(value):
@@ -1159,135 +1259,6 @@ class ObjectIdentifier(base.SimpleAsn1Type):
return '.'.join([str(x) for x in value])
class RelativeOID(base.SimpleAsn1Type):
"""Create |ASN.1| schema or value object.
|ASN.1| class is based on :class:`~pyasn1.type.base.SimpleAsn1Type`, its
objects are immutable and duck-type Python :class:`tuple` objects
(tuple of non-negative integers).
Keyword Args
------------
value: :class:`tuple`, :class:`str` or |ASN.1| object
Python sequence of :class:`int` or :class:`str` literal or |ASN.1| object.
If `value` is not given, schema object will be created.
tagSet: :py:class:`~pyasn1.type.tag.TagSet`
Object representing non-default ASN.1 tag(s)
subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection`
Object representing non-default ASN.1 subtype constraint(s). Constraints
verification for |ASN.1| type occurs automatically on object
instantiation.
Raises
------
~pyasn1.error.ValueConstraintError, ~pyasn1.error.PyAsn1Error
On constraint violation or bad initializer.
Examples
--------
.. code-block:: python
class RelOID(RelativeOID):
'''
ASN.1 specification:
id-pad-null RELATIVE-OID ::= { 0 }
id-pad-once RELATIVE-OID ::= { 5 6 }
id-pad-twice RELATIVE-OID ::= { 5 6 7 }
'''
id_pad_null = RelOID('0')
id_pad_once = RelOID('5.6')
id_pad_twice = id_pad_once + (7,)
"""
#: Set (on class, not on instance) or return a
#: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s)
#: associated with |ASN.1| type.
tagSet = tag.initTagSet(
tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x0d)
)
#: Set (on class, not on instance) or return a
#: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object
#: imposing constraints on |ASN.1| type initialization values.
subtypeSpec = constraint.ConstraintsIntersection()
# Optimization for faster codec lookup
typeId = base.SimpleAsn1Type.getTypeId()
def __add__(self, other):
return self.clone(self._value + other)
def __radd__(self, other):
return self.clone(other + self._value)
def asTuple(self):
return self._value
# Sequence object protocol
def __len__(self):
return len(self._value)
def __getitem__(self, i):
if i.__class__ is slice:
return self.clone(self._value[i])
else:
return self._value[i]
def __iter__(self):
return iter(self._value)
def __contains__(self, value):
return value in self._value
def index(self, suboid):
return self._value.index(suboid)
def isPrefixOf(self, other):
"""Indicate if this |ASN.1| object is a prefix of other |ASN.1| object.
Parameters
----------
other: |ASN.1| object
|ASN.1| object
Returns
-------
: :class:`bool`
:obj:`True` if this |ASN.1| object is a parent (e.g. prefix) of the other |ASN.1| object
or :obj:`False` otherwise.
"""
l = len(self)
if l <= len(other):
if self._value[:l] == other[:l]:
return True
return False
def prettyIn(self, value):
if isinstance(value, RelativeOID):
return tuple(value)
elif isinstance(value, str):
if '-' in value:
raise error.PyAsn1Error(
# sys.exc_info in case prettyIn was called while handling an exception
'Malformed RELATIVE-OID %s at %s: %s' % (value, self.__class__.__name__, sys.exc_info()[1])
)
try:
return tuple([int(subOid) for subOid in value.split('.') if subOid])
except ValueError as exc:
raise error.PyAsn1Error(
'Malformed RELATIVE-OID %s at %s: %s' % (value, self.__class__.__name__, exc)
)
try:
tupleOfInts = tuple([int(subOid) for subOid in value if subOid >= 0])
except (ValueError, TypeError) as exc:
raise error.PyAsn1Error(
'Malformed RELATIVE-OID %s at %s: %s' % (value, self.__class__.__name__, exc)
)
if len(tupleOfInts) == len(value):
return tupleOfInts
raise error.PyAsn1Error('Malformed RELATIVE-OID %s at %s' % (value, self.__class__.__name__))
def prettyOut(self, value):
return '.'.join([str(x) for x in value])
class Real(base.SimpleAsn1Type):
"""Create |ASN.1| schema or value object.
@@ -1368,9 +1339,9 @@ class Real(base.SimpleAsn1Type):
def prettyIn(self, value):
if isinstance(value, tuple) and len(value) == 3:
if (not isinstance(value[0], (int, float)) or
not isinstance(value[1], int) or
not isinstance(value[2], int)):
if (not isinstance(value[0], numericTypes) or
not isinstance(value[1], intTypes) or
not isinstance(value[2], intTypes)):
raise error.PyAsn1Error('Lame Real value syntax: %s' % (value,))
if (isinstance(value[0], float) and
self._inf and value[0] in self._inf):
@@ -1382,10 +1353,10 @@ class Real(base.SimpleAsn1Type):
if value[1] == 10:
value = self.__normalizeBase10(value)
return value
elif isinstance(value, int):
elif isinstance(value, intTypes):
return self.__normalizeBase10((value, 10, 0))
elif isinstance(value, float) or isinstance(value, str):
if isinstance(value, str):
elif isinstance(value, float) or octets.isStringType(value):
if octets.isStringType(value):
try:
value = float(value)
except ValueError:
@@ -1472,21 +1443,32 @@ class Real(base.SimpleAsn1Type):
def __rpow__(self, value):
return self.clone(pow(value, float(self)))
def __truediv__(self, value):
return self.clone(float(self) / value)
if sys.version_info[0] <= 2:
def __div__(self, value):
return self.clone(float(self) / value)
def __rtruediv__(self, value):
return self.clone(value / float(self))
def __rdiv__(self, value):
return self.clone(value / float(self))
else:
def __truediv__(self, value):
return self.clone(float(self) / value)
def __divmod__(self, value):
return self.clone(float(self) // value)
def __rtruediv__(self, value):
return self.clone(value / float(self))
def __rdivmod__(self, value):
return self.clone(value // float(self))
def __divmod__(self, value):
return self.clone(float(self) // value)
def __rdivmod__(self, value):
return self.clone(value // float(self))
def __int__(self):
return int(float(self))
if sys.version_info[0] <= 2:
def __long__(self):
return long(float(self))
def __float__(self):
if self._value in self._inf:
return self._value
@@ -1517,8 +1499,9 @@ class Real(base.SimpleAsn1Type):
def __ceil__(self):
return self.clone(math.ceil(float(self)))
def __trunc__(self):
return self.clone(math.trunc(float(self)))
if sys.version_info[0:2] > (2, 5):
def __trunc__(self):
return self.clone(math.trunc(float(self)))
def __lt__(self, value):
return float(self) < value
@@ -1538,10 +1521,14 @@ class Real(base.SimpleAsn1Type):
def __ge__(self, value):
return float(self) >= value
def __bool__(self):
return bool(float(self))
if sys.version_info[0] <= 2:
def __nonzero__(self):
return bool(float(self))
else:
def __bool__(self):
return bool(float(self))
__hash__ = base.SimpleAsn1Type.__hash__
__hash__ = base.SimpleAsn1Type.__hash__
def __getitem__(self, idx):
if self._value in self._inf:
@@ -1686,15 +1673,15 @@ class SequenceOfAndSetOfBase(base.ConstructedAsn1Type):
try:
return self.getComponentByPosition(idx)
except error.PyAsn1Error as exc:
raise IndexError(exc)
except error.PyAsn1Error:
raise IndexError(sys.exc_info()[1])
def __setitem__(self, idx, value):
try:
self.setComponentByPosition(idx, value)
except error.PyAsn1Error as exc:
raise IndexError(exc)
except error.PyAsn1Error:
raise IndexError(sys.exc_info()[1])
def append(self, value):
if self._componentValues is noValue:
@@ -1727,8 +1714,8 @@ class SequenceOfAndSetOfBase(base.ConstructedAsn1Type):
try:
return indices[values.index(value, start, stop)]
except error.PyAsn1Error as exc:
raise ValueError(exc)
except error.PyAsn1Error:
raise ValueError(sys.exc_info()[1])
def reverse(self):
self._componentValues.reverse()
@@ -2085,7 +2072,8 @@ class SequenceOfAndSetOfBase(base.ConstructedAsn1Type):
# Represent SequenceOf/SetOf as a bare dict to constraints chain
self.subtypeSpec(mapping)
except error.PyAsn1Error as exc:
except error.PyAsn1Error:
exc = sys.exc_info()[1]
return exc
return False
@@ -2236,38 +2224,38 @@ class SequenceAndSetBase(base.ConstructedAsn1Type):
self._dynamicNames = self._componentTypeLen or self.DynamicNames()
def __getitem__(self, idx):
if isinstance(idx, str):
if octets.isStringType(idx):
try:
return self.getComponentByName(idx)
except error.PyAsn1Error as exc:
except error.PyAsn1Error:
# duck-typing dict
raise KeyError(exc)
raise KeyError(sys.exc_info()[1])
else:
try:
return self.getComponentByPosition(idx)
except error.PyAsn1Error as exc:
except error.PyAsn1Error:
# duck-typing list
raise IndexError(exc)
raise IndexError(sys.exc_info()[1])
def __setitem__(self, idx, value):
if isinstance(idx, str):
if octets.isStringType(idx):
try:
self.setComponentByName(idx, value)
except error.PyAsn1Error as exc:
except error.PyAsn1Error:
# duck-typing dict
raise KeyError(exc)
raise KeyError(sys.exc_info()[1])
else:
try:
self.setComponentByPosition(idx, value)
except error.PyAsn1Error as exc:
except error.PyAsn1Error:
# duck-typing list
raise IndexError(exc)
raise IndexError(sys.exc_info()[1])
def __contains__(self, key):
if self._componentTypeLen:
@@ -2716,7 +2704,8 @@ class SequenceAndSetBase(base.ConstructedAsn1Type):
# Represent Sequence/Set as a bare dict to constraints chain
self.subtypeSpec(mapping)
except error.PyAsn1Error as exc:
except error.PyAsn1Error:
exc = sys.exc_info()[1]
return exc
return False
@@ -3025,8 +3014,12 @@ class Choice(Set):
return self._componentValues[self._currentIdx] >= other
return NotImplemented
def __bool__(self):
return bool(self._componentValues)
if sys.version_info[0] <= 2:
def __nonzero__(self):
return self._componentValues and True or False
else:
def __bool__(self):
return self._componentValues and True or False
def __len__(self):
return self._currentIdx is not None and 1 or 0
@@ -3231,14 +3224,15 @@ class Any(OctetString):
"""Create |ASN.1| schema or value object.
|ASN.1| class is based on :class:`~pyasn1.type.base.SimpleAsn1Type`,
its objects are immutable and duck-type :class:`bytes`.
When used in Unicode context, |ASN.1| type assumes
its objects are immutable and duck-type Python 2 :class:`str` or Python 3
:class:`bytes`. When used in Unicode context, |ASN.1| type assumes
"|encoding|" serialisation.
Keyword Args
------------
value: :class:`unicode`, :class:`str`, :class:`bytes` or |ASN.1| object
:class:`bytes`, alternatively :class:`str`
:class:`str` (Python 2) or :class:`bytes` (Python 3), alternatively
:class:`unicode` object (Python 2) or :class:`str` (Python 3)
representing character string to be serialised into octets (note
`encoding` parameter) or |ASN.1| object.
If `value` is not given, schema object will be created.
@@ -3252,8 +3246,8 @@ class Any(OctetString):
instantiation.
encoding: :py:class:`str`
Unicode codec ID to encode/decode
:class:`str` the payload when |ASN.1| object is used
Unicode codec ID to encode/decode :class:`unicode` (Python 2) or
:class:`str` (Python 3) the payload when |ASN.1| object is used
in text string context.
binValue: :py:class:`str`

View File

@@ -1,12 +1,14 @@
#
# This file is part of pyasn1 software.
#
# Copyright (c) 2005-2020, Ilya Etingof <etingof@gmail.com>
# License: https://pyasn1.readthedocs.io/en/latest/license.html
# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com>
# License: http://snmplabs.com/pyasn1/license.html
#
import datetime
from pyasn1 import error
from pyasn1.compat import dateandtime
from pyasn1.compat import string
from pyasn1.type import char
from pyasn1.type import tag
from pyasn1.type import univ
@@ -72,9 +74,9 @@ class TimeMixIn(object):
elif '-' in text or '+' in text:
if '+' in text:
text, plusminus, tz = text.partition('+')
text, plusminus, tz = string.partition(text, '+')
else:
text, plusminus, tz = text.partition('-')
text, plusminus, tz = string.partition(text, '-')
if self._shortTZ and len(tz) == 2:
tz += '00'
@@ -97,9 +99,9 @@ class TimeMixIn(object):
if '.' in text or ',' in text:
if '.' in text:
text, _, ms = text.partition('.')
text, _, ms = string.partition(text, '.')
else:
text, _, ms = text.partition(',')
text, _, ms = string.partition(text, ',')
try:
ms = int(ms) * 1000
@@ -116,7 +118,7 @@ class TimeMixIn(object):
text += '00'
try:
dt = datetime.datetime.strptime(text, self._yearsDigits == 4 and '%Y%m%d%H%M%S' or '%y%m%d%H%M%S')
dt = dateandtime.strptime(text, self._yearsDigits == 4 and '%Y%m%d%H%M%S' or '%y%m%d%H%M%S')
except ValueError:
raise error.PyAsn1Error('malformed datetime format %s' % self)