Opened 3 years ago

Closed 6 weeks ago

#27486 closed Cleanup/optimization (fixed)

intword and filesizeformat filters shouldn't pass non-integers to gettext

Reported by: Tim Graham Owned by: Mariusz Felisiak <felisiak.mariusz@…>
Component: Template system Version: master
Severity: Normal Keywords:
Cc: Triage Stage: Accepted
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

Python plans to deprecate selecting plural form by fractional numbers. The intword and filesizeformat template filters are currently doing this:

$ python -Wall tests/runtests.py humanize_tests.tests.HumanizeTests.test_i18n_intword
Testing against Django installed in '/home/tim/code/django/django' with up to 3 processes
Creating test database for alias 'default'...
Creating test database for alias 'other'...
/home/tim/code/django/django/utils/translation/trans_real.py:373: DeprecationWarning: Plural value must be an integer, got float
  return getattr(t, translation_function)(singular, plural, number)
.
python -Wall tests/runtests.py template_tests.filter_tests.test_filesizeformat.FunctionTests.test_localized_formats 
Testing against Django installed in '/home/tim/code/django/django' with up to 3 processes
Creating test database for alias 'default'...
Creating test database for alias 'other'...
/home/tim/code/django/django/utils/translation/trans_real.py:373: DeprecationWarning: Plural value must be an integer, got float
  return getattr(t, translation_function)(singular, plural, number)
.

Change History (6)

comment:1 Changed 3 years ago by Claude Paroz

The exact rule about pluralizing floats/decimals depends on the language, so whether we floor or ceil the number before passing it to ngettext we'll do the right thing for some languages and wrong for others. This is a known limitation of the gettext spec (in C, ngettext is only accepting integers). We should make a choice and then document the limitation.

It would not be impossible to try providing a language-specific hook in the LANG_INFO structure and call that hook when converting floats to ints.

comment:2 Changed 3 years ago by Tim Graham

My PR does naive int() casting. I closed it since it seems a more involved solution would be better. Perhaps we could look to see how other projects handle the issue.

comment:3 Changed 2 years ago by Tim Graham

Owner: Tim Graham deleted
Status: assignednew

comment:4 Changed 6 weeks ago by Jon Dufresne

Has patch: set

comment:5 Changed 6 weeks ago by Mariusz Felisiak <felisiak.mariusz@…>

In 53ea535f:

Refs #27486 -- Added tests for filesizeformat filter.

comment:6 Changed 6 weeks ago by Mariusz Felisiak <felisiak.mariusz@…>

Owner: set to Mariusz Felisiak <felisiak.mariusz@…>
Resolution: fixed
Status: newclosed

In 9e38ed05:

Fixed #27486 -- Fixed Python 3.7 DeprecationWarning in intword and filesizeformat filters.

intword and filesizeformat passed floats to ngettext() which is
deprecated in Python 3.7. The rationale for this warning is documented
in BPO-28692: https://bugs.python.org/issue28692.

For filesizeformat, the filesize value is expected to be an int -- it
fills %d string formatting placeholders. It was likely coerced to a
float to ensure floating point division on Python 2. Python 3 always
does floating point division, so coerce to an int instead of a float to
fix the warning.

For intword, the number may contain a decimal component. In English, a
decimal component makes the noun plural. A helper function,
round_away_from_one(), was added to convert the float to an integer that
is appropriate for ngettext().

Note: See TracTickets for help on using tickets.
Back to Top