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

Handle NaN #63

Merged
merged 19 commits into from Oct 26, 2022
Merged

Handle NaN #63

merged 19 commits into from Oct 26, 2022

Conversation

The-Debarghya
Copy link
Contributor

Fixes #62 Handling math.nan in metric() method

Changes proposed in this pull request:

  • Check if the value parameter is NaN and return if it is so.
  • The rest logic remains same.

Copy link
Contributor

@carterbox carterbox left a comment

Choose a reason for hiding this comment

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

IN addition to comment below, docstring needs to be updated to specify what happens with nonfinite numbers. I believe floats can also represent inf, so it would be great if you used math.isfinite() to handle both inf and nan.

src/humanize/number.py Outdated Show resolved Hide resolved
src/humanize/number.py Outdated Show resolved Hide resolved
@hugovk hugovk added the changelog: Fixed For any bug fixes label Oct 5, 2022
@codecov-commenter
Copy link

codecov-commenter commented Oct 5, 2022

Codecov Report

Merging #63 (9245532) into main (c35fa9c) will decrease coverage by 0.92%.
The diff coverage is 72.00%.

@@            Coverage Diff             @@
##             main      #63      +/-   ##
==========================================
- Coverage   99.29%   98.36%   -0.93%     
==========================================
  Files           9        9              
  Lines         710      735      +25     
==========================================
+ Hits          705      723      +18     
- Misses          5       12       +7     
Flag Coverage Δ
macos-latest 96.73% <72.00%> (-0.88%) ⬇️
ubuntu-latest 96.73% <72.00%> (-0.88%) ⬇️
windows-latest 95.51% <72.00%> (-0.83%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted Files Coverage Δ
src/humanize/number.py 93.16% <68.18%> (-3.96%) ⬇️
tests/test_number.py 100.00% <100.00%> (ø)
tests/test_time.py 100.00% <100.00%> (ø)

Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here.

@hugovk
Copy link
Member

hugovk commented Oct 6, 2022

Please could you also add tests?

The inputs and expected outputs can go in this list:

"test_args, expected",
[
([0], "0.00"),
([1, "Hz"], "1.00 Hz"),
([1.0, "W"], "1.00 W"),
([3, "C"], "3.00 C"),
([3, "W", 5], "3.0000 W"),
([1.23456], "1.23"),
([12.3456], "12.3"),
([123.456], "123"),
([1234.56], "1.23 k"),
([12345, "", 6], "12.3450 k"),
([200_000], "200 k"),
([1e25, "m"], "10.0 Ym"),
([1e26, "m"], "100 Ym"),
([1e27, "A"], "1.00 x 10²⁷A"),
([1.234e28, "A"], "1.23 x 10²⁸A"),
([-1500, "V"], "-1.50 kV"),
([0.12], "120 m"),
([0.012], "12.0 m"),
([0.0012], "1.20 m"),
([0.00012], "120 μ"),
([1e-23], "10.0 y"),
([1e-24], "1.00 y"),
([1e-25], "1.00 x 10⁻²⁵"),
([1e-26], "1.00 x 10⁻²⁶"),
([1, "°"], "1.00°"),
([0.1, "°"], "100m°"),
([100], "100"),
([0.1], "100 m"),
],

@The-Debarghya
Copy link
Contributor Author

Is it ok now or should I add more tests?

@hugovk
Copy link
Member

hugovk commented Oct 9, 2022

@carterbox @bersbersbers Thanks for your reviews, how's it look now?

@bersbersbers
Copy link

Looks good for metric. Might handle other functions here or in a separate PR, #62 (comment)

@The-Debarghya
Copy link
Contributor Author

The-Debarghya commented Oct 9, 2022

Thanks for your feedback!
Should I make a separate PR for other methods or push further commits in this PR?

@hugovk
Copy link
Member

hugovk commented Oct 9, 2022

Should I make a separate PR for other methods or push further commits in this PR?

I'd prefer pushing to this PR, but either way is fine :)

@The-Debarghya
Copy link
Contributor Author

I have just raised a ValueError for nan and handled the inf case with OverflowError is this logic ok or it needs some tweaking.
Also if I need to add tests please mention.

@bersbersbers
Copy link

When you raise a ValueError, and in case of ValueError, the output is nan and inf, right? That is different from what we have for metric().

My rule thumb is, if you wonder if a test is necessary, a test is necessary.

@The-Debarghya
Copy link
Contributor Author

Okay then adding the check for nan and inf in other methods.

@bersbersbers
Copy link

I wonder if it might make sense to have a format_non_finite method somewhere, so that each formatting function can simply check for isfinite (covering NaN and +/-Inf) and fall back to format_non_finite, which in turns handles conversion of each possible value into one globally consistent string output.

return "NaN"
if math.isinf(value) and value < 0:
return "-Inf"
elif math.isinf(value) and value > 0:

Choose a reason for hiding this comment

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

return "-Inf"
elif math.isinf(value) and value > 0:
return "+Inf"
else:

Choose a reason for hiding this comment

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

Same

Comment on lines 29 to 37
def format_non_finite(value: float) -> str:
"""Utility function to handle infinite and nan cases."""
if math.isnan(value):
return "NaN"
if math.isinf(value) and value < 0:
return "-Inf"
elif math.isinf(value) and value > 0:
return "+Inf"
return ""
Copy link
Contributor

Choose a reason for hiding this comment

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

This function seems overly complicated and not necessary to me. Why not just use the built-in string conversions? "nan", "-inf", and "inf"?

if not math.isfinite(float(value)):
   return str(float(value))

Choose a reason for hiding this comment

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

My argument for NaN was the capitalization in https://en.wikipedia.org/wiki/NaN, which I also prefer. But I don't have a strong opinion on that.

@@ -26,6 +26,17 @@
NumberOrString: TypeAlias = "float | str"


def format_non_finite(value: float) -> str:
Copy link
Member

Choose a reason for hiding this comment

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

Let's have this as a "private" function:

Suggested change
def format_non_finite(value: float) -> str:
def _format_non_finite(value: float) -> str:

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm making it private...will it be merged then?

Copy link
Member

Choose a reason for hiding this comment

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

Will merge when it's ready, thank you for all your work!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

What more to add?

src/humanize/number.py Outdated Show resolved Hide resolved
src/humanize/number.py Outdated Show resolved Hide resolved
src/humanize/number.py Outdated Show resolved Hide resolved
src/humanize/number.py Outdated Show resolved Hide resolved
src/humanize/number.py Outdated Show resolved Hide resolved
src/humanize/number.py Outdated Show resolved Hide resolved
src/humanize/number.py Outdated Show resolved Hide resolved
src/humanize/number.py Outdated Show resolved Hide resolved
@hugovk hugovk merged commit ba53432 into python-humanize:main Oct 26, 2022
@hugovk
Copy link
Member

hugovk commented Oct 26, 2022

Thank you for the PR!

@hugovk hugovk changed the title Bug-Fix: handle NaN Handle NaN Dec 30, 2022
@The-Debarghya The-Debarghya deleted the bug-62-handle-nan branch July 24, 2023 05:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
changelog: Fixed For any bug fixes
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Feature request: handle NaN
5 participants