Skip to content

Commit

Permalink
refactor eliminate version parameter for supported version since supp…
Browse files Browse the repository at this point in the history
…orted versions better determined by

entries in Serder.Fields table.
  • Loading branch information
SmithSamuelM committed Mar 24, 2024
1 parent cbc9dbf commit 75f7024
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 75 deletions.
74 changes: 30 additions & 44 deletions src/keri/core/serdering.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,17 +120,16 @@ class Serdery:
"""

def __init__(self, *, version=None):
def __init__(self, *pa, **kwa):
"""Init instance
Parameters:
version (Versionage | None): instance supported protocol version
None means do not enforce a supported version
"""
self.version = version # default version
pass


def reap(self, ims, *, version=None):
def reap(self, ims):
"""Extract and return Serder subclass based on protocol type reaped from
version string inside serialized raw of Serder.
Expand All @@ -144,14 +143,14 @@ def reap(self, ims, *, version=None):
version (Versionage | None): instance supported protocol version
None means do not enforce a supported version
"""
version = version if version is not None else self.version
#version = version if version is not None else self.version

smellage = smell(ims, version=version)
smellage = smell(ims)

if smellage.protocol == Protos.keri:
return SerderKERI(raw=ims, strip=True, version=version, smellage=smellage)
return SerderKERI(raw=ims, strip=True, smellage=smellage)
elif smellage.protocol == Protos.acdc:
return SerderACDC(raw=ims, strip=True, version=version, smellage=smellage)
return SerderACDC(raw=ims, strip=True, smellage=smellage)
else:
raise ProtocolError(f"Unsupported protocol type = {smellage.proto}.")

Expand Down Expand Up @@ -189,8 +188,8 @@ class Serder:
Digests (dict): map of digestive codes. Should be same set of codes as
in coring.DigestCodex coring.DigDex so that .digestive property works.
Use unit tests to ensure codex sets match
Protocol (str): default protocol version type
Proto (str): default CESR protocol genus type
Protocol (str): class specific message protocol
Proto (str): default message protocol
Vrsn (Versionage): default version
Kind (str): default serialization kind one of Serials
Fields (dict): nested dict of field labels keyed by protocol, version,
Expand Down Expand Up @@ -270,9 +269,8 @@ class Serder:
}

#override in subclass to enforce specific protocol
Protocol = None # required protocol, None means any in Protos is ok

Proto = Protos.keri # default CESR protocol type for makify on base Serder
Protocol = None # class based message protocol, None means any in Protos is ok
Proto = Protos.keri # default message protocol type for makify on base Serder
Vrsn = Vrsn_1_0 # default protocol version for protocol type
Kind = Serials.json # default serialization kind

Expand Down Expand Up @@ -441,7 +439,7 @@ class Serder:
}


def __init__(self, *, raw=b'', sad=None, strip=False, version=Version,
def __init__(self, *, raw=b'', sad=None, strip=False,
smellage=None, verify=True, makify=False,
proto=None, vrsn=None, kind=None, ilk=None, saids=None):
"""Deserialize raw if provided. Update properties from deserialized raw.
Expand All @@ -460,8 +458,6 @@ def __init__(self, *, raw=b'', sad=None, strip=False, version=Version,
strip (bool): True means strip (delete) raw from input stream
bytearray after parsing. False means do not strip.
Assumes that raw is bytearray when strip is True.
version (Versionage | None): instance supported protocol version
None means do not enforce a supported version
smellage (Smellage | None): instance of deconstructed and converted
version string elements. If none or empty ignore otherwise assume
that raw already had its version string extracted (reaped) into the
Expand Down Expand Up @@ -493,9 +489,7 @@ def __init__(self, *, raw=b'', sad=None, strip=False, version=Version,

if raw: # deserialize raw using property setter
# self._inhale works because it only references class attributes
sad, proto, vrsn, kind, size = self._inhale(raw=raw,
version=version,
smellage=smellage)
sad, proto, vrsn, kind, size = self._inhale(raw=raw, smellage=smellage)
self._raw = bytes(raw[:size]) # crypto ops require bytes not bytearray
self._sad = sad
self._proto = proto
Expand Down Expand Up @@ -528,14 +522,13 @@ def __init__(self, *, raw=b'', sad=None, strip=False, version=Version,

elif sad or makify: # serialize sad into raw or make sad
if makify: # recompute properties and said(s) and reset sad
# makify resets sad, raw, proto, version, kind, and size
self.makify(sad=sad, version=version,
proto=proto, vrsn=vrsn, kind=kind, ilk=ilk, saids=saids)
# makify resets sad, raw, proto, vrsn, kind, ilk, and size
self.makify(sad=sad, proto=proto, vrsn=vrsn, kind=kind,
ilk=ilk, saids=saids)

else:
# self._exhale works because it only access class attributes
raw, sad, proto, vrsn, kind, size = self._exhale(sad=sad,
version=version)
raw, sad, proto, vrsn, kind, size = self._exhale(sad=sad)
self._raw = raw
self._sad = sad
self._proto = proto
Expand Down Expand Up @@ -680,8 +673,7 @@ def _verify(self):
# verified successfully since no exception


def makify(self, sad, *, version=None,
proto=None, vrsn=None, kind=None, ilk=None, saids=None):
def makify(self, sad, *, proto=None, vrsn=None, kind=None, ilk=None, saids=None):
"""Makify given sad dict makes the versions string and computes the said
field values and sets associated properties:
raw, sad, proto, version, kind, size
Expand All @@ -699,8 +691,6 @@ def makify(self, sad, *, version=None,
Parameters:
sad (dict): serializable saidified field map of message.
Ignored if raw provided
version (Versionage): instance supported protocol version
None means do not enforce version
proto (str | None): desired protocol type str value of Protos
If None then its extracted from sad or uses default .Proto
vrsn (Versionage | None): instance desired protocol version
Expand All @@ -721,7 +711,7 @@ def makify(self, sad, *, version=None,
sproto = svrsn = skind = silk = None
if sad and 'v' in sad: # attempt to get from vs in sad
try: # extract version string elements as defaults if provided
sproto, svrsn, skind, _ = deversify(sad["v"], version=version)
sproto, svrsn, skind, _ = deversify(sad["v"])
except ValueError as ex:
pass
else:
Expand Down Expand Up @@ -750,11 +740,11 @@ def makify(self, sad, *, version=None,
raise SerializeError(f"Expected protocol = {self.Protocol}, got "
f"{proto} instead.")

if version is not None: # compatible version with vrsn
if (vrsn.major > version.major or
(vrsn.major == version.major and vrsn.minor > version.minor)):
raise SerializeError(f"Incompatible {version=}, with "
f"{vrsn=}.")
#if version is not None: # compatible version with vrsn
#if (vrsn.major > version.major or
#(vrsn.major == version.major and vrsn.minor > version.minor)):
#raise SerializeError(f"Incompatible {version=}, with "
#f"{vrsn=}.")


if kind not in Serials:
Expand Down Expand Up @@ -895,7 +885,7 @@ def makify(self, sad, *, version=None,


@classmethod
def _inhale(clas, raw, version=Version, smellage=None):
def _inhale(clas, raw, *, smellage=None):
"""Deserializes raw.
Parses serilized event ser of serialization kind and assigns to
instance attributes and returns tuple of associated elements.
Expand All @@ -914,7 +904,6 @@ def _inhale(clas, raw, version=Version, smellage=None):
Parameters:
clas (Serder): class reference
raw (bytes): serialized sad message
version (Versionage): instance supported protocol version
smellage (Smellage | None): instance of deconstructed version string
elements. If none or empty ignore otherwise assume that raw
already had its version string extracted (reaped) into the
Expand All @@ -928,7 +917,7 @@ def _inhale(clas, raw, version=Version, smellage=None):
if smellage: # passed in so don't need to smell raw again
proto, vrsn, kind, size = smellage # tuple unpack
else: # not passed in so smell raw
proto, vrsn, kind, size = smell(raw, version=version)
proto, vrsn, kind, size = smell(raw)

sad = clas.loads(raw=raw, size=size, kind=kind)

Expand Down Expand Up @@ -996,9 +985,8 @@ def _loads(clas, raw, size=None):


@classmethod
def _exhale(clas, sad, version=None):
"""Serializes sad given kind and version and sets the serialized size
in the version string.
def _exhale(clas, sad):
"""Serializes sad and sets the serialized size in its version string.
As classmethod enables bootstrap of valid sad dict that has correct size
in version string. This obviates sizeify. This can be called on self as
Expand All @@ -1014,16 +1002,14 @@ def _exhale(clas, sad, version=None):
Parameters:
clas (Serder): class reference
sad (dict): serializable attribute dict of saidified data
version (Versionage | None): supported protocol version for message
None means do not enforce a supported version
"""
if "v" not in sad:
raise SerializeError(f"Missing version string field in {sad}.")

# extract elements so can replace size element but keep others
proto, vrsn, kind, size = deversify(sad["v"], version=version)
proto, vrsn, kind, size = deversify(sad["v"])

raw = clas.dumps(sad, kind)
size = len(raw)
Expand Down
38 changes: 17 additions & 21 deletions src/keri/kering.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,16 +66,15 @@
"""
Smellage = namedtuple("Smellage", "protocol version kind size")

def rematch(match, *, version=None):
def rematch(match):
"""
Returns:
smellage (Smellage): named tuple extracted from version string regex match
(protocol, version, kind, size)
Parameters:
match (re.Match): instance of Match class
version (Versionage | None): supported version. None means do not check
for supported version. namedtuple (major, minor)
"""
full = match.group() # full matched version string
Expand All @@ -91,11 +90,11 @@ def rematch(match, *, version=None):
vrsn = Versionage(major=b64ToInt(major), minor=b64ToInt(minor))
if vrsn.major < 2: # version2 vs but major < 2
raise VersionError(f"Incompatible {vrsn=} with version string.")
if version is not None: # compatible version with vrsn
if (vrsn.major > version.major or
(vrsn.major == version.major and vrsn.minor > version.minor)):
raise VersionError(f"Incompatible {version=}, with "
f"{vrsn=}.")
#if version is not None: # compatible version with vrsn
#if (vrsn.major > version.major or
#(vrsn.major == version.major and vrsn.minor > version.minor)):
#raise VersionError(f"Incompatible {version=}, with "
#f"{vrsn=}.")

kind = kind.decode("utf-8")
if kind not in Serials:
Expand All @@ -114,11 +113,11 @@ def rematch(match, *, version=None):
vrsn = Versionage(major=int(major, 16), minor=int(minor, 16))
if vrsn.major > 1: # version1 vs but major > 1
raise VersionError(f"Incompatible {vrsn=} with version string.")
if version is not None: # compatible version with vrsn
if (vrsn.major > version.major or
(vrsn.major == version.major and vrsn.minor > version.minor)):
raise VersionError(f"Incompatible {version=}, with "
f"{vrsn=}.")
#if version is not None: # compatible version with vrsn
#if (vrsn.major > version.major or
#(vrsn.major == version.major and vrsn.minor > version.minor)):
#raise VersionError(f"Incompatible {version=}, with "
#f"{vrsn=}.")

kind = kind.decode("utf-8")
if kind not in Serials:
Expand Down Expand Up @@ -153,7 +152,7 @@ def versify(protocol=Protos.keri, version=Version, kind=Serials.json, size=0):



def deversify(vs, version=None):
def deversify(vs):
"""
Returns: tuple(proto, kind, version, size) Where:
proto (str): value is protocol type identifier one of Protos (Protocolage)
Expand All @@ -166,8 +165,6 @@ def deversify(vs, version=None):
Parameters:
vs (str | bytes): version string to extract from
version (Versionage | None): supported version. None means do not check
for supported version. namedtuple of ints (major, minor)
Uses regex match to extract:
protocol type
Expand All @@ -182,12 +179,12 @@ def deversify(vs, version=None):
if not match:
raise VersionError(f"Invalid version string = '{vs}'.")

return rematch(match, version=version)
return rematch(match)




def smell(raw, *, version=None):
def smell(raw):
"""Extract and return instance of Smellage from version string inside
raw serialization.
Expand All @@ -198,8 +195,7 @@ def smell(raw, *, version=None):
raw (bytearray) of serialized incoming message stream. Assumes start
of stream is JSON, CBOR, or MGPK field map with first field
is labeled 'v' and value is version string.
version (Versionage | None): instance supported protocol version
None means do not enforce a supported version
"""
if len(raw) < SMELLSIZE:
raise ShortageError(f"Need more raw bytes to smell full version string.")
Expand All @@ -209,7 +205,7 @@ def smell(raw, *, version=None):
raise VersionError(f"Invalid version string from smelled raw = "
f"{raw[: SMELLSIZE]}.")

return rematch(match, version=version)
return rematch(match)



Expand Down
19 changes: 9 additions & 10 deletions tests/core/test_serdering.py
Original file line number Diff line number Diff line change
Expand Up @@ -2487,31 +2487,31 @@ def test_serder_v2():


with pytest.raises(ValueError):
serder = Serder(version=kering.Vrsn_2_0)
serder = Serder()

#Test Serder bare makify bootstrap for ACDC JSON
serder = Serder(makify=True,
proto=kering.Protos.acdc,
vrsn=kering.Vrsn_2_0,
version=kering.Vrsn_2_0) # make defaults for ACDC
vrsn=kering.Vrsn_2_0) # make defaults for ACDC
assert serder.sad == {'v': 'ACDCCAAJSONAABZ.',
'd': 'EN-uBXL6rsJpJvDSsyOAnttQiI9gka4qLbe3MlIoYwYy',
'i': '',
's': ''}
assert serder.raw == (b'{"v":"ACDCCAAJSONAABZ.","d":"EN-uBXL6rsJpJvDSsyOAnttQiI9gka4qLbe3MlIoYwYy","'
b'i":"","s":""}')
assert serder.verify()
assert serder.vrsn == serder.version == kering.Vrsn_2_0
sad = serder.sad
raw = serder.raw
said = serder.said
size = serder.size

serder = Serder(sad=sad, version=kering.Vrsn_2_0)
serder = Serder(sad=sad)
assert serder.raw == raw
assert isinstance(serder.raw, bytes)
assert serder.sad == sad
assert serder.proto == kering.Protos.acdc
assert serder.vrsn == kering.Vrsn_2_0
assert serder.vrsn == kering.Vrsn_2_0 == serder.version
assert serder.size == size
assert serder.kind == kering.Serials.json
assert serder.said == said
Expand All @@ -2527,12 +2527,12 @@ def test_serder_v2():
' "s": ""\n'
'}')

serder = Serder(raw=raw, version=kering.Vrsn_2_0)
serder = Serder(raw=raw)
assert serder.raw == raw
assert isinstance(serder.raw, bytes)
assert serder.sad == sad
assert serder.proto == kering.Protos.acdc
assert serder.vrsn == kering.Vrsn_2_0
assert serder.vrsn == kering.Vrsn_2_0 == serder.version
assert serder.size == size
assert serder.kind == kering.Serials.json
assert serder.said == said
Expand All @@ -2541,7 +2541,7 @@ def test_serder_v2():
assert serder.compare(said=said)
assert serder.compare(said=said.encode("utf-8"))

serder = Serder(sad=sad, makify=True, version=kering.Vrsn_2_0) # test makify with sad
serder = Serder(sad=sad, makify=True) # test makify with sad
assert serder.raw == raw
assert isinstance(serder.raw, bytes)
assert serder.sad == sad
Expand All @@ -2556,8 +2556,7 @@ def test_serder_v2():

# test default
serder = Serder(makify=True,
vrsn=kering.Vrsn_2_0,
version=kering.Vrsn_2_0) # make defaults for default proto
vrsn=kering.Vrsn_2_0) # make defaults for default proto


assert serder.sad == {'v': 'KERICAAJSONAADO.',
Expand Down

0 comments on commit 75f7024

Please sign in to comment.