Kaydet (Commit) 48d5e508 authored tarafından Walter Dörwald's avatar Walter Dörwald

Bug #947906: Add classes LocaleTextCalendar and LocaleHTMLCalendar,

that output localized month and weekday names and can cope
with encodings.
üst 1c5a59f8
......@@ -176,6 +176,24 @@ to the system default encoding).
\end{methoddesc}
\begin{classdesc}{LocaleTextCalendar}{\optional{firstweekday\optional{, locale}}}
This subclass of \class{TextCalendar} can be passed a locale name in the
constructor and will return month and weekday names in the specified locale.
If this locale includes an encoding all strings containing month and weekday
names will be returned as unicode.
\versionadded{2.5}
\end{classdesc}
\begin{classdesc}{LocaleHTMLCalendar}{\optional{firstweekday\optional{, locale}}}
This subclass of \class{HTMLCalendar} can be passed a locale name in the
constructor and will return month and weekday names in the specified locale.
If this locale includes an encoding all strings containing month and weekday
names will be returned as unicode.
\versionadded{2.5}
\end{classdesc}
For simple text calendars this module provides the following functions.
\begin{funcdesc}{setfirstweekday}{weekday}
......
......@@ -5,7 +5,7 @@ default, these calendars have Monday as the first day of the week, and
Sunday as the last (the European convention). Use setfirstweekday() to
set the first day of the week (0=Monday, 6=Sunday)."""
import sys, datetime
import sys, datetime, locale
__all__ = ["IllegalMonthError", "IllegalWeekdayError", "setfirstweekday",
"firstweekday", "isleap", "leapdays", "weekday", "monthrange",
......@@ -297,11 +297,13 @@ class TextCalendar(Calendar):
"""
return ' '.join(self.formatweekday(i, width) for i in self.iterweekdays())
def formatmonthname(self, theyear, themonth, width):
def formatmonthname(self, theyear, themonth, width, withyear=True):
"""
Return a formatted month name.
"""
s = "%s %r" % (month_name[themonth], theyear)
s = month_name[themonth]
if withyear:
s = "%s %r" % (s, theyear)
return s.center(width)
def prmonth(self, theyear, themonth, w=0, l=0):
......@@ -343,9 +345,12 @@ class TextCalendar(Calendar):
# months in this row
months = xrange(m*i+1, min(m*(i+1)+1, 13))
a('\n'*l)
a(formatstring((month_name[k] for k in months), colwidth, c).rstrip())
names = (self.formatmonthname(theyear, k, colwidth, False)
for k in months)
a(formatstring(names, colwidth, c).rstrip())
a('\n'*l)
a(formatstring((header for k in months), colwidth, c).rstrip())
headers = (header for k in months)
a(formatstring(headers, colwidth, c).rstrip())
a('\n'*l)
# max number of weeks for this row
height = max(len(cal) for cal in row)
......@@ -474,7 +479,92 @@ class HTMLCalendar(Calendar):
a(self.formatyear(theyear, width))
a('</body>\n')
a('</html>\n')
return ''.join(v).encode(encoding)
return ''.join(v).encode(encoding, "xmlcharrefreplace")
class LocaleTextCalendar(TextCalendar):
"""
This class can be passed a locale name in the constructor and will return
month and weekday names in the specified locale. If this locale includes
an encoding all strings containing month and weekday names will be returned
as unicode.
"""
def __init__(self, firstweekday=0, locale=None):
TextCalendar.__init__(self, firstweekday)
if locale is None:
locale = locale.getdefaultlocale()
self.locale = locale
def formatweekday(self, day, width):
oldlocale = locale.setlocale(locale.LC_TIME, self.locale)
try:
encoding = locale.getlocale(locale.LC_TIME)[1]
if width >= 9:
names = day_name
else:
names = day_abbr
name = names[day]
if encoding is not None:
name = name.decode(encoding)
result = name[:width].center(width)
finally:
locale.setlocale(locale.LC_TIME, oldlocale)
return result
def formatmonthname(self, theyear, themonth, width, withyear=True):
oldlocale = locale.setlocale(locale.LC_TIME, self.locale)
try:
encoding = locale.getlocale(locale.LC_TIME)[1]
s = month_name[themonth]
if encoding is not None:
s = s.decode(encoding)
if withyear:
s = "%s %r" % (s, theyear)
result = s.center(width)
finally:
locale.setlocale(locale.LC_TIME, oldlocale)
return result
class LocaleHTMLCalendar(HTMLCalendar):
"""
This class can be passed a locale name in the constructor and will return
month and weekday names in the specified locale. If this locale includes
an encoding all strings containing month and weekday names will be returned
as unicode.
"""
def __init__(self, firstweekday=0, locale=None):
HTMLCalendar.__init__(self, firstweekday)
if locale is None:
locale = locale.getdefaultlocale()
self.locale = locale
def formatweekday(self, day):
oldlocale = locale.setlocale(locale.LC_TIME, self.locale)
try:
encoding = locale.getlocale(locale.LC_TIME)[1]
s = day_abbr[day]
if encoding is not None:
s = s.decode(encoding)
result = '<th class="%s">%s</th>' % (self.cssclasses[day], s)
finally:
locale.setlocale(locale.LC_TIME, oldlocale)
return result
def formatmonthname(self, theyear, themonth, withyear=True):
oldlocale = locale.setlocale(locale.LC_TIME, self.locale)
try:
encoding = locale.getlocale(locale.LC_TIME)[1]
s = month_name[themonth]
if encoding is not None:
s = s.decode(encoding)
if withyear:
s = '%s %s' % (s, theyear)
result = '<tr><th colspan="7" class="month">%s</th></tr>' % s
finally:
locale.setlocale(locale.LC_TIME, oldlocale)
return result
# Support for old module level interface
......@@ -524,34 +614,60 @@ def timegm(tuple):
def main(args):
import optparse
parser = optparse.OptionParser(usage="usage: %prog [options] [year] [month]")
parser.add_option("-w", "--width",
dest="width", type="int", default=2,
help="width of date column (default 2, text only)")
parser.add_option("-l", "--lines",
dest="lines", type="int", default=1,
help="number of lines for each week (default 1, text only)")
parser.add_option("-s", "--spacing",
dest="spacing", type="int", default=6,
help="spacing between months (default 6, text only)")
parser.add_option("-m", "--months",
dest="months", type="int", default=3,
help="months per row (default 3, text only)")
parser.add_option("-c", "--css",
dest="css", default="calendar.css",
help="CSS to use for page (html only)")
parser.add_option("-e", "--encoding",
dest="encoding", default=None,
help="Encoding to use for CSS output (html only)")
parser.add_option("-t", "--type",
dest="type", default="text",
choices=("text", "html"),
help="output type (text or html)")
parser = optparse.OptionParser(usage="usage: %prog [options] [year [month]]")
parser.add_option(
"-w", "--width",
dest="width", type="int", default=2,
help="width of date column (default 2, text only)"
)
parser.add_option(
"-l", "--lines",
dest="lines", type="int", default=1,
help="number of lines for each week (default 1, text only)"
)
parser.add_option(
"-s", "--spacing",
dest="spacing", type="int", default=6,
help="spacing between months (default 6, text only)"
)
parser.add_option(
"-m", "--months",
dest="months", type="int", default=3,
help="months per row (default 3, text only)"
)
parser.add_option(
"-c", "--css",
dest="css", default="calendar.css",
help="CSS to use for page (html only)"
)
parser.add_option(
"-L", "--locale",
dest="locale", default=None,
help="locale to be used from month and weekday names"
)
parser.add_option(
"-e", "--encoding",
dest="encoding", default=None,
help="Encoding to use for output"
)
parser.add_option(
"-t", "--type",
dest="type", default="text",
choices=("text", "html"),
help="output type (text or html)"
)
(options, args) = parser.parse_args(args)
if options.locale and not options.encoding:
parser.error("if --locale is specified --encoding is required")
sys.exit(1)
if options.type == "html":
cal = HTMLCalendar()
if options.locale:
cal = LocaleHTMLCalendar(locale=options.locale)
else:
cal = HTMLCalendar()
encoding = options.encoding
if encoding is None:
encoding = sys.getdefaultencoding()
......@@ -564,20 +680,26 @@ def main(args):
parser.error("incorrect number of arguments")
sys.exit(1)
else:
cal = TextCalendar()
if options.locale:
cal = LocaleTextCalendar(locale=options.locale)
else:
cal = TextCalendar()
optdict = dict(w=options.width, l=options.lines)
if len(args) != 3:
optdict["c"] = options.spacing
optdict["m"] = options.months
if len(args) == 1:
print cal.formatyear(datetime.date.today().year, **optdict)
result = cal.formatyear(datetime.date.today().year, **optdict)
elif len(args) == 2:
print cal.formatyear(int(args[1]), **optdict)
result = cal.formatyear(int(args[1]), **optdict)
elif len(args) == 3:
print cal.formatmonth(int(args[1]), int(args[2]), **optdict)
result = cal.formatmonth(int(args[1]), int(args[2]), **optdict)
else:
parser.error("incorrect number of arguments")
sys.exit(1)
if options.encoding:
result = result.encode(options.encoding)
print result
if __name__ == "__main__":
......
......@@ -920,7 +920,9 @@ Library
- Bug #947906: An object oriented interface has been added to the calendar
module. It's possible to generate HTML calendar now and the module can be
called as a script (e.g. via ``python -mcalendar``).
called as a script (e.g. via ``python -mcalendar``). Localized month and
weekday names can be ouput (even if an exotic encoding is used) using
special classes that use unicode.
Build
-----
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment