Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cid/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
CIDJSONEncoder,
CIDv0,
CIDv1,
Undef,
extract_encoding,
from_bytes,
from_bytes_strict,
Expand Down
33 changes: 33 additions & 0 deletions cid/cid.py
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,39 @@ def prefix(self) -> "Prefix":
)


class _UndefCID:
"""Sentinel for undefined/nil CID (go-cid ``Undef``)."""

_instance: "_UndefCID | None" = None

def __new__(cls) -> "_UndefCID":
if cls._instance is None:
cls._instance = cast("_UndefCID", super().__new__(cls))
return cls._instance

def defined(self) -> bool:
"""Return False; an undefined CID is never defined."""
return False

def __bool__(self) -> bool:
return False

def __repr__(self) -> str:
return "CID.Undef"

def __str__(self) -> str:
return "CID.Undef"

def __eq__(self, other: object) -> bool:
return isinstance(other, _UndefCID)

def __hash__(self) -> int:
return hash(_UndefCID)


Undef = _UndefCID()


class CIDv0(BaseCID):
"""CID version 0 object"""

Expand Down
8 changes: 7 additions & 1 deletion docs/usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,7 @@ Defined Check

.. code-block:: python

>>> from cid import CIDv0
>>> from cid import CIDv0, Undef
>>> import multihash
>>> import hashlib
>>>
Expand All @@ -363,6 +363,12 @@ Defined Check
>>> cid = CIDv0(mhash)
>>> cid.defined()
True
>>>
>>> # Undef is a sentinel for an undefined/nil CID (like go-cid Undef)
>>> Undef.defined()
False
>>> bool(Undef)
False

Stream Parsing
--------------
Expand Down
1 change: 1 addition & 0 deletions newsfragments/68.feature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add ``Undef`` sentinel for representing undefined/nil CIDs, matching go-cid ``Undef``.
33 changes: 33 additions & 0 deletions tests/test_new_features.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
CIDSet,
CIDv0,
CIDv1,
Undef,
V0Builder,
V1Builder,
extract_encoding,
Expand All @@ -19,6 +20,7 @@
must_parse,
parse_ipfs_path,
)
from cid.cid import _UndefCID


@pytest.fixture
Expand Down Expand Up @@ -321,6 +323,37 @@ def test_defined_cidv1(self, cidv1):
assert cidv1.defined() is True


class TestUndef:
"""Tests for Undef sentinel"""

def test_undef_defined_is_false(self):
assert Undef.defined() is False

def test_undef_bool_is_false(self):
assert bool(Undef) is False

def test_undef_repr_and_str(self):
assert repr(Undef) == "CID.Undef"
assert str(Undef) == "CID.Undef"

def test_undef_is_singleton(self):
assert Undef is Undef
assert _UndefCID() is Undef

def test_undef_equality(self, cidv0):
assert Undef == Undef
assert Undef == _UndefCID()
assert Undef != cidv0

def test_undef_hashable(self):
assert Undef in {Undef}
mapping = {Undef: "unset"}
assert mapping[Undef] == "unset"

def test_undef_not_cid_instance(self):
assert not isinstance(Undef, (CIDv0, CIDv1))


class TestFromReader:
"""Tests for from_reader function"""

Expand Down
Loading