Skip to content

Commit

Permalink
Merge branch 'master' into ref_template
Browse files Browse the repository at this point in the history
  • Loading branch information
Kilo59 committed Jul 4, 2020
2 parents 4f67753 + dac6764 commit 54f8940
Show file tree
Hide file tree
Showing 184 changed files with 1,723 additions and 287 deletions.
2 changes: 1 addition & 1 deletion .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -1 +1 @@
patreon: samuelcolvin
github: samuelcolvin
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
.idea/
env/
venv/
env36/
env37/
env38/
Expand Down Expand Up @@ -31,4 +32,4 @@ pydantic/*.so
/sandbox/
/.ghtopdep_cache/
/fastapi/
/codecov.sh
/codecov.sh
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ clean:

.PHONY: docs
docs:
flake8 --max-line-length=80 docs/examples/
python docs/build/main.py
mkdocs build

Expand Down
22 changes: 15 additions & 7 deletions benchmarks/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,37 +18,44 @@
try:
from test_trafaret import TestTrafaret
except Exception:
print('WARNING: unable to import TestTrafaret')
TestTrafaret = None

try:
from test_drf import TestDRF
except Exception:
print('WARNING: unable to import TestDRF')
TestDRF = None

try:
from test_marshmallow import TestMarshmallow
except Exception:
print('WARNING: unable to import TestMarshmallow')
TestMarshmallow = None


try:
from test_valideer import TestValideer
except Exception:
print('WARNING: unable to import TestValideer')
TestValideer = None

try:
from test_cattrs import TestCAttrs
except Exception:
print('WARNING: unable to import TestCAttrs')
TestCAttrs = None

try:
from test_cerberus import TestCerberus
except Exception:
print('WARNING: unable to import TestCerberus')
TestCerberus = None

try:
from test_voluptuous import TestVoluptuous
except Exception as e:
print('WARNING: unable to import TestVoluptuous')
TestVoluptuous = None

PUNCTUATION = ' \t\n!"#$%&\'()*+,-./'
Expand All @@ -58,11 +65,8 @@
random = random.SystemRandom()

# in order of performance for csv
other_tests = [
t for t in
[TestCAttrs, TestValideer, TestMarshmallow, TestVoluptuous, TestTrafaret, TestDRF, TestCerberus]
if t is not None
]
other_tests = [TestCAttrs, TestValideer, TestMarshmallow, TestVoluptuous, TestTrafaret, TestDRF, TestCerberus]
active_other_tests = [t for t in other_tests if t is not None]


class GenerateData:
Expand Down Expand Up @@ -209,7 +213,7 @@ def main():

tests = [TestPydantic]
if 'pydantic-only' not in sys.argv:
tests += other_tests
tests += active_other_tests

repeats = int(os.getenv('BENCHMARK_REPEATS', '5'))
test_json = 'TEST_JSON' in os.environ
Expand Down Expand Up @@ -251,7 +255,7 @@ def diff():

allow_extra = True
pydantic = TestPydantic(allow_extra)
others = [t(allow_extra) for t in other_tests]
others = [t(allow_extra) for t in active_other_tests]

for case in cases:
pydantic_passed, pydantic_result = pydantic.validate(case)
Expand All @@ -269,3 +273,7 @@ def diff():
diff()
else:
main()

if None in other_tests:
print('not all libraries could be imported!')
sys.exit(1)
2 changes: 1 addition & 1 deletion benchmarks/test_pydantic.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ def validate(self, data):
try:
return True, self.model(**data)
except ValidationError as e:
return False, str(e)
return False, e.errors()

def to_json(self, model):
return model.json()
3 changes: 3 additions & 0 deletions changes/1173-calvinwyoung.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Updates OpenAPI schema generation to output all enums as separate models.
Instead of inlining the enum values in the model schema, models now use a `$ref`
property to point to the enum definition.
1 change: 1 addition & 0 deletions changes/1275-samuelcolvin.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Remove `user_required = True` from `RedisDsn`, neither user nor password are required.
1 change: 1 addition & 0 deletions changes/1364-DBCerigo.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fix model validation to handle nested literals, e.g. `Literal['foo', Literal['bar']]`.
1 change: 1 addition & 0 deletions changes/1414-patrickkwang.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Squash internal `__root__` dicts in `.dict()` (and, by extension, in `.json()`).
1 change: 1 addition & 0 deletions changes/1466-MrMrRobat.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Make `BaseModel.__signature__` class-only, so getting `__signature__` from model instance will raise `AttributeError`
1 change: 1 addition & 0 deletions changes/1487-mikegrima.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Added docs about dumping dataclasses to JSON.
2 changes: 2 additions & 0 deletions changes/1491-PrettyWood.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Avoid some side effects of `default_factory` by calling it only once
if possible and by not setting a default value in the schema
1 change: 1 addition & 0 deletions changes/1499-hultner.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Added a "Discussion of Pydantic" section to the documentation, with a link to "Pydantic Introduction" video by Alexander Hultnér
1 change: 1 addition & 0 deletions changes/1500-koxudaxi.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add datamodel-code-generator link in pydantic document site.
1 change: 1 addition & 0 deletions changes/1514-stephen-bunn.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add `NameEmail.__eq__` so duplicate `NameEmail` instances are evaluated as equal.
1 change: 1 addition & 0 deletions changes/1523-therefromhere.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add a test assertion that `default_factory` can return a singleton
1 change: 1 addition & 0 deletions changes/1541-shawnwall.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Added support for UUID instantiation through 16 byte strings such as `b'\x12\x34\x56\x78' * 4`. This was done to support `BINARY(16)` columns in sqlalchemy.
1 change: 1 addition & 0 deletions changes/1545-dcHHH.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Move the assignment of `field.validate_always` in `fields.py` so the `always` parameter of validators work on inheritance.
1 change: 1 addition & 0 deletions changes/1552-PrettyWood.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Call `__modify_schema__` only for the field schema
1 change: 1 addition & 0 deletions changes/1557-wangpeibao.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
change `schema.field_class_to_schema` to support `frozenset` in schema.
1 change: 1 addition & 0 deletions changes/1566-samueldeklund.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Subclass validators do not run when referencing a `List` field defined in a parent class when `each_item=True`. Added an example to the docs illustrating this.
1 change: 1 addition & 0 deletions changes/1581-therefromhere.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Make `__modify_schema__` on Enums apply to the enum schema rather than fields that use the enum.
1 change: 1 addition & 0 deletions changes/1586-beezee.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Adjust handling of root validators so that errors are aggregated from _all_ failing root validators, instead of reporting on only the first root validator to fail.
1 change: 1 addition & 0 deletions changes/1598-samuelcolvin.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Update mypy, remove `AnyType` alias for `Type[Any]`
1 change: 1 addition & 0 deletions changes/1600-mlbiche.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Update datetime parser to support negative timestamps
1 change: 1 addition & 0 deletions changes/1614-PrettyWood.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Ensure `SchemaExtraCallable` is always defined to get type hints on BaseConfig.
1 change: 1 addition & 0 deletions changes/1615-PrettyWood.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Allow custom encoding for `dotenv` files.
1 change: 1 addition & 0 deletions changes/1616-PrettyWood.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
make *pydantic* errors (un)pickable
1 change: 1 addition & 0 deletions changes/1623-patrickkwang.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add `conset()`, analogous to `conlist()`
3 changes: 3 additions & 0 deletions changes/1642-cool-RR.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Use `chain.from_iterable` in class_validators.py. This is a faster and more idiomatic way of using `itertools.chain`.
Instead of computing all the items in the iterable and storing them in memory, they are computed one-by-one and never
stored as a huge list. This can save on both runtime and memory space.
1 change: 1 addition & 0 deletions changes/1648-yurikhan.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Document default `regex` anchoring semantics
1 change: 1 addition & 0 deletions changes/1654-flapili.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
add port check to `AnyUrl` (can't exceed 65536) ports are 16 insigned bits: `0 <= port <= 2**16-1` src: [rfc793 header format](https://tools.ietf.org/html/rfc793#section-3.1)
2 changes: 1 addition & 1 deletion docs/build/exec_examples.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ def error(desc: str):
error('file not used anywhere')

file_text = file.read_text('utf-8')
if '\n\n\n' in file_text:
if '\n\n\n\n' in file_text:
error('too many new lines')
if not file_text.endswith('\n'):
error('no trailing new line')
Expand Down
78 changes: 78 additions & 0 deletions docs/datamodel_code_generator.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
[datamodel-code-generator](https://github.com/koxudaxi/datamodel-code-generator/) is a command to generate pydantic models from other data types.


* Supported source types
* OpenAPI 3 (YAML/JSON)
* JSON Schema
* JSON/YAML Data (It will be converted to JSON Schema)

## Install
```bash
pip install datamodel-code-generato
```

## Example
In this case, The datamodel-code-generator creates pydantic models from JSON Schema.
```bash
datamodel-codegen --input person.json --input-file-type jsonschema --output model.py
```

person.json:
```json
{
"$id": "person.json",
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Person",
"type": "object",
"properties": {
"first_name": {
"type": "string",
"description": "The person's first name."
},
"last_name": {
"type": "string",
"description": "The person's last name."
},
"age": {
"description": "Age in years.",
"type": "integer",
"minimum": 0
},
"pets": {
"type": "array",
"items": [
{
"$ref": "#/definitions/Pet"
}
]
},
"comment": {
"type": "null"
}
},
"required": [
"first_name",
"last_name"
],
"definitions": {
"Pet": {
"properties": {
"name": {
"type": "string"
},
"age": {
"type": "integer"
}
}
}
}
}
```

model.py:
```py
{!.tmp_examples/generate_models_person_model.py!}
```

More information can be found on the
[official documentation](https://koxudaxi.github.io/datamodel-code-generator/)
2 changes: 2 additions & 0 deletions docs/examples/dataclasses_default_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@
from typing import List
from pydantic.dataclasses import dataclass


@dataclass
class User:
id: int
name: str = 'John Doe'
friends: List[int] = dataclasses.field(default_factory=lambda: [0])


user = User(id='42')
print(user.__pydantic_model__.schema())
2 changes: 2 additions & 0 deletions docs/examples/dataclasses_initvars.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

from pydantic.dataclasses import dataclass


@dataclass
class PathData:
path: Path
Expand All @@ -16,6 +17,7 @@ def __post_init_post_parse__(self, base_path):
if base_path is not None:
self.path = base_path / self.path


path_data = PathData('world', base_path='/hello')
# Received path='world', base_path='/hello'
assert path_data.path == Path('/hello/world')
17 changes: 17 additions & 0 deletions docs/examples/dataclasses_json_dumps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import dataclasses
import json
from typing import List

from pydantic.dataclasses import dataclass
from pydantic.json import pydantic_encoder


@dataclass
class User:
id: int
name: str = 'John Doe'
friends: List[int] = dataclasses.field(default_factory=lambda: [0])


user = User(id='42')
print(json.dumps(user, indent=4, default=pydantic_encoder))
2 changes: 2 additions & 0 deletions docs/examples/dataclasses_main.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
from datetime import datetime
from pydantic.dataclasses import dataclass


@dataclass
class User:
id: int
name: str = 'John Doe'
signup_ts: datetime = None


user = User(id='42', signup_ts='2032-06-21T12:00')
print(user)
3 changes: 3 additions & 0 deletions docs/examples/dataclasses_nested.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
from pydantic import AnyUrl
from pydantic.dataclasses import dataclass


@dataclass
class NavbarButton:
href: AnyUrl


@dataclass
class Navbar:
button: NavbarButton


navbar = Navbar(button=('https://example.com',))
print(navbar)
4 changes: 3 additions & 1 deletion docs/examples/dataclasses_post_init_post_parse.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
from datetime import datetime
from pydantic.dataclasses import dataclass


@dataclass
class Birth:
year: int
month: int
day: int


@dataclass
class User:
birth: Birth
Expand All @@ -17,4 +18,5 @@ def __post_init__(self):
def __post_init_post_parse__(self):
print(self.birth)


user = User(**{'birth': {'year': 1995, 'month': 3, 'day': 2}})

0 comments on commit 54f8940

Please sign in to comment.