Coverage for /home/martinb/.local/share/virtualenvs/camcops/lib/python3.6/site-packages/pandas/_config/localization.py : 22%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1"""
2Helpers for configuring locale settings.
4Name `localization` is chosen to avoid overlap with builtin `locale` module.
5"""
6from contextlib import contextmanager
7import locale
8import re
9import subprocess
11from pandas._config.config import options
14@contextmanager
15def set_locale(new_locale, lc_var=locale.LC_ALL):
16 """
17 Context manager for temporarily setting a locale.
19 Parameters
20 ----------
21 new_locale : str or tuple
22 A string of the form <language_country>.<encoding>. For example to set
23 the current locale to US English with a UTF8 encoding, you would pass
24 "en_US.UTF-8".
25 lc_var : int, default `locale.LC_ALL`
26 The category of the locale being set.
28 Notes
29 -----
30 This is useful when you want to run a particular block of code under a
31 particular locale, without globally setting the locale. This probably isn't
32 thread-safe.
33 """
34 current_locale = locale.getlocale()
36 try:
37 locale.setlocale(lc_var, new_locale)
38 normalized_locale = locale.getlocale()
39 if all(x is not None for x in normalized_locale):
40 yield ".".join(normalized_locale)
41 else:
42 yield new_locale
43 finally:
44 locale.setlocale(lc_var, current_locale)
47def can_set_locale(lc, lc_var=locale.LC_ALL):
48 """
49 Check to see if we can set a locale, and subsequently get the locale,
50 without raising an Exception.
52 Parameters
53 ----------
54 lc : str
55 The locale to attempt to set.
56 lc_var : int, default `locale.LC_ALL`
57 The category of the locale being set.
59 Returns
60 -------
61 is_valid : bool
62 Whether the passed locale can be set
63 """
65 try:
66 with set_locale(lc, lc_var=lc_var):
67 pass
68 except (ValueError, locale.Error):
69 # horrible name for a Exception subclass
70 return False
71 else:
72 return True
75def _valid_locales(locales, normalize):
76 """
77 Return a list of normalized locales that do not throw an ``Exception``
78 when set.
80 Parameters
81 ----------
82 locales : str
83 A string where each locale is separated by a newline.
84 normalize : bool
85 Whether to call ``locale.normalize`` on each locale.
87 Returns
88 -------
89 valid_locales : list
90 A list of valid locales.
91 """
92 if normalize:
93 normalizer = lambda x: locale.normalize(x.strip())
94 else:
95 normalizer = lambda x: x.strip()
97 return list(filter(can_set_locale, map(normalizer, locales)))
100def _default_locale_getter():
101 raw_locales = subprocess.check_output(["locale -a"], shell=True)
102 return raw_locales
105def get_locales(prefix=None, normalize=True, locale_getter=_default_locale_getter):
106 """
107 Get all the locales that are available on the system.
109 Parameters
110 ----------
111 prefix : str
112 If not ``None`` then return only those locales with the prefix
113 provided. For example to get all English language locales (those that
114 start with ``"en"``), pass ``prefix="en"``.
115 normalize : bool
116 Call ``locale.normalize`` on the resulting list of available locales.
117 If ``True``, only locales that can be set without throwing an
118 ``Exception`` are returned.
119 locale_getter : callable
120 The function to use to retrieve the current locales. This should return
121 a string with each locale separated by a newline character.
123 Returns
124 -------
125 locales : list of strings
126 A list of locale strings that can be set with ``locale.setlocale()``.
127 For example::
129 locale.setlocale(locale.LC_ALL, locale_string)
131 On error will return None (no locale available, e.g. Windows)
133 """
134 try:
135 raw_locales = locale_getter()
136 except subprocess.CalledProcessError:
137 # Raised on (some? all?) Windows platforms because Note: "locale -a"
138 # is not defined
139 return None
141 try:
142 # raw_locales is "\n" separated list of locales
143 # it may contain non-decodable parts, so split
144 # extract what we can and then rejoin.
145 raw_locales = raw_locales.split(b"\n")
146 out_locales = []
147 for x in raw_locales:
148 try:
149 out_locales.append(str(x, encoding=options.display.encoding))
150 except UnicodeError:
151 # 'locale -a' is used to populated 'raw_locales' and on
152 # Redhat 7 Linux (and maybe others) prints locale names
153 # using windows-1252 encoding. Bug only triggered by
154 # a few special characters and when there is an
155 # extensive list of installed locales.
156 out_locales.append(str(x, encoding="windows-1252"))
158 except TypeError:
159 pass
161 if prefix is None:
162 return _valid_locales(out_locales, normalize)
164 pattern = re.compile(f"{prefix}.*")
165 found = pattern.findall("\n".join(out_locales))
166 return _valid_locales(found, normalize)