summaryrefslogtreecommitdiff
path: root/tests/errors
diff options
context:
space:
mode:
authorda-woods <dw-git@d-woods.co.uk>2022-01-29 16:06:55 +0000
committerGitHub <noreply@github.com>2022-01-29 17:06:55 +0100
commit102366d162e2c54ec628023bab8b1e7f836a3b6f (patch)
tree1388d05604934a1e398999ed09e7326dbb3e64b5 /tests/errors
parent07f45205f46a6ab04e01f7c8244577fe41a0652f (diff)
downloadcython-102366d162e2c54ec628023bab8b1e7f836a3b6f.tar.gz
Implement cdef dataclasses (GH-3400)
New decorator/function "@cython.dataclasses.dataclass" and "cython.dataclasses.field()" to mark dataclasses and their fields. Tries to match the interface provided by a regular dataclass as much as possible. This means taking the types from the dataclasses module if available (so they match exactly) or a fallback Python version that just implements the core parts (executed with "PyRun_String()" in the C source). Use of placeholders in generated "__init__" code means the code in the C file isn't hugely readable. Probably not a huge issue, but don't really see a way round that. As part of this I've also also implemented a Cython version of "typing.ClassVar". Although really designed for use with dataclasses it behaves sensibly when used in types in a normal cdef class. This is worth documenting more thoroughly. Closes https://github.com/cython/cython/issues/2903
Diffstat (limited to 'tests/errors')
-rw-r--r--tests/errors/dataclass_e1.pyx22
-rw-r--r--tests/errors/dataclass_e2.pyx13
-rw-r--r--tests/errors/dataclass_e3.pyx13
-rw-r--r--tests/errors/dataclass_e4.pyx11
4 files changed, 59 insertions, 0 deletions
diff --git a/tests/errors/dataclass_e1.pyx b/tests/errors/dataclass_e1.pyx
new file mode 100644
index 000000000..39337ba6d
--- /dev/null
+++ b/tests/errors/dataclass_e1.pyx
@@ -0,0 +1,22 @@
+# mode: error
+
+cimport cython
+
+@cython.dataclasses.dataclass(1, shouldnt_be_here=True, init=5, unsafe_hash=True)
+cdef class C:
+ a: list = [] # mutable
+ b: int = cython.dataclasses.field(default=5, default_factory=int)
+ c: int
+
+ def __hash__(self):
+ pass
+
+_ERRORS = """
+6:5: Arguments passed to cython.dataclasses.dataclass must be True or False
+6:5: Cannot overwrite attribute __hash__ in class C
+6:5: cython.dataclasses.dataclass() got an unexpected keyword argument 'shouldnt_be_here'
+6:5: cython.dataclasses.dataclass takes no positional arguments
+7:14: mutable default <class 'list'> for field a is not allowed: use default_factory
+8:37: cannot specify both default and default_factory
+9:4: non-default argument 'c' follows default argument in dataclass __init__
+"""
diff --git a/tests/errors/dataclass_e2.pyx b/tests/errors/dataclass_e2.pyx
new file mode 100644
index 000000000..e25965938
--- /dev/null
+++ b/tests/errors/dataclass_e2.pyx
@@ -0,0 +1,13 @@
+# mode: error
+# tag: dataclass
+
+import dataclasses
+
+@dataclasses.dataclass
+cdef class C:
+ pass
+
+_ERRORS = """
+6:0: Cdef functions/classes cannot take arbitrary decorators.
+6:0: Use '@cython.dataclasses.dataclass' on cdef classes to create a dataclass
+"""
diff --git a/tests/errors/dataclass_e3.pyx b/tests/errors/dataclass_e3.pyx
new file mode 100644
index 000000000..85a900172
--- /dev/null
+++ b/tests/errors/dataclass_e3.pyx
@@ -0,0 +1,13 @@
+# mode: compile
+# tag: dataclass, warnings
+
+cimport cython
+from dataclass import field
+
+@cython.dataclasses.dataclass
+cdef class E:
+ a: int = field()
+
+_WARNINGS="""
+9:18: Do you mean cython.dataclasses.field instead?
+"""
diff --git a/tests/errors/dataclass_e4.pyx b/tests/errors/dataclass_e4.pyx
new file mode 100644
index 000000000..007487bb8
--- /dev/null
+++ b/tests/errors/dataclass_e4.pyx
@@ -0,0 +1,11 @@
+# mode: error
+
+cimport cython
+
+@cython.dataclasses.dataclass
+cdef class C:
+ a: int = cython.dataclasses.field(unexpected=True)
+
+_ERRORS = """
+7:49: cython.dataclasses.field() got an unexpected keyword argument 'unexpected'
+"""