Alpine linux で Django の DecimalField の quantize に失敗した場合

(Comments)

Alpine の Docker 環境で、Django Cartridge のテストに失敗していた

  File "/var/src/venv/lib/python3.6/site-packages/django/db/models/sql/compiler.py", line 958, in prepare_value
value = field.get_db_prep_save(value, connection=self.connection)
File "/var/src/venv/lib/python3.6/site-packages/django/db/models/fields/__init__.py", line 1612, in get_db_prep_save
self.max_digits, self.decimal_places)
File "/var/src/venv/lib/python3.6/site-packages/django/db/backends/base/operations.py", line 493, in adapt_decimalfield_value
return utils.format_number(value, max_digits, decimal_places)
File "/var/src/venv/lib/python3.6/site-packages/django/db/backends/utils.py", line 200, in format_number
value = value.quantize(decimal.Decimal(".1") ** decimal_places, context=context)
decimal.InvalidOperation: [<class 'decimal.InvalidOperation'>]
InvalidOperation: [<class 'decimal.InvalidOperation'>]


が出ていた。

調査すると

decimal_places が 127 になってた。

(別のテスト環境だと0で、テストが成功していた)

decimal_places は、

./manage.py shell

from locale import localeconv; localeconv()
{'currency_symbol': '¥',
'decimal_point': '.',
'frac_digits': 0,
'grouping': [],
'int_curr_symbol': 'JPY ',
'int_frac_digits': 0,
'mon_decimal_point': '.',
'mon_grouping': [3, 3, 0],
'mon_thousands_sep': ',',
'n_cs_precedes': 1,
'n_sep_by_space': 0,
'n_sign_posn': 4,
'negative_sign': '-',
'p_cs_precedes': 1,
'p_sep_by_space': 0,
'p_sign_posn': 1,
'positive_sign': '',
'thousands_sep': ''}

この、frac_digits が使われる。

テストが失敗する環境だと

 {'currency_symbol': '',
'decimal_point': '.',
'frac_digits': 127,
'grouping': [],
'int_curr_symbol': '',
'int_frac_digits': 127,
'mon_decimal_point': '',
'mon_grouping': [],
'mon_thousands_sep': '',
'n_cs_precedes': 127,
'n_sep_by_space': 127,
'n_sign_posn': 127,
'negative_sign': '',
'p_cs_precedes': 127,
'p_sep_by_space': 127,
'p_sign_posn': 127,
'positive_sign': '',
'thousands_sep': ''}


となっている。ロケールが足りないっぽい。



Dockerfile をこのように書いて、ロケール musl-locales を作ってみたが

ENV MUSL_LOCPATH="/usr/share/i18n/locales/musl"

RUN apk --no-cache add libintl && \
apk --no-cache --virtual .locale_build add cmake make musl-dev gcc gettext-dev git && \
git clone https://gitlab.com/ytyng/musl-locales && \
cd musl-locales && cmake -DLOCALE_PROFILE=OFF -DCMAKE_INSTALL_PREFIX:PATH=/usr . && make && make install && \
cd .. && rm -r musl-locales && \
apk del .locale_build


それでも int_frac_digits は変更されなかった。

方法がわからなかったので、
django の settings で

setattr(locale, '_override_localeconv',
{'currency_symbol': '¥',
'decimal_point': '.',
'frac_digits': 0,
'grouping': [],
'int_curr_symbol': 'JPY ',
'int_frac_digits': 0,
'mon_decimal_point': '.',
'mon_grouping': [3, 3, 0],
'mon_thousands_sep': ',',
'n_cs_precedes': 1,
'n_sep_by_space': 0,
'n_sign_posn': 4,
'negative_sign': '-',
'p_cs_precedes': 1,
'p_sep_by_space': 0,
'p_sign_posn': 1,
'positive_sign': '',
'thousands_sep': ''})


こんな感じで、locale._override_localeconv をパッチすると、テストが通るようになった。

ロケールが絡む環境では、Alpine Linux より Debian などを使ったほうがいいかもしれない。

Currently unrated

Comments

Recent Tweets

  • ytyng

    ytyng @ytyng

    俺もスタバアプリにログインできないよ
    10 months, 2 weeks ago

  • 安藤拓郎 Takuro Ando

    安藤拓郎 Takuro Ando @takuroando

    ytyng

    これまでいろんなグッズを作ってきたけど、今回は「お米」と聞いて買うしかないなと。今夜の夕食はコシヒカリ!箸もセットだし^^ https://t.co/01ucQx9qtw #腰乃展 #マンガ展 https://t.co/4VL2vOe0Og
    11 months ago

  • ytyng

    ytyng @ytyng

    講談社さんとやった全部入り電子書籍セットがギネスブックに登録されたよー https://t.co/rbkd3IYub0
    11 months ago