@@ -46,6 +46,7 @@ class attribute. Documentation is in strings immediately following the
4646
4747from __future__ import annotations
4848import builtins
49+ from types import EllipsisType
4950from typing import (
5051 Annotated ,
5152 Callable ,
@@ -135,7 +136,7 @@ def property(default_factory: ValueFactory, readonly: bool = False) -> Value: ..
135136
136137
137138def property (
138- default : Value | ValueGetter | None = None ,
139+ default : Value | ValueGetter | EllipsisType = ... ,
139140 * ,
140141 default_factory : ValueFactory | None = None ,
141142 readonly : bool = False ,
@@ -195,6 +196,11 @@ def property(
195196 as ``mypy`` will check that the default is valid for the type of the
196197 field, and won't raise an error about assigning, for example, an
197198 instance of ``DataProperty[int]`` to a field annotated as ``int``.
199+
200+ Finally, the type of the ``default`` argument includes `.EllipsisType`
201+ so that we can use ``...`` as its default value. This allows us to
202+ distinguish between ``default`` not being set (``...``) and a desired
203+ default value of ``None``.
198204 """
199205 if callable (default ):
200206 # If the default is callable, we're being used as a decorator
@@ -231,7 +237,7 @@ class DataProperty(BaseProperty[Value], Generic[Value]):
231237
232238 def __init__ (
233239 self ,
234- default : Value | None = None ,
240+ default : Value | EllipsisType = ... ,
235241 * ,
236242 default_factory : ValueFactory | None ,
237243 readonly : bool = False ,
@@ -256,7 +262,9 @@ def __init__(
256262 ``__init__``.
257263
258264 :param default: the default value. This or ``default_factory`` must
259- be provided.
265+ be provided. Note that, as ``None`` is a valid default value,
266+ this uses ``...`` instead as a way of checking whether ``default``
267+ has been set.
260268 :param default_factory: a function that returns the default value.
261269 This is appropriate for datatypes such as lists, where using
262270 a mutable default value can lead to odd behaviour.
@@ -268,13 +276,17 @@ def __init__(
268276 factory function are specified.
269277 :raises MissingDefaultError: if no default is provided.
270278 """
271- if default_factory is not None :
272- if default is not None :
273- raise OverspecifiedDefaultError ()
274- self ._default_value : Value = default_factory ()
275- if default is None :
279+ if default_factory is not None and default is not ...:
280+ raise OverspecifiedDefaultError ()
281+ if default_factory is None and default is ...:
276282 raise MissingDefaultError ()
277- self ._default_value : Value = default
283+ # The default value will come from whichever of `default` and `default_factory`
284+ # is specified. The two checks above ensure that exactly one will exist.
285+ self ._default_value : Value
286+ if default_factory :
287+ self ._default_value = default_factory
288+ else :
289+ self ._default_value = default
278290 self .readonly = readonly
279291 self ._type : type | None = None # Will be set in __set_name__
280292
@@ -498,7 +510,7 @@ def property_affordance(
498510
499511
500512def setting (
501- default : Value | None = None ,
513+ default : Value | EllipsisType = ... ,
502514 * ,
503515 default_factory : ValueFactory | None = None ,
504516 readonly : bool = False ,
0 commit comments