diff options
Diffstat (limited to 'addons/base_import/models/base_import.py')
| -rw-r--r-- | addons/base_import/models/base_import.py | 46 |
1 files changed, 41 insertions, 5 deletions
diff --git a/addons/base_import/models/base_import.py b/addons/base_import/models/base_import.py index d3c932e0358..9fc3feff1bd 100644 --- a/addons/base_import/models/base_import.py +++ b/addons/base_import/models/base_import.py @@ -2,6 +2,7 @@ # Part of Odoo. See LICENSE file for full copyright and licensing details. import base64 +import binascii import codecs import collections import unicodedata @@ -29,7 +30,7 @@ FIELDS_RECURSION_LIMIT = 2 ERROR_PREVIEW_BYTES = 200 DEFAULT_IMAGE_TIMEOUT = 3 DEFAULT_IMAGE_MAXBYTES = 10 * 1024 * 1024 -DEFAULT_IMAGE_REGEX = r"(?:http|https)://.*(?:png|jpe?g|tiff?|gif|bmp)" +DEFAULT_IMAGE_REGEX = r"^(?:http|https)://" DEFAULT_IMAGE_CHUNK_SIZE = 32768 IMAGE_FIELDS = ["icon", "image", "logo", "picture"] _logger = logging.getLogger(__name__) @@ -444,7 +445,11 @@ class Import(models.TransientModel): 'date_format') else [] user_date_format = self.env['res.lang']._lang_get(self.env.user.lang).date_format if user_date_format: - date_patterns.append(user_date_format) + try: + to_re(user_date_format) + date_patterns.append(user_date_format) + except KeyError: + pass date_patterns.extend(DATE_PATTERNS) match = check_patterns(date_patterns, preview_values) if match: @@ -600,6 +605,17 @@ class Import(models.TransientModel): has_relational_match = any(len(match) > 1 for field, match in matches.items() if match) advanced_mode = has_relational_header or has_relational_match + batch = False + batch_cutoff = options.get('limit') + if batch_cutoff: + if count > batch_cutoff: + batch = len(preview) > batch_cutoff + else: + batch = bool(next( + itertools.islice(rows, batch_cutoff - count, None), + None + )) + return { 'fields': fields, 'matches': matches or False, @@ -609,6 +625,7 @@ class Import(models.TransientModel): 'options': options, 'advanced_mode': advanced_mode, 'debug': self.user_has_groups('base.group_no_one'), + 'batch': batch, } except Exception as error: # Due to lazy generators, UnicodeDecodeError (for @@ -662,7 +679,9 @@ class Import(models.TransientModel): if any(row) ] - return data, import_fields + # slicing needs to happen after filtering out empty rows as the + # data offsets from load are post-filtering + return data[options.get('skip'):], import_fields @api.model def _remove_currency_symbol(self, value): @@ -772,6 +791,11 @@ class Import(models.TransientModel): raise AccessError(_("You can not import images via URL, check with your administrator or support for the reason.")) line[index] = self._import_image_by_url(line[index], session, name, num) + else: + try: + base64.b64decode(line[index], validate=True) + except binascii.Error: + raise ValueError(_("Found invalid image data, images should be imported as either URLs or base64-encoded data.")) return data @@ -882,7 +906,8 @@ class Import(models.TransientModel): _logger.info('importing %d rows...', len(data)) name_create_enabled_fields = options.pop('name_create_enabled_fields', {}) - model = self.env[self.res_model].with_context(import_file=True, name_create_enabled_fields=name_create_enabled_fields) + import_limit = options.pop('limit', None) + model = self.env[self.res_model].with_context(import_file=True, name_create_enabled_fields=name_create_enabled_fields, _import_limit=import_limit) import_result = model.load(import_fields, data) _logger.info('done') @@ -920,10 +945,21 @@ class Import(models.TransientModel): }) if 'name' in import_fields: index_of_name = import_fields.index('name') - import_result['name'] = [x[index_of_name] for x in data] + skipped = options.get('skip', 0) + # pad front as data doesn't contain anythig for skipped lines + r = import_result['name'] = [''] * skipped + # only add names for the window being imported + r.extend(x[index_of_name] for x in data[:import_limit]) + # pad back (though that's probably not useful) + r.extend([''] * (len(data) - (import_limit or 0))) else: import_result['name'] = [] + skip = options.get('skip', 0) + # convert load's internal nextrow to the imported file's + if import_result['nextrow']: # don't update if nextrow = 0 (= no nextrow) + import_result['nextrow'] += skip + return import_result _SEPARATORS = [' ', '/', '-', ''] |
