Skip to content

Commit 9916b99

Browse files
committed
add hash method
1 parent 0465578 commit 9916b99

3 files changed

Lines changed: 20 additions & 0 deletions

File tree

src/duckdb_py/include/duckdb_python/pytype.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ class DuckDBPyType : public enable_shared_from_this<DuckDBPyType> {
3030

3131
public:
3232
bool Equals(const shared_ptr<DuckDBPyType> &other) const;
33+
ssize_t Hash() const;
3334
bool EqualsString(const string &type_str) const;
3435
shared_ptr<DuckDBPyType> GetAttribute(const string &name) const;
3536
py::list Children() const;

src/duckdb_py/typing/pytype.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,10 @@ bool DuckDBPyType::Equals(const shared_ptr<DuckDBPyType> &other) const {
4646
return type == other->type;
4747
}
4848

49+
ssize_t DuckDBPyType::Hash() const {
50+
return py::hash(py::str(ToString()));
51+
}
52+
4953
bool DuckDBPyType::EqualsString(const string &type_str) const {
5054
return StringUtil::CIEquals(type.ToString(), type_str);
5155
}
@@ -328,6 +332,7 @@ void DuckDBPyType::Initialize(py::handle &m) {
328332
type_module.def("__repr__", &DuckDBPyType::ToString, "Stringified representation of the type object");
329333
type_module.def("__eq__", &DuckDBPyType::Equals, "Compare two types for equality", py::arg("other"), py::is_operator());
330334
type_module.def("__eq__", &DuckDBPyType::EqualsString, "Compare two types for equality", py::arg("other"), py::is_operator());
335+
type_module.def("__hash__", &DuckDBPyType::Hash, "Hashes the type, equal to stringifying+hashing");
331336
type_module.def_property_readonly("id", &DuckDBPyType::GetId);
332337
type_module.def_property_readonly("children", &DuckDBPyType::Children);
333338
type_module.def(py::init<>([](const string &type_str, shared_ptr<DuckDBPyConnection> connection = nullptr) {

tests/fast/test_type.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,20 @@ def test_struct_from_dict(self):
214214
res = duckdb.list_type({'a': VARCHAR, 'b': VARCHAR})
215215
assert res == 'STRUCT(a VARCHAR, b VARCHAR)[]'
216216

217+
def test_hash_method(self):
218+
type1 = duckdb.list_type({'a': VARCHAR, 'b': VARCHAR})
219+
type2 = duckdb.list_type({'b': VARCHAR, 'a': VARCHAR})
220+
type3 = VARCHAR
221+
222+
type_set = set()
223+
type_set.add(type1)
224+
type_set.add(type2)
225+
type_set.add(type3)
226+
227+
type_set.add(type1)
228+
expected = ['STRUCT(a VARCHAR, b VARCHAR)[]', 'STRUCT(b VARCHAR, a VARCHAR)[]', 'VARCHAR']
229+
assert sorted([str(x) for x in list(type_set)]) == expected
230+
217231
# NOTE: we can support this, but I don't think going through hoops for an outdated version of python is worth it
218232
@pytest.mark.skipif(sys.version_info < (3, 9), reason="python3.7 does not store Optional[..] in a recognized way")
219233
def test_optional(self):

0 commit comments

Comments
 (0)