Commit 6b3d1301 authored by Stefan Rijnhart (Opener)'s avatar Stefan Rijnhart (Opener) Committed by GitHub

Merge pull request #80 from hbrunn/master-load_data-update

[ADD] support update mode where we never try to create records
parents a0e70c9c 522665b2
......@@ -24,6 +24,10 @@ import os
import inspect
import uuid
import logging
try:
from StringIO import StringIO
except ImportError:
from io import StringIO
from contextlib import contextmanager
try:
from contextlib import ExitStack
......@@ -46,6 +50,7 @@ except ImportError:
self._cms.pop().__exit__(exc_type, exc_value, traceback)
from psycopg2.extensions import AsIs
from lxml import etree
from . import openupgrade_tools
core = None
......@@ -249,9 +254,14 @@ def load_data(cr, module_name, filename, idref=None, mode='init'):
:param filename: the path to the filename, relative to the module \
directory.
:param idref: optional hash with ?id mapping cache?
:param mode: one of 'init', 'update', 'demo'. Always use 'init' \
for adding new items from files that are marked with 'noupdate'. Defaults \
to 'init'.
:param mode: one of 'init', 'update', 'demo', 'init_no_create'. \
Always use 'init' for adding new items from files that are marked with \
'noupdate'. Defaults to 'init'.
'init_no_create' is a hack to load data for records which have \
forcecreate=False set. As those records won't be recreated during the \
update, standard Odoo would recreate the record if it was deleted, \
but this will fail in cases where there are required fields to be \
filled which are not contained in the data file.
"""
if idref is None:
......@@ -267,11 +277,45 @@ def load_data(cr, module_name, filename, idref=None, mode='init'):
cr, module_name, pathname, fp.read(), idref, mode, noupdate)
elif ext == '.yml':
yaml_import(cr, module_name, fp, None, idref=idref, mode=mode)
elif mode == 'init_no_create':
for fp2 in _get_existing_records(cr, fp, module_name):
tools.convert_xml_import(
cr, module_name, fp2, idref, mode='init',
)
else:
tools.convert_xml_import(cr, module_name, fp, idref, mode=mode)
finally:
fp.close()
def _get_existing_records(cr, fp, module_name):
"""yield file like objects per 'leaf' node in the xml file that exists.
This is for not trying to create a record with partial data in case the
record was removed in the database."""
def yield_element(node, path=None):
if node.tag not in ['openerp', 'odoo', 'data']:
if node.tag == 'record':
xmlid = node.attrib['id']
if '.' not in xmlid:
module = module_name
else:
module, xmlid = xmlid.split('.', 1)
cr.execute(
'select id from ir_model_data where module=%s and name=%s',
(module, xmlid)
)
if not cr.rowcount:
return
yield StringIO(etree.tostring(path))
else:
for child in node:
for value in yield_element(
child,
etree.SubElement(path, node.tag, node.attrib)
if path else etree.Element(node.tag, node.attrib)
):
yield value
return yield_element(etree.parse(fp).getroot())
# for backwards compatibility
load_xml = load_data
table_exists = openupgrade_tools.table_exists
......
......@@ -3,3 +3,4 @@ coveralls
# Version locked due to https://gitlab.com/pycqa/flake8/issues/268
flake8==3.2.0
pep8-naming
lxml
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment