From acfa2fcc24493a69626c17b23df3de8d771cbcc6 Mon Sep 17 00:00:00 2001 From: Ilya Etingof Date: Sun, 23 Jul 2017 13:37:14 +0200 Subject: ASN.1 types __init__(), .clone()/.subtype() refactored into kwargs --- CHANGES.rst | 2 + pyasn1/codec/ber/decoder.py | 10 +- pyasn1/codec/ber/encoder.py | 2 +- pyasn1/codec/ber/eoo.py | 4 +- pyasn1/type/base.py | 168 ++++++++++++------------ pyasn1/type/char.py | 27 ++-- pyasn1/type/univ.py | 312 ++++++++++++-------------------------------- 7 files changed, 191 insertions(+), 334 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index fafd7a2..94926e9 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -2,6 +2,8 @@ Revision 0.3.1, released XX-07-2017 ----------------------------------- +- ASN.1 types __init__(), .clone() and .subtype() signatures + refactored into keyword arguments to simplify their signatures. - ASN.1 types initialization refactored to minimize the use of relatively expensive isNoValue() call - Lazily pre-populate list of values of Sequence/Set/Choice types diff --git a/pyasn1/codec/ber/decoder.py b/pyasn1/codec/ber/decoder.py index fc51c85..ede16a7 100644 --- a/pyasn1/codec/ber/decoder.py +++ b/pyasn1/codec/ber/decoder.py @@ -32,11 +32,11 @@ class AbstractSimpleDecoder(AbstractDecoder): def substrateCollector(asn1Object, substrate, length): return substrate[:length], substrate[length:] - def _createComponent(self, asn1Spec, tagSet, value=None): + def _createComponent(self, asn1Spec, tagSet, value=base.noValue): if tagSet[0].tagFormat not in self.tagFormats: raise error.PyAsn1Error('Invalid tag format %s for %s' % (tagSet[0], self.protoComponent.prettyPrintType())) if asn1Spec is None: - return self.protoComponent.clone(value, tagSet) + return self.protoComponent.clone(value, tagSet=tagSet) elif value is None: return asn1Spec else: @@ -47,11 +47,11 @@ class AbstractConstructedDecoder(AbstractDecoder): tagFormats = (tag.tagFormatConstructed,) # noinspection PyUnusedLocal - def _createComponent(self, asn1Spec, tagSet, value=None): + def _createComponent(self, asn1Spec, tagSet, value=base.noValue): if tagSet[0].tagFormat not in self.tagFormats: raise error.PyAsn1Error('Invalid tag format %s for %s' % (tagSet[0], self.protoComponent.prettyPrintType())) if asn1Spec is None: - return self.protoComponent.clone(tagSet) + return self.protoComponent.clone(tagSet=tagSet) else: return asn1Spec.clone() @@ -107,7 +107,7 @@ class IntegerDecoder(AbstractSimpleDecoder): class BooleanDecoder(IntegerDecoder): protoComponent = univ.Boolean(0) - def _createComponent(self, asn1Spec, tagSet, value=None): + def _createComponent(self, asn1Spec, tagSet, value=base.noValue): return IntegerDecoder._createComponent(self, asn1Spec, tagSet, value and 1 or 0) diff --git a/pyasn1/codec/ber/encoder.py b/pyasn1/codec/ber/encoder.py index 14bd609..dfef38f 100644 --- a/pyasn1/codec/ber/encoder.py +++ b/pyasn1/codec/ber/encoder.py @@ -88,7 +88,7 @@ class EndOfOctetsEncoder(AbstractItemEncoder): class ExplicitlyTaggedItemEncoder(AbstractItemEncoder): def encodeValue(self, encodeFun, value, defMode, maxChunkSize): if isinstance(value, base.AbstractConstructedAsn1Item): - value = value.clone(tagSet=value.tagSet[:-1], cloneValueFlag=1) + value = value.clone(tagSet=value.tagSet[:-1], cloneValueFlag=True) else: value = value.clone(tagSet=value.tagSet[:-1]) return encodeFun(value, defMode, maxChunkSize), True, True diff --git a/pyasn1/codec/ber/eoo.py b/pyasn1/codec/ber/eoo.py index b02f5cc..28e33c5 100644 --- a/pyasn1/codec/ber/eoo.py +++ b/pyasn1/codec/ber/eoo.py @@ -15,9 +15,9 @@ class EndOfOctets(base.AbstractSimpleAsn1Item): _instance = None - def __new__(cls, *args): + def __new__(cls, *args, **kwargs): if cls._instance is None: - cls._instance = object.__new__(cls, *args) + cls._instance = object.__new__(cls, *args, **kwargs) return cls._instance diff --git a/pyasn1/type/base.py b/pyasn1/type/base.py index 4ee5c21..0f088c6 100644 --- a/pyasn1/type/base.py +++ b/pyasn1/type/base.py @@ -34,13 +34,14 @@ class Asn1ItemBase(Asn1Item): # Disambiguation ASN.1 types identification typeId = None - def __init__(self, tagSet=None, subtypeSpec=None): - if tagSet is not None: - self.tagSet = tagSet - if subtypeSpec is not None: - self.subtypeSpec = subtypeSpec - self.readOnly = 'subtypeSpec' - self.readOnly = 'tagSet' + def __init__(self, **kwargs): + for key in ('tagSet', 'subtypeSpec'): + if key not in kwargs: + kwargs[key] = getattr(self, key) + + for key, value in kwargs.items(): + setattr(self, key, value) + self.readOnly = key def __setattr__(self, name, value): if not name.startswith('_'): @@ -220,8 +221,8 @@ class AbstractSimpleAsn1Item(Asn1ItemBase): #: Default payload value defaultValue = noValue - def __init__(self, value=noValue, tagSet=None, subtypeSpec=None): - Asn1ItemBase.__init__(self, tagSet, subtypeSpec) + def __init__(self, value=noValue, **kwargs): + Asn1ItemBase.__init__(self, **kwargs) if value is None or value is noValue: value = self.defaultValue else: @@ -300,7 +301,7 @@ class AbstractSimpleAsn1Item(Asn1ItemBase): """ return self._value is not noValue - def clone(self, value=noValue, tagSet=None, subtypeSpec=None): + def clone(self, value=noValue, **kwargs): """Create a copy of a |ASN.1| type or object. Any parameters to the *clone()* method will replace corresponding @@ -323,28 +324,19 @@ class AbstractSimpleAsn1Item(Asn1ItemBase): : new instance of |ASN.1| type/value """ - isModified = False - if value is None or value is noValue: + if not kwargs: + return self + value = self._value - else: - isModified = True - if tagSet is None or tagSet is noValue: - tagSet = self.tagSet - else: - isModified = True - if subtypeSpec is None or subtypeSpec is noValue: - subtypeSpec = self.subtypeSpec - else: - isModified = True - if isModified: - return self.__class__(value, tagSet, subtypeSpec) - else: - return self + for arg in self.readOnly: + if arg not in kwargs: + kwargs[arg] = getattr(self, arg) + + return self.__class__(value, **kwargs) - def subtype(self, value=noValue, implicitTag=None, explicitTag=None, - subtypeSpec=None): + def subtype(self, value=noValue, **kwargs): """Create a copy of a |ASN.1| type or object. Any parameters to the *subtype()* method will be added to the corresponding @@ -374,31 +366,32 @@ class AbstractSimpleAsn1Item(Asn1ItemBase): ------- : new instance of |ASN.1| type/value - """ - isModified = False - + """ if value is None or value is noValue: + if not kwargs: + return self + value = self._value - else: - isModified = True - if implicitTag is not None and implicitTag is not noValue: - tagSet = self.tagSet.tagImplicitly(implicitTag) - isModified = True - elif explicitTag is not None and explicitTag is not noValue: - tagSet = self.tagSet.tagExplicitly(explicitTag) - isModified = True - else: - tagSet = self.tagSet - if subtypeSpec is None or subtypeSpec is noValue: - subtypeSpec = self.subtypeSpec - else: - subtypeSpec += self.subtypeSpec - isModified = True - if isModified: - return self.__class__(value, tagSet, subtypeSpec) - else: - return self + for arg in self.readOnly: + if arg in kwargs: + kwargs[arg] += getattr(self, arg) + else: + kwargs[arg] = getattr(self, arg) + + try: + kwargs['tagSet'] = self.tagSet.tagImplicitly(kwargs['implicitTag']) + + except KeyError: + pass + + try: + kwargs['tagSet'] = self.tagSet.tagExplicitly(kwargs['explicitTag']) + + except KeyError: + pass + + return self.__class__(value, **kwargs) def prettyIn(self, value): return value @@ -472,16 +465,14 @@ class AbstractConstructedAsn1Item(Asn1ItemBase): componentType = None sizeSpec = None - def __init__(self, componentType=None, tagSet=None, - subtypeSpec=None, sizeSpec=None): - Asn1ItemBase.__init__(self, tagSet, subtypeSpec) - if componentType is not None: - self.componentType = componentType - if sizeSpec is not None: - self.sizeSpec = sizeSpec + def __init__(self, **kwargs): + for key in ('componentType', 'sizeSpec'): + if key not in kwargs: + kwargs[key] = getattr(self, key) + + Asn1ItemBase.__init__(self, **kwargs) + self._componentValues = [] - self.readOnly = 'componentType' - self.readOnly = 'sizeSpec' def __repr__(self): representation = [] @@ -527,7 +518,7 @@ class AbstractConstructedAsn1Item(Asn1ItemBase): def _cloneComponentValues(self, myClone, cloneValueFlag): pass - def clone(self, tagSet=None, subtypeSpec=None, sizeSpec=None, cloneValueFlag=None): + def clone(self, **kwargs): """Create a copy of a |ASN.1| type or object. Any parameters to the *clone()* method will replace corresponding @@ -550,19 +541,20 @@ class AbstractConstructedAsn1Item(Asn1ItemBase): new instance of |ASN.1| type/value """ - if tagSet is None: - tagSet = self.tagSet - if subtypeSpec is None: - subtypeSpec = self.subtypeSpec - if sizeSpec is None: - sizeSpec = self.sizeSpec - clone = self.__class__(self.componentType, tagSet, subtypeSpec, sizeSpec) + cloneValueFlag = kwargs.pop('cloneValueFlag', False) + + for arg in self.readOnly: + if arg not in kwargs: + kwargs[arg] = getattr(self, arg) + + clone = self.__class__(**kwargs) + if cloneValueFlag: self._cloneComponentValues(clone, cloneValueFlag) + return clone - def subtype(self, implicitTag=None, explicitTag=None, subtypeSpec=None, - sizeSpec=None, cloneValueFlag=None): + def subtype(self, **kwargs): """Create a copy of a |ASN.1| type or object. Any parameters to the *subtype()* method will be added to the corresponding @@ -585,23 +577,31 @@ class AbstractConstructedAsn1Item(Asn1ItemBase): new instance of |ASN.1| type/value """ - if implicitTag is not None and implicitTag is not noValue: - tagSet = self.tagSet.tagImplicitly(implicitTag) - elif explicitTag is not None and explicitTag is not noValue: - tagSet = self.tagSet.tagExplicitly(explicitTag) - else: - tagSet = self.tagSet - if subtypeSpec is None or subtypeSpec is noValue: - subtypeSpec = self.subtypeSpec - else: - subtypeSpec += self.subtypeSpec - if sizeSpec is None or sizeSpec is noValue: - sizeSpec = self.sizeSpec - else: - sizeSpec += self.sizeSpec - clone = self.__class__(self.componentType, tagSet, subtypeSpec, sizeSpec) + cloneValueFlag = kwargs.pop('cloneValueFlag', False) + + for arg in self.readOnly: + if arg in kwargs: + kwargs[arg] += getattr(self, arg) + else: + kwargs[arg] = getattr(self, arg) + + try: + kwargs['tagSet'] = self.tagSet.tagImplicitly(kwargs['implicitTag']) + + except KeyError: + pass + + try: + kwargs['tagSet'] = self.tagSet.tagExplicitly(kwargs['explicitTag']) + + except KeyError: + pass + + clone = self.__class__(**kwargs) + if cloneValueFlag: self._cloneComponentValues(clone, cloneValueFlag) + return clone def verifySizeSpec(self): diff --git a/pyasn1/type/char.py b/pyasn1/type/char.py index 039e536..4bb46aa 100644 --- a/pyasn1/type/char.py +++ b/pyasn1/type/char.py @@ -50,10 +50,10 @@ class AbstractCharacterString(univ.OctetString): if sys.version_info[0] <= 2: def __str__(self): try: - return self._value.encode(self._encoding) + return self._value.encode(self.encoding) except UnicodeEncodeError: raise error.PyAsn1Error( - 'Can\'t encode string \'%s\' with \'%s\' codec' % (self._value, self._encoding) + 'Can\'t encode string \'%s\' with \'%s\' codec' % (self._value, self.encoding) ) def __unicode__(self): @@ -64,10 +64,10 @@ class AbstractCharacterString(univ.OctetString): return value elif isinstance(value, str): try: - return value.decode(self._encoding) + return value.decode(self.encoding) except (LookupError, UnicodeDecodeError): raise error.PyAsn1Error( - 'Can\'t decode string \'%s\' with \'%s\' codec' % (value, self._encoding) + 'Can\'t decode string \'%s\' with \'%s\' codec' % (value, self.encoding) ) elif isinstance(value, (tuple, list)): try: @@ -96,10 +96,10 @@ class AbstractCharacterString(univ.OctetString): def __bytes__(self): try: - return self._value.encode(self._encoding) + return self._value.encode(self.encoding) except UnicodeEncodeError: raise error.PyAsn1Error( - 'Can\'t encode string \'%s\' with \'%s\' codec' % (self._value, self._encoding) + 'Can\'t encode string \'%s\' with \'%s\' codec' % (self._value, self.encoding) ) def prettyIn(self, value): @@ -107,10 +107,10 @@ class AbstractCharacterString(univ.OctetString): return value elif isinstance(value, bytes): try: - return value.decode(self._encoding) + return value.decode(self.encoding) except UnicodeDecodeError: raise error.PyAsn1Error( - 'Can\'t decode string \'%s\' with \'%s\' codec' % (value, self._encoding) + 'Can\'t decode string \'%s\' with \'%s\' codec' % (value, self.encoding) ) elif isinstance(value, (tuple, list)): return self.prettyIn(bytes(value)) @@ -134,8 +134,7 @@ class AbstractCharacterString(univ.OctetString): def __reversed__(self): return reversed(self._value) - def clone(self, value=noValue, tagSet=None, subtypeSpec=None, - encoding=None, binValue=noValue, hexValue=noValue): + def clone(self, value=noValue, **kwargs): """Creates a copy of a |ASN.1| type or object. Any parameters to the *clone()* method will replace corresponding @@ -165,10 +164,9 @@ class AbstractCharacterString(univ.OctetString): new instance of |ASN.1| type/value """ - return univ.OctetString.clone(self, value, tagSet, subtypeSpec, encoding, binValue, hexValue) + return univ.OctetString.clone(self, value, **kwargs) - def subtype(self, value=noValue, implicitTag=None, explicitTag=None, - subtypeSpec=None, encoding=None, binValue=noValue, hexValue=noValue): + def subtype(self, value=noValue, **kwargs): """Creates a copy of a |ASN.1| type or object. Any parameters to the *subtype()* method will be added to the corresponding @@ -205,8 +203,7 @@ class AbstractCharacterString(univ.OctetString): new instance of |ASN.1| type/value """ - return univ.OctetString.subtype(self, value, implicitTag, explicitTag, subtypeSpec, encoding, binValue, hexValue) - + return univ.OctetString.subtype(self, value, **kwargs) class NumericString(AbstractCharacterString): __doc__ = AbstractCharacterString.__doc__ diff --git a/pyasn1/type/univ.py b/pyasn1/type/univ.py index 298869b..038744e 100644 --- a/pyasn1/type/univ.py +++ b/pyasn1/type/univ.py @@ -64,14 +64,11 @@ class Integer(base.AbstractSimpleAsn1Item): # Optimization for faster codec lookup typeId = base.AbstractSimpleAsn1Item.getTypeId() - def __init__(self, value=noValue, tagSet=None, subtypeSpec=None, - namedValues=None): - if namedValues is not None: - self.namedValues = namedValues - base.AbstractSimpleAsn1Item.__init__( - self, value, tagSet, subtypeSpec - ) - self.readOnly = 'namedValues' + def __init__(self, value=noValue, **kwargs): + if 'namedValues' not in kwargs: + kwargs['namedValues'] = self.namedValues + + base.AbstractSimpleAsn1Item.__init__(self, value, **kwargs) def __repr__(self): if self.namedValues is not self.__class__.namedValues: @@ -245,7 +242,7 @@ class Integer(base.AbstractSimpleAsn1Item): except KeyError: return str(value) - def clone(self, value=noValue, tagSet=None, subtypeSpec=None, namedValues=None): + def clone(self, value=noValue, **kwargs): """Create a copy of a |ASN.1| type or object. Any parameters to the *clone()* method will replace corresponding @@ -271,32 +268,9 @@ class Integer(base.AbstractSimpleAsn1Item): : new instance of |ASN.1| type/value """ - isModified = False - - if value is None or value is noValue: - value = self._value - else: - isModified = True - if tagSet is None or tagSet is noValue: - tagSet = self.tagSet - else: - isModified = True - if subtypeSpec is None or subtypeSpec is noValue: - subtypeSpec = self.subtypeSpec - else: - isModified = True - if namedValues is None or namedValues is noValue: - namedValues = self.namedValues - else: - isModified = True - - if isModified: - return self.__class__(value, tagSet, subtypeSpec, namedValues) - else: - return self + return base.AbstractSimpleAsn1Item.clone(self, value, **kwargs) - def subtype(self, value=noValue, implicitTag=None, explicitTag=None, - subtypeSpec=None, namedValues=None): + def subtype(self, value=noValue, **kwargs): """Create a copy of a |ASN.1| type or object. Any parameters to the *subtype()* method will be added to the corresponding @@ -332,35 +306,7 @@ class Integer(base.AbstractSimpleAsn1Item): : new instance of |ASN.1| type/value """ - isModified = False - - if value is None or value is noValue: - value = self._value - else: - isModified = True - if implicitTag is not None and implicitTag is not noValue: - tagSet = self.tagSet.tagImplicitly(implicitTag) - isModified = True - elif explicitTag is not None and explicitTag is not noValue: - tagSet = self.tagSet.tagExplicitly(explicitTag) - isModified = True - else: - tagSet = self.tagSet - if subtypeSpec is None or subtypeSpec is noValue: - subtypeSpec = self.subtypeSpec - else: - subtypeSpec += self.subtypeSpec - isModified = True - if namedValues is None or namedValues is noValue: - namedValues = self.namedValues - else: - namedValues += self.namedValues - isModified = True - - if isModified: - return self.__class__(value, tagSet, subtypeSpec, namedValues) - else: - return self + return base.AbstractSimpleAsn1Item.subtype(self, value, **kwargs) # backward compatibility @@ -465,24 +411,34 @@ class BitString(base.AbstractSimpleAsn1Item): return self.bitLength - def __init__(self, value=noValue, tagSet=None, subtypeSpec=None, - namedValues=None, binValue=noValue, hexValue=noValue): - if namedValues is not None: - self.namedValues = namedValues - if binValue is not noValue: - value = self.fromBinaryString(binValue) - elif hexValue is not noValue: - value = self.fromHexString(hexValue) - elif value is None or value is noValue: + def __init__(self, value=noValue, **kwargs): + if value is noValue or value is None: + if kwargs: + try: + value = self.fromBinaryString(kwargs.pop('binValue')) + + except KeyError: + pass + + try: + value = self.fromHexString(kwargs.pop('hexValue')) + + except KeyError: + pass + + if value is noValue or value is None: if self.defaultBinValue is not noValue: value = self.fromBinaryString(self.defaultBinValue) + elif self.defaultHexValue is not noValue: value = self.fromHexString(self.defaultHexValue) - base.AbstractSimpleAsn1Item.__init__(self, value, tagSet, subtypeSpec) - self._readOnly.add('namedValues') - def clone(self, value=noValue, tagSet=None, subtypeSpec=None, - namedValues=None, binValue=noValue, hexValue=noValue): + if 'namedValues' not in kwargs: + kwargs['namedValues'] = self.namedValues + + base.AbstractSimpleAsn1Item.__init__(self, value, **kwargs) + + def clone(self, value=noValue, **kwargs): """Create a copy of a |ASN.1| type or object. Any parameters to the *clone()* method will replace corresponding @@ -516,32 +472,9 @@ class BitString(base.AbstractSimpleAsn1Item): : new instance of |ASN.1| type/value """ - isModified = False - - if (value is None or value is noValue) and binValue is noValue and hexValue is noValue: - value = self._value - else: - isModified = True - if tagSet is None or tagSet is noValue: - tagSet = self.tagSet - else: - isModified = True - if subtypeSpec is None or subtypeSpec is noValue: - subtypeSpec = self.subtypeSpec - else: - isModified = True - if namedValues is None or namedValues is noValue: - namedValues = self.namedValues - else: - isModified = True + return base.AbstractSimpleAsn1Item.clone(self, value, **kwargs) - if isModified: - return self.__class__(value, tagSet, subtypeSpec, namedValues, binValue, hexValue) - else: - return self - - def subtype(self, value=noValue, implicitTag=None, explicitTag=None, - subtypeSpec=None, namedValues=None, binValue=noValue, hexValue=noValue): + def subtype(self, value=noValue, **kwargs): """Create a copy of a |ASN.1| type or object. Any parameters to the *subtype()* method will be added to the corresponding @@ -585,35 +518,7 @@ class BitString(base.AbstractSimpleAsn1Item): : new instance of |ASN.1| type/value """ - isModified = False - - if (value is None or value is noValue) and binValue is noValue and hexValue is noValue: - value = self._value - else: - isModified = True - if implicitTag is not None and implicitTag is not noValue: - tagSet = self.tagSet.tagImplicitly(implicitTag) - isModified = True - elif explicitTag is not None and explicitTag is not noValue: - tagSet = self.tagSet.tagExplicitly(explicitTag) - isModified = True - else: - tagSet = self.tagSet - if subtypeSpec is None or subtypeSpec is noValue: - subtypeSpec = self.subtypeSpec - else: - subtypeSpec += self.subtypeSpec - isModified = True - if namedValues is None or namedValues is noValue: - namedValues = self.namedValues - else: - namedValues += self.namedValues - isModified = True - - if isModified: - return self.__class__(value, tagSet, subtypeSpec, namedValues, binValue, hexValue) - else: - return self + return base.AbstractSimpleAsn1Item.subtype(self, value, **kwargs) def __str__(self): return self.asBinary() @@ -877,26 +782,36 @@ class OctetString(base.AbstractSimpleAsn1Item): defaultBinValue = defaultHexValue = noValue encoding = 'iso-8859-1' - def __init__(self, value=noValue, tagSet=None, subtypeSpec=None, - encoding=None, binValue=noValue, hexValue=noValue): - if encoding is None: - self._encoding = self.encoding - else: - self._encoding = encoding - if binValue is not noValue: - value = self.fromBinaryString(binValue) - elif hexValue is not noValue: - value = self.fromHexString(hexValue) - elif value is None or value is noValue: + def __init__(self, value=noValue, **kwargs): + if kwargs: + if value is noValue or value is None: + try: + value = self.fromBinaryString(kwargs.pop('binValue')) + + except KeyError: + pass + + try: + value = self.fromHexString(kwargs.pop('hexValue')) + + except KeyError: + pass + + if value is noValue or value is None: if self.defaultBinValue is not noValue: value = self.fromBinaryString(self.defaultBinValue) + elif self.defaultHexValue is not noValue: value = self.fromHexString(self.defaultHexValue) + + if 'encoding' not in kwargs: + kwargs['encoding'] = self.encoding + self.__asNumbersCache = None - base.AbstractSimpleAsn1Item.__init__(self, value, tagSet, subtypeSpec) - def clone(self, value=noValue, tagSet=None, subtypeSpec=None, - encoding=None, binValue=noValue, hexValue=noValue): + base.AbstractSimpleAsn1Item.__init__(self, value, **kwargs) + + def clone(self, value=noValue, **kwargs): """Create a copy of a |ASN.1| type or object. Any parameters to the *clone()* method will replace corresponding @@ -930,33 +845,9 @@ class OctetString(base.AbstractSimpleAsn1Item): : new instance of |ASN.1| type/value """ - isModified = False + return base.AbstractSimpleAsn1Item.clone(self, value, **kwargs) - if (value is None or value is noValue) and binValue is noValue and hexValue is noValue: - value = self._value - else: - isModified = True - if tagSet is None or tagSet is noValue: - tagSet = self.tagSet - else: - isModified = True - if subtypeSpec is None or subtypeSpec is noValue: - subtypeSpec = self.subtypeSpec - else: - isModified = True - if encoding is None or encoding is noValue: - encoding = self._encoding - else: - isModified = True - - if isModified: - return self.__class__(value, tagSet, subtypeSpec, encoding, binValue, hexValue) - else: - return self - - def subtype(self, value=noValue, implicitTag=None, explicitTag=None, - subtypeSpec=None, encoding=None, binValue=noValue, - hexValue=noValue): + def subtype(self, value=noValue, **kwargs): """Create a copy of a |ASN.1| type or object. Any parameters to the *subtype()* method will be added to the corresponding @@ -998,34 +889,7 @@ class OctetString(base.AbstractSimpleAsn1Item): : new instance of |ASN.1| type/value """ - isModified = False - - if (value is None or value is noValue) and binValue is noValue and hexValue is noValue: - value = self._value - else: - isModified = True - if implicitTag is not None and implicitTag is not noValue: - tagSet = self.tagSet.tagImplicitly(implicitTag) - isModified = True - elif explicitTag is not None and explicitTag is not noValue: - tagSet = self.tagSet.tagExplicitly(explicitTag) - isModified = True - else: - tagSet = self.tagSet - if subtypeSpec is None or subtypeSpec is noValue: - subtypeSpec = self.subtypeSpec - else: - subtypeSpec += self.subtypeSpec - isModified = True - if encoding is None or encoding is noValue: - encoding = self._encoding - else: - isModified = True - - if isModified: - return self.__class__(value, tagSet, subtypeSpec, encoding, binValue, hexValue) - else: - return self + return base.AbstractSimpleAsn1Item.subtype(self, value, **kwargs) if sys.version_info[0] <= 2: def prettyIn(self, value): @@ -1033,10 +897,10 @@ class OctetString(base.AbstractSimpleAsn1Item): return value elif isinstance(value, unicode): try: - return value.encode(self._encoding) + return value.encode(self.encoding) except (LookupError, UnicodeEncodeError): raise error.PyAsn1Error( - 'Can\'t encode string \'%s\' with \'%s\' codec' % (value, self._encoding) + 'Can\'t encode string \'%s\' with \'%s\' codec' % (value, self.encoding) ) elif isinstance(value, (tuple, list)): try: @@ -1053,11 +917,11 @@ class OctetString(base.AbstractSimpleAsn1Item): def __unicode__(self): try: - return self._value.decode(self._encoding) + return self._value.decode(self.encoding) except UnicodeDecodeError: raise error.PyAsn1Error( - 'Can\'t decode string \'%s\' with \'%s\' codec' % (self._value, self._encoding) + 'Can\'t decode string \'%s\' with \'%s\' codec' % (self._value, self.encoding) ) def asOctets(self): @@ -1074,10 +938,10 @@ class OctetString(base.AbstractSimpleAsn1Item): return value elif isinstance(value, str): try: - return value.encode(self._encoding) + return value.encode(self.encoding) except UnicodeEncodeError: raise error.PyAsn1Error( - 'Can\'t encode string \'%s\' with \'%s\' codec' % (value, self._encoding) + 'Can\'t encode string \'%s\' with \'%s\' codec' % (value, self.encoding) ) elif isinstance(value, OctetString): # a shortcut, bytes() would work the same way return value.asOctets() @@ -1090,11 +954,11 @@ class OctetString(base.AbstractSimpleAsn1Item): def __str__(self): try: - return self._value.decode(self._encoding) + return self._value.decode(self.encoding) except UnicodeDecodeError: raise error.PyAsn1Error( - 'Can\'t decode string \'%s\' with \'%s\' codec at \'%s\'' % (self._value, self._encoding, self.__class__.__name__) + 'Can\'t decode string \'%s\' with \'%s\' codec at \'%s\'' % (self._value, self.encoding, self.__class__.__name__) ) def __bytes__(self): @@ -1118,12 +982,12 @@ class OctetString(base.AbstractSimpleAsn1Item): return octets.octs2str('0x') + ''.join(('%.2x' % x for x in numbers)) else: try: - return value.decode(self._encoding) + return value.decode(self.encoding) except UnicodeDecodeError: raise error.PyAsn1Error( 'Can\'t decode string \'%s\' with \'%s\' codec at \'%s\'' % ( - value, self._encoding, self.__class__.__name__) + value, self.encoding, self.__class__.__name__) ) @staticmethod @@ -1179,8 +1043,8 @@ class OctetString(base.AbstractSimpleAsn1Item): r.append('tagSet=%r' % (self.tagSet,)) if self.subtypeSpec is not self.__class__.subtypeSpec: r.append('subtypeSpec=%r' % (self.subtypeSpec,)) - if self.encoding is not self._encoding: - r.append('encoding=%r' % (self._encoding,)) + if self.encoding is not self.__class__.encoding: + r.append('encoding=%r' % (self.encoding,)) if doHex: r.append('hexValue=%r' % ''.join(['%.2x' % x for x in self.asNumbers()])) return '%s(%s)' % (self.__class__.__name__, ', '.join(r)) @@ -1257,7 +1121,7 @@ class Null(OctetString): # Optimization for faster codec lookup typeId = OctetString.getTypeId() - def clone(self, value=noValue, tagSet=None): + def clone(self, value=noValue, **kwargs): """Create a copy of a |ASN.1| type or object. Any parameters to the *clone()* method will replace corresponding @@ -1277,9 +1141,9 @@ class Null(OctetString): : :py:class:`~pyasn1.type.univ.Null` new instance of NULL type/value """ - return OctetString.clone(self, value, tagSet) + return OctetString.clone(self, value, **kwargs) - def subtype(self, value=noValue, implicitTag=None, explicitTag=None): + def subtype(self, value=noValue, **kwargs): """Create a copy of a |ASN.1| type or object. Any parameters to the *subtype()* method will be added to the corresponding @@ -1306,7 +1170,7 @@ class Null(OctetString): : :py:class:`~pyasn1.type.univ.Null` new instance of NULL type/value """ - return OctetString.subtype(self, value, implicitTag, explicitTag) + return OctetString.subtype(self, value, **kwargs) if sys.version_info[0] <= 2: @@ -1493,7 +1357,7 @@ class Real(base.AbstractSimpleAsn1Item): # Optimization for faster codec lookup typeId = base.AbstractSimpleAsn1Item.getTypeId() - def clone(self, value=noValue, tagSet=None, subtypeSpec=None): + def clone(self, value=noValue, **kwargs): """Create a copy of a |ASN.1| type or object. Any parameters to the *clone()* method will replace corresponding @@ -1516,10 +1380,9 @@ class Real(base.AbstractSimpleAsn1Item): : new instance of |ASN.1| type/value """ - return base.AbstractSimpleAsn1Item.clone(self, value, tagSet, subtypeSpec) + return base.AbstractSimpleAsn1Item.clone(self, value, **kwargs) - def subtype(self, value=noValue, implicitTag=None, explicitTag=None, - subtypeSpec=None): + def subtype(self, value=noValue, **kwargs): """Create a copy of a |ASN.1| type or object. Any parameters to the *subtype()* method will be added to the corresponding @@ -1549,7 +1412,7 @@ class Real(base.AbstractSimpleAsn1Item): : new instance of |ASN.1| type/value """ - return base.AbstractSimpleAsn1Item.subtype(self, value, implicitTag, explicitTag) + return base.AbstractSimpleAsn1Item.subtype(self, value, **kwargs) @staticmethod def __normalizeBase10(value): @@ -1821,8 +1684,6 @@ class SequenceOfAndSetOfBase(base.AbstractConstructedAsn1Item): Object representing collection size constraint """ - componentType = None - # Python list protocol def clear(self): @@ -1935,7 +1796,7 @@ class SequenceOfAndSetOfBase(base.AbstractConstructedAsn1Item): if len(self._componentValues) < idx: raise error.PyAsn1Error('Component index out of range') - if value is None or value is noValue: + if value is noValue or value is None: if componentType is not None: value = componentType.clone() elif currentValue is None: @@ -2099,11 +1960,8 @@ class SequenceAndSetBase(base.AbstractConstructedAsn1Item): #: object representing named ASN.1 types allowed within |ASN.1| type componentType = namedtype.NamedTypes() - def __init__(self, componentType=None, tagSet=None, - subtypeSpec=None, sizeSpec=None): - base.AbstractConstructedAsn1Item.__init__( - self, componentType, tagSet, subtypeSpec, sizeSpec - ) + def __init__(self, **kwargs): + base.AbstractConstructedAsn1Item.__init__(self, **kwargs) self._componentTypeLen = len(self.componentType) def __getitem__(self, idx): -- cgit v1.2.3