Logo Search packages:      
Sourcecode: schooltool version File versions  Download package

__init__.py

##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Locale and LocaleProvider Implementation.

$Id: __init__.py 38178 2005-08-30 21:50:19Z mj $
"""
import os
from datetime import datetime, date
from time import strptime

from zope.interface import implements
from zope.i18n.interfaces.locales import ILocale
from zope.i18n.interfaces.locales import ILocaleDisplayNames, ILocaleDates
from zope.i18n.interfaces.locales import ILocaleVersion, ILocaleIdentity
from zope.i18n.interfaces.locales import ILocaleTimeZone, ILocaleCalendar
from zope.i18n.interfaces.locales import ILocaleCurrency, ILocaleNumbers
from zope.i18n.interfaces.locales import ILocaleFormat, ILocaleFormatLength
from zope.i18n.interfaces.locales import ILocaleOrientation
from zope.i18n.format import NumberFormat, DateTimeFormat
from zope.i18n.locales.inheritance import \
     AttributeInheritance, InheritingDictionary, NoParentException
from zope.i18n.locales.provider import LocaleProvider, LoadLocaleError

# Setup the locale directory
from zope import i18n
LOCALEDIR = os.path.join(os.path.dirname(i18n.__file__), "locales", "data")

# Global LocaleProvider. We really just need this single one.
locales = LocaleProvider(LOCALEDIR)

# Define some constants that can be used

JANUARY = 1
FEBRUARY = 2
MARCH = 3
APRIL = 4
MAY = 5
JUNE = 6
JULY = 7
AUGUST = 8
SEPTEMBER = 9
OCTOBER = 10
NOVEMBER = 11
DECEMBER = 12

MONDAY = 1
TUESDAY = 2
WEDNESDAY = 3
THURSDAY = 4
FRIDAY = 5
SATURDAY = 6
SUNDAY = 7

dayMapping = {'mon': 1, 'tue': 2, 'wed': 3, 'thu': 4,
              'fri': 5, 'sat': 6, 'sun': 7}

BC = 1
AD = 2

00071 class LocaleIdentity(object):
    """Represents a unique identification of the locale

    This class does not have to deal with inheritance.

    Examples::

      >>> id = LocaleIdentity('en')
      >>> id
      <LocaleIdentity (en, None, None, None)>

      >>> id = LocaleIdentity('en', 'latin')
      >>> id
      <LocaleIdentity (en, latin, None, None)>

      >>> id = LocaleIdentity('en', 'latin', 'US')
      >>> id
      <LocaleIdentity (en, latin, US, None)>

      >>> id = LocaleIdentity('en', 'latin', 'US', 'POSIX')
      >>> id
      <LocaleIdentity (en, latin, US, POSIX)>

      >>> id = LocaleIdentity('en', None, 'US', 'POSIX')
      >>> id
      <LocaleIdentity (en, None, US, POSIX)>
    """
    implements(ILocaleIdentity)

00100     def __init__(self, language=None, script=None, territory=None, variant=None):
        """Initialize object."""
        self.language = language
        self.script = script
        self.territory = territory
        self.variant = variant

00107     def __repr__(self):
        """See zope.i18n.interfaces.ILocaleIdentity
        """
        return "<LocaleIdentity (%s, %s, %s, %s)>" %(
            self.language, self.script, self.territory, self.variant)


00114 class LocaleVersion(object):
    """Represents a particular version of a locale

    This class does not have to deal with inheritance.

    Examples::

      >>> cmp(LocaleVersion('1.0', datetime(2004, 1, 1), 'no notes'),
      ...     LocaleVersion('1.0', datetime(2004, 1, 1), 'no notes again'))
      0

      >>> cmp(LocaleVersion('1.0', datetime(2004, 1, 1), 'no notes'),
      ...     LocaleVersion('1.0', datetime(2004, 1, 2), 'no notes again'))
      -1

      >>> cmp(LocaleVersion('1.0', datetime(2004, 1, 1), 'no notes'),
      ...     LocaleVersion('0.9', datetime(2004, 1, 2), 'no notes again'))
      -1

      >>> cmp(LocaleVersion('1.0', datetime(2004, 1, 1), 'no notes'),
      ...     LocaleVersion('0.9', datetime(2004, 1, 1), 'no notes again'))
      1

    """
    implements(ILocaleVersion)

00140     def __init__(self, number, generationDate, notes):
        """Initialize object."""
        self.number = number
        assert(isinstance(generationDate, (date, type(None))))
        self.generationDate = generationDate
        self.notes = notes

    def __cmp__(self, other):
        "See zope.i18n.interfaces.ILocaleVersion"
        return cmp((self.generationDate, self.number),
                   (other.generationDate, other.number))


00153 class LocaleDisplayNames(AttributeInheritance):
    """Locale display names with inheritable data.

    Examples::

      >>> from zope.i18n.locales.tests.test_docstrings import \\
      ...     LocaleInheritanceStub
      >>> root = LocaleInheritanceStub()
      >>> root.displayNames = LocaleDisplayNames()
      >>> root.displayNames.languages = ['en', 'de']
      >>> root.displayNames.keys = ['foo', 'bar']

      >>> locale = LocaleInheritanceStub(nextLocale=root)
      >>> locale.displayNames = LocaleDisplayNames()
      >>> locale.displayNames.keys = ['fu', 'bahr']

      Here you can see the inheritance in action

      >>> locale.displayNames.languages
      ['en', 'de']
      >>> locale.displayNames.keys
      ['fu', 'bahr']
    """
    implements(ILocaleDisplayNames)


00179 class LocaleTimeZone(object):
    """Specifies one of the timezones of a specific locale.

    The attributes of this class are not inherited, since all timezone
    information is always provided together.

    Example::

      >>> tz = LocaleTimeZone('Europe/Berlin')
      >>> tz.cities = ['Berlin']
      >>> tz.names = {'standard': ('Mitteleuropaeische Zeit', 'MEZ'),
      ...             'daylight': ('Mitteleuropaeische Sommerzeit', 'MESZ')}

      >>> tz.type
      'Europe/Berlin'
      >>> tz.cities
      ['Berlin']
    """
    implements(ILocaleTimeZone)

00199     def __init__(self, type):
        """Initialize the object."""
        self.type = type
        self.cities = []
        self.names = {}


00206 class LocaleFormat(object):
    """Specifies one of the format of a specific format length.

    The attributes of this class are not inherited, since all format
    information is always provided together. Note that this information by
    itself is often not useful, since other calendar data is required to use
    the specified pattern for formatting and parsing.
    """
    implements(ILocaleFormat)

00216     def __init__(self, type=None):
        """Initialize the object."""
        self.type = type
        self.displayName = u''
        self.pattern = u''


00223 class LocaleFormatLength(AttributeInheritance):
    """Specifies one of the format lengths of a specific quantity, like
    numbers, dates, times and datetimes."""

    implements(ILocaleFormatLength)

00229     def __init__(self, type=None):
        """Initialize the object."""
        self.type = type
        self.default = None


00235 class LocaleCalendar(AttributeInheritance):
    """Represents locale data for a calendar, like 'gregorian'.

    This object is particular tricky, since the calendar not only inherits
    from higher-up locales, but also from the specified gregorian calendar
    available for this locale. This was done, since most other calendars have
    different year and era data, but everything else remains the same.

    Example::

      Even though the 'Locale' object has no 'calendar' attribute for real, it
      helps us here to make the example simpler.

      >>> from zope.i18n.locales.tests.test_docstrings import \\
      ...     LocaleInheritanceStub
      >>> root = LocaleInheritanceStub()
      >>> root.calendar = LocaleCalendar('gregorian')
      >>> locale = LocaleInheritanceStub(nextLocale=root)
      >>> locale.calendar = LocaleCalendar('gregorian')

      >>> root.calendar.months = InheritingDictionary(
      ...     {1: (u'January', u'Jan'), 2: (u'February', u'Feb')})
      >>> locale.calendar.months = InheritingDictionary(
      ...     {2: (u'Februar', u'Feb'), 3: (u'Maerz', u'Mrz')})
      >>> locale.calendar.getMonthNames()[:4]
      [u'January', u'Februar', u'Maerz', None]
      >>> locale.calendar.getMonthTypeFromName(u'January')
      1
      >>> locale.calendar.getMonthTypeFromName(u'Februar')
      2
      >>> locale.calendar.getMonthAbbreviations()[:4]
      [u'Jan', u'Feb', u'Mrz', None]
      >>> locale.calendar.getMonthTypeFromAbbreviation(u'Jan')
      1
      >>> locale.calendar.getMonthTypeFromAbbreviation(u'Mrz')
      3

      >>> root.calendar.days = InheritingDictionary(
      ...     {1: (u'Monday', u'Mon'), 2: (u'Tuesday', u'Tue')})
      >>> locale.calendar.days = InheritingDictionary(
      ...     {2: (u'Dienstag', u'Die'), 3: (u'Mittwoch', u'Mit')})
      >>> locale.calendar.getDayNames()[:4]
      [u'Monday', u'Dienstag', u'Mittwoch', None]
      >>> locale.calendar.getDayTypeFromName(u'Monday')
      1
      >>> locale.calendar.getDayTypeFromName(u'Dienstag')
      2
      >>> locale.calendar.getDayAbbreviations()[:4]
      [u'Mon', u'Die', u'Mit', None]
      >>> locale.calendar.getDayTypeFromAbbreviation(u'Mon')
      1
      >>> locale.calendar.getDayTypeFromAbbreviation(u'Die')
      2

      Let's test the direct attribute access as well.

      >>> root.am = u'AM'
      >>> root.pm = u'PM'
      >>> locale.pm = u'nachm.'
      >>> locale.pm
      u'nachm.'
      >>> locale.am
      u'AM'
    """
    implements(ILocaleCalendar)

00301     def __init__(self, type):
        """Initialize the object."""
        self.type = type

00305     def getMonthNames(self):
        """See zope.i18n.interfaces.ILocaleCalendar"""
        return [self.months.get(type, (None, None))[0] for type in range(1, 13)]

00309     def getMonthTypeFromName(self, name):
        """See zope.i18n.interfaces.ILocaleCalendar"""
        for item in self.months.items():
            if item[1][0] == name:
                return item[0]

00315     def getMonthAbbreviations(self):
        """See zope.i18n.interfaces.ILocaleCalendar"""
        return [self.months.get(type, (None, None))[1] for type in range(1, 13)]

00319     def getMonthTypeFromAbbreviation(self, abbr):
        """See zope.i18n.interfaces.ILocaleCalendar"""
        for item in self.months.items():
            if item[1][1] == abbr:
                return item[0]

00325     def getDayNames(self):
        """See zope.i18n.interfaces.ILocaleCalendar"""
        return [self.days.get(type, (None, None))[0] for type in range(1, 8)]

00329     def getDayTypeFromName(self, name):
        """See zope.i18n.interfaces.ILocaleCalendar"""
        for item in self.days.items():
            if item[1][0] == name:
                return item[0]

00335     def getDayAbbreviations(self):
        """See zope.i18n.interfaces.ILocaleCalendar"""
        return [self.days.get(type, (None, None))[1] for type in range(1, 8)]

00339     def getDayTypeFromAbbreviation(self, abbr):
        """See zope.i18n.interfaces.ILocaleCalendar"""
        for item in self.days.items():
            if item[1][1] == abbr:
                return item[0]

00345     def isWeekend(self, datetime):
        """See zope.i18n.interfaces.ILocaleCalendar"""
        day = datetime.weekday()
        time = datetime.time()
        # TODO: Implement this method
        return False

00352     def getFirstWeekDayName(self):
        """See zope.i18n.interfaces.ILocaleCalendar"""
        return self.days[dayMapping[self.week['firstDay']]][0]


00357 class LocaleDates(AttributeInheritance):
    """Simple ILocaleDates implementation that can inherit data from other
    locales.

    Examples::

      >>> from zope.i18n.tests.test_formats import LocaleCalendarStub as Stub
      >>> from datetime import datetime, date, time
      >>> dates = LocaleDates()
      >>> cal = LocaleCalendar('gregorian')
      >>> cal.months = Stub.months
      >>> cal.days = Stub.days
      >>> cal.am = Stub.am
      >>> cal.pm = Stub.pm
      >>> cal.eras = Stub.eras
      >>> cal.week = {'firstDay': 1, 'minDays': 1}
      >>> dates.calendars = {'gregorian': cal}

    Setting up and accessing date format through a specific length
    (very common scenario)

      >>> fulllength = LocaleFormatLength()
      >>> format = LocaleFormat()
      >>> format.pattern = u'EEEE, d. MMMM yyyy'
      >>> fulllength.formats = {None: format}

      >>> mediumlength = LocaleFormatLength()
      >>> format = LocaleFormat()
      >>> format.pattern = u'dd.MM.yyyy'
      >>> mediumlength.formats = {None: format}

      >>> cal.dateFormats = {'full': fulllength, 'medium': mediumlength}
      >>> cal.defaultDateFormat = 'medium'

      >>> formatter = dates.getFormatter('date')
      >>> formatter.format(date(2004, 02, 04))
      u'04.02.2004'

      >>> formatter = dates.getFormatter('date', length='full')
      >>> formatter.format(date(2004, 02, 04))
      u'Mittwoch, 4. Februar 2004'

    Let's also test the time formatter

      >>> fulllength = LocaleFormatLength()
      >>> format = LocaleFormat()
      >>> format.pattern = u"H:mm' Uhr 'z"
      >>> fulllength.formats = {None: format}

      >>> mediumlength = LocaleFormatLength()
      >>> format = LocaleFormat()
      >>> format.pattern = u'HH:mm:ss'
      >>> mediumlength.formats = {None: format}

      >>> cal.timeFormats = {'full': fulllength, 'medium': mediumlength}
      >>> cal.defaultTimeFormat = 'medium'

      >>> formatter = dates.getFormatter('time')
      >>> formatter.format(time(12, 15, 00))
      u'12:15:00'

      >>> formatter = dates.getFormatter('time', length='full')
      >>> formatter.format(time(12, 15, 00))
      u'12:15 Uhr +000'

    The datetime formatter is a bit special, since it is constructed from
    the other two:

      >>> length = LocaleFormatLength()
      >>> format = LocaleFormat()
      >>> format.pattern = u'{1} {0}'
      >>> length.formats = {None: format}
      >>> cal.dateTimeFormats = {None: length}

      >>> formatter = dates.getFormatter('dateTime')
      >>> formatter.format(datetime(2004, 02, 04, 12, 15, 00))
      u'04.02.2004 12:15:00'

      >>> formatter = dates.getFormatter('dateTime', length='full')
      >>> formatter.format(datetime(2004, 02, 04, 12, 15, 00))
      u'Mittwoch, 4. Februar 2004 12:15 Uhr +000'

    Finally, we'll test some invalid input:

      >>> dates.getFormatter('timeDate')
      Traceback (most recent call last):
      ValueError: Invalid category: timeDate

      >>> dates.getFormatter('date', length='superlong')
      Traceback (most recent call last):
      ValueError: Invalid format length: superlong

      >>> dates.getFormatter('date', calendar='irish-catholic')
      Traceback (most recent call last):
      ValueError: Invalid calendar: irish-catholic

    """
    implements(ILocaleDates)

00456     def getFormatter(self, category, length=None, name=None,
                     calendar=u'gregorian'):
        """See zope.i18n.interfaces.locales.ILocaleDates"""
        if category not in (u'date', u'time', u'dateTime'):
            raise ValueError('Invalid category: %s' % category)
        if calendar not in (u'gregorian', u'arabic', u'chinese',
                            u'civil-arabic', u'hebrew', u'japanese',
                            u'thai-buddhist'):
            raise ValueError('Invalid calendar: %s' % calendar)
        if length not in (u'short', u'medium', u'long', u'full', None):
            raise ValueError('Invalid format length: %s' % length)

        cal = self.calendars[calendar]

        formats = getattr(cal, category+'Formats')
        if length is None:
            length = getattr(
                cal,
                'default'+category[0].upper()+category[1:]+'Format',
                formats.keys()[0])

        # 'datetime' is always a bit special; we often do not have a length
        # specification, but we need it for looking up the date and time
        # formatters
        if category == 'dateTime':
            formatLength = formats.get(length, formats[None])
        else:
            formatLength = formats[length]

        if name is None:
            name = formatLength.default

        format = formatLength.formats[name]
        pattern = format.pattern

        if category == 'dateTime':
            date_pat = self.getFormatter(
                'date', length, name, calendar).getPattern()
            time_pat = self.getFormatter(
                'time', length, name, calendar).getPattern()
            pattern = pattern.replace('{1}', date_pat)
            pattern = pattern.replace('{0}', time_pat)

        return DateTimeFormat(pattern, cal)


00502 class LocaleCurrency(object):
    """Simple implementation of ILocaleCurrency without inheritance support,
    since it is not needed for a single currency."""
    implements(ILocaleCurrency)

00507     def __init__(self, type):
        """Initialize object."""
        self.type = type
        self.symbol = None
        self.symbolChoice = False
        self.displayName = None


00515 class LocaleNumbers(AttributeInheritance):
    """Implementation of ILocaleCurrency including inheritance support.

`    Examples::

      >>> numbers = LocaleNumbers()
      >>> numbers.symbols = {
      ...     'decimal': ',', 'group': '.', 'list': ';', 'percentSign': '%',
      ...     'nativeZeroDigit': '0', 'patternDigit': '#', 'plusSign': '+',
      ...     'minusSign': '-', 'exponential': 'E', 'perMille': 'o/oo',
      ...     'infinity': 'oo', 'nan': 'N/A'}

      Setting up and accessing totally unnamed decimal format
      (very common scenario)

      >>> length = LocaleFormatLength()
      >>> format = LocaleFormat()
      >>> format.pattern = u'#,##0.###;-#,##0.###'
      >>> length.formats = {None: format}
      >>> numbers.decimalFormats = {None: length}
      >>> formatter = numbers.getFormatter('decimal')
      >>> formatter.format(3.4)
      u'3,4'
      >>> formatter.format(-3.4567)
      u'-3,457'
      >>> formatter.format(3210.4)
      u'3.210,4'

      Setting up and accessing scientific formats with named format lengths

      >>> longlength = LocaleFormatLength('long')
      >>> format = LocaleFormat()
      >>> format.pattern = u'0.000###E+00'
      >>> longlength.formats = {None: format}
      >>> mediumlength = LocaleFormatLength('long')
      >>> format = LocaleFormat()
      >>> format.pattern = u'0.00##E+00'
      >>> mediumlength.formats = {None: format}
      >>> numbers.scientificFormats = {'long': longlength,
      ...                              'medium': mediumlength}
      >>> numbers.defaultScientificFormat = 'long'
      >>> formatter = numbers.getFormatter('scientific')
      >>> formatter.format(1234.5678)
      u'1,234568E+03'
      >>> formatter = numbers.getFormatter('scientific', 'medium')
      >>> formatter.format(1234.5678)
      u'1,2346E+03'

      Setting up and accessing percent formats with named format lengths
      and format names

      >>> longlength = LocaleFormatLength('long')
      >>> fooformat = LocaleFormat()
      >>> fooformat.pattern = u'0.##0%'
      >>> barformat = LocaleFormat()
      >>> barformat.pattern = u'0%'
      >>> longlength.formats = {None: fooformat, 'bar': barformat}
      >>> numbers.percentFormats = {'long': longlength}
      >>> numbers.defaultPercentFormat = 'long'
      >>> formatter = numbers.getFormatter('percent')
      >>> formatter.format(123.45678)
      u'123,457%'
      >>> formatter = numbers.getFormatter('percent', name='bar')
      >>> formatter.format(123.45678)
      u'123%'

      ...using a default name

      >>> numbers.percentFormats['long'].default = 'bar'
      >>> formatter = numbers.getFormatter('percent')
      >>> formatter.format(123.45678)
      u'123%'

    """
    implements(ILocaleNumbers)

00591     def getFormatter(self, category, length=None, name=None):
        """See zope.i18n.interfaces.locales.ILocaleNumbers"""
        assert category in (u'decimal', u'percent', u'scientific', u'currency')
        assert length in (u'short', u'medium', u'long', u'full', None)

        formats = getattr(self, category+'Formats')
        if length is None:
            length = getattr(
                self,
                'default'+category[0].upper()+category[1:]+'Format',
                formats.keys()[0])
        formatLength = formats[length]

        if name is None:
            name = formatLength.default

        format = formatLength.formats[name]

        return NumberFormat(format.pattern, self.symbols)


00612 class LocaleOrientation(AttributeInheritance):
    """Implementation of ILocaleOrientation
    """
    implements(ILocaleOrientation)

00617 class Locale(AttributeInheritance):
    """Implementation of the ILocale interface."""
    implements(ILocale)

    def __init__(self, id):
        self.id = id

00624     def getLocaleID(self):
        """Return the locale id."""
        id = self.id
        pieces = filter(None,
                        (id.language, id.script, id.territory, id.variant))
        id_string = '_'.join(pieces)
        # TODO: What about keys??? Where do I get this info from?
        pieces = [key+'='+type for key, type in ()]
        if pieces:
            id_string += '@' + ','.join(pieces)
        return id_string

00636     def getInheritedSelf(self):
        """See zope.i18n.interfaces.locales.ILocaleInheritance

        This is the really interesting method that looks up the next (more
        general) Locale object. This is used in case this locale object does
        not have the required information.

        This method works closely with with LocaleProvider.
        """
        language = self.id.language
        territory = self.id.territory
        variant = self.id.variant
        if variant is not None:
            return locales.getLocale(language, territory, None)
        elif territory is not None:
            return locales.getLocale(language, None, None)
        elif language is not None:
            return locales.getLocale(None, None, None)
        else:
            # Well, this is bad; we are already at the root locale
            raise NoParentException('Cannot find a more general locale.')

Generated by  Doxygen 1.6.0   Back to index