__init__.py revision 469cdad8228df7bc294dc946b8cd4c0b7f810735
1""" Standard "encodings" Package
2
3    Standard Python encoding modules are stored in this package
4    directory.
5
6    Codec modules must have names corresponding to standard lower-case
7    encoding names with hyphens mapped to underscores, e.g. 'utf-8' is
8    implemented by the module 'utf_8.py'.
9
10    Each codec module must export the following interface:
11
12    * getregentry() -> (encoder, decoder, stream_reader, stream_writer)
13    The getregentry() API must return callable objects which adhere to
14    the Python Codec Interface Standard.
15
16    In addition, a module may optionally also define the following
17    APIs which are then used by the package's codec search function:
18
19    * getaliases() -> sequence of encoding name strings to use as aliases
20
21    Alias names returned by getaliases() must be standard encoding
22    names as defined above (lower-case, hyphens converted to
23    underscores).
24
25Written by Marc-Andre Lemburg (mal@lemburg.com).
26
27(c) Copyright CNRI, All Rights Reserved. NO WARRANTY.
28
29"""#"
30
31import codecs,exceptions
32
33_cache = {}
34_unknown = '--unknown--'
35_import_tail = ['*']
36
37class CodecRegistryError(exceptions.LookupError,
38                         exceptions.SystemError):
39    pass
40
41def search_function(encoding):
42
43    # Cache lookup
44    entry = _cache.get(encoding, _unknown)
45    if entry is not _unknown:
46        return entry
47
48    # Import the module:
49    #
50    # First look in the encodings package, then try to lookup the
51    # encoding in the aliases mapping and retry the import using the
52    # default import module lookup scheme with the alias name.
53    #
54    modname = encoding.replace('-', '_')
55    try:
56        mod = __import__('encodings.' + modname,
57                         globals(), locals(), _import_tail)
58    except ImportError:
59        import aliases
60        modname = aliases.aliases.get(modname, modname)
61        try:
62            mod = __import__(modname, globals(), locals(), _import_tail)
63        except ImportError:
64            mod = None
65
66    try:
67        getregentry = mod.getregentry
68    except AttributeError:
69        # Not a codec module
70        mod = None
71
72    if mod is None:
73        # Cache misses
74        _cache[encoding] = None
75        return None
76
77    # Now ask the module for the registry entry
78    entry = tuple(getregentry())
79    if len(entry) != 4:
80        raise CodecRegistryError,\
81              'module "%s" (%s) failed to register' % \
82              (mod.__name__, mod.__file__)
83    for obj in entry:
84        if not callable(obj):
85            raise CodecRegistryError,\
86                  'incompatible codecs in module "%s" (%s)' % \
87                  (mod.__name__, mod.__file__)
88
89    # Cache the codec registry entry
90    _cache[encoding] = entry
91
92    # Register its aliases (without overwriting previously registered
93    # aliases)
94    try:
95        codecaliases = mod.getaliases()
96    except AttributeError:
97        pass
98    else:
99        import aliases
100        for alias in codecaliases:
101            if not aliases.aliases.has_key(alias):
102                aliases.aliases[alias] = modname
103
104    # Return the registry entry
105    return entry
106
107# Register the search_function in the Python codec registry
108codecs.register(search_function)
109