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

bpo-46659: Enhance LocaleTextCalendar for C locale #31214

Merged
merged 1 commit into from
Feb 24, 2022
Merged

bpo-46659: Enhance LocaleTextCalendar for C locale #31214

merged 1 commit into from
Feb 24, 2022

Conversation

vstinner
Copy link
Member

@vstinner vstinner commented Feb 8, 2022

If the LC_TIME locale is "C", use the user preferred locale.

https://bugs.python.org/issue46659

@vstinner
Copy link
Member Author

vstinner commented Feb 8, 2022

cc @serhiy-storchaka @eryksun

Lib/calendar.py Outdated
Comment on lines 554 to 565
self.oldlocale = _locale.setlocale(_locale.LC_TIME, None)
if self.locale is not None:
_locale.setlocale(_locale.LC_TIME, self.locale)
else:
if self.oldlocale in ("C", "POSIX"):
# The locale does not seem to be configured:
# get the user preferred locale.
_locale.setlocale(_locale.LC_TIME, "")
else:
# Otherwise simply use the current LC_TIME locale.
# The locale is not changed, __exit__() does nothing.
self.oldlocale = None
Copy link
Contributor

Choose a reason for hiding this comment

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

The problem with this is that it can change based on environment variables:

>>> locale.setlocale(locale.LC_TIME, '')
'ru_RU.utf8'
>>> os.environ['LC_ALL'] = 'en_US.utf8'
>>> locale.setlocale(locale.LC_TIME, '')
'en_US.utf8'

But the instance is supposed to capture the preferred locale when it's created.

Copy link
Member Author

Choose a reason for hiding this comment

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

Why is it so important for you to get the locale when Python is started? As you shown, there are many ways to change locales. And using an locale set before all the changes is irrelevant, so it's now outdated, no?

Copy link
Contributor

Choose a reason for hiding this comment

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

The previous code based on getdefaultlocale() was a one time check of LC_ALL, LC_CTYPE, and LANG. This was technically wrong, but in practice the default LC_TIME is usually the same as the default LC_CTYPE.

I think it's correct to use the current LC_TIME locale, if it was configured already. Not doing so was a bug. However, it should try to remain close to the previous default behavior when instantiating LocaleTextCalendar() when LC_TIME is the initial "C" value, which is usually the case if a script doesn't explicitly set LC_ALL or LC_TIME.

But changing it to re-evaluate the default via setlocale(LC_TIME, "") for every formatweekday() call is going too far. That depends on the current values of the environment variables LC_ALL, LC_TIME, and LANG, which is very different from the one-time getdefaultlocale() call in the previous code.

Lib/calendar.py Outdated
Comment on lines 568 to 583
if locale is None:
locale = _locale.getlocale(_locale.LC_TIME)
self.locale = locale
Copy link
Contributor

@eryksun eryksun Feb 8, 2022

Choose a reason for hiding this comment

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

Suggestion:

if locale is None:
    locale = _locale.getlocale(_locale.LC_TIME)
    if locale == (None, None):
        with different_locale(""):
            locale = _locale.getlocale(_locale.LC_TIME)
self.locale = locale

Copy link
Member Author

Choose a reason for hiding this comment

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

I would prefer to not change the locale in the constructor. That's why I proposed this specific PR.

Copy link
Contributor

Choose a reason for hiding this comment

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

Why is not okay to temporarily modify LC_TIME in __init__(), but fine to do so in formatweekday() and formatmonthname()? The class is documented as not thread safe with respect to the process locale.

Copy link
Member Author

Choose a reason for hiding this comment

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

It is ok to call setlocale() in __init__(). But setlocale() affects all threads, so I prefer to avoid calling it if possible.

Copy link
Contributor

@eryksun eryksun Feb 9, 2022

Choose a reason for hiding this comment

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

I think that change is the less of the two. I don't think it's worth changing the behavior from the previous code that looked up the default locale to use via getdefaultlocale() only once, instead of calling it on every entry of different_locale. But that's just me voicing one opinion. I'd prefer for other people to way in on exactly which default behaviors are important to preserve, or whether the entire default behavior of locale=None should change to use the LC_TIME locale even if it's "C".

If the LC_TIME locale is "C", use the user preferred locale.
@vstinner
Copy link
Member Author

@eryksun: I modified the implementation to only get the user preferred locale once, in the constructor. Is it better?

@vstinner
Copy link
Member Author

I tested manually the change on FreeBSD: it works, LC_TIME is also "C" at Python startup.

FreeBSD has a "POSIX" locale, but it's not used when LC_ALL, LC_CTYPE and LANG environment variable at not set: LC_CTYPE is "C" in this case.

@vstinner vstinner merged commit 4fccf91 into python:main Feb 24, 2022
@vstinner vstinner deleted the calendar_c_locale branch February 24, 2022 13:29
@vstinner
Copy link
Member Author

I merged my PR. Thanks @eryksun for your feedback and the nice idea of reusing with different_locale(""): to get the user preferred locale :-)

calendar should now be a little bit better in some corner cases, but for the regular use case, there should be no change between Python 3.10 and 3.11.

asvetlov pushed a commit that referenced this pull request Feb 26, 2022
If the LC_TIME locale is "C", use the user preferred locale.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants