Skip to content

Commit 2e6201f

Browse files
committed
Apply __new__ approach to disabling __init__
The starting point for this change was extracted from PR #458: * #458 (comment) * #458 (comment)
1 parent a52e562 commit 2e6201f

File tree

6 files changed

+64
-57
lines changed

6 files changed

+64
-57
lines changed

cuda_core/cuda/core/experimental/_context.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,13 @@ class ContextOptions:
1515
class Context:
1616
__slots__ = ("_handle", "_id")
1717

18-
def __init__(self):
19-
raise NotImplementedError("TODO")
18+
def __new__(self, *args, **kwargs):
19+
raise RuntimeError("Context objects cannot be instantiated directly. Please use Device or Stream APIs.")
2020

21-
@staticmethod
22-
def _from_ctx(obj, dev_id):
21+
@classmethod
22+
def _from_ctx(cls, obj, dev_id):
2323
assert isinstance(obj, driver.CUcontext)
24-
ctx = Context.__new__(Context)
24+
ctx = super().__new__(cls)
2525
ctx._handle = obj
2626
ctx._id = dev_id
2727
return ctx

cuda_core/cuda/core/experimental/_device.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,14 @@ class DeviceProperties:
2222
Attributes are read-only and provide information about the device.
2323
"""
2424

25-
def __init__(self):
26-
raise RuntimeError("DeviceProperties should not be instantiated directly")
25+
def __new__(self, *args, **kwargs):
26+
raise RuntimeError("DeviceProperties cannot be instantiated directly. Please use Device APIs.")
2727

2828
__slots__ = ("_handle", "_cache")
2929

30-
def _init(handle):
31-
self = DeviceProperties.__new__(DeviceProperties)
30+
@classmethod
31+
def _init(cls, handle):
32+
self = super().__new__(cls)
3233
self._handle = handle
3334
self._cache = {}
3435
return self

cuda_core/cuda/core/experimental/_event.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -67,14 +67,14 @@ def close(self):
6767
handle_return(driver.cuEventDestroy(self.handle))
6868
self.handle = None
6969

70-
__slots__ = ("__weakref__", "_mnff", "_timing_disabled", "_busy_waited")
70+
def __new__(self, *args, **kwargs):
71+
raise RuntimeError("Event objects cannot be instantiated directly. Please use Stream APIs (record).")
7172

72-
def __init__(self):
73-
raise NotImplementedError("directly creating an Event object can be ambiguous. Please call Stream.record().")
73+
__slots__ = ("__weakref__", "_mnff", "_timing_disabled", "_busy_waited")
7474

75-
@staticmethod
76-
def _init(options: Optional[EventOptions] = None):
77-
self = Event.__new__(Event)
75+
@classmethod
76+
def _init(cls, options: Optional[EventOptions] = None):
77+
self = super().__new__(cls)
7878
self._mnff = Event._MembersNeededForFinalize(self, None)
7979

8080
options = check_or_create_options(EventOptions, options, "Event options")

cuda_core/cuda/core/experimental/_module.py

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -47,13 +47,14 @@ def _lazy_init():
4747

4848

4949
class KernelAttributes:
50-
def __init__(self):
51-
raise RuntimeError("KernelAttributes should not be instantiated directly")
50+
def __new__(self, *args, **kwargs):
51+
raise RuntimeError("KernelAttributes cannot be instantiated directly. Please use Kernel APIs.")
5252

5353
slots = ("_handle", "_cache", "_backend_version", "_loader")
5454

55-
def _init(handle):
56-
self = KernelAttributes.__new__(KernelAttributes)
55+
@classmethod
56+
def _init(cls, handle):
57+
self = super().__new__(cls)
5758
self._handle = handle
5859
self._cache = {}
5960

@@ -189,14 +190,14 @@ class Kernel:
189190

190191
__slots__ = ("_handle", "_module", "_attributes")
191192

192-
def __init__(self):
193-
raise RuntimeError("directly constructing a Kernel instance is not supported")
193+
def __new__(self, *args, **kwargs):
194+
raise RuntimeError("Kernel objects cannot be instantiated directly. Please use ObjectCode APIs.")
194195

195-
@staticmethod
196-
def _from_obj(obj, mod):
196+
@classmethod
197+
def _from_obj(cls, obj, mod):
197198
assert isinstance(obj, _kernel_ctypes)
198199
assert isinstance(mod, ObjectCode)
199-
ker = Kernel.__new__(Kernel)
200+
ker = super().__new__(cls)
200201
ker._handle = obj
201202
ker._module = mod
202203
ker._attributes = None
@@ -237,15 +238,15 @@ class ObjectCode:
237238
__slots__ = ("_handle", "_backend_version", "_code_type", "_module", "_loader", "_sym_map")
238239
_supported_code_type = ("cubin", "ptx", "ltoir", "fatbin")
239240

240-
def __init__(self):
241-
raise NotImplementedError(
242-
"directly creating an ObjectCode object can be ambiguous. Please either call Program.compile() "
243-
"or one of the ObjectCode.from_*() constructors"
241+
def __new__(self, *args, **kwargs):
242+
raise RuntimeError(
243+
"ObjectCode objects cannot be instantiated directly. "
244+
"Please use ObjectCode APIs (from_cubin, from_ptx) or Program APIs (compile)."
244245
)
245246

246-
@staticmethod
247-
def _init(module, code_type, *, symbol_mapping: Optional[dict] = None):
248-
self = ObjectCode.__new__(ObjectCode)
247+
@classmethod
248+
def _init(cls, module, code_type, *, symbol_mapping: Optional[dict] = None):
249+
self = super().__new__(cls)
249250
assert code_type in self._supported_code_type, f"{code_type=} is not supported"
250251
_lazy_init()
251252

cuda_core/cuda/core/experimental/_stream.py

Lines changed: 30 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -71,18 +71,37 @@ def close(self):
7171
self.owner = None
7272
self.handle = None
7373

74+
def __new__(self, *args, **kwargs):
75+
raise RuntimeError(
76+
"Stream objects cannot be instantiated directly. "
77+
"Please use Device APIs (create_stream) or other Stream APIs (from_handle, wait)."
78+
)
79+
7480
__slots__ = ("__weakref__", "_mnff", "_nonblocking", "_priority", "_device_id", "_ctx_handle")
7581

76-
def __init__(self):
77-
raise NotImplementedError(
78-
"directly creating a Stream object can be ambiguous. Please either "
79-
"call Device.create_stream() or, if a stream pointer is already "
80-
"available from somewhere else, Stream.from_handle()"
81-
)
82+
@classmethod
83+
def _legacy_default(cls):
84+
self = super().__new__(cls)
85+
self._mnff = Stream._MembersNeededForFinalize(self, driver.CUstream(driver.CU_STREAM_LEGACY), None, True)
86+
self._nonblocking = None # delayed
87+
self._priority = None # delayed
88+
self._device_id = None # delayed
89+
self._ctx_handle = None # delayed
90+
return self
8291

83-
@staticmethod
84-
def _init(obj=None, *, options: Optional[StreamOptions] = None):
85-
self = Stream.__new__(Stream)
92+
@classmethod
93+
def _per_thread_default(cls):
94+
self = super().__new__(cls)
95+
self._mnff = Stream._MembersNeededForFinalize(self, driver.CUstream(driver.CU_STREAM_PER_THREAD), None, True)
96+
self._nonblocking = None # delayed
97+
self._priority = None # delayed
98+
self._device_id = None # delayed
99+
self._ctx_handle = None # delayed
100+
return self
101+
102+
@classmethod
103+
def _init(cls, obj=None, *, options: Optional[StreamOptions] = None):
104+
self = super().__new__(cls)
86105
self._mnff = Stream._MembersNeededForFinalize(self, None, None, False)
87106

88107
if obj is not None and options is not None:
@@ -295,22 +314,8 @@ def __cuda_stream__(self):
295314
return Stream._init(obj=_stream_holder())
296315

297316

298-
class _LegacyDefaultStream(Stream):
299-
def __init__(self):
300-
self._mnff = Stream._MembersNeededForFinalize(self, driver.CUstream(driver.CU_STREAM_LEGACY), None, True)
301-
self._nonblocking = None # delayed
302-
self._priority = None # delayed
303-
304-
305-
class _PerThreadDefaultStream(Stream):
306-
def __init__(self):
307-
self._mnff = Stream._MembersNeededForFinalize(self, driver.CUstream(driver.CU_STREAM_PER_THREAD), None, True)
308-
self._nonblocking = None # delayed
309-
self._priority = None # delayed
310-
311-
312-
LEGACY_DEFAULT_STREAM = _LegacyDefaultStream()
313-
PER_THREAD_DEFAULT_STREAM = _PerThreadDefaultStream()
317+
LEGACY_DEFAULT_STREAM = Stream._legacy_default()
318+
PER_THREAD_DEFAULT_STREAM = Stream._per_thread_default()
314319

315320

316321
def default_stream():

cuda_core/tests/test_stream.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515

1616

1717
def test_stream_init():
18-
with pytest.raises(NotImplementedError):
18+
with pytest.raises(RuntimeError):
1919
Stream()
2020

2121

0 commit comments

Comments
 (0)