#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
+# Copyright (C) 2010 OpenERP s.a. (<http://openerp.com>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
import release
import socket
import re
+from itertools import islice
+import threading
+from which import which
+
if sys.version_info[:2] < (2, 4):
from threadinglocal import local
cr.commit()
for i in addons.get_modules():
- terp_file = addons.get_module_resource(i, '__terp__.py')
mod_path = addons.get_module_path(i)
if not mod_path:
continue
- info = False
- if os.path.isfile(terp_file) or os.path.isfile(mod_path+'.zip'):
- info = eval(file_open(terp_file).read())
- if info:
- categs = info.get('category', 'Uncategorized').split('/')
- p_id = None
- while categs:
- if p_id is not None:
- cr.execute('select id \
- from ir_module_category \
- where name=%s and parent_id=%s', (categs[0], p_id))
- else:
- cr.execute('select id \
- from ir_module_category \
- where name=%s and parent_id is NULL', (categs[0],))
- c_id = cr.fetchone()
- if not c_id:
- cr.execute('select nextval(\'ir_module_category_id_seq\')')
- c_id = cr.fetchone()[0]
- cr.execute('insert into ir_module_category \
- (id, name, parent_id) \
- values (%s, %s, %s)', (c_id, categs[0], p_id))
- else:
- c_id = c_id[0]
- p_id = c_id
- categs = categs[1:]
-
- active = info.get('active', False)
- installable = info.get('installable', True)
- if installable:
- if active:
- state = 'to install'
- else:
- state = 'uninstalled'
+
+ info = addons.load_information_from_description_file(i)
+
+ if not info:
+ continue
+ categs = info.get('category', 'Uncategorized').split('/')
+ p_id = None
+ while categs:
+ if p_id is not None:
+ cr.execute('select id \
+ from ir_module_category \
+ where name=%s and parent_id=%s', (categs[0], p_id))
+ else:
+ cr.execute('select id \
+ from ir_module_category \
+ where name=%s and parent_id is NULL', (categs[0],))
+ c_id = cr.fetchone()
+ if not c_id:
+ cr.execute('select nextval(\'ir_module_category_id_seq\')')
+ c_id = cr.fetchone()[0]
+ cr.execute('insert into ir_module_category \
+ (id, name, parent_id) \
+ values (%s, %s, %s)', (c_id, categs[0], p_id))
+ else:
+ c_id = c_id[0]
+ p_id = c_id
+ categs = categs[1:]
+
+ active = info.get('active', False)
+ installable = info.get('installable', True)
+ if installable:
+ if active:
+ state = 'to install'
else:
- state = 'uninstallable'
- cr.execute('select nextval(\'ir_module_module_id_seq\')')
- id = cr.fetchone()[0]
- cr.execute('insert into ir_module_module \
- (id, author, website, name, shortdesc, description, \
- category_id, state, certificate) \
- values (%s, %s, %s, %s, %s, %s, %s, %s, %s)', (
- id, info.get('author', ''),
- info.get('website', ''), i, info.get('name', False),
- info.get('description', ''), p_id, state, info.get('certificate')))
- cr.execute('insert into ir_model_data \
- (name,model,module, res_id, noupdate) values (%s,%s,%s,%s,%s)', (
- 'module_meta_information', 'ir.module.module', i, id, True))
- dependencies = info.get('depends', [])
- for d in dependencies:
- cr.execute('insert into ir_module_module_dependency \
- (module_id,name) values (%s, %s)', (id, d))
- cr.commit()
+ state = 'uninstalled'
+ else:
+ state = 'uninstallable'
+ cr.execute('select nextval(\'ir_module_module_id_seq\')')
+ id = cr.fetchone()[0]
+ cr.execute('insert into ir_module_module \
+ (id, author, website, name, shortdesc, description, \
+ category_id, state, certificate) \
+ values (%s, %s, %s, %s, %s, %s, %s, %s, %s)', (
+ id, info.get('author', ''),
+ info.get('website', ''), i, info.get('name', False),
+ info.get('description', ''), p_id, state, info.get('certificate') or None))
+ cr.execute('insert into ir_model_data \
+ (name,model,module, res_id, noupdate) values (%s,%s,%s,%s,%s)', (
+ 'module_meta_information', 'ir.module.module', i, id, True))
+ dependencies = info.get('depends', [])
+ for d in dependencies:
+ cr.execute('insert into ir_module_module_dependency \
+ (module_id,name) values (%s, %s)', (id, d))
+ cr.commit()
def find_in_path(name):
- if os.name == "nt":
- sep = ';'
- else:
- sep = ':'
- path = [dir for dir in os.environ['PATH'].split(sep)
- if os.path.isdir(dir)]
- for dir in path:
- val = os.path.join(dir, name)
- if os.path.isfile(val) or os.path.islink(val):
- return val
- return None
+ try:
+ return which(name)
+ except IOError:
+ return None
def find_pg_tool(name):
+ path = None
if config['pg_path'] and config['pg_path'] != 'None':
- return os.path.join(config['pg_path'], name)
- else:
- return find_in_path(name)
+ path = config['pg_path']
+ try:
+ return which(name, path=path)
+ except IOError:
+ return None
def exec_pg_command(name, *args):
prog = find_pg_tool(name)
## (c) Fry-IT, www.fry-it.com, 2007
## <peter@fry-it.com>
## download here: http://www.peterbe.com/plog/html2plaintext
-
-
+
+
""" from an HTML text, convert the HTML to plain text.
- If @body_id is provided then this is the tag where the
+ If @body_id is provided then this is the tag where the
body (not necessarily <body>) starts.
"""
try:
from BeautifulSoup import BeautifulSoup, SoupStrainer, Comment
except:
return html
-
+
urls = []
if body_id is not None:
strainer = SoupStrainer(id=body_id)
else:
strainer = SoupStrainer('body')
-
+
soup = BeautifulSoup(html, parseOnlyThese=strainer, fromEncoding=encoding)
for link in soup.findAll('a'):
title = link.renderContents()
urls.append(dict(url=url, tag=str(link), title=title))
html = soup.__str__()
-
+
url_index = []
i = 0
for d in urls:
html = html.replace('<h2>','**').replace('</h2>','**')
html = html.replace('<h1>','**').replace('</h1>','**')
html = html.replace('<em>','/').replace('</em>','/')
-
- # the only line breaks we respect is those of ending tags and
+
+ # the only line breaks we respect is those of ending tags and
# breaks
-
+
html = html.replace('\n',' ')
html = html.replace('<br>', '\n')
html = html.replace('<tr>', '\n')
html = html.replace(' ' * 2, ' ')
- # for all other tags we failed to clean up, just remove then and
+ # for all other tags we failed to clean up, just remove then and
# complain about them on the stderr
def desperate_fixer(g):
#print >>sys.stderr, "failed to clean up %s" % str(g.group())
msg['X-Generated-By'] = 'OpenERP (http://www.openerp.com)'
msg['X-OpenERP-Server-Host'] = socket.gethostname()
msg['X-OpenERP-Server-Version'] = release.version
-
msg['X-Priority'] = priorities.get(priority, '3 (Normal)')
# Add dynamic X Header
for key, value in x_headers.iteritems():
msg['X-OpenERP-%s' % key] = str(value)
+ msg['%s' % key] = str(value)
if openobject_id:
msg['Message-Id'] = "<%s-openobject-%s@%s>" % (time.time(), openobject_id, socket.gethostname())
return True
except Exception,e:
netsvc.Logger().notifyChannel('email_send (maildir)', netsvc.LOG_ERROR, e)
- return False
-
+ return False
+
try:
oldstderr = smtplib.stderr
s = smtplib.SMTP()
if debug:
smtplib.stderr = WriteToLogger()
- s.set_debuglevel(int(bool(debug))) # 0 or 1
+ s.set_debuglevel(int(bool(debug))) # 0 or 1
s.connect(smtp_server, config['smtp_port'])
if ssl:
s.ehlo()
s.ehlo()
if config['smtp_user'] or config['smtp_password']:
- s.login(config['smtp_user'], config['smtp_password'])
+ s.login(config['smtp_user'], config['smtp_password'])
s.sendmail(email_from,
flatten([email_to, email_cc, email_bcc]),
msg.as_string()
if *args and **kwargs are both empty, clear all the keys related to this database
"""
if not args and not kwargs:
- keys_to_del = [key for key in self.cache if key[0][1] == dbname]
+ keys_to_del = [key for key in self.cache.keys() if key[0][1] == dbname]
else:
kwargs2 = self._unify_args(*args, **kwargs)
- keys_to_del = [key for key, _ in self._generate_keys(dbname, kwargs2) if key in self.cache]
+ keys_to_del = [key for key, _ in self._generate_keys(dbname, kwargs2) if key in self.cache.keys()]
for key in keys_to_del:
- del self.cache[key]
+ self.cache.pop(key)
@classmethod
def clean_caches_for_db(cls, dbname):
if time.time()-int(self.timeout) > self.lasttime:
self.lasttime = time.time()
t = time.time()-int(self.timeout)
- old_keys = [key for key in self.cache if self.cache[key][1] < t]
+ old_keys = [key for key in self.cache.keys() if self.cache[key][1] < t]
for key in old_keys:
- del self.cache[key]
+ self.cache.pop(key)
kwargs2 = self._unify_args(*args, **kwargs)
def to_xml(s):
return s.replace('&','&').replace('<','<').replace('>','>')
+def get_encodings():
+ yield 'utf8'
+ from locale import getpreferredencoding
+ prefenc = getpreferredencoding()
+ if prefenc:
+ yield prefenc
+
+ prefenc = {
+ 'latin1': 'latin9',
+ 'iso-8859-1': 'iso8859-15',
+ 'cp1252': '1252',
+ }.get(prefenc.lower())
+ if prefenc:
+ yield prefenc
+
+
def ustr(value):
"""This method is similar to the builtin `str` method, except
it will return Unicode string.
@rtype: unicode
@return: unicode string
"""
+ orig = value
+ if isinstance(value, Exception):
+ return exception_to_unicode(value)
if isinstance(value, unicode):
return value
- if hasattr(value, '__unicode__'):
+ try:
return unicode(value)
-
- if not isinstance(value, str):
- value = str(value)
-
- try: # first try utf-8
- return unicode(value, 'utf-8')
except:
pass
- try: # then extened iso-8858
- return unicode(value, 'iso-8859-15')
- except:
- pass
+ for ln in get_encodings():
+ try:
+ return unicode(value, ln)
+ except:
+ pass
+ raise UnicodeError('unable de to convert %r' % (orig,))
- # else use default system locale
- from locale import getlocale
- return unicode(value, getlocale()[1])
def exception_to_unicode(e):
if (sys.version_info[:2] < (2,6)) and hasattr(e, 'message'):
__builtin__.any = any
del any
-get_iso = {'ca_ES':'ca',
-'cs_CZ': 'cs',
-'et_EE': 'et',
-'sv_SE': 'sv',
-'sq_AL': 'sq',
-'uk_UA': 'uk',
-'vi_VN': 'vi',
-'af_ZA': 'af',
-'be_BY': 'be',
-'ja_JP': 'ja',
-'ko_KR': 'ko'
-}
-
def get_iso_codes(lang):
- if lang in get_iso:
- lang = get_iso[lang]
- elif lang.find('_') != -1:
+ if lang.find('_') != -1:
if lang.split('_')[0] == lang.split('_')[1].lower():
lang = lang.split('_')[0]
return lang
def get_languages():
languages={
+ 'ab_RU': u'Abkhazian (RU)',
'ar_AR': u'Arabic / الْعَرَبيّة',
'bg_BG': u'Bulgarian / български',
'bs_BS': u'Bosnian / bosanski jezik',
'es_AR': u'Spanish (AR) / Español (AR)',
'es_ES': u'Spanish / Español',
'et_EE': u'Estonian / Eesti keel',
+ 'fa_IR': u'Persian / فارس',
'fi_FI': u'Finland / Suomi',
'fr_BE': u'French (BE) / Français (BE)',
'fr_CH': u'French (CH) / Français (CH)',
'fr_FR': u'French / Français',
+ 'gl_ES': u'Galician / Galego',
+ 'gu_IN': u'Gujarati / India',
+ 'hi_IN': u'Hindi / India',
'hr_HR': u'Croatian / hrvatski jezik',
'hu_HU': u'Hungarian / Magyar',
'id_ID': u'Indonesian / Bahasa Indonesia',
'it_IT': u'Italian / Italiano',
+ 'iu_CA': u'Inuktitut / Canada',
+ 'ja_JP': u'Japanese / Japan',
+ 'ko_KP': u'Korean / Korea, Democratic Peoples Republic of',
+ 'ko_KR': u'Korean / Korea, Republic of',
'lt_LT': u'Lithuanian / Lietuvių kalba',
+ 'lv_LV': u'Latvian / Latvia',
+ 'ml_IN': u'Malayalam / India',
+ 'mn_MN': u'Mongolian / Mongolia',
+ 'nb_NO': u'Norwegian Bokmål / Norway',
'nl_NL': u'Dutch / Nederlands',
'nl_BE': u'Dutch (Belgium) / Nederlands (Belgïe)',
+ 'oc_FR': u'Occitan (post 1500) / France',
'pl_PL': u'Polish / Język polski',
'pt_BR': u'Portugese (BR) / português (BR)',
'pt_PT': u'Portugese / português',
'ro_RO': u'Romanian / limba română',
'ru_RU': u'Russian / русский язык',
- 'sl_SL': u'Slovenian / slovenščina',
+ 'si_LK': u'Sinhalese / Sri Lanka',
+ 'sl_SI': u'Slovenian / slovenščina',
+ 'sk_SK': u'Slovak / Slovenský jazyk',
'sq_AL': u'Albanian / Shqipëri',
+ 'sr_RS': u'Serbian / Serbia',
'sv_SE': u'Swedish / svenska',
+ 'te_IN': u'Telugu / India',
'tr_TR': u'Turkish / Türkçe',
'vi_VN': u'Vietnam / Cộng hòa xã hội chủ nghĩa Việt Nam',
'uk_UA': u'Ukrainian / украї́нська мо́ва',
+ 'ur_PK': u'Urdu / Pakistan',
'zh_CN': u'Chinese (CN) / 简体中文',
+ 'zh_HK': u'Chinese (HK)',
'zh_TW': u'Chinese (TW) / 正體字',
'th_TH': u'Thai / ภาษาไทย',
'tlh_TLH': u'Klingon',
'terp-account', 'terp-crm', 'terp-mrp', 'terp-product', 'terp-purchase',
'terp-sale', 'terp-tools', 'terp-administration', 'terp-hr', 'terp-partner',
'terp-project', 'terp-report', 'terp-stock', 'terp-calendar', 'terp-graph',
+'terp-check','terp-go-month','terp-go-year','terp-go-today','terp-document-new','terp-camera_test',
+'terp-emblem-important','terp-gtk-media-pause','terp-gtk-stop','terp-gnome-cpu-frequency-applet+',
+'terp-dialog-close','terp-gtk-jump-to-rtl','terp-gtk-jump-to-ltr','terp-accessories-archiver',
+'terp-stock_align_left_24','terp-stock_effects-object-colorize','terp-go-home','terp-gtk-go-back-rtl',
+'terp-gtk-go-back-ltr','terp-personal','terp-personal-','terp-personal+','terp-accessories-archiver-minus',
+'terp-accessories-archiver+','terp-stock_symbol-selection','terp-call-start','terp-dolar',
+'terp-face-plain','terp-folder-blue','terp-folder-green','terp-folder-orange','terp-folder-yellow',
+'terp-gdu-smart-failing','terp-go-week','terp-gtk-select-all','terp-locked','terp-mail-forward',
+'terp-mail-message-new','terp-mail-replied','terp-rating-rated','terp-stage','terp-stock_format-scientific',
+'terp-dolar_ok!','terp-idea','terp-stock_format-default','terp-mail-','terp-mail_delete'
])
def extract_zip_file(zip_file, outdirectory):
# RATIONALE BEHIND TIMESTAMP CALCULATIONS AND TIMEZONE MANAGEMENT:
# The server side never does any timestamp calculation, always
# sends them in a naive (timezone agnostic) format supposed to be
-# expressed within the server timezone, and expects the clients to
+# expressed within the server timezone, and expects the clients to
# provide timestamps in the server timezone as well.
-# It stores all timestamps in the database in naive format as well,
+# It stores all timestamps in the database in naive format as well,
# which also expresses the time in the server timezone.
# For this reason the server makes its timezone name available via the
# common/timezone_get() rpc method, which clients need to read
return 'UTC'
+def split_every(n, iterable, piece_maker=tuple):
+ """Splits an iterable into length-n pieces. The last piece will be shorter
+ if ``n`` does not evenly divide the iterable length.
+ @param ``piece_maker``: function to build the pieces
+ from the slices (tuple,list,...)
+ """
+ iterator = iter(iterable)
+ piece = piece_maker(islice(iterator, n))
+ while piece:
+ yield piece
+ piece = piece_maker(islice(iterator, n))
+
if __name__ == '__main__':
import doctest
doctest.testmod()
+class upload_data_thread(threading.Thread):
+ def __init__(self, email, data, type):
+ self.args = [('email',email),('type',type),('data',data)]
+ super(upload_data_thread,self).__init__()
+ def run(self):
+ try:
+ import urllib
+ args = urllib.urlencode(self.args)
+ fp = urllib.urlopen('http://www.openerp.com/scripts/survey.php', args)
+ fp.read()
+ fp.close()
+ except:
+ pass
+def upload_data(email, data, type='SURVEY'):
+ a = upload_data_thread(email, data, type)
+ a.start()
+ return True
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: