From 6998300da97e534c197126082559e3a4c0466816 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 19 Sep 2013 16:50:52 +0200 Subject: [PATCH] [ADD] doc string --- async_move_line_importer/model/account.py | 17 ++++- .../model/move_line_importer.py | 65 +++++++++++++++---- 2 files changed, 67 insertions(+), 15 deletions(-) diff --git a/async_move_line_importer/model/account.py b/async_move_line_importer/model/account.py index fd920afea..51968b86e 100644 --- a/async_move_line_importer/model/account.py +++ b/async_move_line_importer/model/account.py @@ -30,11 +30,18 @@ def _format_inserts_values(vals): class account_move(orm.Model): """redefine account move create to bypass orm - if async_bypass_create is True in context""" + if async_bypass_create is set to True in context""" _inherit = "account.move" def _prepare_line(self, cr, uid, move_id, line, vals, context=None): + """Take incomming move line vals and complete line dict with + missing data + :param move_id: parent move id + :param line: dict of vals of move line + :param vals: dict of vals of move + :returns: dict of val of move line completed + """ if isinstance(line, tuple): line = line[2] line['journal_id'] = vals.get('journal_id') @@ -53,6 +60,8 @@ class account_move(orm.Model): return line def _bypass_create(self, cr, uid, vals, context=None): + """Create entries using cursor directly + :returns: created id""" mvl_obj = self.pool['account.move.line'] vals['company_id'] = context.get('company_id', False) vals['state'] = 'draft' @@ -70,6 +79,7 @@ class account_move(orm.Model): return created_id def create(self, cr, uid, vals, context=None): + """Please refer to orm.BaseModel.create documentation""" if context is None: context = {} if context.get('async_bypass_create'): @@ -79,11 +89,12 @@ class account_move(orm.Model): class account_move_line(orm.Model): """redefine account move line create to bypass orm - if async_bypass_create is True in context""" + if async_bypass_create is set to True in context""" _inherit = "account.move.line" def create(self, cr, uid, vals, context=None): + """Please refer to orm.BaseModel.create documentation""" if context is None: context = {} if context.get('async_bypass_create'): @@ -91,6 +102,8 @@ class account_move_line(orm.Model): return super(account_move_line, self).create(cr, uid, vals, context=context) def _bypass_create(self, cr, uid, vals, context=None): + """Create entries using cursor directly + :returns: created id""" sql = u"Insert INTO account_move_line (%s) VALUES (%s) RETURNING id" sql = sql % _format_inserts_values(vals) cr.execute(sql, vals) diff --git a/async_move_line_importer/model/move_line_importer.py b/async_move_line_importer/model/move_line_importer.py index e7bf7e32e..e55963b37 100644 --- a/async_move_line_importer/model/move_line_importer.py +++ b/async_move_line_importer/model/move_line_importer.py @@ -30,13 +30,16 @@ import openerp.pooler as pooler from openerp.osv import orm, fields from openerp.tools.translate import _ -USE_THREAD = True _logger = logging.getLogger(__name__) class move_line_importer(orm.Model): - """Move line importer""" + """Asynchrone move /move line importer. + It will parse the saved CSV file using orm.BaseModel.load + in a thread. If you set bypass_orm to True then the load function + will use a totally overriden create function that is a lot faster + but that totally bypass the ORM""" _name = "move.line.importer" _inherit = ['mail.thread'] @@ -49,9 +52,11 @@ class move_line_importer(orm.Model): context=context) def track_success(sef, cr, uid, obj, context=None): + """Used by mail subtype""" return obj['state'] == 'done' def track_error(sef, cr, uid, obj, context=None): + """Used by mail subtype""" return obj['state'] == 'error' _track = { @@ -70,7 +75,6 @@ class move_line_importer(orm.Model): ('error', 'Error')], readonly=True, string='Status'), - 'report': fields.text('Report', readonly=True), 'file': fields.binary('File', @@ -85,7 +89,7 @@ class move_line_importer(orm.Model): " it will not use orm and may" " not support all CSV canvas. \n" "Entry posted option will be skipped. \n" - "AA lines will only be crated when" + "AA lines will only be created when" " moves are posted. \n" "Tax lines computation will be skipped. \n" "This option should be used with caution" @@ -104,9 +108,12 @@ class move_line_importer(orm.Model): 'company_id': _get_current_company} def _parse_csv(self, cr, uid, imp_id): - """Parse stored CSV file in order to be usable by load method. + """Parse stored CSV file in order to be usable by BaseModel.load method. Manage base 64 decoding. - It will return head (list of first row) and data list of list""" + :param imp_id: current importer id + :returns: (head [list of first row], data [list of list]) + """ + # We use tempfile in order to avoid memory error with large files with tempfile.TemporaryFile() as src: imp = self.read(cr, uid, imp_id, ['file', 'delimiter']) content = imp['file'] @@ -119,8 +126,12 @@ class move_line_importer(orm.Model): return self._prepare_csv_data(decoded, delimiter) def _prepare_csv_data(self, csv_file, delimiter=","): - """Parse and decoded CSV file and return head list - and data list""" + """Parse a decoded CSV file and return head list + and data list + :param csv_file: decoded CSV file + :delimiter: CSV file delimiter char + :returns: (head [list of first row], data [list of list]) + """ data = csv.reader(csv_file, delimiter=str(delimiter)) head = data.next() head = [x.replace(' ', '') for x in head] @@ -129,6 +140,10 @@ class move_line_importer(orm.Model): return (head, values) def format_messages(self, messages): + """Format error messages generated by the BaseModel.load method + :parmam messages: return of BaseModel.load messages key + :returns: formatted string + """ res = [] for msg in messages: rows = msg.get('rows', {}) @@ -139,7 +154,16 @@ class move_line_importer(orm.Model): return "\n \n".join(res) def _manage_load_results(self, cr, uid, imp_id, result, _do_commit=True, context=None): - """Manage the load function out put and store report and exception""" + """Manage the BaseModel.load function output and store exception. + Will generate success/failure report and store it into report field. + Manage commit and rollback even if load method uses PostgreSQL + Savepoints. + :param imp_id: current importer id + :param result: BaseModel.laod return {ids: list(int)|False, messages: [Message]} + :params _do_commit: toggle commit management only used for testing purpose only + :returns: current importer id + """ + # Import sucessful if not result['messages']: msg = _("%s lines imported" % len(result['ids'] or [])) self.write(cr, uid, [imp_id], {'state': 'done', @@ -155,9 +179,13 @@ class move_line_importer(orm.Model): return imp_id def _load_data(self, cr, uid, imp_id, head, data, _do_commit=True, context=None): - """Function that does the load management, exception and load report. - _do_commit is only used for testing purpose in order not to commit - imported line during tests + """Function that does the load of parsed CSV file. + If will log exception and susccess into the report fields. + :param imp_id: current importer id + :param head: CSV file head (list of header) + :param data: CSV file content (list of data list) + :params _do_commit: toggle commit management only used for testing purpose only + :returns: current importer id """ try: res = self.pool['account.move'].load(cr, uid, head, data, context=context) @@ -181,7 +209,11 @@ class move_line_importer(orm.Model): return imp_id def _allows_thread(self, imp_id): - """Check if there is a async import of this file running""" + """Check if there is a async import of this file running + :param imp_id: current importer id + :returns: void + :raise: orm.except in case on failure + """ for th in threading.enumerate(): if th.getName() == 'async_move_line_import_%s' % imp_id: raise orm.except_orm(_('An import of this file is already running'), @@ -197,6 +229,13 @@ class move_line_importer(orm.Model): move_line_obj.check_access_rights(cr, uid, 'create', raise_exception=True) def import_file(self, cr, uid, imp_id, context=None): + """ Will do an asynchronous load of a CSV file. + Will generate an success/failure report and generate some + maile threads. It uses BaseModel.load to lookup CSV. + If you set bypass_orm to True then the load function + will use a totally overriden create function that is a lot faster + but that totally bypass the ORM""" + if isinstance(imp_id, list): imp_id = imp_id[0] if context is None: