Skip to content
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

fix #2293: Properly encode Decimals without any decimal places. #2294

Merged
merged 6 commits into from
Feb 24, 2021

Conversation

Hultner
Copy link
Contributor

@Hultner Hultner commented Jan 27, 2021

Change Summary

Adds a custom encoder for Decimals which handles both decimals with decimal places as well as those without.

Related issue number

Closes: #2293

Checklist

  • Unit tests for the changes exist
  • Tests pass on CI and coverage remains at 100%
    Tests where at 99% when i ran them before my change, I do have tests covering my changes
  • Documentation reflects the changes where applicable
  • changes/<pull request or issue id>-<github username>.md file added describing change
    (see changes/README.md for details)

@codecov
Copy link

codecov bot commented Jan 27, 2021

Codecov Report

Merging #2294 (d5f796f) into master (cc3010c) will decrease coverage by 0.07%.
The diff coverage is 100.00%.

@@            Coverage Diff             @@
##           master    #2294      +/-   ##
==========================================
- Coverage   99.97%   99.90%   -0.08%     
==========================================
  Files          23       25       +2     
  Lines        4496     5043     +547     
  Branches      909     1032     +123     
==========================================
+ Hits         4495     5038     +543     
  Misses          1        1              
- Partials        0        4       +4     
Impacted Files Coverage Δ
pydantic/json.py 100.00% <100.00%> (ø)
pydantic/mypy.py 100.00% <0.00%> (ø)
pydantic/types.py 100.00% <0.00%> (ø)
pydantic/fields.py 100.00% <0.00%> (ø)
pydantic/schema.py 100.00% <0.00%> (ø)
pydantic/validators.py 100.00% <0.00%> (ø)
pydantic/annotated_types.py 100.00% <0.00%> (ø)
pydantic/_hypothesis_plugin.py 100.00% <0.00%> (ø)
pydantic/main.py 99.06% <0.00%> (ø)
pydantic/__init__.py 100.00% <0.00%> (ø)
... and 1 more

Continue to review full report at Codecov.

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

@Hultner
Copy link
Contributor Author

Hultner commented Feb 11, 2021

@PrettyWood @samuelcolvin Any thoughts on this?

Copy link
Member

@samuelcolvin samuelcolvin left a comment

Choose a reason for hiding this comment

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

otherwise LGTM.

@@ -0,0 +1 @@
fix #2293: Properly encode `Decimal` with, or without any decimal places.
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
fix #2293: Properly encode `Decimal` with, or without any decimal places.
Properly encode `Decimal` with, or without any decimal places.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed

@@ -0,0 +1,28 @@
"""
Copy link
Member

Choose a reason for hiding this comment

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

I know the test files could do with cleaning up, but this doesn't require a standalone test file.

Please move into test_json.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Have done that now :)

@samuelcolvin samuelcolvin added the awaiting author revision awaiting changes from the PR author label Feb 13, 2021
@Hultner
Copy link
Contributor Author

Hultner commented Feb 15, 2021

@samuelcolvin Thanks for the feedback! I know that you are busy. 😃
I moved the test into test_json, right below the time-delta encoder as that's the functionality I saw the most resemblance with. I also removed the prefix from the changelog entry and resolved the merge conflicts agains master which have arose.

Does it look good now?

@Hultner Hultner requested a review from samuelcolvin February 15, 2021 09:38
decimal_places = 0
ge = 0

ObjId = Id
Copy link
Member

Choose a reason for hiding this comment

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

This is unnecssary, better to use condecimal anyway.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You mean the ConstrainedDecimal subclass? I'm cursion to hear why is condecimal better?

I use the subclasses since typers doesn't like the id: condecimal(args) approach, and it's neat with reusable types.


class Obj(BaseModel):
id: ObjId
name: str
Copy link
Member

Choose a reason for hiding this comment

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

this field is not relevant to the test.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, I'll remove it.

Comment on lines 191 to 193
test_obj = Obj(id=1, name='Test Obj')
cycled_obj = Obj.parse_raw(test_obj.json())
assert test_obj == cycled_obj
Copy link
Member

Choose a reason for hiding this comment

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

This is smart, but not the cleanest way of writing tests. Tests should demonstrate what they're checking explicitly.

Better to do something like

assert Obj(id=1).json() == '{"id": 1, "price": 0.01}'

Copy link
Contributor Author

@Hultner Hultner Feb 24, 2021

Choose a reason for hiding this comment

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

I wanted to include this since the problematic behaviour were strictly related to encoding and then parsing an object.
But I'll change it if you prefer the other way. However it doesn't capture that parsing the object back also works so maybe add a second parse as well?

Using your method that could look like this.

assert Obj(id=1).json() == '{"id": 1, "price": 0.01}'
assert Obj.parse_raw('{"id": 1, "price": 0.01}') == Obj(id=1)

Edit: Small fix in raw json.

@Hultner Hultner requested a review from samuelcolvin February 24, 2021 11:21
@Hultner
Copy link
Contributor Author

Hultner commented Feb 24, 2021

@samuelcolvin I updated the test and responded to your comments :)

@samuelcolvin samuelcolvin merged commit eab9d05 into pydantic:master Feb 24, 2021
@samuelcolvin
Copy link
Member

This is great, thank you.

sthagen added a commit to sthagen/pydantic-pydantic that referenced this pull request Feb 24, 2021
fix pydantic#2293: Properly encode Decimals without any decimal places. (pydantic#2294)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
awaiting author revision awaiting changes from the PR author
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Can't roundtrip json encode/prase properly with ConstrainedDecimal
2 participants