Opened 7 years ago

Closed 5 years 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: dev
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 by Claude Paroz, 7 years ago

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 by Tim Graham, 7 years ago

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 by Tim Graham, 7 years ago

Owner: Tim Graham removed
Status: assignednew

comment:4 by Jon Dufresne, 5 years ago

Has patch: set

comment:5 by Mariusz Felisiak <felisiak.mariusz@…>, 5 years ago

In 53ea535f:

Refs #27486 -- Added tests for filesizeformat filter.

comment:6 by Mariusz Felisiak <felisiak.mariusz@…>, 5 years ago

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