mirror of
https://github.com/kennethreitz/pydantic.git
synced 2026-06-05 23:00:18 +00:00
94706bc834
* Update schema tests to conform to JSON Schema spec * Add JSON Schema tests for all supported types including datetime and all supported Pydantic.types * Add JSON Schema conforming schema sub module * Update BaseModel to use schema module for JSON Schema generation and update/simplify internal Schema methods * Remove Schema code from Field class, replaced with JSON Schema module * Add submodules to test model name generation for JSON Schemas * Refactor/rewrite schema module to generate definions and refs * Update and augment JSON Schema tests to include definitions and refs and generation of a single JSON Schema with definitions from multiple (unrelated) models * Add ref_prefix functionality to JSON Schema generation functions * Test custom ref_prefix in JSON Schema generation * Remove un-used BaseModel method, now refactored to schema module * Update formating of test_schema * Fix long lines in test_schema * Fix imported but unused in fields * Fix imported but unused in main.py * Ignore imported but unused for testing modulec * Refactor schema module for complexity * Add conflicting name model to raise coverage * Add conflicting model to test other flow and raise coverage * Ignore complexity as destructuring more would make it more complex and more difficult to understand, similar to .fields.validate * Fix import sorting * Update formatting with black, with CI settings * Fix test for schemas with email validation * Check if field is class before checking if is subclass * Improve schema error when using unsuported types * Add additional tests for corner cases, raise coverage to 100% * Rename BaseModel.schema_json to schema_str (EAFP Python style) * Add more tests to utils.display_as_type to increase the coverage for enums * Remove unused catched error in schema tests * Fix formatting with black * Update docs schema example * Add schema examples for top-level schema with multiple models * Update docs, section Schema, with new JSON Schema generation details * Update docs, history, with new features * Update fields, remove unnecessary schema code for enums * Update docs, fix links and typos in Schema section * Trigger CI, as Python 3.7-dev seems to have random CI errors * Revert Model.schema_str to Model.schema_json as requested * Remove unnecessary assert in schema module as requested * Remove annotations in internal functions, as requested * Refactor get_flat_models_from_fields and reuse * Use set short assignment syntax in schema module * Remove unwanted assertion * Make get_long_model_name a single line f-string * Update model_name_map, add docstring and remove first return value * Simplify dict operation in get_model_name_map as requested * Make more concise model_name_map computation * Remove bool from field check in schema as is subclass of int * Make ref_prefix default to None and use global default * Fix formatting for schema.py * Refactor field_singleton_schema to use data structures * Move main functions to top of schema, and add docstrings for them * Implement __all__, move and order parts of schema * Remove schema testing sub-package code as requested * Generate schema testing subpackage in code * Update schema tests with several related fields to use parametrized pytest * Fix formatting and imports I missed after rebase * Fix new formatting errors from CI * Re-trigger Travis CI, Python 3.7-dev random error again, no re-run click in Travis for non owners * Trigger annotation error with non-forward references * Add docstrings for submodel schema * tweaks and rewrite schema mapping table in python * support complex defaults * use str not int as dict keys * Fix links to JSON Schema and OpenAPI
138 lines
4.3 KiB
Python
138 lines
4.3 KiB
Python
import os
|
|
from enum import Enum
|
|
from typing import Union
|
|
|
|
import pytest
|
|
|
|
from pydantic.utils import display_as_type, import_string, make_dsn, validate_email
|
|
|
|
try:
|
|
import email_validator
|
|
except ImportError:
|
|
email_validator = None
|
|
|
|
|
|
@pytest.mark.skipif(not email_validator, reason='email_validator not installed')
|
|
@pytest.mark.parametrize(
|
|
'value,name,email',
|
|
[
|
|
('foobar@example.com', 'foobar', 'foobar@example.com'),
|
|
('s@muelcolvin.com', 's', 's@muelcolvin.com'),
|
|
('Samuel Colvin <s@muelcolvin.com>', 'Samuel Colvin', 's@muelcolvin.com'),
|
|
('foobar <foobar@example.com>', 'foobar', 'foobar@example.com'),
|
|
(' foo.bar@example.com', 'foo.bar', 'foo.bar@example.com'),
|
|
('foo.bar@example.com ', 'foo.bar', 'foo.bar@example.com'),
|
|
('foo BAR <foobar@example.com >', 'foo BAR', 'foobar@example.com'),
|
|
('FOO bar <foobar@example.com> ', 'FOO bar', 'foobar@example.com'),
|
|
('<FOOBAR@example.com> ', 'FOOBAR', 'foobar@example.com'),
|
|
('ñoñó@example.com', 'ñoñó', 'ñoñó@example.com'),
|
|
('我買@example.com', '我買', '我買@example.com'),
|
|
('甲斐黒川日本@example.com', '甲斐黒川日本', '甲斐黒川日本@example.com'),
|
|
(
|
|
'чебурашкаящик-с-апельсинами.рф@example.com',
|
|
'чебурашкаящик-с-апельсинами.рф',
|
|
'чебурашкаящик-с-апельсинами.рф@example.com',
|
|
),
|
|
('उदाहरण.परीक्ष@domain.with.idn.tld', 'उदाहरण.परीक्ष', 'उदाहरण.परीक्ष@domain.with.idn.tld'),
|
|
('foo.bar@example.com', 'foo.bar', 'foo.bar@example.com'),
|
|
('foo.bar@exam-ple.com ', 'foo.bar', 'foo.bar@exam-ple.com'),
|
|
('ιωάννης@εεττ.gr', 'ιωάννης', 'ιωάννης@εεττ.gr'),
|
|
],
|
|
)
|
|
def test_address_valid(value, name, email):
|
|
assert validate_email(value) == (name, email)
|
|
|
|
|
|
@pytest.mark.skipif(not email_validator, reason='email_validator not installed')
|
|
@pytest.mark.parametrize(
|
|
'value',
|
|
[
|
|
'f oo.bar@example.com ',
|
|
'foo.bar@exam\nple.com ',
|
|
'foobar',
|
|
'foobar <foobar@example.com',
|
|
'@example.com',
|
|
'foobar@.example.com',
|
|
'foobar@.com',
|
|
'foo bar@example.com',
|
|
'foo@bar@example.com',
|
|
'\n@example.com',
|
|
'\r@example.com',
|
|
'\f@example.com',
|
|
' @example.com',
|
|
'\u0020@example.com',
|
|
'\u001f@example.com',
|
|
'"@example.com',
|
|
'\"@example.com',
|
|
',@example.com',
|
|
'foobar <foobar<@example.com>',
|
|
],
|
|
)
|
|
def test_address_invalid(value):
|
|
with pytest.raises(ValueError):
|
|
validate_email(value)
|
|
|
|
|
|
@pytest.mark.skipif(email_validator, reason='email_validator is installed')
|
|
def test_email_validator_not_installed():
|
|
with pytest.raises(ImportError):
|
|
validate_email('s@muelcolvin.com')
|
|
|
|
|
|
def test_empty_dsn():
|
|
assert make_dsn(driver='foobar') == 'foobar://'
|
|
|
|
|
|
def test_dsn_odd_user():
|
|
assert make_dsn(driver='foobar', user='foo@bar') == 'foobar://foo%40bar@'
|
|
|
|
|
|
def test_import_module():
|
|
assert import_string('os.path') == os.path
|
|
|
|
|
|
def test_import_module_invalid():
|
|
with pytest.raises(ImportError) as exc_info:
|
|
import_string('xx')
|
|
assert exc_info.value.args[0] == '"xx" doesn\'t look like a module path'
|
|
|
|
|
|
def test_import_no_attr():
|
|
with pytest.raises(ImportError) as exc_info:
|
|
import_string('os.foobar')
|
|
assert exc_info.value.args[0] == 'Module "os" does not define a "foobar" attribute'
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
'value,expected', ((str, 'str'), ('string', 'str'), (Union[str, int], 'typing.Union[str, int]'))
|
|
)
|
|
def test_display_as_type(value, expected):
|
|
assert display_as_type(value) == expected
|
|
|
|
|
|
def test_display_as_type_enum():
|
|
class SubField(Enum):
|
|
a = 1
|
|
b = 'b'
|
|
|
|
displayed = display_as_type(SubField)
|
|
assert displayed == 'enum'
|
|
|
|
|
|
def test_display_as_type_enum_int():
|
|
class SubField(int, Enum):
|
|
a = 1
|
|
b = 2
|
|
|
|
displayed = display_as_type(SubField)
|
|
assert displayed == 'int'
|
|
|
|
|
|
def test_display_as_type_enum_str():
|
|
class SubField(str, Enum):
|
|
a = 'a'
|
|
b = 'b'
|
|
|
|
displayed = display_as_type(SubField)
|
|
assert displayed == 'str'
|