10000 API: Create Preliminary DTypeMeta class and np.dtype subclasses by seberg · Pull Request #15508 · numpy/numpy · GitHub
[go: up one dir, main page]

Skip to content

API: Create Preliminary DTypeMeta class and np.dtype subclasses #15508

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
May 27, 2020
Prev Previous commit
Next Next commit
Improve docs and test slightl; Reject also kwargs in dtype from type …
…creation
  • Loading branch information
seberg committed Mar 18, 2020
commit 7c365448314fc47f6bc99c562caf238efe986b36
7 changes: 4 additions & 3 deletions numpy/core/src/multiarray/dtypemeta.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,8 @@ dtypemeta_traverse(PyArray_DTypeMeta *type, visitproc visit, void *arg)
/*
* We have to traverse the base class (if it is a HeapType).
* PyType_Type will handle this logic for us.
* TODO: In the future, we may have to VISIT some python objects held,
* however, only if we are a Py_TPFLAGS_HEAPTYPE.
* This function is currently not used, but may be necessary in the future
* when we implement HeapTypes (python/dynamically defined types).
*/
assert(!type->is_legacy && (PyTypeObject *)type != &PyArrayDescr_Type);
Py_VISIT(type->singleton);
Expand All @@ -90,7 +90,8 @@ legacy_dtype_default_new(PyArray_DTypeMeta *self,
return NULL;
}

if (PyTuple_GET_SIZE(args) != 0) {
if (PyTuple_GET_SIZE(args) != 0 ||
(kwargs != NULL && PyDict_GET_SIZE(kwargs))) {
PyErr_Format(PyExc_TypeError,
"currently only the no-argument instantiation is supported; "
"use `np.dtype` instead.");
Expand Down
8 changes: 8 additions & 0 deletions numpy/core/tests/test_dtype.py
Original file line number Diff line number Diff line change
Expand Up @@ -1104,6 +1104,9 @@ def test_basic_dtypes_subclass_properties(self, dtype):
assert type(dtype).__module__ == "numpy"
assert not type(dtype)._abstract

# the flexible dtypes and datetime/timedelta have additional parameters
# which are more than just storage information, these would need to be
# given when creating a dtype:
parametric = (np.void, np.str_, np.bytes_, np.datetime64, np.timedelta64)
if dtype.type not in parametric:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i find the following behavior a bit confusing :

>>> dtype = np.dtype("float32")
>>> dtype.type == type(dtype).type
True

maybe attribute name being different from type/_type will help ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have to figure this out before 1.20. I currently see the dtype type as non-existing, i.e. its a class attribute, which the instance simply looks up on the class. But: I think there may be use-cases which DType.type is NULL, and in that case, there may be some use in dtype.type being non-null. Although I suspect that is useless in practice (at least unless I expand some of the classmethods to also work as instance-methods in the NEP).

For now, I would view it as being a bad implementation of:

class DType:
    type = something
    @property 
    def dtype(self):
        return self.type  # returns the class attribute always.

but we store it also on the dtype for backward compatibility reasons.

assert not type(dtype)._parametric
Expand All @@ -1114,6 +1117,11 @@ def test_basic_dtypes_subclass_properties(self, dtype):
type(dtype)()

def test_dtype_superclass(self):
assert type(np.dtype) is not type
assert isinstance(np.dtype, type)

assert type(np.dtype).__name__ == "_DTypeMeta"
assert type(np.dtype).__module__ == "numpy"
assert np.dtype._abstract


Expand Down
0