Skip to content

Commit f9e0f8c

Browse files
committed
Chaining classmethod and property no longer supported in Python 3.13
1 parent f374411 commit f9e0f8c

File tree

1 file changed

+15
-29
lines changed

1 file changed

+15
-29
lines changed

pymc/distributions/distribution.py

+15-29
Original file line numberDiff line numberDiff line change
@@ -192,20 +192,19 @@ def support_point(op, rv, *dist_params):
192192
return new_cls
193193

194194

195-
class _class_or_instancemethod(classmethod):
196-
"""Allow a method to be called both as a classmethod and an instancemethod.
195+
class _class_or_instance_property(property):
196+
"""Allow a property to be accessed from a class or an instance.
197197
198-
Priority is given to the instancemethod.
198+
Priority is given to the instance.
199199
200200
This is used to allow extracting information from the signature of a SymbolicRandomVariable
201-
which may be provided either as a class attribute or as an instance attribute.
201+
which may be available early as a class attribute or only later as an instance attribute.
202202
203-
Adapted from https://stackoverflow.com/a/28238047
203+
Adapted from https://stackoverflow.com/a/13624858
204204
"""
205205

206-
def __get__(self, instance, type_):
207-
descr_get = super().__get__ if instance is None else self.__func__.__get__
208-
return descr_get(instance, type_)
206+
def __get__(self, owner_self, owner_cls):
207+
return self.fget(owner_self if owner_self is not None else owner_cls)
209208

210209

211210
class SymbolicRandomVariable(MeasurableOp, OpFromGraph):
@@ -241,8 +240,7 @@ class SymbolicRandomVariable(MeasurableOp, OpFromGraph):
241240
_print_name: tuple[str, str] = ("Unknown", "\\operatorname{Unknown}")
242241
"""Tuple of (name, latex name) used for for pretty-printing variables of this type"""
243242

244-
@_class_or_instancemethod
245-
@property
243+
@_class_or_instance_property
246244
def signature(cls_or_self) -> None | str:
247245
# Convert "expanded" signature into "vanilla" signature that has no rng and size tokens
248246
extended_signature = cls_or_self.extended_signature
@@ -257,40 +255,28 @@ def signature(cls_or_self) -> None | str:
257255

258256
return signature
259257

260-
@_class_or_instancemethod
261-
@property
258+
@_class_or_instance_property
262259
def ndims_params(cls_or_self) -> Sequence[int] | None:
263-
"""Number of core dimensions of the distribution's parameters."""
260+
"""Return number of core dimensions of the distribution's parameters."""
264261
signature = cls_or_self.signature
265262
if signature is None:
266263
return None
267264
inputs_signature, _ = _parse_gufunc_signature(signature)
268265
return [len(sig) for sig in inputs_signature]
269266

270-
@_class_or_instancemethod
271-
@property
267+
@_class_or_instance_property
272268
def ndim_supp(cls_or_self) -> int | None:
273-
"""Number of support dimensions of the RandomVariable.
269+
"""Return number of support dimensions of the RandomVariable.
274270
275271
(0 for scalar, 1 for vector, ...)
276272
"""
277273
signature = cls_or_self.signature
278274
if signature is None:
279-
return None
275+
return getattr(cls_or_self, "_ndim_supp", None)
280276
_, outputs_params_signature = _parse_gufunc_signature(signature)
281277
return max(len(out_sig) for out_sig in outputs_params_signature)
282278

283-
@_class_or_instancemethod
284-
def _parse_extended_signature(cls_or_self) -> tuple[tuple[str, ...], tuple[str, ...]] | None:
285-
extended_signature = cls_or_self.extended_signature
286-
if extended_signature is None:
287-
return None
288-
289-
fake_signature = extended_signature.replace("[rng]", "(rng)").replace("[size]", "(size)")
290-
return _parse_gufunc_signature(fake_signature)
291-
292-
@_class_or_instancemethod
293-
@property
279+
@_class_or_instance_property
294280
def default_output(cls_or_self) -> int | None:
295281
extended_signature = cls_or_self.extended_signature
296282
if extended_signature is None:
@@ -374,7 +360,7 @@ def __init__(
374360
if "ndim_supp" in kwargs:
375361
# For backwards compatibility we allow passing ndim_supp without signature
376362
# This is the only variable that PyMC absolutely needs to work with SymbolicRandomVariables
377-
self.ndim_supp = kwargs.pop("ndim_supp")
363+
self._ndim_supp = kwargs.pop("ndim_supp")
378364

379365
if self.ndim_supp is None:
380366
raise ValueError("ndim_supp or signature must be provided")

0 commit comments

Comments
 (0)