diff --git a/addons/account/account.py b/addons/account/account.py
index 6e96ce73962..caf1d68c45d 100644
--- a/addons/account/account.py
+++ b/addons/account/account.py
@@ -24,11 +24,12 @@ from datetime import datetime
from dateutil.relativedelta import relativedelta
from operator import itemgetter
-import netsvc
+import logging
import pooler
from osv import fields, osv
import decimal_precision as dp
from tools.translate import _
+_logger = logging.getLogger(__name__)
def check_cycle(self, cr, uid, ids, context=None):
""" climbs the ``self._table.parent_id`` chains for 100 levels or
@@ -212,7 +213,6 @@ class account_account(osv.osv):
_name = "account.account"
_description = "Account"
_parent_store = True
- logger = netsvc.Logger()
def search(self, cr, uid, args, offset=0, limit=None, order=None,
context=None, count=False):
@@ -295,8 +295,7 @@ class account_account(osv.osv):
if aml_query.strip():
wheres.append(aml_query.strip())
filters = " AND ".join(wheres)
- self.logger.notifyChannel('addons.'+self._name, netsvc.LOG_DEBUG,
- 'Filters: %s'%filters)
+ _logger.debug('Filters: %s',(filters))
# IN might not work ideally in case there are too many
# children_and_consolidated, in that case join on a
# values() e.g.:
@@ -312,8 +311,7 @@ class account_account(osv.osv):
" GROUP BY l.account_id")
params = (tuple(children_and_consolidated),) + query_params
cr.execute(request, params)
- self.logger.notifyChannel('addons.'+self._name, netsvc.LOG_DEBUG,
- 'Status: %s'%cr.statusmessage)
+ _logger.debug('Status: %s',(cr.statusmessage))
for res in cr.dictfetchall():
accounts[res['id']] = res
@@ -2095,9 +2093,7 @@ class account_tax(osv.osv):
}
def compute(self, cr, uid, taxes, price_unit, quantity, product=None, partner=None):
- logger = netsvc.Logger()
- logger.notifyChannel("warning", netsvc.LOG_WARNING,
- "Deprecated, use compute_all(...)['taxes'] instead of compute(...) to manage prices with tax included")
+ _logger.warning("Deprecated, use compute_all(...)['taxes'] instead of compute(...) to manage prices with tax included")
return self._compute(cr, uid, taxes, price_unit, quantity, product, partner)
def _compute(self, cr, uid, taxes, price_unit, quantity, product=None, partner=None):
diff --git a/addons/account/installer.py b/addons/account/installer.py
index 6cf52f58f6c..5a2b0b346c4 100644
--- a/addons/account/installer.py
+++ b/addons/account/installer.py
@@ -30,11 +30,11 @@ from tools.translate import _
from osv import fields, osv
import netsvc
import tools
+_logger = logging.getLogger(__name__)
class account_installer(osv.osv_memory):
_name = 'account.installer'
_inherit = 'res.config.installer'
- __logger = logging.getLogger(_name)
def _get_charts(self, cr, uid, context=None):
modules = self.pool.get('ir.module.module')
@@ -149,7 +149,7 @@ class account_installer(osv.osv_memory):
cr, uid, ids, context=context)
chart = self.read(cr, uid, ids, ['charts'],
context=context)[0]['charts']
- self.__logger.debug('Installing chart of accounts %s', chart)
+ _logger.debug('Installing chart of accounts %s', chart)
return modules | set([chart])
account_installer()
diff --git a/addons/account/project/report/cost_ledger.py b/addons/account/project/report/cost_ledger.py
index c7423675c15..6ca17a7ac0a 100644
--- a/addons/account/project/report/cost_ledger.py
+++ b/addons/account/project/report/cost_ledger.py
@@ -75,10 +75,10 @@ class account_analytic_cost_ledger(report_sxw.rml_parse):
return res
def _account_sum_debit(self, account, date1, date2):
- return self._sum_debit(self, [account], date1, date2)
+ return self._sum_debit([account], date1, date2)
def _account_sum_credit(self, account, date1, date2):
- return self._sum_credit(self, [account], date1, date2)
+ return self._sum_credit([account], date1, date2)
def _account_sum_balance(self, account, date1, date2):
debit = self._account_sum_debit(account, date1, date2)
diff --git a/addons/account/report/account_general_ledger.rml b/addons/account/report/account_general_ledger.rml
index 0ba4e4b6a3c..6897e15078d 100644
--- a/addons/account/report/account_general_ledger.rml
+++ b/addons/account/report/account_general_ledger.rml
@@ -497,7 +497,7 @@
[[ strip_name(line['partner_name'],10) ]]
- [[ strip_name(line['lref'],9) ]]
+ [[ line['lref'] and strip_name(line['lref'],9) ]]
|
[[ strip_name(line['move'],9) ]]
@@ -590,7 +590,7 @@
[[ strip_name(line['partner_name'],20) ]]
|
- [[ strip_name(line['lref'],9) ]]
+ [[ line['lref'] and strip_name(line['lref'],9) ]]
|
[[ strip_name(line['move'],9) ]]
diff --git a/addons/account/report/account_general_ledger_landscape.rml b/addons/account/report/account_general_ledger_landscape.rml
index 79003c5aaa6..7ae5db98f20 100644
--- a/addons/account/report/account_general_ledger_landscape.rml
+++ b/addons/account/report/account_general_ledger_landscape.rml
@@ -505,7 +505,7 @@
[[ formatLang(sum_credit_account(o), digits=get_digits(dp='Account')) ]]
|
- [[ formatLang(sum_balance_account(o), digits=get_digits(dp='Account'), currency = company.currency_id) ]]
+ [[ formatLang(sum_balance_account(o), digits=get_digits(dp='Account'), currency_obj= company.currency_id) ]]
|
[[ o.currency_id and formatLang(sum_currency_amount_account(o), digits=get_digits(dp='Account'),currency_obj=o.currency_id) or '' ]]
@@ -529,7 +529,7 @@
[[ strip_name(line['partner_name'],20) ]]
|
- [[ strip_name(line['lref'],17) ]]
+ [[ line['lref'] and strip_name(line['lref'],17) ]]
|
[[ line['move'] ]]
diff --git a/addons/account/report/account_partner_ledger.rml b/addons/account/report/account_partner_ledger.rml
index 8fcb41d5ca6..0d7122369c6 100644
--- a/addons/account/report/account_partner_ledger.rml
+++ b/addons/account/report/account_partner_ledger.rml
@@ -519,7 +519,7 @@
[[ line['a_code'] ]]
|
- [[ strip_name(line['ref'],10) ]] - [[ strip_name(line['name'],15) ]]
+ [[ line['ref'] and strip_name(line['ref'],10) ]] - [[ strip_name(line['name'],15) ]]
|
[[ formatLang((line['debit'])) ]]
diff --git a/addons/account/report/account_partner_ledger_other.rml b/addons/account/report/account_partner_ledger_other.rml
index c61b8147a69..b878ab44e47 100644
--- a/addons/account/report/account_partner_ledger_other.rml
+++ b/addons/account/report/account_partner_ledger_other.rml
@@ -524,7 +524,7 @@
[[ line['a_code'] ]]
|
- [[ strip_name(line['ref'],10) ]] - [[ strip_name(line['name'],15) ]]
+ [[ line['ref'] and strip_name(line['ref'],10) ]] - [[ strip_name(line['name'],15) ]]
|
[[ formatLang((line['debit'])) ]]
diff --git a/addons/account/report/account_print_invoice.rml b/addons/account/report/account_print_invoice.rml
index 7c5007a24fb..0d18a35b8a1 100644
--- a/addons/account/report/account_print_invoice.rml
+++ b/addons/account/report/account_print_invoice.rml
@@ -162,7 +162,7 @@
|
[[ (o.partner_id and o.partner_id.title and o.partner_id.title.name) or '' ]] [[ (o.partner_id and o.partner_id.name) or '' ]]
- [[ display_address(o.partner_id,'invoice') ]]
+ [[ display_address(o.partner_id) ]]
diff --git a/addons/account/wizard/account_fiscalyear_close_state.py b/addons/account/wizard/account_fiscalyear_close_state.py
index 68c758eb495..2af649ba19f 100644
--- a/addons/account/wizard/account_fiscalyear_close_state.py
+++ b/addons/account/wizard/account_fiscalyear_close_state.py
@@ -20,6 +20,7 @@
##############################################################################
from osv import fields, osv
+from tools.translate import _
class account_fiscalyear_close_state(osv.osv_memory):
"""
@@ -53,10 +54,6 @@ class account_fiscalyear_close_state(osv.osv_memory):
cr.execute('UPDATE account_fiscalyear ' \
'SET state = %s WHERE id = %s', ('done', fy_id))
- # Log message for Fiscalyear
- fy_pool = self.pool.get('account.fiscalyear')
- fy_code = fy_pool.browse(cr, uid, fy_id, context=context).code
- fy_pool.log(cr, uid, fy_id, "Fiscal year '%s' is closed, no more modification allowed." % (fy_code))
return {'type': 'ir.actions.act_window_close'}
account_fiscalyear_close_state()
diff --git a/addons/account/wizard/account_period_close.py b/addons/account/wizard/account_period_close.py
index fecf43f07ab..b2c61d9197a 100644
--- a/addons/account/wizard/account_period_close.py
+++ b/addons/account/wizard/account_period_close.py
@@ -53,11 +53,8 @@ class account_period_close(osv.osv_memory):
cr.execute('update account_journal_period set state=%s where period_id=%s', (mode, id))
cr.execute('update account_period set state=%s where id=%s', (mode, id))
- # Log message for Period
- for period_id, name in period_pool.name_get(cr, uid, [id]):
- period_pool.log(cr, uid, period_id, "Period '%s' is closed, no more modification allowed for this period." % (name))
return {'type': 'ir.actions.act_window_close'}
account_period_close()
-# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
\ No newline at end of file
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/account_analytic_plans/report/crossovered_analytic.py b/addons/account_analytic_plans/report/crossovered_analytic.py
index e2ad9e05b04..3e8eec81c55 100644
--- a/addons/account_analytic_plans/report/crossovered_analytic.py
+++ b/addons/account_analytic_plans/report/crossovered_analytic.py
@@ -109,7 +109,6 @@ class crossovered_analytic(report_sxw.rml_parse):
res['ref_qty'] = info[0]['qty']
res['ref_amt'] = info[0]['amt']
self.base_amount = info[0]['amt']
-
result.append(res)
return result
diff --git a/addons/account_analytic_plans/report/crossovered_analytic.rml b/addons/account_analytic_plans/report/crossovered_analytic.rml
index 766fb9f0d0d..48e7c13b0a1 100644
--- a/addons/account_analytic_plans/report/crossovered_analytic.rml
+++ b/addons/account_analytic_plans/report/crossovered_analytic.rml
@@ -237,10 +237,10 @@
[[ a['ref_code'] ]]
|
- [[ formatLang(a['ref_qty']) ]]
+ [[ a['ref_qty'] and formatLang(a['ref_qty']) ]]
|
- [[ formatLang(a['ref_amt'], currency_obj=company.currency_id) ]]
+ [[ a['ref_amt'] and formatLang(a['ref_amt'], currency_obj=company.currency_id) ]]
|
100.00%
diff --git a/addons/account_bank_statement_extensions/account_bank_statement.py b/addons/account_bank_statement_extensions/account_bank_statement.py
index d42e188679a..29b4c4fdb84 100644
--- a/addons/account_bank_statement_extensions/account_bank_statement.py
+++ b/addons/account_bank_statement_extensions/account_bank_statement.py
@@ -23,7 +23,6 @@
import time
from osv import osv, fields
import decimal_precision as dp
-import netsvc
from tools.translate import _
class account_bank_statement(osv.osv):
diff --git a/addons/account_bank_statement_extensions/report/bank_statement_balance_report.py b/addons/account_bank_statement_extensions/report/bank_statement_balance_report.py
index 8e1e4b09e47..5dcaafe4845 100644
--- a/addons/account_bank_statement_extensions/report/bank_statement_balance_report.py
+++ b/addons/account_bank_statement_extensions/report/bank_statement_balance_report.py
@@ -23,13 +23,13 @@
import time
from report import report_sxw
import pooler
-import netsvc
-logger=netsvc.Logger()
+import logging
+_logger = logging.getLogger(__name__)
class bank_statement_balance_report(report_sxw.rml_parse):
def set_context(self, objects, data, ids, report_type=None):
- #logger.notifyChannel('addons.'+__name__, netsvc.LOG_WARNING, 'set_context, objects = %s, data = %s, ids = %s' % (objects, data, ids))
+ #_logger.warning('addons.'+__name__, 'set_context, objects = %s, data = %s, ids = %s' % (objects, data, ids))
cr = self.cr
uid = self.uid
context = self.context
diff --git a/addons/account_coda/account_coda.py b/addons/account_coda/account_coda.py
index e3cc6f40a0c..36700c97b84 100644
--- a/addons/account_coda/account_coda.py
+++ b/addons/account_coda/account_coda.py
@@ -22,9 +22,7 @@
from osv import osv, fields
import decimal_precision as dp
-import netsvc
from tools.translate import _
-logger=netsvc.Logger()
class coda_bank_account(osv.osv):
_name= 'coda.bank.account'
diff --git a/addons/account_coda/wizard/account_coda_import.py b/addons/account_coda/wizard/account_coda_import.py
index c49eb9f1dbd..daa8bbd1026 100644
--- a/addons/account_coda/wizard/account_coda_import.py
+++ b/addons/account_coda/wizard/account_coda_import.py
@@ -24,11 +24,11 @@ import time
import base64
from osv import fields,osv
from tools.translate import _
-import netsvc
+import logging
import re
from traceback import format_exception
from sys import exc_info
-logger=netsvc.Logger()
+_logger = logging.getLogger(__name__)
class account_coda_import(osv.osv_memory):
_name = 'account.coda.import'
@@ -816,7 +816,7 @@ class account_coda_import(osv.osv_memory):
ttype = line['type'] == 'supplier' and 'payment' or 'receipt',
date = line['val_date'],
context = context)
- #logger.notifyChannel('addons.'+self._name, netsvc.LOG_WARNING, 'voucher_dict = %s' % voucher_dict)
+ #_logger.warning('voucher_dict = %s' % voucher_dict)
voucher_line_vals = False
if voucher_dict['value']['line_ids']:
for line_dict in voucher_dict['value']['line_ids']:
@@ -889,22 +889,19 @@ class account_coda_import(osv.osv_memory):
nb_err += 1
err_string += _('\nError ! ') + str(e)
tb = ''.join(format_exception(*exc_info()))
- logger.notifyChannel('addons.'+self._name, netsvc.LOG_ERROR,
- 'Application Error while processing Statement %s\n%s' % (statement.get('name', '/'),tb))
+ _logger.error('Application Error while processing Statement %s\n%s' % (statement.get('name', '/'),tb))
except Exception, e:
cr.rollback()
nb_err += 1
err_string += _('\nSystem Error : ') + str(e)
tb = ''.join(format_exception(*exc_info()))
- logger.notifyChannel('addons.'+self._name, netsvc.LOG_ERROR,
- 'System Error while processing Statement %s\n%s' % (statement.get('name', '/'),tb))
+ _logger.error('System Error while processing Statement %s\n%s' % (statement.get('name', '/'),tb))
except :
cr.rollback()
nb_err += 1
err_string = _('\nUnknown Error : ') + str(e)
tb = ''.join(format_exception(*exc_info()))
- logger.notifyChannel('addons.'+self._name, netsvc.LOG_ERROR,
- 'Unknown Error while processing Statement %s\n%s' % (statement.get('name', '/'),tb))
+ _logger.error('Unknown Error while processing Statement %s\n%s' % (statement.get('name', '/'),tb))
# end 'for statement in coda_statements'
diff --git a/addons/account_invoice_layout/report/report_account_invoice_layout.rml b/addons/account_invoice_layout/report/report_account_invoice_layout.rml
index 79bce6248d3..f2539e6d444 100644
--- a/addons/account_invoice_layout/report/report_account_invoice_layout.rml
+++ b/addons/account_invoice_layout/report/report_account_invoice_layout.rml
@@ -193,7 +193,7 @@
|
[[ (o.partner_id and o.partner_id.title and o.partner_id.title.name) or '' ]] [[ (o.partner_id and o.partner_id.name) or '' ]]
- [[ display_address(o.partner_id, 'invoice') ]]
+ [[ display_address(o.partner_id) ]]
diff --git a/addons/account_invoice_layout/report/special_message_invoice.rml b/addons/account_invoice_layout/report/special_message_invoice.rml
index 84049b18f0a..8bfcfd17654 100644
--- a/addons/account_invoice_layout/report/special_message_invoice.rml
+++ b/addons/account_invoice_layout/report/special_message_invoice.rml
@@ -197,7 +197,7 @@
|
[[ (o.partner_id and o.partner_id.title and o.partner_id.title.name) or '' ]] [[ (o.partner_id and o.partner_id.name) or '' ]]
- [[ display_address(o.partner_id, 'invoice') ]]
+ [[ display_address(o.partner_id) ]]
diff --git a/addons/account_voucher/report/account_voucher.py b/addons/account_voucher/report/account_voucher.py
index e44adee974e..146fcbc258a 100644
--- a/addons/account_voucher/report/account_voucher.py
+++ b/addons/account_voucher/report/account_voucher.py
@@ -72,4 +72,4 @@ report_sxw.report_sxw(
parser=report_voucher,header="external"
)
-# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
\ No newline at end of file
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/account_voucher/report/account_voucher_print.py b/addons/account_voucher/report/account_voucher_print.py
index 8bd8644c03c..6a5762be493 100644
--- a/addons/account_voucher/report/account_voucher_print.py
+++ b/addons/account_voucher/report/account_voucher_print.py
@@ -93,4 +93,4 @@ report_sxw.report_sxw(
parser=report_voucher_print,header="external"
)
-# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
\ No newline at end of file
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/auth_openid/controllers/main.py b/addons/auth_openid/controllers/main.py
index af30566a643..0ee7f98a020 100644
--- a/addons/auth_openid/controllers/main.py
+++ b/addons/auth_openid/controllers/main.py
@@ -44,8 +44,8 @@ from .. import utils
-_logger = logging.getLogger('web.auth_openid')
-oidutil.log = logging.getLogger('openid').debug
+_logger = logging.getLogger(__name__)
+oidutil.log = _logger.debug
class GoogleAppsAwareConsumer(consumer.GenericConsumer):
diff --git a/addons/base_crypt/crypt.py b/addons/base_crypt/crypt.py
index 9b91f7d3108..8a9d1ac1dc7 100644
--- a/addons/base_crypt/crypt.py
+++ b/addons/base_crypt/crypt.py
@@ -42,8 +42,10 @@ from osv import fields,osv
import pooler
from tools.translate import _
from service import security
+import logging
magic_md5 = '$1$'
+_logger = logging.getLogger(__name__)
def gen_salt( length=8, symbols=ascii_letters + digits ):
seed()
@@ -179,8 +181,7 @@ class users(osv.osv):
cr = pooler.get_db(db).cursor()
return self._login(cr, db, login, password)
except Exception:
- import logging
- logging.getLogger('netsvc').exception('Could not authenticate')
+ _logger.exception('Could not authenticate')
return Exception('Access Denied')
finally:
if cr is not None:
diff --git a/addons/base_report_designer/plugin/openerp_report_designer/bin/script/lib/logreport.py b/addons/base_report_designer/plugin/openerp_report_designer/bin/script/lib/logreport.py
index 2aab8596862..42198337450 100644
--- a/addons/base_report_designer/plugin/openerp_report_designer/bin/script/lib/logreport.py
+++ b/addons/base_report_designer/plugin/openerp_report_designer/bin/script/lib/logreport.py
@@ -27,21 +27,20 @@ LOG_INFO='info'
LOG_WARNING='warn'
LOG_ERROR='error'
LOG_CRITICAL='critical'
+_logger = logging.getLogger(__name__)
def log_detail(self):
import os
- logger = logging.getLogger()
logfile_name = os.path.join(tempfile.gettempdir(), "openerp_report_designer.log")
hdlr = logging.FileHandler(logfile_name)
formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
hdlr.setFormatter(formatter)
- logger.addHandler(hdlr)
- logger.setLevel(logging.INFO)
+ _logger.addHandler(hdlr)
+ _logger.setLevel(logging.INFO)
class Logger(object):
def log_write(self,name,level,msg):
- log = logging.getLogger(name)
- getattr(log,level)(msg)
+ getattr(_logger,level)(msg)
def shutdown(self):
logging.shutdown()
diff --git a/addons/base_vat/base_vat.py b/addons/base_vat/base_vat.py
index 7b8363ffd6b..e76442b62fe 100644
--- a/addons/base_vat/base_vat.py
+++ b/addons/base_vat/base_vat.py
@@ -23,11 +23,12 @@ import logging
import string
import datetime
import re
+_logger = logging.getLogger(__name__)
try:
import vatnumber
except ImportError:
- logging.getLogger('base_vat').warning("VAT validation partially unavailable because the `vatnumber` Python library cannot be found. "
+ _logger.warning("VAT validation partially unavailable because the `vatnumber` Python library cannot be found. "
"Install it to support more countries, for example with `easy_install vatnumber`.")
vatnumber = None
diff --git a/addons/caldav/caldav_node.py b/addons/caldav/caldav_node.py
index 71e9bdc2468..da5c5f017a6 100644
--- a/addons/caldav/caldav_node.py
+++ b/addons/caldav/caldav_node.py
@@ -23,6 +23,7 @@ from document_webdav import nodes
from document.nodes import _str2time, nodefd_static
import logging
from orm_utils import get_last_modified
+_logger = logging.getLogger(__name__)
try:
from tools.dict_tools import dict_merge2
@@ -223,7 +224,6 @@ class node_calendar(nodes.node_class):
res = []
if not filters:
return res
- _log = logging.getLogger('caldav.query')
if filters.localName == 'calendar-query':
res = []
for filter_child in filters.childNodes:
diff --git a/addons/caldav/calendar.py b/addons/caldav/calendar.py
index 94d28e4ad37..fb98e00a86f 100644
--- a/addons/caldav/calendar.py
+++ b/addons/caldav/calendar.py
@@ -34,6 +34,7 @@ import logging
from caldav_node import res_node_calendar
from orm_utils import get_last_modified
from tools.safe_eval import safe_eval as eval
+_logger = logging.getLogger(__name__)
try:
import vobject
@@ -240,7 +241,6 @@ def map_data(cr, uid, obj, context=None):
class CalDAV(object):
__attribute__ = {}
- _logger = logging.getLogger('document.caldav')
def ical_set(self, name, value, type):
""" set calendar Attribute
@@ -725,13 +725,13 @@ class Calendar(CalDAV, osv.osv):
objs.append(cal_children[child.name.lower()])
elif child.name.upper() == 'CALSCALE':
if child.value.upper() != 'GREGORIAN':
- self._logger.warning('How do I handle %s calendars?',child.value)
+ _logger.warning('How do I handle %s calendars?',child.value)
elif child.name.upper() in ('PRODID', 'VERSION'):
pass
elif child.name.upper().startswith('X-'):
- self._logger.debug("skipping custom node %s", child.name)
+ _logger.debug("skipping custom node %s", child.name)
else:
- self._logger.debug("skipping node %s", child.name)
+ _logger.debug("skipping node %s", child.name)
res = []
for obj_name in list(set(objs)):
diff --git a/addons/caldav/calendar_collection.py b/addons/caldav/calendar_collection.py
index 1abbf573ef0..3a5604b2f67 100644
--- a/addons/caldav/calendar_collection.py
+++ b/addons/caldav/calendar_collection.py
@@ -23,6 +23,7 @@ from osv import osv, fields
from tools.translate import _
import caldav_node
import logging
+_logger = logging.getLogger(__name__)
class calendar_collection(osv.osv):
_inherit = 'document.directory'
@@ -44,8 +45,7 @@ class calendar_collection(osv.osv):
root_cal_dir = self.browse(cr,uid, root_id, context=context)
return root_cal_dir.name
except Exception:
- logger = logging.getLogger('document')
- logger.warning('Cannot set root directory for Calendars:', exc_info=True)
+ _logger.warning('Cannot set root directory for Calendars:', exc_info=True)
return False
return False
diff --git a/addons/crm/crm_meeting.py b/addons/crm/crm_meeting.py
index cadd813a959..1e21d535c55 100644
--- a/addons/crm/crm_meeting.py
+++ b/addons/crm/crm_meeting.py
@@ -26,6 +26,7 @@ import logging
from osv import fields, osv
import tools
from tools.translate import _
+_logger = logging.getLogger(__name__)
class crm_lead(base_stage, osv.osv):
""" CRM Leads """
@@ -180,7 +181,7 @@ class res_users(osv.osv):
'user_id': user_id}, context=context)
except:
# Tolerate a missing shortcut. See product/product.py for similar code.
- logging.getLogger('orm').debug('Skipped meetings shortcut for user "%s"', data.get('name','
-
+
diff --git a/addons/document/content_index.py b/addons/document/content_index.py
index 64b480ee736..f24c033a7ec 100644
--- a/addons/document/content_index.py
+++ b/addons/document/content_index.py
@@ -22,7 +22,7 @@ import logging
import os
import tempfile
from subprocess import Popen, PIPE
-
+_logger = logging.getLogger(__name__)
class NhException(Exception):
pass
@@ -116,7 +116,7 @@ def mime_match(mime, mdict):
return (None, None)
class contentIndex(object):
- __logger = logging.getLogger('addons.document.content_index')
+
def __init__(self):
self.mimes = {}
self.exts = {}
@@ -132,7 +132,7 @@ class contentIndex(object):
f = True
if f:
- self.__logger.debug('Register content indexer: %r', obj)
+ _logger.debug('Register content indexer: %r', obj)
if not f:
raise Exception("Your indexer should at least suport a mimetype or extension")
@@ -169,22 +169,22 @@ class contentIndex(object):
(result, _) = pop.communicate()
mime2 = result.split(';')[0]
- self.__logger.debug('File gave us: %s', mime2)
+ _logger.debug('File gave us: %s', mime2)
# Note that the temporary file still exists now.
mime,fobj = mime_match(mime2, self.mimes)
if not mime:
mime = mime2
except Exception:
- self.__logger.exception('Cannot determine mime type')
+ _logger.exception('Cannot determine mime type')
try:
if fobj:
res = (mime, fobj.indexContent(content,filename,fname or realfname) )
else:
- self.__logger.debug("Have no object, return (%s, None)", mime)
+ _logger.debug("Have no object, return (%s, None)", mime)
res = (mime, None )
except Exception:
- self.__logger.exception("Could not index file %s (%s)",
+ _logger.exception("Could not index file %s (%s)",
filename, fname or realfname)
res = None
@@ -193,8 +193,7 @@ class contentIndex(object):
try:
os.unlink(fname)
except Exception:
- self.__logger.exception("Could not unlink %s", fname)
-
+ _logger.exception("Could not unlink %s", fname)
return res
cntIndex = contentIndex()
diff --git a/addons/document/document.py b/addons/document/document.py
index 92ece063a47..fa65f8d9966 100644
--- a/addons/document/document.py
+++ b/addons/document/document.py
@@ -30,12 +30,15 @@ from tools.translate import _
import nodes
import logging
+_logger = logging.getLogger(__name__)
+
DMS_ROOT_PATH = tools.config.get('document_path', os.path.join(tools.config['root_path'], 'filestore'))
class document_file(osv.osv):
_inherit = 'ir.attachment'
_rec_name = 'datas_fname'
-
+
+
def _attach_parent_id(self, cr, uid, ids=None, context=None):
"""Migrate ir.attachments to the document module.
@@ -54,7 +57,7 @@ class document_file(osv.osv):
parent_id = self.pool.get('document.directory')._get_root_directory(cr,uid)
if not parent_id:
- logging.getLogger('document').warning("at _attach_parent_id(), still not able to set the parent!")
+ _logger.warning("at _attach_parent_id(), still not able to set the parent!")
return False
if ids is not None:
@@ -140,8 +143,8 @@ class document_file(osv.osv):
_defaults = {
'user_id': lambda self, cr, uid, ctx:uid,
+ 'parent_id': __get_def_directory,
'file_size': lambda self, cr, uid, ctx:0,
- 'parent_id': __get_def_directory
}
_sql_constraints = [
# filename_uniq is not possible in pure SQL
@@ -336,7 +339,7 @@ class document_file(osv.osv):
if r:
unres.append(r)
else:
- logging.getLogger('document').warning("Unlinking attachment #%s %s that has no storage",
+ self.loggerdoc.warning("Unlinking attachment #%s %s that has no storage",
f.id, f.name)
res = super(document_file, self).unlink(cr, uid, ids, context)
stor.do_unlink(cr, uid, unres)
diff --git a/addons/document/document_data.xml b/addons/document/document_data.xml
index ac7a174b05f..a7bc98de6f3 100644
--- a/addons/document/document_data.xml
+++ b/addons/document/document_data.xml
@@ -104,6 +104,5 @@
-
diff --git a/addons/document/document_directory.py b/addons/document/document_directory.py
index d09d2cc86d5..03b2dcc47bf 100644
--- a/addons/document/document_directory.py
+++ b/addons/document/document_directory.py
@@ -22,10 +22,10 @@
from osv import osv, fields
from osv.orm import except_orm
-
+import logging
import nodes
from tools.translate import _
-
+_logger = logging.getLogger(__name__)
class document_directory(osv.osv):
_name = 'document.directory'
_description = 'Directory'
@@ -78,9 +78,8 @@ class document_directory(osv.osv):
root_id = objid.read(cr, uid, mid, ['res_id'])['res_id']
return root_id
except Exception, e:
- import netsvc
- logger = netsvc.Logger()
- logger.notifyChannel("document", netsvc.LOG_WARNING, 'Cannot set directory root:'+ str(e))
+
+ _logger.warning('Cannot set directory root:'+ str(e))
return False
return objid.browse(cr, uid, mid, context=context).res_id
diff --git a/addons/document/document_storage.py b/addons/document/document_storage.py
index fe757e7876d..339b320e9a7 100644
--- a/addons/document/document_storage.py
+++ b/addons/document/document_storage.py
@@ -29,18 +29,15 @@ import logging
import shutil
from StringIO import StringIO
import psycopg2
-
from tools.misc import ustr
from tools.translate import _
-
from osv.orm import except_orm
-
import random
import string
import pooler
import nodes
from content_index import cntIndex
-
+_logger = logging.getLogger(__name__)
DMS_ROOT_PATH = tools.config.get('document_path', os.path.join(tools.config.get('root_path'), 'filestore'))
@@ -130,7 +127,7 @@ class nodefd_file(nodes.node_descriptor):
mime, icont = cntIndex.doIndex(None, filename=filename,
content_type=None, realfname=fname)
except Exception:
- logging.getLogger('document.storage').debug('Cannot index file:', exc_info=True)
+ _logger.debug('Cannot index file:', exc_info=True)
pass
try:
@@ -150,7 +147,7 @@ class nodefd_file(nodes.node_descriptor):
cr.commit()
cr.close()
except Exception:
- logging.getLogger('document.storage').warning('Cannot save file indexed content:', exc_info=True)
+ _logger.warning('Cannot save file indexed content:', exc_info=True)
elif self.mode in ('a', 'a+' ):
try:
@@ -164,7 +161,7 @@ class nodefd_file(nodes.node_descriptor):
cr.commit()
cr.close()
except Exception:
- logging.getLogger('document.storage').warning('Cannot save file appended content:', exc_info=True)
+ _logger.warning('Cannot save file appended content:', exc_info=True)
@@ -191,7 +188,7 @@ class nodefd_db(StringIO, nodes.node_descriptor):
elif mode == 'a':
StringIO.__init__(self, None)
else:
- logging.getLogger('document.storage').error("Incorrect mode %s specified", mode)
+ _logger.error("Incorrect mode %s specified", mode)
raise IOError(errno.EINVAL, "Invalid file mode")
self.mode = mode
@@ -217,7 +214,7 @@ class nodefd_db(StringIO, nodes.node_descriptor):
mime, icont = cntIndex.doIndex(data, filename=filename,
content_type=None, realfname=None)
except Exception:
- logging.getLogger('document.storage').debug('Cannot index file:', exc_info=True)
+ _logger.debug('Cannot index file:', exc_info=True)
pass
try:
@@ -241,7 +238,7 @@ class nodefd_db(StringIO, nodes.node_descriptor):
(out, len(data), par.file_id))
cr.commit()
except Exception:
- logging.getLogger('document.storage').exception('Cannot update db file #%d for close:', par.file_id)
+ _logger.exception('Cannot update db file #%d for close:', par.file_id)
raise
finally:
cr.close()
@@ -271,7 +268,7 @@ class nodefd_db64(StringIO, nodes.node_descriptor):
elif mode == 'a':
StringIO.__init__(self, None)
else:
- logging.getLogger('document.storage').error("Incorrect mode %s specified", mode)
+ _logger.error("Incorrect mode %s specified", mode)
raise IOError(errno.EINVAL, "Invalid file mode")
self.mode = mode
@@ -297,7 +294,7 @@ class nodefd_db64(StringIO, nodes.node_descriptor):
mime, icont = cntIndex.doIndex(data, filename=filename,
content_type=None, realfname=None)
except Exception:
- logging.getLogger('document.storage').debug('Cannot index file:', exc_info=True)
+ self.logger.debug('Cannot index file:', exc_info=True)
pass
try:
@@ -320,7 +317,7 @@ class nodefd_db64(StringIO, nodes.node_descriptor):
(base64.encodestring(data), len(data), par.file_id))
cr.commit()
except Exception:
- logging.getLogger('document.storage').exception('Cannot update db file #%d for close:', par.file_id)
+ _logger.exception('Cannot update db file #%d for close:', par.file_id)
raise
finally:
cr.close()
@@ -339,7 +336,6 @@ class document_storage(osv.osv):
"""
_name = 'document.storage'
_description = 'Storage Media'
- _doclog = logging.getLogger('document')
_columns = {
'name': fields.char('Name', size=64, required=True, select=1),
@@ -402,7 +398,7 @@ class document_storage(osv.osv):
npath = filter(lambda x: x is not None, npath)
# if self._debug:
- # self._doclog.debug('Npath: %s', npath)
+ # self._logger.debug('Npath: %s', npath)
for n in npath:
if n == '..':
raise ValueError("Invalid '..' element in path")
@@ -413,7 +409,7 @@ class document_storage(osv.osv):
dpath += npath[:-1]
path = os.path.join(*dpath)
if not os.path.isdir(path):
- self._doclog.debug("Create dirs: %s", path)
+ _logger.debug("Create dirs: %s", path)
os.makedirs(path)
return path, npath
@@ -451,7 +447,7 @@ class document_storage(osv.osv):
# try to fix their directory.
if mode in ('r','r+'):
if ira.file_size:
- self._doclog.warning( "ir.attachment #%d does not have a filename, but is at filestore, fix it!" % ira.id)
+ _logger.warning( "ir.attachment #%d does not have a filename, but is at filestore, fix it!" % ira.id)
raise IOError(errno.ENOENT, 'No file can be located')
else:
store_fname = self.__get_random_fname(boo.path)
@@ -493,7 +489,7 @@ class document_storage(osv.osv):
# On a migrated db, some files may have the wrong storage type
# try to fix their directory.
if ira.file_size:
- self._doclog.warning( "ir.attachment #%d does not have a filename, but is at filestore, fix it!" % ira.id)
+ _logger.warning( "ir.attachment #%d does not have a filename, but is at filestore, fix it!" % ira.id)
return None
fpath = os.path.join(boo.path, ira.store_fname)
return file(fpath, 'rb').read()
@@ -517,7 +513,7 @@ class document_storage(osv.osv):
# On a migrated db, some files may have the wrong storage type
# try to fix their directory.
if ira.file_size:
- self._doclog.warning("ir.attachment #%d does not have a filename, trying the name." %ira.id)
+ _logger.warning("ir.attachment #%d does not have a filename, trying the name." %ira.id)
# sfname = ira.name
fpath = os.path.join(boo.path,ira.store_fname or ira.name)
if os.path.exists(fpath):
@@ -550,7 +546,7 @@ class document_storage(osv.osv):
if boo.readonly:
raise IOError(errno.EPERM, "Readonly medium")
- self._doclog.debug( "Store data for ir.attachment #%d" % ira.id)
+ _logger.debug( "Store data for ir.attachment #%d" % ira.id)
store_fname = None
fname = None
if boo.type == 'filestore':
@@ -563,13 +559,13 @@ class document_storage(osv.osv):
fp.write(data)
finally:
fp.close()
- self._doclog.debug( "Saved data to %s" % fname)
+ _logger.debug( "Saved data to %s" % fname)
filesize = len(data) # os.stat(fname).st_size
# TODO Here, an old file would be left hanging.
except Exception, e:
- self._doclog.warning( "Couldn't save data to %s", path, exc_info=True)
+ _logger.warning( "Couldn't save data to %s", path, exc_info=True)
raise except_orm(_('Error!'), str(e))
elif boo.type == 'db':
filesize = len(data)
@@ -592,12 +588,12 @@ class document_storage(osv.osv):
fp.write(data)
finally:
fp.close()
- self._doclog.debug("Saved data to %s", fname)
+ _logger.debug("Saved data to %s", fname)
filesize = len(data) # os.stat(fname).st_size
store_fname = os.path.join(*npath)
# TODO Here, an old file would be left hanging.
except Exception,e :
- self._doclog.warning("Couldn't save data:", exc_info=True)
+ _logger.warning("Couldn't save data:", exc_info=True)
raise except_orm(_('Error!'), str(e))
elif boo.type == 'virtual':
@@ -616,7 +612,7 @@ class document_storage(osv.osv):
mime, icont = cntIndex.doIndex(data, ira.datas_fname,
ira.file_type or None, fname)
except Exception:
- self._doclog.debug('Cannot index file:', exc_info=True)
+ _logger.debug('Cannot index file:', exc_info=True)
pass
try:
@@ -633,7 +629,7 @@ class document_storage(osv.osv):
file_node.content_type = mime
return True
except Exception, e :
- self._doclog.warning("Couldn't save data:", exc_info=True)
+ self._logger.warning("Couldn't save data:", exc_info=True)
# should we really rollback once we have written the actual data?
# at the db case (only), that rollback would be safe
raise except_orm(_('Error at doc write!'), str(e))
@@ -671,9 +667,9 @@ class document_storage(osv.osv):
try:
os.unlink(fname)
except Exception:
- self._doclog.warning("Could not remove file %s, please remove manually.", fname, exc_info=True)
+ _logger.warning("Could not remove file %s, please remove manually.", fname, exc_info=True)
else:
- self._doclog.warning("Unknown unlink key %s" % ktype)
+ _logger.warning("Unknown unlink key %s" % ktype)
return True
@@ -703,9 +699,9 @@ class document_storage(osv.osv):
fname = ira.store_fname
if not fname:
- self._doclog.warning("Trying to rename a non-stored file")
+ _logger.warning("Trying to rename a non-stored file")
if fname != os.path.join(*npath):
- self._doclog.warning("inconsistency in realstore: %s != %s" , fname, repr(npath))
+ _logger.warning("inconsistency in realstore: %s != %s" , fname, repr(npath))
oldpath = os.path.join(path, npath[-1])
newpath = os.path.join(path, new_name)
@@ -743,7 +739,7 @@ class document_storage(osv.osv):
break
par = par.parent_id
if file_node.storage_id != psto:
- self._doclog.debug('Cannot move file %r from %r to %r', file_node, file_node.parent, ndir_bro.name)
+ _logger.debug('Cannot move file %r from %r to %r', file_node, file_node.parent, ndir_bro.name)
raise NotImplementedError('Cannot move files between storage media')
if sbro.type in ('filestore', 'db', 'db64'):
@@ -756,9 +752,9 @@ class document_storage(osv.osv):
fname = ira.store_fname
if not fname:
- self._doclog.warning("Trying to rename a non-stored file")
+ _logger.warning("Trying to rename a non-stored file")
if fname != os.path.join(*opath):
- self._doclog.warning("inconsistency in realstore: %s != %s" , fname, repr(opath))
+ _logger.warning("inconsistency in realstore: %s != %s" , fname, repr(opath))
oldpath = os.path.join(path, opath[-1])
@@ -766,12 +762,12 @@ class document_storage(osv.osv):
npath = filter(lambda x: x is not None, npath)
newdir = os.path.join(*npath)
if not os.path.isdir(newdir):
- self._doclog.debug("Must create dir %s", newdir)
+ _logger.debug("Must create dir %s", newdir)
os.makedirs(newdir)
npath.append(opath[-1])
newpath = os.path.join(*npath)
- self._doclog.debug("Going to move %s from %s to %s", opath[-1], oldpath, newpath)
+ _logger.debug("Going to move %s from %s to %s", opath[-1], oldpath, newpath)
shutil.move(oldpath, newpath)
store_path = npath[1:] + [opath[-1],]
diff --git a/addons/document/nodes.py b/addons/document/nodes.py
index ee89f3d4c6c..273be7effa4 100644
--- a/addons/document/nodes.py
+++ b/addons/document/nodes.py
@@ -41,8 +41,7 @@ from StringIO import StringIO
# file: objct = ir.attachement
# root: if we are at the first directory of a ressource
#
-
-logger = logging.getLogger('doc2.nodes')
+_logger = logging.getLogger(__name__)
def _str2time(cre):
""" Convert a string with time representation (from db) into time (float)
@@ -328,7 +327,7 @@ class node_class(object):
if self.DAV_M_NS.has_key(ns):
prefix = self.DAV_M_NS[ns]
else:
- logger.debug('No namespace: %s ("%s")',ns, prop)
+ _logger.debug('No namespace: %s ("%s")',ns, prop)
return None
mname = prefix + "_" + prop.replace('-','_')
@@ -341,7 +340,7 @@ class node_class(object):
r = m(cr)
return r
except AttributeError:
- logger.debug('Property %s not supported' % prop, exc_info=True)
+ _logger.debug('Property %s not supported' % prop, exc_info=True)
return None
def get_dav_resourcetype(self, cr):
@@ -384,13 +383,13 @@ class node_class(object):
def create_child(self, cr, path, data=None):
""" Create a regular file under this node
"""
- logger.warning("Attempted to create a file under %r, not possible.", self)
+ _logger.warning("Attempted to create a file under %r, not possible.", self)
raise IOError(errno.EPERM, "Not allowed to create files here")
def create_child_collection(self, cr, objname):
""" Create a child collection (directory) under self
"""
- logger.warning("Attempted to create a collection under %r, not possible.", self)
+ _logger.warning("Attempted to create a collection under %r, not possible.", self)
raise IOError(errno.EPERM, "Not allowed to create folders here")
def rm(self, cr):
@@ -725,7 +724,7 @@ class node_dir(node_database):
assert self.parent
if self.parent != ndir_node:
- logger.debug('Cannot move dir %r from %r to %r', self, self.parent, ndir_node)
+ _logger.debug('Cannot move dir %r from %r to %r', self, self.parent, ndir_node)
raise NotImplementedError('Cannot move dir to another dir')
ret = {}
@@ -998,7 +997,7 @@ class node_res_obj(node_class):
def get_dav_eprop_DEPR(self, cr, ns, prop):
# Deprecated!
if ns != 'http://groupdav.org/' or prop != 'resourcetype':
- logger.warning("Who asked for %s:%s?" % (ns, prop))
+ _logger.warning("Who asked for %s:%s?" % (ns, prop))
return None
cntobj = self.context._dirobj.pool.get('document.directory.content')
uid = self.context.uid
@@ -1328,7 +1327,7 @@ class node_file(node_class):
ret = {}
if ndir_node and self.parent != ndir_node:
if not (isinstance(self.parent, node_dir) and isinstance(ndir_node, node_dir)):
- logger.debug('Cannot move file %r from %r to %r', self, self.parent, ndir_node)
+ _logger.debug('Cannot move file %r from %r to %r', self, self.parent, ndir_node)
raise NotImplementedError('Cannot move files between dynamic folders')
if not ndir_obj:
@@ -1452,6 +1451,7 @@ class node_content(node_class):
return ''
class nodefd_content(StringIO, node_descriptor):
+
""" A descriptor to content nodes
"""
def __init__(self, parent, cr, mode, ctx):
@@ -1473,7 +1473,7 @@ class nodefd_content(StringIO, node_descriptor):
elif mode == 'a':
StringIO.__init__(self, None)
else:
- logging.getLogger('document.content').error("Incorrect mode %s specified", mode)
+ _logger.error("Incorrect mode %s specified", mode)
raise IOError(errno.EINVAL, "Invalid file mode")
self.mode = mode
@@ -1499,13 +1499,14 @@ class nodefd_content(StringIO, node_descriptor):
raise NotImplementedError
cr.commit()
except Exception:
- logging.getLogger('document.content').exception('Cannot update db content #%d for close:', par.cnt_id)
+ _logger.exception('Cannot update db content #%d for close:', par.cnt_id)
raise
finally:
cr.close()
StringIO.close(self)
class nodefd_static(StringIO, node_descriptor):
+
""" A descriptor to nodes with static data.
"""
def __init__(self, parent, cr, mode, ctx=None):
@@ -1526,7 +1527,7 @@ class nodefd_static(StringIO, node_descriptor):
elif mode == 'a':
StringIO.__init__(self, None)
else:
- logging.getLogger('document.nodes').error("Incorrect mode %s specified", mode)
+ _logger.error("Incorrect mode %s specified", mode)
raise IOError(errno.EINVAL, "Invalid file mode")
self.mode = mode
@@ -1551,7 +1552,7 @@ class nodefd_static(StringIO, node_descriptor):
raise NotImplementedError
cr.commit()
except Exception:
- logging.getLogger('document.nodes').exception('Cannot update db content #%d for close:', par.cnt_id)
+ _logger.exception('Cannot update db content #%d for close:', par.cnt_id)
raise
finally:
cr.close()
diff --git a/addons/document/std_index.py b/addons/document/std_index.py
index e153d018bf0..49ac9a5c906 100644
--- a/addons/document/std_index.py
+++ b/addons/document/std_index.py
@@ -25,6 +25,7 @@ import StringIO
import odt2txt
import sys, zipfile, xml.dom.minidom
import logging
+_logger = logging.getLogger(__name__)
def _to_unicode(s):
try:
@@ -101,9 +102,9 @@ class DocIndex(indexer):
(data, _) = pop.communicate()
return _to_unicode(data)
except OSError:
- logger = logging.getLogger('document.DocIndex')
- logger.warn("Failed attempt to execute antiword (MS Word reader). Antiword is necessary to index the file %s of MIME type %s. Detailed error available at DEBUG level.", fname, self._getMimeTypes()[0])
- logger.debug("Trace of the failed file indexing attempt: ", exc_info=True)
+
+ _logger.warn("Failed attempt to execute antiword (MS Word reader). Antiword is necessary to index the file %s of MIME type %s. Detailed error available at DEBUG level.", fname, self._getMimeTypes()[0])
+ _logger.debug("Trace of the failed file indexing attempt: ", exc_info=True)
return False
cntIndex.register(DocIndex())
diff --git a/addons/document_ftp/ftpserver/__init__.py b/addons/document_ftp/ftpserver/__init__.py
index 2e09a938a05..59aff85c633 100644
--- a/addons/document_ftp/ftpserver/__init__.py
+++ b/addons/document_ftp/ftpserver/__init__.py
@@ -23,9 +23,9 @@ import threading
import ftpserver
import authorizer
import abstracted_fs
-import netsvc
+import logging
from tools import config
-
+_logger = logging.getLogger(__name__)
def start_server():
HOST = config.get('ftp_server_host', '127.0.0.1')
PORT = int(config.get('ftp_server_port', '8021'))
@@ -35,10 +35,7 @@ def start_server():
PASSIVE_PORTS = int(pps[0]), int(pps[1])
class ftp_server(threading.Thread):
- def log(self, level, message):
- logger = netsvc.Logger()
- logger.notifyChannel('FTP', level, message)
-
+
def run(self):
autho = authorizer.authorizer()
ftpserver.FTPHandler.authorizer = autho
@@ -48,17 +45,17 @@ def start_server():
if PASSIVE_PORTS:
ftpserver.FTPHandler.passive_ports = PASSIVE_PORTS
- ftpserver.log = lambda msg: self.log(netsvc.LOG_INFO, msg)
+ ftpserver.log = lambda msg: _logger.info(msg)
ftpserver.logline = lambda msg: None
- ftpserver.logerror = lambda msg: self.log(netsvc.LOG_ERROR, msg)
+ ftpserver.logerror = lambda msg: _logger.error(msg)
ftpd = ftpserver.FTPServer((HOST, PORT), ftpserver.FTPHandler)
ftpd.serve_forever()
if HOST.lower() == 'none':
- netsvc.Logger().notifyChannel("FTP", netsvc.LOG_INFO, "\n Server FTP Not Started\n")
+ _logger.info("\n Server FTP Not Started\n")
else:
- netsvc.Logger().notifyChannel("FTP", netsvc.LOG_INFO, "\n Serving FTP on %s:%s\n" % (HOST, PORT))
+ _logger.info("\n Serving FTP on %s:%s\n" % (HOST, PORT))
ds = ftp_server()
ds.daemon = True
ds.start()
diff --git a/addons/document_ftp/ftpserver/abstracted_fs.py b/addons/document_ftp/ftpserver/abstracted_fs.py
index 83cd1cde725..429016a2376 100644
--- a/addons/document_ftp/ftpserver/abstracted_fs.py
+++ b/addons/document_ftp/ftpserver/abstracted_fs.py
@@ -56,7 +56,7 @@ class abstracted_fs(object):
self.cwd = '/'
self.cwd_node = None
self.rnfr = None
- self._log = logging.getLogger('FTP.fs')
+ self._log = logging.getLogger(__name__)
# Ok
def db_list(self):
diff --git a/addons/document_webdav/redirect.py b/addons/document_webdav/redirect.py
index 7bc0883f9e8..31f462bcbbe 100644
--- a/addons/document_webdav/redirect.py
+++ b/addons/document_webdav/redirect.py
@@ -24,9 +24,9 @@ import logging
import urlparse
from service.websrv_lib import FixSendError, HTTPHandler, HttpOptions
from service.http_server import HttpLogHandler
-
+_logger = logging.getLogger(__name__)
class RedirectHTTPHandler(HttpLogHandler, FixSendError, HttpOptions, HTTPHandler):
- _logger = logging.getLogger('httpd.well-known')
+
_HTTP_OPTIONS = { 'Allow': ['OPTIONS', 'GET', 'HEAD', 'PROPFIND'] }
redirect_paths = {}
@@ -80,7 +80,7 @@ class RedirectHTTPHandler(HttpLogHandler, FixSendError, HttpOptions, HTTPHandler
self.send_header("Content-Length", 0)
self.end_headers()
# Do we need a Cache-content: header here?
- self._logger.debug("redirecting %s to %s", self.path, redir_path)
+ _logger.debug("redirecting %s to %s", self.path, redir_path)
return None
def do_PROPFIND(self):
diff --git a/addons/document_webdav/test_davclient.py b/addons/document_webdav/test_davclient.py
index 3c20cfed5b8..a4dda231bd8 100755
--- a/addons/document_webdav/test_davclient.py
+++ b/addons/document_webdav/test_davclient.py
@@ -43,7 +43,7 @@ from xmlrpclib import Transport, ProtocolError
import StringIO
import base64
-log = logging.getLogger('http-client')
+_logger = logging.getLogger(__name__)
class HTTP11(httplib.HTTP):
_http_vsn = 11
@@ -62,7 +62,7 @@ class PersistentTransport(Transport):
if not self._http.has_key(host):
host, extra_headers, x509 = self.get_host_info(host)
self._http[host] = HTTP11(host)
- log.debug("New connection to %s", host)
+ _logger.debug("New connection to %s", host)
return self._http[host]
def get_host_info(self, host):
@@ -170,7 +170,7 @@ class SafePersistentTransport(PersistentTransport):
if not self._http.has_key(host):
host, extra_headers, x509 = self.get_host_info(host)
self._http[host] = httplib.HTTPS(host, None, **(x509 or {}))
- log.debug("New connection to %s", host)
+ _logger.debug("New connection to %s", host)
return self._http[host]
class AuthClient(object):
@@ -191,8 +191,8 @@ class BasicAuthClient(AuthClient):
return super(BasicAuthClient,self).getAuth(atype, realm)
if not self._realm_dict.has_key(realm):
- log.debug("realm dict: %r", self._realm_dict)
- log.debug("missing key: \"%s\"" % realm)
+ _logger.debug("realm dict: %r", self._realm_dict)
+ _logger.debug("missing key: \"%s\"" % realm)
self.resolveFailedRealm(realm)
return 'Basic '+ self._realm_dict[realm]
@@ -239,7 +239,7 @@ class addAuthTransport:
# This line will bork if self.setAuthClient has not
# been issued. That is a programming error, fix your code!
auths = self._auth_client.getAuth(atype, realm)
- log.debug("sending authorization: %s", auths)
+ _logger.debug("sending authorization: %s", auths)
h.putheader('Authorization', auths)
self.send_content(h, request_body)
@@ -255,8 +255,8 @@ class addAuthTransport:
log.warning("Why have data on a 401 auth. message?")
if realm.startswith('realm="') and realm.endswith('"'):
realm = realm[7:-1]
- log.debug("Resp: %r %r", resp.version,resp.isclosed(), resp.will_close)
- log.debug("Want to do auth %s for realm %s", atype, realm)
+ _logger.debug("Resp: %r %r", resp.version,resp.isclosed(), resp.will_close)
+ _logger.debug("Want to do auth %s for realm %s", atype, realm)
if atype != 'Basic':
raise ProtocolError(host+handler, 403,
"Unknown authentication method: %s" % atype, resp.msg)
@@ -315,7 +315,7 @@ class HTTPSConnection(httplib.HTTPSConnection):
lf = (len(ssl.PEM_FOOTER)+1)
if cert[0-lf] != '\n':
cert = cert[:0-lf]+'\n'+cert[0-lf:]
- log.debug("len-footer: %s cert: %r", lf, cert[0-lf])
+ _logger.debug("len-footer: %s cert: %r", lf, cert[0-lf])
return cert
@@ -390,7 +390,7 @@ class DAVClient(object):
import base64
dbg = self.dbg
hdrs.update(self.hdrs)
- log.debug("Getting %s http://%s:%d/%s", method, self.host, self.port, path)
+ _logger.debug("Getting %s http://%s:%d/%s", method, self.host, self.port, path)
conn = httplib.HTTPConnection(self.host, port=self.port, timeout=self.timeout)
conn.set_debuglevel(dbg)
if not path:
@@ -409,8 +409,8 @@ class DAVClient(object):
data1 = r1.read()
if not self.user:
raise Exception('Must auth, have no user/pass!')
- log.debug("Ver: %s, closed: %s, will close: %s", r1.version,r1.isclosed(), r1.will_close)
- log.debug("Want to do auth %s for realm %s", atype, realm)
+ _logger.debug("Ver: %s, closed: %s, will close: %s", r1.version,r1.isclosed(), r1.will_close)
+ _logger.debug("Want to do auth %s for realm %s", atype, realm)
if atype == 'Basic' :
auths = base64.encodestring(self.user + ':' + self.passwd)
if auths[-1] == "\n":
@@ -422,22 +422,22 @@ class DAVClient(object):
else:
raise Exception("Unknown auth type %s" %atype)
else:
- log.warning("Got 401, cannot auth")
+ _logger.warning("Got 401, cannot auth")
raise Exception('No auth')
- log.debug("Reponse: %s %s",r1.status, r1.reason)
+ _logger.debug("Reponse: %s %s",r1.status, r1.reason)
data1 = r1.read()
if method != 'GET':
- log.debug("Body:\n%s\nEnd of body", data1)
+ _logger.debug("Body:\n%s\nEnd of body", data1)
try:
ctype = r1.msg.getheader('content-type')
if ctype and ';' in ctype:
ctype, encoding = ctype.split(';',1)
if ctype == 'text/xml':
doc = xml.dom.minidom.parseString(data1)
- log.debug("XML Body:\n %s", doc.toprettyxml(indent="\t"))
+ _logger.debug("XML Body:\n %s", doc.toprettyxml(indent="\t"))
except Exception:
- log.warning("could not print xml", exc_info=True)
+ _logger.warning("could not print xml", exc_info=True)
pass
conn.close()
return r1.status, r1.msg, data1
@@ -474,7 +474,7 @@ class DAVClient(object):
s, m, d = self._http_request(path, method='OPTIONS', hdrs=hdrs)
assert s == 200, "Status: %r" % s
assert 'OPTIONS' in m.getheader('Allow')
- log.debug('Options: %r', m.getheader('Allow'))
+ _logger.debug('Options: %r', m.getheader('Allow'))
if expect:
self._assert_headers(expect, m)
@@ -493,10 +493,10 @@ class DAVClient(object):
for cnod in node.childNodes:
if cnod.nodeType != node.ELEMENT_NODE:
if strict:
- log.debug("Found %r inside <%s>", cnod, node.tagName)
+ _logger.debug("Found %r inside <%s>", cnod, node.tagName)
continue
if namespaces and (cnod.namespaceURI not in namespaces):
- log.debug("Ignoring <%s> in <%s>", cnod.tagName, node.localName)
+ _logger.debug("Ignoring <%s> in <%s>", cnod.tagName, node.localName)
continue
yield cnod
@@ -533,10 +533,10 @@ class DAVClient(object):
assert htver == 'HTTP/1.1'
rstatus = int(sta)
else:
- log.debug("What is <%s> inside a ?", pno.tagName)
+ _logger.debug("What is <%s> inside a ?", pno.tagName)
else:
- log.debug("Unknown node: %s", cno.tagName)
+ _logger.debug("Unknown node: %s", cno.tagName)
res.setdefault(href,[]).append((status, res_nss))
@@ -637,7 +637,7 @@ class DAVClient(object):
if lsp[1] in davprops:
lsline[lsp[0]] = lsp[2]
else:
- log.debug("Strange status: %s", st)
+ _logger.debug("Strange status: %s", st)
res.append(lsline)
diff --git a/addons/document_webdav/webdav_server.py b/addons/document_webdav/webdav_server.py
index ae75d0b80fc..65ebb49ff5f 100644
--- a/addons/document_webdav/webdav_server.py
+++ b/addons/document_webdav/webdav_server.py
@@ -54,7 +54,7 @@ from DAV.propfind import PROPFIND
# from DAV.constants import DAV_VERSION_1, DAV_VERSION_2
from xml.dom import minidom
from redirect import RedirectHTTPHandler
-
+_logger = logging.getLogger(__name__)
khtml_re = re.compile(r' KHTML/([0-9\.]+) ')
def OpenDAVConfig(**kw):
@@ -73,7 +73,7 @@ def OpenDAVConfig(**kw):
class DAVHandler(HttpOptions, FixSendError, DAVRequestHandler):
verbose = False
- _logger = logging.getLogger('webdav')
+
protocol_version = 'HTTP/1.1'
_HTTP_OPTIONS= { 'DAV' : ['1', '2'],
'Allow' : [ 'GET', 'HEAD', 'COPY', 'MOVE', 'POST', 'PUT',
@@ -127,10 +127,10 @@ class DAVHandler(HttpOptions, FixSendError, DAVRequestHandler):
return self.davpath
def log_message(self, format, *args):
- self._logger.debug(format % args)
+ _logger.debug(format % args)
def log_error(self, format, *args):
- self._logger.warning(format % args)
+ _logger.warning(format % args)
def _prep_OPTIONS(self, opts):
ret = opts
@@ -477,7 +477,7 @@ class dummy_dav_interface(object):
uri2 = uri.split('/')
if len(uri2) < 3:
return True
- logging.getLogger('webdav').debug("Requested uri: %s", uri)
+ _logger.debug("Requested uri: %s", uri)
return None # no
def is_collection(self, uri):
@@ -487,6 +487,7 @@ class dummy_dav_interface(object):
class DAVStaticHandler(http_server.StaticHTTPHandler):
""" A variant of the Static handler, which will serve dummy DAV requests
"""
+
verbose = False
protocol_version = 'HTTP/1.1'
_HTTP_OPTIONS= { 'DAV' : ['1', '2'],
@@ -573,7 +574,7 @@ try:
conf = OpenDAVConfig(**_dc)
handler._config = conf
reg_http_service(directory, DAVHandler, DAVAuthProvider)
- logging.getLogger('webdav').info("WebDAV service registered at path: %s/ "% directory)
+ _logger.info("WebDAV service registered at path: %s/ "% directory)
if not (config.get_misc('webdav', 'no_root_hack', False)):
# Now, replace the static http handler with the dav-enabled one.
@@ -595,7 +596,7 @@ try:
reg_http_service('/', DAVStaticHandler)
except Exception, e:
- logging.getLogger('webdav').error('Cannot launch webdav: %s' % e)
+ _logger.error('Cannot launch webdav: %s' % e)
def init_well_known():
@@ -616,6 +617,8 @@ def init_well_known():
init_well_known()
class PrincipalsRedirect(RedirectHTTPHandler):
+
+
redirect_paths = {}
def _find_redirect(self):
@@ -639,7 +642,7 @@ def init_principals_redirect():
if dbname:
PrincipalsRedirect.redirect_paths[''] = '/webdav/%s/principals' % dbname
reg_http_service('/principals', PrincipalsRedirect)
- logging.getLogger("web-services").info(
+ _logger.info(
"Registered HTTP redirect handler for /principals to the %s db.",
dbname)
diff --git a/addons/document_webdav/webdav_view.xml b/addons/document_webdav/webdav_view.xml
index 404e60588e3..44af9f2af3a 100644
--- a/addons/document_webdav/webdav_view.xml
+++ b/addons/document_webdav/webdav_view.xml
@@ -78,7 +78,7 @@
form
-
+
@@ -98,7 +98,7 @@
-
+
diff --git a/addons/edi/__init__.py b/addons/edi/__init__.py
index b4a80c0f1dd..46fabbc2fd0 100644
--- a/addons/edi/__init__.py
+++ b/addons/edi/__init__.py
@@ -23,12 +23,13 @@ import logging
import models
import edi_service
from models.edi import EDIMixin, edi_document
+_logger = logging.getLogger(__name__)
# web
try:
import controllers
except ImportError:
- logging.getLogger('init.load').warn(
+ _logger.warn(
"""Could not load openerp-web section of EDI, EDI will not behave correctly
To fix, launch openerp-web in embedded mode""")
diff --git a/addons/edi/edi_service.py b/addons/edi/edi_service.py
index 074720a03e9..f48cc60950a 100644
--- a/addons/edi/edi_service.py
+++ b/addons/edi/edi_service.py
@@ -23,7 +23,7 @@ import logging
import netsvc
import openerp
-_logger = logging.getLogger('edi.service')
+_logger = logging.getLogger(__name__)
class edi(netsvc.ExportService):
diff --git a/addons/edi/models/edi.py b/addons/edi/models/edi.py
index 589922ff178..383d8c7aaba 100644
--- a/addons/edi/models/edi.py
+++ b/addons/edi/models/edi.py
@@ -35,6 +35,7 @@ import pooler
from osv import osv,fields,orm
from tools.translate import _
from tools.safe_eval import safe_eval as eval
+_logger = logging.getLogger(__name__)
EXTERNAL_ID_PATTERN = re.compile(r'^([^.:]+)(?::([^.]+))?\.(\S+)$')
EDI_VIEW_WEB_URL = '%s/edi/view?db=%s&token=%s'
@@ -72,7 +73,6 @@ def last_update_for(record):
return record_log.get('write_date') or record_log.get('create_date') or False
return False
-_logger = logging.getLogger('edi')
class edi_document(osv.osv):
_name = 'edi.document'
diff --git a/addons/edi/models/res_partner.py b/addons/edi/models/res_partner.py
index 357fdec061b..86d8c81b790 100644
--- a/addons/edi/models/res_partner.py
+++ b/addons/edi/models/res_partner.py
@@ -24,6 +24,7 @@ from osv import fields,osv
from edi import EDIMixin
from openerp import SUPERUSER_ID
from tools.translate import _
+_logger = logging.getLogger(__name__)
RES_PARTNER_EDI_STRUCT = {
'name': True,
@@ -63,7 +64,7 @@ class res_partner(osv.osv, EDIMixin):
code, label = 'edi_generic', 'Generic Bank Type (auto-created for EDI)'
bank_code_ids = res_partner_bank_type.search(cr, uid, [('code','=',code)], context=context)
if not bank_code_ids:
- logging.getLogger('edi.res_partner').info('Normal bank account type is missing, creating '
+ _logger.info('Normal bank account type is missing, creating '
'a generic bank account type for EDI.')
self.res_partner_bank_type.create(cr, SUPERUSER_ID, {'name': label,
'code': label})
@@ -84,7 +85,7 @@ class res_partner(osv.osv, EDIMixin):
bank_name, ext_bank_id, context=import_ctx)
except osv.except_osv:
# failed to import it, try again with unrestricted default type
- logging.getLogger('edi.res_partner').warning('Failed to import bank account using'
+ _logger.warning('Failed to import bank account using'
'bank type: %s, ignoring', import_ctx['default_state'],
exc_info=True)
return contact_id
diff --git a/addons/email_template/email_template.py b/addons/email_template/email_template.py
index fff9bdc0f1a..c4ed2eedb85 100644
--- a/addons/email_template/email_template.py
+++ b/addons/email_template/email_template.py
@@ -29,11 +29,12 @@ from osv import fields
import tools
from tools.translate import _
from urllib import quote as quote
+_logger = logging.getLogger(__name__)
try:
from mako.template import Template as MakoTemplate
except ImportError:
- logging.getLogger('init').warning("email_template: mako templates not available, templating features will not work!")
+ _logger.warning("email_template: mako templates not available, templating features will not work!")
class email_template(osv.osv):
"Templates for sending email"
@@ -75,7 +76,7 @@ class email_template(osv.osv):
result = u''
return result
except Exception:
- logging.exception("failed to render mako template value %r", template)
+ _logger.exception("failed to render mako template value %r", template)
return u""
def get_email_template(self, cr, uid, template_id=False, record_id=None, context=None):
diff --git a/addons/event_sale/event_sale.py b/addons/event_sale/event_sale.py
index 0d6497c45f2..9e65a034544 100644
--- a/addons/event_sale/event_sale.py
+++ b/addons/event_sale/event_sale.py
@@ -78,7 +78,6 @@ class sale_order_line(osv.osv):
dic = {
'name': order_line.order_id.partner_invoice_id.name,
'partner_id': order_line.order_id.partner_id.id,
- 'contact_id': order_line.order_id.partner_invoice_id.id,
'nb_register': int(order_line.product_uom_qty),
'email': order_line.order_id.partner_id.email,
'phone': order_line.order_id.partner_id.phone,
@@ -89,5 +88,5 @@ class sale_order_line(osv.osv):
}
registration_id = registration_obj.create(cr, uid, dic, context=context)
message = _("The registration %s has been created from the Sale Order %s.") % (registration_id, order_line.order_id.name)
- registration_obj.log(cr, uid, registration_id, message)
+ registration_obj.message_append_note(cr, uid, [registration_id], body=message, context=context)
return super(sale_order_line, self).button_confirm(cr, uid, ids, context=context)
diff --git a/addons/fetchmail/fetchmail.py b/addons/fetchmail/fetchmail.py
index 93ebd063051..cddcf642dc4 100644
--- a/addons/fetchmail/fetchmail.py
+++ b/addons/fetchmail/fetchmail.py
@@ -39,7 +39,7 @@ from osv import osv, fields
import tools
from tools.translate import _
-logger = logging.getLogger('fetchmail')
+_logger = logging.getLogger(__name__)
class fetchmail_server(osv.osv):
"""Incoming POP/IMAP mail server account"""
diff --git a/addons/google_docs/__openerp__.py b/addons/google_docs/__openerp__.py
index 1df94f34221..8cc5671e08a 100644
--- a/addons/google_docs/__openerp__.py
+++ b/addons/google_docs/__openerp__.py
@@ -30,6 +30,7 @@
'web': True,
'js': ['static/src/js/gdocs.js'],
'update_xml': [
+ 'security/ir.model.access.csv',
'res_config_user_view.xml'
],
'depends': ['google_base_account'],
diff --git a/addons/google_docs/security/ir.model.access.csv b/addons/google_docs/security/ir.model.access.csv
new file mode 100644
index 00000000000..9393d586fb8
--- /dev/null
+++ b/addons/google_docs/security/ir.model.access.csv
@@ -0,0 +1,3 @@
+id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
+access_google_docs,google.docs.config,model_google_docs_config,,1,0,0,0
+access_google_docs,google.docs.config,model_google_docs_config,base.group_system,1,1,1,1
\ No newline at end of file
diff --git a/addons/hr/hr.py b/addons/hr/hr.py
index e2bca73a72e..e4c08f60559 100644
--- a/addons/hr/hr.py
+++ b/addons/hr/hr.py
@@ -25,6 +25,7 @@ import logging
from osv import fields, osv
from PIL import Image
import StringIO
+_logger = logging.getLogger(__name__)
class hr_employee_category(osv.osv):
@@ -304,7 +305,7 @@ class res_users(osv.osv):
'user_id': user_id}, context=context)
except:
# Tolerate a missing shortcut. See product/product.py for similar code.
- logging.getLogger('orm').debug('Skipped meetings shortcut for user "%s"', data.get('name','Francois
fpi
fpi
- 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
+ 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
Julien
jth
jth
- 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
+ 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
diff --git a/addons/import_base/import_framework.py b/addons/import_base/import_framework.py
index 44243aa952c..8bcda79c64e 100644
--- a/addons/import_base/import_framework.py
+++ b/addons/import_base/import_framework.py
@@ -30,7 +30,7 @@ import logging
import StringIO
import traceback
pp = pprint.PrettyPrinter(indent=4)
-
+_logger = logging.getLogger(__name__)
@@ -60,7 +60,6 @@ class import_framework(Thread):
self.context = context or {}
self.email = email_to_notify
self.table_list = []
- self.logger = logging.getLogger(module_name)
self.initialize()
"""
@@ -165,7 +164,7 @@ class import_framework(Thread):
data_i is a map external field_name => value
and each data_i have a external id => in data_id['id']
"""
- self.logger.info(' Importing %s into %s' % (table, model))
+ _logger.info(' Importing %s into %s' % (table, model))
if not datas:
return (0, 'No data found')
mapping['id'] = 'id_new'
@@ -188,7 +187,7 @@ class import_framework(Thread):
model_obj = self.obj.pool.get(model)
if not model_obj:
raise ValueError(_("%s is not a valid model name") % model)
- self.logger.debug(_(" fields imported : ") + str(fields))
+ _logger.debug(_(" fields imported : ") + str(fields))
(p, r, warning, s) = model_obj.import_data(self.cr, self.uid, fields, res, mode='update', current_module=self.module_name, noupdate=True, context=self.context)
for (field, field_name) in self_dependencies:
self._import_self_dependencies(model_obj, field, datas)
@@ -431,9 +430,9 @@ class import_framework(Thread):
'auto_delete' : True})
email_obj.send(self.cr, self.uid, [email_id])
if error:
- self.logger.error(_("Import failed due to an unexpected error"))
+ _logger.error(_("Import failed due to an unexpected error"))
else:
- self.logger.info(_("Import finished, notification email sended"))
+ _logger.info(_("Import finished, notification email sended"))
def get_email_subject(self, result, error=False):
"""
diff --git a/addons/import_sugarcrm/sugar.py b/addons/import_sugarcrm/sugar.py
index 35103a41173..df2aa386992 100644
--- a/addons/import_sugarcrm/sugar.py
+++ b/addons/import_sugarcrm/sugar.py
@@ -33,7 +33,7 @@ import import_sugarcrm
import logging
import sys
-
+_logger = logging.getLogger(__name__)
debug = False
@@ -119,7 +119,7 @@ def get_contact_by_email(portType, username, password, email_address=None):
email_list.append(list.Email_address)
return email_list
except Exception,e:
- logging.getLogger('sugarcrm_soap').error('Exception: %s\n' % (tools.ustr(e)))
+ _logger.error('Exception: %s\n' % (tools.ustr(e)))
return False
def get_document_revision_search(portType, sessionid, module_id=None):
diff --git a/addons/l10n_be_invoice_bba/invoice.py b/addons/l10n_be_invoice_bba/invoice.py
index 997036c0cec..4cdbca84c0a 100644
--- a/addons/l10n_be_invoice_bba/invoice.py
+++ b/addons/l10n_be_invoice_bba/invoice.py
@@ -23,8 +23,8 @@
import re, time, random
from osv import fields, osv
from tools.translate import _
-import netsvc
-logger=netsvc.Logger()
+import logging
+_logger = logging.getLogger(__name__)
"""
account.invoice object:
@@ -41,7 +41,7 @@ class account_invoice(osv.osv):
context=context)
res[[i for i,x in enumerate(res) if x[0] == 'none'][0]] = ('none', 'Free Communication')
res.append(('bba', 'BBA Structured Communication'))
- #logger.notifyChannel('addons.'+self._name, netsvc.LOG_WARNING, 'reference_type = %s' %res )
+ #l_logger.warning('reference_type = %s' %res )
return res
def check_bbacomm(self, val):
@@ -68,7 +68,7 @@ class account_invoice(osv.osv):
result = super(account_invoice, self).onchange_partner_id(cr, uid, ids, type, partner_id,
date_invoice, payment_term, partner_bank_id, company_id)
# reference_type = self.default_get(cr, uid, ['reference_type'])['reference_type']
-# logger.notifyChannel('addons.'+self._name, netsvc.LOG_WARNING, 'partner_id %s' % partner_id)
+# _logger.warning('partner_id %s' % partner_id)
reference = False
reference_type = 'none'
if partner_id:
@@ -215,5 +215,5 @@ class account_invoice(osv.osv):
]
account_invoice()
-
-# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/l10n_be_invoice_bba/partner.py b/addons/l10n_be_invoice_bba/partner.py
index 04a51c3a6ab..8951be5dfa2 100644
--- a/addons/l10n_be_invoice_bba/partner.py
+++ b/addons/l10n_be_invoice_bba/partner.py
@@ -24,8 +24,6 @@
from osv import fields, osv
import time
from tools.translate import _
-import netsvc
-logger=netsvc.Logger()
class res_partner(osv.osv):
""" add field to indicate default 'Communication Type' on customer invoices """
diff --git a/addons/l10n_multilang/l10n_multilang.py b/addons/l10n_multilang/l10n_multilang.py
index c4130f2761d..c4c6be74e4b 100644
--- a/addons/l10n_multilang/l10n_multilang.py
+++ b/addons/l10n_multilang/l10n_multilang.py
@@ -22,8 +22,8 @@
from osv import fields, osv
import os
from tools.translate import _
-import netsvc
-logger=netsvc.Logger()
+import logging
+_logger = logging.getLogger(__name__)
class wizard_multi_charts_accounts(osv.osv_memory):
"""
@@ -80,8 +80,7 @@ class wizard_multi_charts_accounts(osv.osv_memory):
if context.get('lang') == lang:
self.pool.get(out_obj._name).write(cr, uid, out_ids[j], {in_field: value[in_id]})
else:
- logger.notifyChannel('addons.'+self._name, netsvc.LOG_WARNING,
- 'Language: %s. Translation from template: there is no translation available for %s!' %(lang, src[in_id]))#out_obj._name))
+ _logger.info('Language: %s. Translation from template: there is no translation available for %s!' %(lang, src[in_id]))#out_obj._name))
return True
def execute(self, cr, uid, ids, context=None):
diff --git a/addons/mail/mail_message.py b/addons/mail/mail_message.py
index f86ae29c80f..e45d4f07807 100644
--- a/addons/mail/mail_message.py
+++ b/addons/mail/mail_message.py
@@ -36,7 +36,7 @@ from osv import fields
from tools.translate import _
from openerp import SUPERUSER_ID
-_logger = logging.getLogger('mail')
+_logger = logging.getLogger(__name__)
def format_date_tz(date, tz=None):
if not date:
diff --git a/addons/mail/mail_subscription_view.xml b/addons/mail/mail_subscription_view.xml
index 52b72127b78..7dbaea098dc 100644
--- a/addons/mail/mail_subscription_view.xml
+++ b/addons/mail/mail_subscription_view.xml
@@ -10,7 +10,7 @@
mail.subscription.tree
mail.subscription
tree
- 10
+ 10
@@ -28,7 +28,7 @@
mail.notification.tree
mail.notification
tree
- 10
+ 10
diff --git a/addons/mail/mail_thread.py b/addons/mail/mail_thread.py
index 2448df383f4..e0f2bfaf455 100644
--- a/addons/mail/mail_thread.py
+++ b/addons/mail/mail_thread.py
@@ -299,7 +299,7 @@ class mail_thread(osv.osv):
}
to_attach.append(ir_attachment.create(cr, uid, data_attach, context=context))
- partner_id = hasattr(thread, 'partner_id') and (thread.partner_id and thread.partner_id.id or False) or False
+ partner_id = ('partner_id' in thread._columns.keys()) and (thread.partner_id and thread.partner_id.id or False) or False
if not partner_id and thread._name == 'res.partner':
partner_id = thread.id
data = {
diff --git a/addons/portal/wizard/portal_wizard.py b/addons/portal/wizard/portal_wizard.py
index 1ec4cbb0e4b..881be3be05f 100644
--- a/addons/portal/wizard/portal_wizard.py
+++ b/addons/portal/wizard/portal_wizard.py
@@ -27,7 +27,7 @@ from tools.misc import email_re
from tools.translate import _
from base.res.res_users import _lang_get
-
+_logger = logging.getLogger(__name__)
# welcome email sent to new portal users (note that calling tools.translate._
@@ -174,7 +174,7 @@ class wizard(osv.osv_memory):
body = _(WELCOME_EMAIL_BODY) % data
res = mail_message_obj.schedule_with_attach(cr, uid, email_from , [email_to], subject, body, context=context)
if not res:
- logging.getLogger('res.portal.wizard').warning(
+ _logger.warning(
'Failed to send email from %s to %s', email_from, email_to)
return {'type': 'ir.actions.act_window_close'}
diff --git a/addons/portal/wizard/share_wizard.py b/addons/portal/wizard/share_wizard.py
index b5c9d165cc6..b2ed8703421 100644
--- a/addons/portal/wizard/share_wizard.py
+++ b/addons/portal/wizard/share_wizard.py
@@ -21,6 +21,8 @@
from osv import osv, fields
from tools.translate import _
+import logging
+_logger = logging.getLogger(__name__)
UID_ROOT = 1
SHARED_DOCS_MENU = "Documents"
@@ -164,19 +166,19 @@ class share_wizard_portal(osv.osv_memory):
# v6.1, the algorithm for combining them will OR the rules, hence
# extending the visible data.
Rules.write(cr, UID_ROOT, share_rule_ids, {'groups': [(4,target_group.id)]})
- self._logger.debug("Linked sharing rules from temporary sharing group to group %s", target_group)
+ _logger.debug("Linked sharing rules from temporary sharing group to group %s", target_group)
# Copy the access rights. This is appropriate too because
# groups have the UNION of all permissions granted by their
# access right lines.
for access_line in share_group.model_access:
Rights.copy(cr, UID_ROOT, access_line.id, default={'group_id': target_group.id})
- self._logger.debug("Copied access rights from temporary sharing group to group %s", target_group)
+ _logger.debug("Copied access rights from temporary sharing group to group %s", target_group)
# finally, delete it after removing its users
Groups.write(cr, UID_ROOT, [share_group_id], {'users': [(6,0,[])]})
Groups.unlink(cr, UID_ROOT, [share_group_id])
- self._logger.debug("Deleted temporary sharing group %s", share_group_id)
+ _logger.debug("Deleted temporary sharing group %s", share_group_id)
def _finish_result_lines(self, cr, uid, wizard_data, share_group_id, context=None):
super(share_wizard_portal,self)._finish_result_lines(cr, uid, wizard_data, share_group_id, context=context)
diff --git a/addons/purchase/purchase.py b/addons/purchase/purchase.py
index 47ff616b548..775aebfaa8f 100644
--- a/addons/purchase/purchase.py
+++ b/addons/purchase/purchase.py
@@ -913,7 +913,7 @@ class purchase_order_line(osv.osv):
# - determine product_qty and date_planned based on seller info
if not date_order:
- date_order = fields.date.context_today(cr,uid,context=context)
+ date_order = fields.date.context_today(self,cr,uid,context=context)
qty = qty or 1.0
supplierinfo = False
diff --git a/addons/report_webkit/webkit_report.py b/addons/report_webkit/webkit_report.py
index 4d0bd6295c6..04980695f8f 100644
--- a/addons/report_webkit/webkit_report.py
+++ b/addons/report_webkit/webkit_report.py
@@ -51,7 +51,7 @@ import tools
from tools.translate import _
from osv.osv import except_osv
-logger = logging.getLogger('report_webkit')
+_logger = logging.getLogger(__name__)
def mako_template(text):
"""Build a Mako template.
@@ -248,7 +248,7 @@ class WebKitParser(report_sxw):
htmls.append(html)
except Exception, e:
msg = exceptions.text_error_template().render()
- logger.error(msg)
+ _logger.error(msg)
raise except_osv(_('Webkit render'), msg)
else:
try :
@@ -259,7 +259,7 @@ class WebKitParser(report_sxw):
htmls.append(html)
except Exception, e:
msg = exceptions.text_error_template().render()
- logger.error(msg)
+ _logger.error(msg)
raise except_osv(_('Webkit render'), msg)
head_mako_tpl = mako_template(header)
try :
@@ -281,7 +281,7 @@ class WebKitParser(report_sxw):
**self.parser_instance.localcontext)
except:
msg = exceptions.text_error_template().render()
- logger.error(msg)
+ _logger.error(msg)
raise except_osv(_('Webkit render'), msg)
if report_xml.webkit_debug :
try :
@@ -292,7 +292,7 @@ class WebKitParser(report_sxw):
**self.parser_instance.localcontext)
except Exception, e:
msg = exceptions.text_error_template().render()
- logger.error(msg)
+ _logger.error(msg)
raise except_osv(_('Webkit render'), msg)
return (deb, 'html')
bin = self.get_lib(cursor, uid)
diff --git a/addons/share/wizard/share_wizard.py b/addons/share/wizard/share_wizard.py
index 07004f333a8..336f56a5f97 100644
--- a/addons/share/wizard/share_wizard.py
+++ b/addons/share/wizard/share_wizard.py
@@ -32,6 +32,7 @@ from osv import expression
from tools.translate import _
from tools.safe_eval import safe_eval
import openerp
+_logger = logging.getLogger(__name__)
FULL_ACCESS = ('perm_read', 'perm_write', 'perm_create', 'perm_unlink')
READ_WRITE_ACCESS = ('perm_read', 'perm_write')
@@ -48,7 +49,6 @@ def generate_random_pass():
return ''.join(random.sample(RANDOM_PASS_CHARACTERS,10))
class share_wizard(osv.osv_memory):
- _logger = logging.getLogger('share.wizard')
_name = 'share.wizard'
_description = 'Share Wizard'
@@ -335,7 +335,7 @@ class share_wizard(osv.osv_memory):
except Exception:
# Note: must catch all exceptions, as UnquoteEvalContext may cause many
# different exceptions, as it shadows builtins.
- self._logger.debug("Failed to cleanup action context as it does not parse server-side", exc_info=True)
+ _logger.debug("Failed to cleanup action context as it does not parse server-side", exc_info=True)
result = context_str
return result
@@ -496,8 +496,8 @@ class share_wizard(osv.osv_memory):
[x.id for x in current_user.groups_id], target_model_ids, context=context)
group_access_map = self._get_access_map_for_groups_and_models(cr, uid,
[group_id], target_model_ids, context=context)
- self._logger.debug("Current user access matrix: %r", current_user_access_map)
- self._logger.debug("New group current access matrix: %r", group_access_map)
+ _logger.debug("Current user access matrix: %r", current_user_access_map)
+ _logger.debug("New group current access matrix: %r", group_access_map)
# Create required rights if allowed by current user rights and not
# already granted
@@ -520,7 +520,7 @@ class share_wizard(osv.osv_memory):
need_creation = True
if need_creation:
model_access_obj.create(cr, UID_ROOT, values)
- self._logger.debug("Creating access right for model %s with values: %r", model.model, values)
+ _logger.debug("Creating access right for model %s with values: %r", model.model, values)
def _link_or_copy_current_user_rules(self, cr, current_user, group_id, fields_relations, context=None):
rule_obj = self.pool.get('ir.rule')
@@ -542,13 +542,13 @@ class share_wizard(osv.osv_memory):
'groups': [(6,0,[group_id])],
'domain_force': rule.domain, # evaluated version!
})
- self._logger.debug("Copying rule %s (%s) on model %s with domain: %s", rule.name, rule.id, model.model, rule.domain_force)
+ _logger.debug("Copying rule %s (%s) on model %s with domain: %s", rule.name, rule.id, model.model, rule.domain_force)
else:
# otherwise we can simply link the rule to keep it dynamic
rule_obj.write(cr, 1, [rule.id], {
'groups': [(4,group_id)]
})
- self._logger.debug("Linking rule %s (%s) on model %s with domain: %s", rule.name, rule.id, model.model, rule.domain_force)
+ _logger.debug("Linking rule %s (%s) on model %s with domain: %s", rule.name, rule.id, model.model, rule.domain_force)
def _check_personal_rule_or_duplicate(self, cr, group_id, rule, context=None):
"""Verifies that the given rule only belongs to the given group_id, otherwise
@@ -567,7 +567,7 @@ class share_wizard(osv.osv_memory):
'groups': [(6,0,[group_id])],
'domain_force': rule.domain_force, # non evaluated!
})
- self._logger.debug("Duplicating rule %s (%s) (domain: %s) for modified access ", rule.name, rule.id, rule.domain_force)
+ _logger.debug("Duplicating rule %s (%s) (domain: %s) for modified access ", rule.name, rule.id, rule.domain_force)
# then disconnect from group_id:
rule.write({'groups':[(3,group_id)]}) # disconnects, does not delete!
return rule_obj.browse(cr, UID_ROOT, new_id, context=context)
@@ -602,7 +602,7 @@ class share_wizard(osv.osv_memory):
if restrict:
continue
else:
- self._logger.debug("Ignoring sharing rule on model %s with domain: %s the same rule exists already", model_id, domain)
+ _logger.debug("Ignoring sharing rule on model %s with domain: %s the same rule exists already", model_id, domain)
return
if restrict:
# restricting existing rules is done by adding the clause
@@ -614,7 +614,7 @@ class share_wizard(osv.osv_memory):
new_clause = expression.normalize(eval(domain, eval_ctx))
combined_domain = expression.AND([new_clause, org_domain])
rule.write({'domain_force': combined_domain, 'name': rule.name + _('(Modified)')})
- self._logger.debug("Combining sharing rule %s on model %s with domain: %s", rule.id, model_id, domain)
+ _logger.debug("Combining sharing rule %s on model %s with domain: %s", rule.id, model_id, domain)
if not rule_ids or not restrict:
# Adding the new rule in the group is ok for normal cases, because rules
# in the same group and for the same model will be combined with OR
@@ -625,7 +625,7 @@ class share_wizard(osv.osv_memory):
'domain_force': domain,
'groups': [(4,group_id)]
})
- self._logger.debug("Created sharing rule on model %s with domain: %s", model_id, domain)
+ _logger.debug("Created sharing rule on model %s with domain: %s", model_id, domain)
def _create_indirect_sharing_rules(self, cr, current_user, wizard_data, group_id, fields_relations, context=None):
rule_name = _('Indirect sharing filter created by user %s (%s) for group %s') % \
@@ -648,7 +648,7 @@ class share_wizard(osv.osv_memory):
group_id, model_id=model.id, domain=str(related_domain),
rule_name=rule_name, restrict=True, context=context)
except Exception:
- self._logger.exception('Failed to create share access')
+ _logger.exception('Failed to create share access')
raise osv.except_osv(_('Sharing access could not be created'),
_('Sorry, the current screen and filter you are trying to share are not supported at the moment.\nYou may want to try a simpler filter.'))
@@ -852,7 +852,7 @@ class share_wizard(osv.osv_memory):
notification_obj.create(cr, uid, {'user_id': result_line.user_id.id, 'message_id': msg_id}, context=context)
def send_emails(self, cr, uid, wizard_data, context=None):
- self._logger.info('Sending share notifications by email...')
+ _logger.info('Sending share notifications by email...')
mail_message = self.pool.get('mail.message')
user = self.pool.get('res.users').browse(cr, UID_ROOT, uid)
if not user.user_email:
@@ -885,7 +885,7 @@ class share_wizard(osv.osv_memory):
msg_ids.append(mail_message.schedule_with_attach(cr, uid, user.user_email, [email_to], subject, body, model='share.wizard', context=context))
# force direct delivery, as users expect instant notification
mail_message.send(cr, uid, msg_ids, context=context)
- self._logger.info('%d share notification(s) sent.', len(msg_ids))
+ _logger.info('%d share notification(s) sent.', len(msg_ids))
def onchange_embed_options(self, cr, uid, ids, opt_title, opt_search, context=None):
wizard = self.browse(cr, uid, ids[0], context)
diff --git a/addons/stock/security/ir.model.access.csv b/addons/stock/security/ir.model.access.csv
index a391f117393..593dc7eb9f3 100644
--- a/addons/stock/security/ir.model.access.csv
+++ b/addons/stock/security/ir.model.access.csv
@@ -12,7 +12,11 @@ access_stock_tracking_user,stock.tracking user,model_stock_tracking,stock.group_
access_stock_tracking_manager,stock.tracking manager,model_stock_tracking,stock.group_stock_manager,1,0,0,0
access_stock_tracking_sales_user,stock.tracking sales.user,model_stock_tracking,base.group_sale_salesman,1,1,1,0
access_stock_picking_user,stock.picking user,model_stock_picking,stock.group_stock_user,1,1,1,1
+access_stock_picking_in_user,stock.picking.in,model_stock_picking_in,stock.group_stock_user,1,1,1,1
+access_stock_picking_out_user,stock.picking.out,model_stock_picking_out,stock.group_stock_user,1,1,1,1
access_stock_picking_manager,stock.picking manager,model_stock_picking,stock.group_stock_manager,1,1,0,0
+access_stock_picking_in_manager,stock.picking.in manager,model_stock_picking_in,stock.group_stock_manager,1,0,0,0
+access_stock_picking_out_manager,stock.picking.out manager,model_stock_picking_out,stock.group_stock_manager,1,0,0,0
access_stock_production_lot_manager,stock.production.lot manager,model_stock_production_lot,stock.group_stock_manager,1,0,0,0
access_stock_production_lot_user,stock.production.lot user,model_stock_production_lot,stock.group_stock_user,1,1,1,1
access_stock_production_lot_revision,stock.production.lot.revision,model_stock_production_lot_revision,stock.group_stock_user,1,1,1,1
diff --git a/addons/stock/stock.py b/addons/stock/stock.py
index 87cf9ade130..a279b8bea6c 100644
--- a/addons/stock/stock.py
+++ b/addons/stock/stock.py
@@ -33,7 +33,7 @@ import tools
from tools import float_compare
import decimal_precision as dp
import logging
-
+_logger = logging.getLogger(__name__)
#----------------------------------------------------------
# Incoterms
@@ -419,9 +419,8 @@ class stock_location(osv.osv):
# so we ROLLBACK to the SAVEPOINT to restore the transaction to its earlier
# state, we return False as if the products were not available, and log it:
cr.execute("ROLLBACK TO stock_location_product_reserve")
- logger = logging.getLogger('stock.location')
- logger.warn("Failed attempt to reserve %s x product %s, likely due to another transaction already in progress. Next attempt is likely to work. Detailed error available at DEBUG level.", product_qty, product_id)
- logger.debug("Trace of the failed product reservation attempt: ", exc_info=True)
+ _logger.warn("Failed attempt to reserve %s x product %s, likely due to another transaction already in progress. Next attempt is likely to work. Detailed error available at DEBUG level.", product_qty, product_id)
+ _logger.debug("Trace of the failed product reservation attempt: ", exc_info=True)
return False
# XXX TODO: rewrite this with one single query, possibly even the quantity conversion
diff --git a/addons/stock_planning/stock_planning.py b/addons/stock_planning/stock_planning.py
index 324aeb0dcd2..e6f3b8d4218 100644
--- a/addons/stock_planning/stock_planning.py
+++ b/addons/stock_planning/stock_planning.py
@@ -29,7 +29,7 @@ from tools.translate import _
import logging
import decimal_precision as dp
-_logger = logging.getLogger('mps')
+_logger = logging.getLogger(__name__)
def rounding(fl, round_value):
diff --git a/addons/users_ldap/users_ldap.py b/addons/users_ldap/users_ldap.py
index 1d0c1e3acb9..e4615907c79 100644
--- a/addons/users_ldap/users_ldap.py
+++ b/addons/users_ldap/users_ldap.py
@@ -27,6 +27,7 @@ import pooler
import tools
from osv import fields, osv
from openerp import SUPERUSER_ID
+_logger = logging.getLogger(__name__)
class CompanyLDAP(osv.osv):
_name = 'res.company.ldap'
@@ -107,8 +108,7 @@ class CompanyLDAP(osv.osv):
except ldap.INVALID_CREDENTIALS:
return False
except ldap.LDAPError, e:
- logger = logging.getLogger('orm.ldap')
- logger.error('An LDAP exception occurred: %s', e)
+ _logger.error('An LDAP exception occurred: %s', e)
return entry
def query(self, conf, filter, retrieve_attributes=None):
@@ -135,7 +135,6 @@ class CompanyLDAP(osv.osv):
"""
results = []
- logger = logging.getLogger('orm.ldap')
try:
conn = self.connect(conf)
conn.simple_bind_s(conf['ldap_binddn'] or '',
@@ -144,9 +143,9 @@ class CompanyLDAP(osv.osv):
filter, retrieve_attributes, timeout=60)
conn.unbind()
except ldap.INVALID_CREDENTIALS:
- logger.error('LDAP bind failed.')
+ _logger.error('LDAP bind failed.')
except ldap.LDAPError, e:
- logger.error('An LDAP exception occurred: %s', e)
+ _logger.error('An LDAP exception occurred: %s', e)
return results
def map_ldap_attributes(self, cr, uid, conf, login, ldap_entry):
@@ -188,8 +187,7 @@ class CompanyLDAP(osv.osv):
if res[1]:
user_id = res[0]
elif conf['create_user']:
- logger = logging.getLogger('orm.ldap')
- logger.debug("Creating new OpenERP user \"%s\" from LDAP" % login)
+ _logger.debug("Creating new OpenERP user \"%s\" from LDAP" % login)
user_obj = self.pool.get('res.users')
values = self.map_ldap_attributes(cr, uid, conf, login, ldap_entry)
if conf['user']:
|