diff --git a/docs/oid.rst b/docs/oid.rst index 2ad8ed4e..97de2688 100644 --- a/docs/oid.rst +++ b/docs/oid.rst @@ -56,9 +56,9 @@ The Oid type >>> raw = unhexlify("cff3ceaefc955f0dbe1957017db181bc49913781") >>> oid2 = Oid(raw=raw) -And the other way around, from an Oid object we can get the hexadecimal and raw -forms. You can use the built-in `str()` (or `unicode()` in python 2) to get the -hexadecimal representation of the Oid. +And the other way around, from an Oid object we can get the raw form via +`oid.raw`. You can use `str(oid)` to get the hexadecimal representation of the +Oid. .. method:: Oid.__str__() .. autoattribute:: pygit2.Oid.raw @@ -68,8 +68,11 @@ The Oid type supports: - rich comparisons, not just for equality, also: lesser-than, lesser-or-equal, etc. -- hashing, so Oid objects can be used as keys in a dictionary. +- `hash(oid)`, so Oid objects can be used as keys in a dictionary. +- `bool(oid)`, returning False if the Oid is a null SHA-1 (all zeros). + +- `str(oid)`, returning the hexadecimal representation of the Oid. Constants ========= diff --git a/pygit2/_pygit2.pyi b/pygit2/_pygit2.pyi index a73da2a3..4895bade 100644 --- a/pygit2/_pygit2.pyi +++ b/pygit2/_pygit2.pyi @@ -262,7 +262,6 @@ class OdbBackendPack(OdbBackend): def __init__(self, *args, **kwargs) -> None: ... class Oid: - hex: str raw: bytes def __init__(self, raw: bytes = ..., hex: str = ...) -> None: ... def __eq__(self, other) -> bool: ... @@ -272,6 +271,7 @@ class Oid: def __le__(self, other) -> bool: ... def __lt__(self, other) -> bool: ... def __ne__(self, other) -> bool: ... + def __bool__(self) -> bool: ... class Patch: data: bytes diff --git a/src/oid.c b/src/oid.c index f8a393e1..ffce36a2 100644 --- a/src/oid.c +++ b/src/oid.c @@ -34,6 +34,8 @@ PyTypeObject OidType; +static const git_oid oid_zero = GIT_OID_SHA1_ZERO; + PyObject * git_oid_to_python(const git_oid *oid) @@ -255,6 +257,13 @@ Oid__str__(Oid *self) return git_oid_to_py_str(&self->oid); } +int +Oid__bool(PyObject *self) +{ + git_oid *oid = &((Oid*)self)->oid; + return !git_oid_equal(oid, &oid_zero); +} + PyDoc_STRVAR(Oid_raw__doc__, "Raw oid, a 20 bytes string."); PyObject * @@ -269,6 +278,45 @@ PyGetSetDef Oid_getseters[] = { {NULL}, }; +PyNumberMethods Oid_as_number = { + 0, /* nb_add */ + 0, /* nb_subtract */ + 0, /* nb_multiply */ + 0, /* nb_remainder */ + 0, /* nb_divmod */ + 0, /* nb_power */ + 0, /* nb_negative */ + 0, /* nb_positive */ + 0, /* nb_absolute */ + Oid__bool, /* nb_bool */ + 0, /* nb_invert */ + 0, /* nb_lshift */ + 0, /* nb_rshift */ + 0, /* nb_and */ + 0, /* nb_xor */ + 0, /* nb_or */ + 0, /* nb_int */ + 0, /* nb_reserved */ + 0, /* nb_float */ + 0, /* nb_inplace_add */ + 0, /* nb_inplace_subtract */ + 0, /* nb_inplace_multiply */ + 0, /* nb_inplace_remainder */ + 0, /* nb_inplace_power */ + 0, /* nb_inplace_lshift */ + 0, /* nb_inplace_rshift */ + 0, /* nb_inplace_and */ + 0, /* nb_inplace_xor */ + 0, /* nb_inplace_or */ + 0, /* nb_floor_divide */ + 0, /* nb_true_divide */ + 0, /* nb_inplace_floor_divide */ + 0, /* nb_inplace_true_divide */ + 0, /* nb_index */ + 0, /* nb_matrix_multiply */ + 0, /* nb_inplace_matrix_multiply */ +}; + PyDoc_STRVAR(Oid__doc__, "Object id."); PyTypeObject OidType = { @@ -282,7 +330,7 @@ PyTypeObject OidType = { 0, /* tp_setattr */ 0, /* tp_compare */ (reprfunc)Oid__str__, /* tp_repr */ - 0, /* tp_as_number */ + &Oid_as_number, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ (hashfunc)Oid_hash, /* tp_hash */ diff --git a/test/test_oid.py b/test/test_oid.py index 93060a41..c6cbf3e8 100644 --- a/test/test_oid.py +++ b/test/test_oid.py @@ -99,3 +99,10 @@ def test_hash(): s.add(Oid(hex='0000000000000000000000000000000000000000')) s.add(Oid(hex='0000000000000000000000000000000000000001')) assert len(s) == 3 + + +def test_bool(): + assert Oid(raw=RAW) + assert Oid(hex=HEX) + assert not Oid(raw=b'') + assert not Oid(hex='0000000000000000000000000000000000000000')