mirror of
https://github.com/janeczku/calibre-web
synced 2024-12-01 05:49:58 +00:00
bbf6d9b026
Bugfix for feeds - removed categories related and up - load new books now working - category random now working login page is free of non accessible elements boolean custom column is vivible in UI books with only with certain languages can be shown book shelfs can be deleted from UI Anonymous user view is more resticted Added browse of series in sidebar Dependencys in vendor folder are updated to newer versions (licencs files are now present) Bugfix editing Authors names Made upload on windows working
210 lines
6.1 KiB
Python
210 lines
6.1 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""
|
|
babel.localedata
|
|
~~~~~~~~~~~~~~~~
|
|
|
|
Low-level locale data access.
|
|
|
|
:note: The `Locale` class, which uses this module under the hood, provides a
|
|
more convenient interface for accessing the locale data.
|
|
|
|
:copyright: (c) 2013 by the Babel Team.
|
|
:license: BSD, see LICENSE for more details.
|
|
"""
|
|
|
|
import os
|
|
import threading
|
|
from collections import MutableMapping
|
|
|
|
from babel._compat import pickle
|
|
|
|
|
|
_cache = {}
|
|
_cache_lock = threading.RLock()
|
|
_dirname = os.path.join(os.path.dirname(__file__), 'localedata')
|
|
|
|
|
|
def exists(name):
|
|
"""Check whether locale data is available for the given locale. Ther
|
|
return value is `True` if it exists, `False` otherwise.
|
|
|
|
:param name: the locale identifier string
|
|
"""
|
|
if name in _cache:
|
|
return True
|
|
return os.path.exists(os.path.join(_dirname, '%s.dat' % name))
|
|
|
|
|
|
def locale_identifiers():
|
|
"""Return a list of all locale identifiers for which locale data is
|
|
available.
|
|
|
|
.. versionadded:: 0.8.1
|
|
|
|
:return: a list of locale identifiers (strings)
|
|
"""
|
|
return [stem for stem, extension in [
|
|
os.path.splitext(filename) for filename in os.listdir(_dirname)
|
|
] if extension == '.dat' and stem != 'root']
|
|
|
|
|
|
def load(name, merge_inherited=True):
|
|
"""Load the locale data for the given locale.
|
|
|
|
The locale data is a dictionary that contains much of the data defined by
|
|
the Common Locale Data Repository (CLDR). This data is stored as a
|
|
collection of pickle files inside the ``babel`` package.
|
|
|
|
>>> d = load('en_US')
|
|
>>> d['languages']['sv']
|
|
u'Swedish'
|
|
|
|
Note that the results are cached, and subsequent requests for the same
|
|
locale return the same dictionary:
|
|
|
|
>>> d1 = load('en_US')
|
|
>>> d2 = load('en_US')
|
|
>>> d1 is d2
|
|
True
|
|
|
|
:param name: the locale identifier string (or "root")
|
|
:param merge_inherited: whether the inherited data should be merged into
|
|
the data of the requested locale
|
|
:raise `IOError`: if no locale data file is found for the given locale
|
|
identifer, or one of the locales it inherits from
|
|
"""
|
|
_cache_lock.acquire()
|
|
try:
|
|
data = _cache.get(name)
|
|
if not data:
|
|
# Load inherited data
|
|
if name == 'root' or not merge_inherited:
|
|
data = {}
|
|
else:
|
|
parts = name.split('_')
|
|
if len(parts) == 1:
|
|
parent = 'root'
|
|
else:
|
|
parent = '_'.join(parts[:-1])
|
|
data = load(parent).copy()
|
|
filename = os.path.join(_dirname, '%s.dat' % name)
|
|
fileobj = open(filename, 'rb')
|
|
try:
|
|
if name != 'root' and merge_inherited:
|
|
merge(data, pickle.load(fileobj))
|
|
else:
|
|
data = pickle.load(fileobj)
|
|
_cache[name] = data
|
|
finally:
|
|
fileobj.close()
|
|
return data
|
|
finally:
|
|
_cache_lock.release()
|
|
|
|
|
|
def merge(dict1, dict2):
|
|
"""Merge the data from `dict2` into the `dict1` dictionary, making copies
|
|
of nested dictionaries.
|
|
|
|
>>> d = {1: 'foo', 3: 'baz'}
|
|
>>> merge(d, {1: 'Foo', 2: 'Bar'})
|
|
>>> items = d.items(); items.sort(); items
|
|
[(1, 'Foo'), (2, 'Bar'), (3, 'baz')]
|
|
|
|
:param dict1: the dictionary to merge into
|
|
:param dict2: the dictionary containing the data that should be merged
|
|
"""
|
|
for key, val2 in dict2.items():
|
|
if val2 is not None:
|
|
val1 = dict1.get(key)
|
|
if isinstance(val2, dict):
|
|
if val1 is None:
|
|
val1 = {}
|
|
if isinstance(val1, Alias):
|
|
val1 = (val1, val2)
|
|
elif isinstance(val1, tuple):
|
|
alias, others = val1
|
|
others = others.copy()
|
|
merge(others, val2)
|
|
val1 = (alias, others)
|
|
else:
|
|
val1 = val1.copy()
|
|
merge(val1, val2)
|
|
else:
|
|
val1 = val2
|
|
dict1[key] = val1
|
|
|
|
|
|
class Alias(object):
|
|
"""Representation of an alias in the locale data.
|
|
|
|
An alias is a value that refers to some other part of the locale data,
|
|
as specified by the `keys`.
|
|
"""
|
|
|
|
def __init__(self, keys):
|
|
self.keys = tuple(keys)
|
|
|
|
def __repr__(self):
|
|
return '<%s %r>' % (type(self).__name__, self.keys)
|
|
|
|
def resolve(self, data):
|
|
"""Resolve the alias based on the given data.
|
|
|
|
This is done recursively, so if one alias resolves to a second alias,
|
|
that second alias will also be resolved.
|
|
|
|
:param data: the locale data
|
|
:type data: `dict`
|
|
"""
|
|
base = data
|
|
for key in self.keys:
|
|
data = data[key]
|
|
if isinstance(data, Alias):
|
|
data = data.resolve(base)
|
|
elif isinstance(data, tuple):
|
|
alias, others = data
|
|
data = alias.resolve(base)
|
|
return data
|
|
|
|
|
|
class LocaleDataDict(MutableMapping):
|
|
"""Dictionary wrapper that automatically resolves aliases to the actual
|
|
values.
|
|
"""
|
|
|
|
def __init__(self, data, base=None):
|
|
self._data = data
|
|
if base is None:
|
|
base = data
|
|
self.base = base
|
|
|
|
def __len__(self):
|
|
return len(self._data)
|
|
|
|
def __iter__(self):
|
|
return iter(self._data)
|
|
|
|
def __getitem__(self, key):
|
|
orig = val = self._data[key]
|
|
if isinstance(val, Alias): # resolve an alias
|
|
val = val.resolve(self.base)
|
|
if isinstance(val, tuple): # Merge a partial dict with an alias
|
|
alias, others = val
|
|
val = alias.resolve(self.base).copy()
|
|
merge(val, others)
|
|
if type(val) is dict: # Return a nested alias-resolving dict
|
|
val = LocaleDataDict(val, base=self.base)
|
|
if val is not orig:
|
|
self._data[key] = val
|
|
return val
|
|
|
|
def __setitem__(self, key, value):
|
|
self._data[key] = value
|
|
|
|
def __delitem__(self, key):
|
|
del self._data[key]
|
|
|
|
def copy(self):
|
|
return LocaleDataDict(self._data.copy(), base=self.base)
|