diff --git a/changes/883-samuelcolvin.md b/changes/883-samuelcolvin.md new file mode 100644 index 0000000..38584c5 --- /dev/null +++ b/changes/883-samuelcolvin.md @@ -0,0 +1 @@ +**Breaking Change:** deprecate the `Model.fields` property, use `Model.__fields__` instead diff --git a/docs/usage/models.md b/docs/usage/models.md index a4b55d3..0fb2059 100644 --- a/docs/usage/models.md +++ b/docs/usage/models.md @@ -92,15 +92,15 @@ Models possess the following methods and attributes: `schema_json()` : returns a JSON string representation of `schema()`; cf. [Schema](schema.md) -`fields` -: a dictionary of the model class's fields +`__fields_set__` +: Set of names of fields which were set when the model instance was initialised + +`__fields__` +: a dictionary of the model's fields `__config__` : the configuration class for the model, cf. [model config](model_config.md) -`__fields_set__` -: the set of names of fields which were set when the model instance was initialised - ## Recursive Models More complex hierarchical data structures can be defined using models themselves as types in annotations. diff --git a/pydantic/main.py b/pydantic/main.py index 176c700..29c5e01 100644 --- a/pydantic/main.py +++ b/pydantic/main.py @@ -268,7 +268,7 @@ class BaseModel(metaclass=ModelMetaclass): elif not self.__config__.allow_mutation: raise TypeError(f'"{self.__class__.__name__}" is immutable and does not support item assignment') elif self.__config__.validate_assignment: - known_field = self.fields.get(name, None) + known_field = self.__fields__.get(name, None) if known_field: value, error_ = known_field.validate(value, self.dict(exclude={name}), loc=name) if error_: @@ -295,7 +295,7 @@ class BaseModel(metaclass=ModelMetaclass): Generate a dictionary representation of the model, optionally specifying which fields to include or exclude. """ get_key = self._get_key_factory(by_alias) - get_key = partial(get_key, self.fields) + get_key = partial(get_key, self.__fields__) allowed_keys = self._calculate_keys(include=include, exclude=exclude, skip_defaults=skip_defaults) return { @@ -457,6 +457,7 @@ class BaseModel(metaclass=ModelMetaclass): @property def fields(self) -> Dict[str, ModelField]: + warnings.warn('`fields` attribute is deprecated, use `__fields__` instead', DeprecationWarning) return self.__fields__ @classmethod diff --git a/tests/test_edge_cases.py b/tests/test_edge_cases.py index 6c97c9a..83afbf4 100644 --- a/tests/test_edge_cases.py +++ b/tests/test_edge_cases.py @@ -27,7 +27,7 @@ def test_str_bytes(): m = Model(v='s') assert m.v == 's' - assert '' == repr(m.fields['v']) + assert '' == repr(m.__fields__['v']) m = Model(v=b'b') assert m.v == 'b' @@ -1066,3 +1066,14 @@ def test_population_by_alias(): assert Model(a='different').a == 'different' assert Model(a='different').dict() == {'a': 'different'} assert Model(a='different').dict(by_alias=True) == {'_a': 'different'} + + +def test_fields_deprecated(): + class Model(BaseModel): + v: str = 'x' + + with pytest.warns(DeprecationWarning, match='`fields` attribute is deprecated, use `__fields__` instead'): + assert Model().fields.keys() == {'v'} + + assert Model().__fields__.keys() == {'v'} + assert Model.__fields__.keys() == {'v'} diff --git a/tests/test_main.py b/tests/test_main.py index faf1b70..c355c2a 100644 --- a/tests/test_main.py +++ b/tests/test_main.py @@ -40,7 +40,7 @@ def test_ultra_simple_failed(): def test_ultra_simple_repr(): m = UltraSimpleModel(a=10.2) assert repr(m) == '' - assert repr(m.fields['a']) == '' + assert repr(m.__fields__['a']) == '' assert dict(m) == {'a': 10.2, 'b': 10} assert m.dict() == {'a': 10.2, 'b': 10} assert m.json() == '{"a": 10.2, "b": 10}'