Skip to content

Commit

Permalink
Add libipld v2.0.0 support (#315)
Browse files Browse the repository at this point in the history
  • Loading branch information
MarshalX authored Sep 9, 2024
1 parent 5b158f5 commit 2b6b85e
Show file tree
Hide file tree
Showing 6 changed files with 396 additions and 277 deletions.
6 changes: 3 additions & 3 deletions packages/atproto_client/models/blob_ref.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@ class BlobRef(BaseModel):

mime_type: str = Field(alias='mimeType') #: Mime type.
size: int #: Size in bytes.
ref: t.Union[str, IpldLink] #: CID.
ref: t.Union[str, bytes, IpldLink] #: CID.

py_type: te.Literal['blob'] = Field(default='blob', alias='$type')

@property
def cid(self) -> 'CID':
"""Get CID."""
if isinstance(self.ref, str):
if self.is_bytes_representation:
return CID.decode(self.ref)

return CID.decode(self.ref.link)
Expand All @@ -48,7 +48,7 @@ def is_bytes_representation(self) -> bool:
Returns:
True if it is bytes representation.
"""
return isinstance(self.ref, str)
return isinstance(self.ref, (str, bytes))

def to_json_representation(self) -> 'BlobRef':
"""Get JSON representation.
Expand Down
36 changes: 28 additions & 8 deletions packages/atproto_core/cid/cid.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,15 @@ class Multihash:

@dataclass(eq=False)
class CID:
_cid: str
version: int
codec: int
hash: Multihash

_stringified_form: t.Optional[str] = None
_raw_byte_form: t.Optional[str] = None

@classmethod
def decode(cls, value: str) -> 'CID':
def decode(cls, value: t.Union[str, bytes]) -> 'CID':
cid = libipld.decode_cid(value)

multihash = Multihash(
Expand All @@ -32,15 +34,25 @@ def decode(cls, value: str) -> 'CID':
digest=cid['hash']['digest'],
)

return cls(
_cid=value,
instance = cls(
version=cid['version'],
codec=cid['codec'],
hash=multihash,
)

if isinstance(value, str):
instance._stringified_form = value
else:
instance._raw_byte_form = value

return instance

def encode(self) -> str:
return self._cid
if self._stringified_form is not None:
return self._stringified_form

self._stringified_form = libipld.encode_cid(self._raw_byte_form)
return self._stringified_form

def __str__(self) -> str:
return self.encode()
Expand All @@ -67,19 +79,26 @@ def __get_pydantic_core_schema__(
) -> core_schema.CoreSchema:
"""We return a pydantic_core.CoreSchema that behaves in the following ways below.
* Strings will be parsed as `CID` instances
* Strings and bytes will be parsed as `CID` instances
* `CID` instances will be parsed as `CID` instances without any changes
* Nothing else will pass validation
* Serialization will always return just a str
"""

def validate_from_str(value: str) -> CID:
def validate_from_value(value: t.Union[str, bytes]) -> CID:
return CID.decode(value)

from_str_schema = core_schema.chain_schema(
[
core_schema.str_schema(),
core_schema.no_info_plain_validator_function(validate_from_str),
core_schema.no_info_plain_validator_function(validate_from_value),
]
)

from_bytes_schema = core_schema.chain_schema(
[
core_schema.bytes_schema(),
core_schema.no_info_plain_validator_function(validate_from_value),
]
)

Expand All @@ -90,6 +109,7 @@ def validate_from_str(value: str) -> CID:
# check if it's an instance first before doing any further work
core_schema.is_instance_schema(CID),
from_str_schema,
from_bytes_schema,
]
),
serialization=core_schema.plain_serializer_function_ser_schema(lambda instance: instance.encode()),
Expand Down
Loading

0 comments on commit 2b6b85e

Please sign in to comment.