Opened 20 years ago
Closed 15 years ago
#2971 closed defect (fixed)
Unicode encoding error w/ Windows & defined locale
| Reported by: | Emmanuel Blot | Owned by: | Christian Boos |
|---|---|---|---|
| Priority: | normal | Milestone: | 0.10 |
| Component: | general | Version: | devel |
| Severity: | major | Keywords: | unicode windows python23 |
| Cc: | lists@… | Branch: | |
| Release Notes: | |||
| API Changes: | |||
| Internal Changes: | |||
Description
The following piece of code:
encoding = locale.getlocale(locale.LC_TIME)[1] or \ locale.getpreferredencoding()
in /trac/util/__init__.py breaks w/ Windows & ActiveState Python 2.3:
ActivePython 2.3.5 Build 236 (ActiveState Corp.) based on Python 2.3.5 (#62, Feb 9 2005, 16:17:08) [MSC v.1200 32 bit (Intel)] on win32
with the following Python stack trace
Traceback (most recent call last):
File "trac\web\main.py", line 308, in dispatch_request
dispatcher.dispatch(req)
File "trac\web\main.py", line 153, in dispatch
populate_hdf(req.hdf, self.env, req)
File "trac\web\main.py", line 69, in populate_hdf
hdf['trac'] = {
File "trac\util\__init__.py", line 198, in format_datetime
return unicode(text, encoding, 'replace')
LookupError: unknown encoding: 1252
when locale is defined.
It seems the trouble comes from the Python encoding:
>>> import locale >>> locale.setlocale(locale.LC_ALL, 'French_France') 'French_France.1252' >>> locale.setlocale(locale.LC_ALL, 'English_United-Kingdom') 'English_United Kingdom.1252' >>> locale.getlocale(locale.LC_TIME)[1] '1252'
The expected code page was cp1252, not 1252:
>>> locale.getpreferredencoding()
'cp1252'
>>> unicode('test', 'cp1252', 'replace')
u'test'
>>> unicode('test', '1252', 'replace')
Traceback (most recent call last):
File "<stdin>", line 1, in ?
LookupError: unknown encoding: 1252
Attachments (0)
Change History (12)
comment:1 by , 20 years ago
| Milestone: | → 0.10 |
|---|---|
| Owner: | changed from to |
comment:2 by , 20 years ago
Emmanuel, this fix worked for me, could you try it out?
Index: trac/util/__init__.py
===================================================================
--- trac/util/__init__.py (revision 3118)
+++ trac/util/__init__.py (working copy)
@@ -208,8 +208,8 @@
t = time.localtime(int(t))
text = time.strftime(format, t)
- encoding = locale.getlocale(locale.LC_TIME)[1] or \
- locale.getpreferredencoding()
+ lc_time_encoding = sys.platform != 'win32' and getlocale(locale.LC_TIME)[1]
+ encoding = lc_time_encoding or locale.getpreferredencoding()
return unicode(text, encoding, 'replace')
def format_date(t=None, format='%x', gmt=False):
comment:4 by , 18 years ago
| Keywords: | python23 added |
|---|
More precisely, that was a win32 issue with Python 2.3. When using 2.4 or 2.5, the original code would have worked just fine ('1252' is a known encoding alias). See follow-up change r6113.
comment:5 by , 17 years ago
| Resolution: | fixed |
|---|---|
| Status: | closed → reopened |
This won't work for Thai on Python 2.5
'abc'.encode('cp874')
'abc'
'abc'.encode('874')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
LookupError: unknown encoding: 874
comment:6 by , 17 years ago
I cannot find information to confirm the behaviour for every python versions across every platforms.
I use this fix for my own Trac:
def format_datetime(t=None, format='%x %X', tzinfo=None):
"""Format the `datetime` object `t` into an `unicode` string
If `t` is None, the current time will be used.
The formatting will be done using the given `format`, which consist
of conventional `strftime` keys. In addition the format can be 'iso8601'
to specify the international date format.
`tzinfo` will default to the local timezone if left to `None`.
"""
t = to_datetime(t, tzinfo).astimezone(tzinfo or localtz)
if format.lower() == 'iso8601':
format = '%Y-%m-%dT%H:%M:%SZ%z'
text = t.strftime(format)
encoding1 = locale.getpreferredencoding() or sys.getdefaultencoding()
encoding2 = locale.getlocale(locale.LC_TIME)[1] or encoding1
try:
return unicode(text, encoding2, 'replace')
except LookupError:
return unicode(text, encoding1, 'replace')
comment:7 by , 17 years ago
| Milestone: | 0.10 → 0.11.1 |
|---|
comment:9 by , 17 years ago
| Milestone: | 0.11.2 → 0.11.3 |
|---|
comment:11 by , 15 years ago
| Cc: | added |
|---|---|
| Milestone: | next-minor-0.12.x → 0.13 |
Python 2.3, is that still supported? py2.4 willbe dropped in trac 0.13, let's close this?
comment:12 by , 15 years ago
| Milestone: | 0.13 → 0.10 |
|---|---|
| Resolution: | → fixed |
| Status: | reopened → closed |
Right, and something has been fixed in 0.10 (comment:3).



Using only
locale.getpreferredencoding()would work on windows, but not on Linux, where setting thelocaledoesn't seem to affect it (e.g. after alocale.setlocale(locale.LC_ALL, 'French'), mylocale.getpreferredencoding()was still 'UTF-8', whereaslocale.getlocale(locale.LC_TIME)[1]gave 'ISO8859-1', which was consistent with the encoding used bystrftime).So I guess some platform dependent code is in order here…