summaryrefslogtreecommitdiff
path: root/addons/base_import/models/base_import.py
diff options
context:
space:
mode:
Diffstat (limited to 'addons/base_import/models/base_import.py')
-rw-r--r--addons/base_import/models/base_import.py46
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 = [' ', '/', '-', '']