Skip to content

bpo-17659: Add locale.getfirstweekday #18142

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

Open
wants to merge 35 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
db86bbd
bpo-17659: Add locale.getfirstweekday
cedk Jan 23, 2020
7adec3b
Use French as testing local on Windows
cedk Jan 23, 2020
149e981
Skip fr_FR test on windows platform
cedk Jan 23, 2020
53d1617
Use BaseLocalizedTest class to test getfirstweekday
cedk Feb 9, 2020
45f60ce
Use links in news
cedk Mar 28, 2020
128512f
Use PyLong_FromLong instead of Py_BuildValue
cedk Mar 28, 2020
c5227db
Add missing args agument
cedk Mar 28, 2020
ca91d71
Merge branch 'master' into locale-first-weekday
cedk Mar 27, 2021
0fc147f
Update versionadded
cedk Mar 27, 2021
fcb49ed
Set only LC_TIME for test
cedk Apr 20, 2021
e2d62f1
Restore original aclocal.m4
cedk Apr 27, 2021
bd1c7de
Merge branch 'main' of https://github.com/python/cpython into locale-…
cedk Oct 7, 2021
727d186
Update versionadded
cedk Oct 7, 2021
1ba7c75
Return None if unknown
cedk Nov 4, 2021
dc6e26a
Merge branch 'main' into locale-first-weekday
cedk Nov 4, 2021
df2b213
Correctly test if start is between 0 and 6
cedk Nov 4, 2021
6503b65
Return None instead of NULL
cedk Nov 4, 2021
6f6b9a4
Fix conversion of windows value
cedk Nov 4, 2021
dd5125c
Default first day of the week on Windows is Sunday
cedk Nov 4, 2021
c898b18
Do not test fallback on glibc
cedk Nov 4, 2021
050f04f
Fix indentation
cedk Nov 5, 2021
351add0
Merge branch 'main' into locale-first-weekday
cedk Dec 8, 2021
d65d016
autoreconf
cedk Dec 8, 2021
3afd7f4
Use aclocal 1.16.3
cedk Dec 9, 2021
aff2d86
Remove unrelated change from generated files
cedk Dec 9, 2021
bff7081
Fix serial
cedk Dec 9, 2021
06e4b07
Simplify preprocessor clause
cedk Dec 9, 2021
b46ccf5
Fix ac usage
cedk Dec 9, 2021
7481abe
Replace test by AS_VAR_IF
cedk Dec 9, 2021
af18d0a
Fix usage of AC_CACHE_CHECK
cedk Dec 9, 2021
5774de6
Add comment about magic constant
cedk Dec 9, 2021
eb6629d
Restore missing define of _NL_TIME_FIRST_WEEKDAY
cedk Dec 9, 2021
b4c59e3
Use AS_VAR_IF
cedk Dec 9, 2021
d04795a
Return None for unknown week_1stday
cedk Dec 9, 2021
fadf91e
Keep default week_1stday as Sunday
cedk Dec 9, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions Doc/library/locale.rst
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,14 @@ The :mod:`locale` module defines the following exception and functions:
0 to 99.


.. function:: getfirstweekday()

Return the first day of week as integer or ``None`` when unknown.
0 is Monday, 6 is Sunday.

.. versionadded:: 3.11


.. function:: getdefaultlocale([envvars])

Tries to determine the default locale settings and returns them as a tuple of
Expand Down
25 changes: 25 additions & 0 deletions Lib/test/test_locale.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from test.support.warnings_helper import check_warnings
import unittest
import locale
import platform
import sys
import codecs

Expand Down Expand Up @@ -583,6 +584,30 @@ def test_invalid_iterable_in_localetuple(self):
locale.setlocale(locale.LC_ALL, (b'not', b'valid'))


class TestGetFirstWeekDay(BaseLocalizedTest):

locale_type = locale.LC_TIME

def test_getfirstweekday(self):
if platform.libc_ver()[0] == 'glibc':
self.assertEqual(locale.getfirstweekday(), 0)
elif platform.system() == 'Windows':
self.assertEqual(locale.getfirstweekday(), 6)
else:
self.assertEqual(locale.getfirstweekday(), None)
Copy link
Member

Choose a reason for hiding this comment

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

Have you verified that the test passes on musl libc?

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 do not have access to such system.


@unittest.skipUnless(
platform.libc_ver()[0] == 'glibc'
or platform.system() == 'Windows',
"Implemented and modifiable only with glibc or on Windows")
def test_getfirstweekday_fr(self):
try:
locale.setlocale(self.locale_type, 'fr_FR')
except locale.Error:
self.skipTest('test needs fr_FR locale')
self.assertEqual(locale.getfirstweekday(), 1)


class BaseDelocalizeTest(BaseLocalizedTest):

def _test_delocalize(self, value, out):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Provide a :func:`locale.getfirstweekday()` function, which returns the integer
of the first day of week.
41 changes: 41 additions & 0 deletions Modules/_localemodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -623,6 +623,45 @@ _locale_nl_langinfo_impl(PyObject *module, int item)
}
#endif /* HAVE_LANGINFO_H */

PyDoc_STRVAR(getfirstweekday__doc__,
"getfirstweekday() -> integer\n"
"Return the first day of week. 0 is Monday, 6 is Sunday and None is unknown");

static PyObject*
PyLocale_getfirstweekday(PyObject* self, PyObject* args)
{
int start = -1;
#if defined(MS_WINDOWS)
char locale[1];

if (!GetLocaleInfo(LOCALE_USER_DEFAULT,
LOCALE_IFIRSTDAYOFWEEK,
locale, sizeof(locale))) {
start = (locale[0] - '0') % 7;
}
#elif defined(HAVE__NL_TIME_FIRST_WEEKDAY)
int first_weekday = nl_langinfo(_NL_TIME_FIRST_WEEKDAY)[0];
long week_1stday = (long)nl_langinfo(_NL_TIME_WEEK_1STDAY);
/* Magic constant is defined by glibc as the third value of the week
* keyword of LC_TIME */
switch (week_1stday) {
default:
Copy link
Member

Choose a reason for hiding this comment

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

Shouldn't default map to None?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Indeed it seems that some version of glibc under en_US does not return one of the two values.

case 19971130:
week_1stday = 0;
break;
case 19971201:
week_1stday = 1;
break;
}
start = (week_1stday + first_weekday - 1) % 7;
#endif
if (0 <= start && start <= 6) {
return PyLong_FromLong(start);
} else {
Py_RETURN_NONE;
}
}

#ifdef HAVE_LIBINTL_H

/*[clinic input]
Expand Down Expand Up @@ -801,6 +840,8 @@ static struct PyMethodDef PyLocale_Methods[] = {
#ifdef HAVE_LANGINFO_H
_LOCALE_NL_LANGINFO_METHODDEF
#endif
{"getfirstweekday", (PyCFunction) PyLocale_getfirstweekday,
METH_NOARGS, getfirstweekday__doc__},
#ifdef HAVE_LIBINTL_H
_LOCALE_GETTEXT_METHODDEF
_LOCALE_DGETTEXT_METHODDEF
Expand Down
39 changes: 39 additions & 0 deletions configure
Original file line number Diff line number Diff line change
Expand Up @@ -19197,6 +19197,45 @@ then

$as_echo "#define HAVE_STAT_TV_NSEC2 1" >>confdefs.h

fi

# checking for glibc extensions to langinfo.h
# _NL_TIME_FIRST_WEEKDAY isn't #define'd, so test it directly
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for _NL_TIME_FIRST_WEEKDAY" >&5
$as_echo_n "checking for _NL_TIME_FIRST_WEEKDAY... " >&6; }
if ${ac_cv_have__nl_time_first_weekday+:} false; then :
$as_echo_n "(cached) " >&6
else

cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <langinfo.h>
int
main ()
{

return !!nl_langinfo(_NL_TIME_FIRST_WEEKDAY);

;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
ac_cv_have__nl_time_first_weekday=yes
else
ac_cv_have__nl_time_first_weekday=no
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext

fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have__nl_time_first_weekday" >&5
$as_echo "$ac_cv_have__nl_time_first_weekday" >&6; }
if test "x$ac_cv_have__nl_time_first_weekday" = xyes; then :


$as_echo "#define HAVE__NL_TIME_FIRST_WEEKDAY 1" >>confdefs.h


fi

# first curses header check
Expand Down
12 changes: 12 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -5476,6 +5476,18 @@ then
[Define if you have struct stat.st_mtimensec])
fi

# checking for glibc extensions to langinfo.h
# _NL_TIME_FIRST_WEEKDAY isn't #define'd, so test it directly
AC_CACHE_CHECK([for _NL_TIME_FIRST_WEEKDAY], [ac_cv_have__nl_time_first_weekday], [
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include <langinfo.h>], [
return !!nl_langinfo(_NL_TIME_FIRST_WEEKDAY);
])], [ac_cv_have__nl_time_first_weekday=yes], [ac_cv_have__nl_time_first_weekday=no])
])
AS_VAR_IF([ac_cv_have__nl_time_first_weekday], [yes], [
AC_DEFINE(HAVE__NL_TIME_FIRST_WEEKDAY, 1,
[Define if you have _NL_TIME_FIRST_WEEKDAY in langinfo.h])
])

# first curses header check
ac_save_cppflags="$CPPFLAGS"
if test "$cross_compiling" = no; then
Expand Down
3 changes: 3 additions & 0 deletions pyconfig.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -1426,6 +1426,9 @@
/* Define to 1 if you have the `_getpty' function. */
#undef HAVE__GETPTY

/* Define if you have _NL_TIME_FIRST_WEEKDAY in langinfo.h */
#undef HAVE__NL_TIME_FIRST_WEEKDAY

/* Define to 1 if `major', `minor', and `makedev' are declared in <mkdev.h>.
*/
#undef MAJOR_IN_MKDEV
Expand Down