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
|
||||
ostat = os.stat
|
||||
osep = os.sep
|
||||
isdir = os.path.isdir
|
||||
is_gae = settings.global_settings.web2py_runtime_gae
|
||||
|
||||
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):
|
||||
if text.strip():
|
||||
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')
|
||||
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_out = maketrans('\x1c\x1d\x1e\x1f', "\\%{}")
|
||||
|
||||
@@ -161,7 +165,7 @@ def read_dict_aux(filename):
|
||||
# clear cache of processed messages:
|
||||
clear_cache(tcache.setdefault(filename, ({}, allocate_lock())))
|
||||
try:
|
||||
return save_eval(lang_text) or {}
|
||||
return safe_eval(lang_text) or {}
|
||||
except Exception, e:
|
||||
status = 'Syntax error in %s (%s)' % (filename, e)
|
||||
logging.error(status)
|
||||
@@ -224,113 +228,61 @@ def read_possible_languages(appdir):
|
||||
langs['default'] = ('en', 'English', 0)
|
||||
return langs
|
||||
|
||||
def read_plural_rules_aux(filename):
|
||||
"""retrieve plural rules from rules/*plural_rules-lang*.py file.
|
||||
def read_global_plural_rules(filename):
|
||||
"""
|
||||
retrieve plural rules from rules/*plural_rules-lang*.py file.
|
||||
|
||||
args:
|
||||
filename (str): plural_rules filename
|
||||
|
||||
returns:
|
||||
tuple(nplurals, get_plural_id, construct_plural_form)
|
||||
e.g.: (3, <function>, <function>)
|
||||
(nplurals, get_plural_id, construct_plural_form, status)
|
||||
e.g.: (3, <function>, <function>, ok)
|
||||
"""
|
||||
f = portalocker.LockedFile(filename, 'r')
|
||||
plural_py=f.read().replace('\r\n','\n')
|
||||
f.close()
|
||||
env = {}
|
||||
lock = portalocker.LockedFile(filename, 'r')
|
||||
try:
|
||||
exec(plural_py)
|
||||
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)
|
||||
execfile(filename) in env
|
||||
status='ok'
|
||||
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)
|
||||
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)
|
||||
|
||||
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():
|
||||
""" create list of all possible plural rules files
|
||||
result is cached to increase speed
|
||||
"""
|
||||
global pcache
|
||||
pdir = abspath('gluon','contrib','rules')
|
||||
plurals = {}
|
||||
# scan rules directory for plural_rules-*.py files:
|
||||
for pname in [f for f in listdir(pdir, regex_plural_rules)
|
||||
if osep not in f]:
|
||||
|
||||
lang=pname[13:-3]
|
||||
fname=ospath.join(pdir, pname)
|
||||
mtime=ostat(fname).st_mtime
|
||||
if lang in pcache and pcache[lang][2] == mtime:
|
||||
# if plural_file's mtime wasn't changed - use previous value:
|
||||
plurals[lang]=pcache[lang]
|
||||
else:
|
||||
# otherwise, reread plural_rules-file:
|
||||
if 'plural_rules-'+lang in cfs:
|
||||
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')
|
||||
for pname in os.listdir(pdir):
|
||||
if not isdir(pname) and regex_plural_rules.match(pname):
|
||||
lang = pname[13:-3]
|
||||
fname = ospath.join(pdir, pname)
|
||||
n, f1, f2, status = read_global_plural_rules(fname)
|
||||
if status == 'ok':
|
||||
plurals[lang] = (lang, n, f1, f2)
|
||||
plurals['default'] = ('default',
|
||||
DEFAULT_NPLURALS,
|
||||
DEFAULT_GET_PLURAL_ID,
|
||||
DEFAULT_CONSTRUCTOR_PLURAL_FORM)
|
||||
return plurals
|
||||
|
||||
PLURAL_RULES = read_possible_plurals()
|
||||
|
||||
def read_plural_dict_aux(filename):
|
||||
fp = portalocker.LockedFile(filename, 'r')
|
||||
lang_text = fp.read().replace('\r\n', '\n')
|
||||
fp.close()
|
||||
if not lang_text.strip():
|
||||
return {}
|
||||
try:
|
||||
return eval(lang_text)
|
||||
return safe_eval(lang_text) or {}
|
||||
except Exception, e:
|
||||
status='Syntax error in %s (%s)' % (filename, e)
|
||||
logging.error(status)
|
||||
@@ -340,7 +292,6 @@ def read_plural_dict(filename):
|
||||
return getcfs('plurals:'+filename, filename,
|
||||
lambda: read_plural_dict_aux(filename))
|
||||
|
||||
|
||||
def write_plural_dict(filename, contents):
|
||||
if '__corrupted__' in contents:
|
||||
return
|
||||
@@ -536,32 +487,27 @@ class translator(object):
|
||||
self.current_languages = languages
|
||||
self.force(self.http_accept_language)
|
||||
|
||||
def set_plural(self, languages):
|
||||
def set_plural(self, language):
|
||||
""" initialize plural forms subsystem
|
||||
invoked from self.force()
|
||||
"""
|
||||
( self.plural_language,
|
||||
self.plural_rules_file,
|
||||
self.nplurals,
|
||||
self.get_plural_id,
|
||||
self.construct_plural_form,
|
||||
self.plural_status
|
||||
) = get_plural_rules(languages)
|
||||
|
||||
if self.plural_language == 'unknown':
|
||||
lang = language[:2]
|
||||
(self.plural_language,
|
||||
self.nplurals,
|
||||
self.get_plural_id,
|
||||
self.construct_plural_form,
|
||||
) = PLURAL_RULES.get(language,PLURAL_RULES['default'])
|
||||
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 = {}
|
||||
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):
|
||||
""" get plural form of word for number *n*
|
||||
"""
|
||||
get plural form of word for number *n*
|
||||
NOTE: *word" MUST be defined in current language
|
||||
(T.accepted_language)
|
||||
|
||||
@@ -579,23 +525,21 @@ class translator(object):
|
||||
if id > 0:
|
||||
forms = self.plural_dict.get(word, [])
|
||||
if forms:
|
||||
try:
|
||||
form = forms[id-1]
|
||||
except:
|
||||
form = None
|
||||
if form: return form
|
||||
form = forms.get(id-1)
|
||||
if form:
|
||||
return form
|
||||
form = self.construct_plural_form(word, id)
|
||||
if len(forms) < nplurals-1:
|
||||
forms.extend('' for i in xrange(nplurals-len(forms)-1))
|
||||
forms[id-1] = form
|
||||
self.plural_dict[word] = forms
|
||||
if (self.plural_file and
|
||||
not settings.global_settings.web2py_runtime_gae):
|
||||
write_plural_dict(self.plural_file, self.plural_dict)
|
||||
not settings.global_settings.web2py_runtime_gae):
|
||||
write_plural_dict(self.plural_file,
|
||||
self.plural_dict)
|
||||
return form
|
||||
return word
|
||||
|
||||
|
||||
def get_possible_languages_info(self, lang=None):
|
||||
"""
|
||||
return info for selected language or dictionary with all
|
||||
@@ -664,7 +608,7 @@ class translator(object):
|
||||
self.language_file = None
|
||||
self.t = {}
|
||||
self.cache = tcache[None]
|
||||
# self.set_plural(language)
|
||||
self.set_plural(language)
|
||||
return languages
|
||||
|
||||
def __call__(self, message, symbols={}, language=None, lazy=None):
|
||||
|
||||
+13
-1
@@ -1,6 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- 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.
|
||||
|
||||
"""
|
||||
@@ -141,6 +142,17 @@ class LockedFile(object):
|
||||
def __del__(self):
|
||||
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__':
|
||||
f = LockedFile('test.txt',mode='wb')
|
||||
f.write('test ok')
|
||||
|
||||
Reference in New Issue
Block a user