8000 Remove code/features made redundant by JsonOrPython validator/serializer by adriangb · Pull Request #599 · pydantic/pydantic-core · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Remove code/features made redundant by JsonOrPython validator/serializer #599

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
May 10, 2023

Conversation

adriangb
Copy link
Member

This removes the now dead code from #598 according to the uprev in pydantic

@codspeed-hq
Copy link
codspeed-hq bot commented May 10, 2023

CodSpeed Performance Report

Merging #599 remove-unused-json-or-python (9090a53) will not alter performances.

Summary

🔥 1 improvements
❌ 0 regressions
✅ 114 untouched benchmarks

🆕 0 new benchmarks
⁉️ 0 dropped benchmarks

Benchmarks breakdown

Benchmark json-or-python remove-unused-json-or-python Change
🔥 test_isinstance_json 31.3 µs 26.3 µs 15.89%

@codecov-commenter
Copy link
codecov-commenter commented May 10, 2023

Codecov Report

Merging #599 (3754021) into json-or-python (24b7471) will increase coverage by 0.03%.
The diff coverage is 100.00%.

❗ Your organization is not using the GitHub App Integration. As a result you may experience degraded service beginning May 15th. Please install the Github App Integration for your organization. Read more.

Additional details and impacted files
@@                Coverage Diff                 @@
##           json-or-python     #599      +/-   ##
==================================================
+ Coverage           94.07%   94.11%   +0.03%     
==================================================
  Files                  98       98              
  Lines               13260    13178      -82     
  Branches               25       25              
==================================================
- Hits                12475    12402      -73     
+ Misses                779      770       -9     
  Partials                6        6              
Impacted Files Coverage Δ
pydantic_core/core_schema.py 96.87% <ø> (-0.01%) ⬇️
src/input/input_json.rs 92.91% <ø> (-0.26%) ⬇️
src/input/input_python.rs 98.72% <ø> (-0.04%) ⬇️
src/input/mod.rs 100.00% <ø> (ø)
src/input/parse_json.rs 100.00% <ø> (+1.42%) ⬆️
src/validators/function.rs 91.04% <ø> (ø)
src/validators/generator.rs 93.33% <ø> (ø)
src/input/input_abstract.rs 85.29% <100.00%> (-2.59%) ⬇️
src/validators/dataclass.rs 94.27% <100.00%> (ø)
src/validators/is_instance.rs 100.00% <100.00%> (ø)
... and 3 more

Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 24b7471...3754021. Read the comment docs.

@adriangb adriangb changed the title Remove unused json or python Remove code/features made redundant by JsonOrPython validator/serializer May 10, 2023
def isinstance_json(
self,
input: 'str | bytes | bytearray',
*,
strict: 'bool | None' = None,
context: Any = None,
self_instance: 'Any | None' = None,
) -> bool: ...
def validate_assignment(
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't being used in pydantic, but I don't see is_instance_python being used anywhere in pydantic proper either. @samuelcolvin is this functionality that we just never ended up using, or am I missing something?

Comment on lines +19 to +24
impl IntoPy<PyObject> for InputType {
fn into_py(self, py: Python<'_>) -> PyObject {
match self {
Self::Json => intern!(py, "json").into(),
Self::Python => intern!(py, "python").into(),
}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Used by validator functions in the ValidationInfo struct

Comment on lines -105 to -111
fn input_is_instance(&self, class: &PyAny, _json_mask: u8) -> PyResult<bool> {
// See PyO3/pyo3#2694 - we can't use `is_instance` here since it requires PyType,
// and some check objects are not types, this logic is lifted from `is_instance` in PyO3
let result = unsafe { ffi::PyObject_IsInstance(self.as_ptr(), class.as_ptr()) };
py_error_on_minusone(self.py(), result)?;
Ok(result == 1)
}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment doesn't seem to be true, I replaced this with calling the method on &PyAny and it works fine, no tests fail here or in Pydantic. I did notice some alleged benchmark regressions for code that is not touched by any other changes here as far as I can tell, so could this be a performance thing? If so I can re-add it (although personally I would happily give up what seems like a very small performance difference to not use unsafe).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok the issue was simpler and had nothing to do with unsafe: the JsonInput version of this short-circuited, but by removing this I was causing the conversion from json -> python object -> check the type. I now added back the short circuit but via matches!(extra.mode, InputType::Python) which is not only more explicit but I suspect might be faster.

Comment on lines -11 to -20
#[derive(Copy, Clone, Debug)]
pub enum JsonType {
Null = 0b10000000,
Bool = 0b01000000,
Int = 0b00100000,
Float = 0b00010000,
String = 0b00001000,
Array = 0b00000100,
Object = 0b00000010,
}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although we won't need this anymore, I'm really curious why we had C-style tags here. What did that do for us that plain enums didn't? I was kinda confused when I saw json_mask: u8.

if input.input_is_instance(class, 0)? {
if input.to_object(py).as_ref(py).is_instance(class)? {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See above comment about possible performance advantage of our current unsafe implementation.

Comment on lines -474 to +473
mode: ValidationMode,
mode: InputType,
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I realize I just created ValidationMode in #598, but since we're getting rid of the get_type() in input we can just re-use it's enum (which was the same except with one more member, which I deleted here). The good news is this will just disappear once we merge this in to #598, so the actual diff will be negative in terms of LOC!

Comment on lines +67 to +70
InputType::Json => Err(ValError::InternalErr(PyNotImplementedError::new_err(
"Cannot check isinstance when validating from json,\
use a JsonOrPython validator instead.",
))),
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Happy to do something else here. We, unfortunately, have to do this at runtime because we build a single validator for all of the options. Since we have StrictOrLax schema and JsonOrPython we may want to eventually re-evaluate that choice which would let us do optimizations like inlining those two branches and doing this check statically instead of during validation, which would lead to a better user experience.

Comment on lines -452 to -478
#[derive(Debug, Clone, Copy)]
pub enum ValidationMode {
Json,
Python,
}

impl<'source> FromPyObject<'source> for ValidationMode {
fn extract(ob: &'source PyAny) -> PyResult<Self> {
match ob.extract::<&str>()? {
"json" => Ok(ValidationMode::Json),
"python" => Ok(ValidationMode::Python),
other => Err(PyTypeError::new_err(format!(
"Expected one of 'json' or 'python', no validation mode '{other}'"
))),
}
}
}

impl IntoPy<PyObject> for ValidationMode {
fn into_py(self, py: Python<'_>) -> PyObject {
match self {
Self::Json => intern!(py, "json").into(),
Self::Python => intern!(py, "python").into(),
}
}
}

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See comment above, this won't be in the final diff.

@adriangb adriangb merged commit 1e38cb9 into json-or-python May 10, 2023
@adriangb adriangb deleted the remove-unused-json-or-python branch May 10, 2023 13:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants
0