better portalocker
This commit is contained in:
@@ -1 +1 @@
|
|||||||
Version 2.00.0 (2012-08-27 07:41:29) dev
|
Version 2.00.0 (2012-08-27 10:06:06) dev
|
||||||
|
|||||||
+58
-114
@@ -31,10 +31,19 @@ __all__ = ['translator', 'findT', 'update_all_languages']
|
|||||||
ospath = os.path
|
ospath = os.path
|
||||||
ostat = os.stat
|
ostat = os.stat
|
||||||
osep = os.sep
|
osep = os.sep
|
||||||
|
isdir = os.path.isdir
|
||||||
is_gae = settings.global_settings.web2py_runtime_gae
|
is_gae = settings.global_settings.web2py_runtime_gae
|
||||||
|
|
||||||
DEFAULT_ACCEPT_LANGUAGE = 'en'
|
DEFAULT_ACCEPT_LANGUAGE = 'en'
|
||||||
|
|
||||||
|
# DEFAULT PLURAL-FORMS RULES:
|
||||||
|
# language doesn't use plural forms
|
||||||
|
DEFAULT_NPLURALS = 1
|
||||||
|
# only one singular/plural form is used
|
||||||
|
DEFAULT_GET_PLURAL_ID = lambda n: 0
|
||||||
|
# word is unchangeable
|
||||||
|
DEFAULT_CONSTRUCTOR_PLURAL_FORM = lambda word, plural_id: word
|
||||||
|
|
||||||
def safe_eval(text):
|
def safe_eval(text):
|
||||||
if text.strip():
|
if text.strip():
|
||||||
try:
|
try:
|
||||||
@@ -79,11 +88,6 @@ upper_fun = lambda s: unicode(s,'utf-8').upper().encode('utf-8')
|
|||||||
title_fun = lambda s: unicode(s,'utf-8').title().encode('utf-8')
|
title_fun = lambda s: unicode(s,'utf-8').title().encode('utf-8')
|
||||||
cap_fun = lambda s: unicode(s,'utf-8').capitalize().encode('utf-8')
|
cap_fun = lambda s: unicode(s,'utf-8').capitalize().encode('utf-8')
|
||||||
|
|
||||||
# DEFAULT PLURAL-FORMS RULES:
|
|
||||||
default_nplurals = 1 # language doesn't use plural forms
|
|
||||||
default_get_plural_id = lambda n: 0 # only one singular/plural form is used
|
|
||||||
default_construct_plural_form = lambda word, plural_id: word # word is unchangeable
|
|
||||||
|
|
||||||
ttab_in = maketrans("\\%{}", '\x1c\x1d\x1e\x1f')
|
ttab_in = maketrans("\\%{}", '\x1c\x1d\x1e\x1f')
|
||||||
ttab_out = maketrans('\x1c\x1d\x1e\x1f', "\\%{}")
|
ttab_out = maketrans('\x1c\x1d\x1e\x1f', "\\%{}")
|
||||||
|
|
||||||
@@ -161,7 +165,7 @@ def read_dict_aux(filename):
|
|||||||
# clear cache of processed messages:
|
# clear cache of processed messages:
|
||||||
clear_cache(tcache.setdefault(filename, ({}, allocate_lock())))
|
clear_cache(tcache.setdefault(filename, ({}, allocate_lock())))
|
||||||
try:
|
try:
|
||||||
return save_eval(lang_text) or {}
|
return safe_eval(lang_text) or {}
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
status = 'Syntax error in %s (%s)' % (filename, e)
|
status = 'Syntax error in %s (%s)' % (filename, e)
|
||||||
logging.error(status)
|
logging.error(status)
|
||||||
@@ -224,113 +228,61 @@ def read_possible_languages(appdir):
|
|||||||
langs['default'] = ('en', 'English', 0)
|
langs['default'] = ('en', 'English', 0)
|
||||||
return langs
|
return langs
|
||||||
|
|
||||||
def read_plural_rules_aux(filename):
|
def read_global_plural_rules(filename):
|
||||||
"""retrieve plural rules from rules/*plural_rules-lang*.py file.
|
"""
|
||||||
|
retrieve plural rules from rules/*plural_rules-lang*.py file.
|
||||||
|
|
||||||
args:
|
args:
|
||||||
filename (str): plural_rules filename
|
filename (str): plural_rules filename
|
||||||
|
|
||||||
returns:
|
returns:
|
||||||
tuple(nplurals, get_plural_id, construct_plural_form)
|
(nplurals, get_plural_id, construct_plural_form, status)
|
||||||
e.g.: (3, <function>, <function>)
|
e.g.: (3, <function>, <function>, ok)
|
||||||
"""
|
"""
|
||||||
f = portalocker.LockedFile(filename, 'r')
|
env = {}
|
||||||
plural_py=f.read().replace('\r\n','\n')
|
lock = portalocker.LockedFile(filename, 'r')
|
||||||
f.close()
|
|
||||||
try:
|
try:
|
||||||
exec(plural_py)
|
execfile(filename) in env
|
||||||
nplurals=locals().get('nplurals', default_nplurals)
|
|
||||||
get_plural_id=locals().get('get_plural_id', default_get_plural_id)
|
|
||||||
construct_plural_form=locals().get('construct_plural_form',
|
|
||||||
default_construct_plural_form)
|
|
||||||
status='ok'
|
status='ok'
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
nplurals=default_nplurals
|
|
||||||
get_plural_id=default_get_plural_id
|
|
||||||
construct_plural_form=default_construct_plural_form
|
|
||||||
status='Syntax error in %s (%s)' % (filename, e)
|
status='Syntax error in %s (%s)' % (filename, e)
|
||||||
logging.error(status)
|
logging.error(status)
|
||||||
|
lock.close()
|
||||||
|
nplurals = env.get('nplurals', DEFAULT_NPLURALS)
|
||||||
|
get_plural_id = env.get('get_plural_id', DEFAULT_GET_PLURAL_ID)
|
||||||
|
construct_plural_form = env.get('construct_plural_form',
|
||||||
|
DEFAULT_CONSTRUCTOR_PLURAL_FORM)
|
||||||
return (nplurals, get_plural_id, construct_plural_form, status)
|
return (nplurals, get_plural_id, construct_plural_form, status)
|
||||||
|
|
||||||
def read_plural_rules(lang):
|
|
||||||
filename = abspath('gluon','contrib','rules', 'plural_rules-%s.py' % lang)
|
|
||||||
return getcfs('plural_rules-'+lang, filename,
|
|
||||||
lambda: read_plural_rules_aux(filename))
|
|
||||||
|
|
||||||
pcache={}
|
|
||||||
def read_possible_plurals():
|
def read_possible_plurals():
|
||||||
""" create list of all possible plural rules files
|
""" create list of all possible plural rules files
|
||||||
result is cached to increase speed
|
result is cached to increase speed
|
||||||
"""
|
"""
|
||||||
global pcache
|
|
||||||
pdir = abspath('gluon','contrib','rules')
|
pdir = abspath('gluon','contrib','rules')
|
||||||
plurals = {}
|
plurals = {}
|
||||||
# scan rules directory for plural_rules-*.py files:
|
# scan rules directory for plural_rules-*.py files:
|
||||||
for pname in [f for f in listdir(pdir, regex_plural_rules)
|
for pname in os.listdir(pdir):
|
||||||
if osep not in f]:
|
if not isdir(pname) and regex_plural_rules.match(pname):
|
||||||
|
lang = pname[13:-3]
|
||||||
lang=pname[13:-3]
|
fname = ospath.join(pdir, pname)
|
||||||
fname=ospath.join(pdir, pname)
|
n, f1, f2, status = read_global_plural_rules(fname)
|
||||||
mtime=ostat(fname).st_mtime
|
if status == 'ok':
|
||||||
if lang in pcache and pcache[lang][2] == mtime:
|
plurals[lang] = (lang, n, f1, f2)
|
||||||
# if plural_file's mtime wasn't changed - use previous value:
|
plurals['default'] = ('default',
|
||||||
plurals[lang]=pcache[lang]
|
DEFAULT_NPLURALS,
|
||||||
else:
|
DEFAULT_GET_PLURAL_ID,
|
||||||
# otherwise, reread plural_rules-file:
|
DEFAULT_CONSTRUCTOR_PLURAL_FORM)
|
||||||
if 'plural_rules-'+lang in cfs:
|
return plurals
|
||||||
n,f1,f2,status=read_plural_rules(lang)
|
|
||||||
else:
|
|
||||||
n,f1,f2,status=read_plural_rules_aux(fname)
|
|
||||||
plurals[lang]=(n, pname, mtime, status)
|
|
||||||
pcache=plurals
|
|
||||||
return pcache
|
|
||||||
|
|
||||||
def get_plural_rules(languages):
|
|
||||||
"""get plural-forms rules for language *lang*
|
|
||||||
if rules not found - default rules will be return and lang=='unknown'
|
|
||||||
|
|
||||||
args:
|
|
||||||
lang (str): the languages, for one of which the plural-forms is return
|
|
||||||
|
|
||||||
returns:
|
|
||||||
tuples(lang, plural_rules-filename, nplurals,
|
|
||||||
get_plural_id(), construct_plural_form(), status)
|
|
||||||
"""
|
|
||||||
if isinstance(languages, str):
|
|
||||||
languages = [languages]
|
|
||||||
|
|
||||||
all_plurals=read_possible_plurals()
|
|
||||||
for lang in languages:
|
|
||||||
match_language = regex_language.match(lang.strip().lower())
|
|
||||||
if match_language:
|
|
||||||
match_language = tuple(part
|
|
||||||
for part in match_language.groups()
|
|
||||||
if part)
|
|
||||||
lang = lang_sampling(match_language, all_plurals.keys())
|
|
||||||
if lang:
|
|
||||||
( nplurals,
|
|
||||||
get_plural_id,
|
|
||||||
construct_plural_form,
|
|
||||||
status
|
|
||||||
) = read_plural_rules(lang)
|
|
||||||
return (lang, all_plurals[lang][1], nplurals,
|
|
||||||
get_plural_id,
|
|
||||||
construct_plural_form,
|
|
||||||
status)
|
|
||||||
return ('unknown', None, default_nplurals,
|
|
||||||
default_get_plural_id,
|
|
||||||
default_construct_plural_form,
|
|
||||||
'ok')
|
|
||||||
|
|
||||||
|
PLURAL_RULES = read_possible_plurals()
|
||||||
|
|
||||||
def read_plural_dict_aux(filename):
|
def read_plural_dict_aux(filename):
|
||||||
fp = portalocker.LockedFile(filename, 'r')
|
fp = portalocker.LockedFile(filename, 'r')
|
||||||
lang_text = fp.read().replace('\r\n', '\n')
|
lang_text = fp.read().replace('\r\n', '\n')
|
||||||
fp.close()
|
fp.close()
|
||||||
if not lang_text.strip():
|
|
||||||
return {}
|
|
||||||
try:
|
try:
|
||||||
return eval(lang_text)
|
return safe_eval(lang_text) or {}
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
status='Syntax error in %s (%s)' % (filename, e)
|
status='Syntax error in %s (%s)' % (filename, e)
|
||||||
logging.error(status)
|
logging.error(status)
|
||||||
@@ -340,7 +292,6 @@ def read_plural_dict(filename):
|
|||||||
return getcfs('plurals:'+filename, filename,
|
return getcfs('plurals:'+filename, filename,
|
||||||
lambda: read_plural_dict_aux(filename))
|
lambda: read_plural_dict_aux(filename))
|
||||||
|
|
||||||
|
|
||||||
def write_plural_dict(filename, contents):
|
def write_plural_dict(filename, contents):
|
||||||
if '__corrupted__' in contents:
|
if '__corrupted__' in contents:
|
||||||
return
|
return
|
||||||
@@ -536,32 +487,27 @@ class translator(object):
|
|||||||
self.current_languages = languages
|
self.current_languages = languages
|
||||||
self.force(self.http_accept_language)
|
self.force(self.http_accept_language)
|
||||||
|
|
||||||
def set_plural(self, languages):
|
def set_plural(self, language):
|
||||||
""" initialize plural forms subsystem
|
""" initialize plural forms subsystem
|
||||||
invoked from self.force()
|
invoked from self.force()
|
||||||
"""
|
"""
|
||||||
( self.plural_language,
|
lang = language[:2]
|
||||||
self.plural_rules_file,
|
(self.plural_language,
|
||||||
self.nplurals,
|
self.nplurals,
|
||||||
self.get_plural_id,
|
self.get_plural_id,
|
||||||
self.construct_plural_form,
|
self.construct_plural_form,
|
||||||
self.plural_status
|
) = PLURAL_RULES.get(language,PLURAL_RULES['default'])
|
||||||
) = get_plural_rules(languages)
|
filename = 'plural-%s.py' % self.plural_language
|
||||||
|
if filename in self.filenames:
|
||||||
if self.plural_language == 'unknown':
|
self.plural_file = ospath.join(self.langpath,filename)
|
||||||
|
self.plural_dict = read_plural_dict(self.plural_file)
|
||||||
|
else:
|
||||||
self.plural_file = None
|
self.plural_file = None
|
||||||
self.plural_dict = {}
|
self.plural_dict = {}
|
||||||
else:
|
|
||||||
filename = 'plural-%s.py' % self.plural_language
|
|
||||||
if filename in self.filenames:
|
|
||||||
self.plural_file = ospath.join(self.langpath,filename)
|
|
||||||
self.plural_dict = read_plural_dict(self.plural_file)
|
|
||||||
else:
|
|
||||||
self.plural_file = None
|
|
||||||
self.plural_dict = {}
|
|
||||||
|
|
||||||
def plural(self, word, n):
|
def plural(self, word, n):
|
||||||
""" get plural form of word for number *n*
|
"""
|
||||||
|
get plural form of word for number *n*
|
||||||
NOTE: *word" MUST be defined in current language
|
NOTE: *word" MUST be defined in current language
|
||||||
(T.accepted_language)
|
(T.accepted_language)
|
||||||
|
|
||||||
@@ -579,23 +525,21 @@ class translator(object):
|
|||||||
if id > 0:
|
if id > 0:
|
||||||
forms = self.plural_dict.get(word, [])
|
forms = self.plural_dict.get(word, [])
|
||||||
if forms:
|
if forms:
|
||||||
try:
|
form = forms.get(id-1)
|
||||||
form = forms[id-1]
|
if form:
|
||||||
except:
|
return form
|
||||||
form = None
|
|
||||||
if form: return form
|
|
||||||
form = self.construct_plural_form(word, id)
|
form = self.construct_plural_form(word, id)
|
||||||
if len(forms) < nplurals-1:
|
if len(forms) < nplurals-1:
|
||||||
forms.extend('' for i in xrange(nplurals-len(forms)-1))
|
forms.extend('' for i in xrange(nplurals-len(forms)-1))
|
||||||
forms[id-1] = form
|
forms[id-1] = form
|
||||||
self.plural_dict[word] = forms
|
self.plural_dict[word] = forms
|
||||||
if (self.plural_file and
|
if (self.plural_file and
|
||||||
not settings.global_settings.web2py_runtime_gae):
|
not settings.global_settings.web2py_runtime_gae):
|
||||||
write_plural_dict(self.plural_file, self.plural_dict)
|
write_plural_dict(self.plural_file,
|
||||||
|
self.plural_dict)
|
||||||
return form
|
return form
|
||||||
return word
|
return word
|
||||||
|
|
||||||
|
|
||||||
def get_possible_languages_info(self, lang=None):
|
def get_possible_languages_info(self, lang=None):
|
||||||
"""
|
"""
|
||||||
return info for selected language or dictionary with all
|
return info for selected language or dictionary with all
|
||||||
@@ -664,7 +608,7 @@ class translator(object):
|
|||||||
self.language_file = None
|
self.language_file = None
|
||||||
self.t = {}
|
self.t = {}
|
||||||
self.cache = tcache[None]
|
self.cache = tcache[None]
|
||||||
# self.set_plural(language)
|
self.set_plural(language)
|
||||||
return languages
|
return languages
|
||||||
|
|
||||||
def __call__(self, message, symbols={}, language=None, lazy=None):
|
def __call__(self, message, symbols={}, language=None, lazy=None):
|
||||||
|
|||||||
+13
-1
@@ -1,6 +1,7 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# portalocker.py - Cross-platform (posix/nt) API for flock-style file locking.
|
# portalocker.py
|
||||||
|
# Cross-platform (posix/nt) API for flock-style file locking.
|
||||||
# Requires python 1.5.2 or better.
|
# Requires python 1.5.2 or better.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
@@ -141,6 +142,17 @@ class LockedFile(object):
|
|||||||
def __del__(self):
|
def __del__(self):
|
||||||
self.close()
|
self.close()
|
||||||
|
|
||||||
|
def read_locked(filename):
|
||||||
|
fp = portalocker.LockedFile(file, 'r')
|
||||||
|
data = fp.read()
|
||||||
|
fp.close()
|
||||||
|
return data
|
||||||
|
|
||||||
|
def write_locked(filename,data):
|
||||||
|
fp = portalocker.LockedFile(file, 'w')
|
||||||
|
data = fp.write(data)
|
||||||
|
fp.close()
|
||||||
|
|
||||||
if __name__=='__main__':
|
if __name__=='__main__':
|
||||||
f = LockedFile('test.txt',mode='wb')
|
f = LockedFile('test.txt',mode='wb')
|
||||||
f.write('test ok')
|
f.write('test ok')
|
||||||
|
|||||||
Reference in New Issue
Block a user