Skip to Content
Menu
This question has been flagged
2 Replies
13147 Views

I'm trying to use the copy_data() function from product_packaging in an inherited class of product_packaging.

I use _set_product_tmpl_id_fnc() in a compute field.

Here is my code:

 @api.one
def _set_product_tmpl_id_fnc(self):
    if len(self.product_tmpl_id.product_variant_ids) >= 1
    for product in self.product_tmpl_id.product_variant_ids
    packaging_copy = self.copy_data(self.id)
packaging_copy.write({'product_id':self.product_id})

I got the following error when executing:

NotImplementedError: 'setdefault' not supported on frozendict

I tried many different parameters in copy_data call, without any success. I am certainly missing something, but to me calling an old API function in a new API model just require specific parameters of the function, not context parameters.




UPDATE (Temur):

Possible BUG


**[BUG] copy_data() function is not compatible with new API **

Impacted versions:

- 8.0

Steps to reproduce:

1. create/get a new API browserecord in a code.

2. call copy_data function of the record: "browserecord.copy_data()"

3. call ends with error: "NotImplementedError: 'setdefault' not supported on frozendict"

Current behavior:

- Can NOT call copy_data() using new API browserecord because of error above.

Expected behavior:

- copy_data() compatible with the new API.


NOTE:

most probably frozendict is used to represent context in the environment (rec.env.context) of the new API, but there is incompatible code with the frozendict context in the function copy_data(). it makes impossible to use copy_data() with the new API.



Avatar
Discard

@Hugo you can report the bug on github, see intruction: https://github.com/odoo/odoo/wiki/Contributing

Author

Ok, I'll take a look ;)

Author

I created an issue here https://github.com/odoo/odoo/issues/7362

Author Best Answer

Yes Temur, I tried. Same issue.

I edited my code while you was answering me, using the singleton instance of the ORM model (packaging_obj in my code) seems to be a better way to do it to me:

 @api.one
def _set_product_tmpl_id_fnc(self):
packaging_obj = self.pool.get('product.packaging')
if len(self.product_tmpl_id.product_variant_ids) >= 1
for product in self.product_tmpl_id.product_variant_ids
packaging_copy = packaging_obj.copy_data(self.id)
packaging_copy.write({'product_id':self.product_id})

But I got the following error message:

TypeError: copy_data() takes at least 4 arguments (2 given)

Here is the copy_data function signature

def copy_data(self, cr, uid, id, default=None, context=None): 


EDIT: Thanks Temur, I made several mistakes.

Here is the code I normally expected:

@api.one
def _set_product_tmpl_id_fnc(self):
if len(self.product_tmpl_id.product_variant_ids) >= 1:
for product in self.product_tmpl_id.product_variant_ids:
packaging_copy_data = self.copy_data()
print "packaging_copy_data :", packaging_copy_data
packaging_copy_data.product_id = product.id
packaging_copy_rec = self.create(packaging_copy_data)

But the error is raise immediately on the  "packaging_copy_data = self.copy_data()" line:

Traceback (most recent call last):
File "/home/hugo/Projets/Projets_TecLib/odoo/openerp/http.py", line 530, in _handle_exception
return super(JsonRequest, self)._handle_exception(exception)
File "/home/hugo/Projets/Projets_TecLib/odoo/openerp/http.py", line 567, in dispatch
result = self._call_function(**self.params)
File "/home/hugo/Projets/Projets_TecLib/odoo/openerp/http.py", line 303, in _call_function
return checked_call(self.db, *args, **kwargs)
File "/home/hugo/Projets/Projets_TecLib/odoo/openerp/service/model.py", line 113, in wrapper
return f(dbname, *args, **kwargs)
File "/home/hugo/Projets/Projets_TecLib/odoo/openerp/http.py", line 300, in checked_call
return self.endpoint(*a, **kw)
File "/home/hugo/Projets/Projets_TecLib/odoo/openerp/http.py", line 796, in __call__
return self.method(*args, **kw)
File "/home/hugo/Projets/Projets_TecLib/odoo/openerp/http.py", line 396, in response_wrap
response = f(*args, **kw)
File "/home/hugo/Projets/Projets_TecLib/odoo/addons/web/controllers/main.py", line 937, in call_kw
return self._call_kw(model, method, args, kwargs)
File "/home/hugo/Projets/Projets_TecLib/odoo/addons/web/controllers/main.py", line 929, in _call_kw
return getattr(request.registry.get(model), method)(request.cr, request.uid, *args, **kwargs)
File "/home/hugo/Projets/Projets_TecLib/odoo/openerp/api.py", line 241, in wrapper
return old_api(self, *args, **kwargs)
File "/home/hugo/Projets/Projets_TecLib/odoo/addons/product/product.py", line 772, in write
res = super(product_template, self).write(cr, uid, ids, vals, context=context)
File "/home/hugo/Projets/Projets_TecLib/odoo/openerp/api.py", line 241, in wrapper
return old_api(self, *args, **kwargs)
File "/home/hugo/Projets/Projets_TecLib/odoo/addons/mail/mail_thread.py", line 431, in write
result = super(mail_thread, self).write(cr, uid, ids, values, context=context)
File "/home/hugo/Projets/Projets_TecLib/odoo/openerp/api.py", line 241, in wrapper
return old_api(self, *args, **kwargs)
File "/home/hugo/Projets/Projets_TecLib/odoo/openerp/api.py", line 363, in old_api
result = method(recs, *args, **kwargs)
File "/home/hugo/Projets/Projets_TecLib/odoo_addons_community/linked/connector/producer.py", line 61, in write
result = write_original(self, vals)
File "/home/hugo/Projets/Projets_TecLib/odoo/openerp/api.py", line 239, in wrapper
return new_api(self, *args, **kwargs)
File "/home/hugo/Projets/Projets_TecLib/odoo/openerp/models.py", line 3774, in write
self._write(old_vals)
File "/home/hugo/Projets/Projets_TecLib/odoo/openerp/api.py", line 239, in wrapper
return new_api(self, *args, **kwargs)
File "/home/hugo/Projets/Projets_TecLib/odoo/openerp/api.py", line 546, in new_api
result = method(self._model, cr, uid, self.ids, *args, **kwargs)
File "/home/hugo/Projets/Projets_TecLib/odoo/openerp/models.py", line 3917, in _write
result += self._columns[field].set(cr, self, id, field, vals[field], user, context=rel_context) or []
File "/home/hugo/Projets/Projets_TecLib/odoo/openerp/osv/fields.py", line 800, in set
id_new = obj.create(cr, user, act[2], context=context)
File "/home/hugo/Projets/Projets_TecLib/odoo/openerp/api.py", line 241, in wrapper
return old_api(self, *args, **kwargs)
File "/home/hugo/Projets/Projets_TecLib/odoo/openerp/api.py", line 336, in old_api
result = method(recs, *args, **kwargs)
File "/home/hugo/Projets/Projets_TecLib/odoo_addons_community/linked/connector/producer.py", line 47, in create
record_id = create_original(self, vals)
File "/home/hugo/Projets/Projets_TecLib/odoo/openerp/api.py", line 239, in wrapper
return new_api(self, *args, **kwargs)
File "/home/hugo/Projets/Projets_TecLib/odoo/openerp/models.py", line 4079, in create
self._fields[key].determine_inverse(record)
File "/home/hugo/Projets/Projets_TecLib/odoo/openerp/fields.py", line 935, in determine_inverse
self.inverse(records)
File "/home/hugo/Projets/Projets_TecLib/odoo/openerp/api.py", line 239, in wrapper
return new_api(self, *args, **kwargs)
File "/home/hugo/Projets/Projets_TecLib/odoo/openerp/api.py", line 397, in new_api
result = [method(rec, *args, **kwargs) for rec in self]
File "/home/hugo/Projets/Projets_TecLib/odoo_addons/auguria_scan_packaging/models/picking.py", line 42, in _set_product_tmpl_id_fnc
packaging_copy_data = self.copy_data()
File "/home/hugo/Projets/Projets_TecLib/odoo/openerp/api.py", line 239, in wrapper
return new_api(self, *args, **kwargs)
File "/home/hugo/Projets/Projets_TecLib/odoo/openerp/api.py", line 503, in new_api
result = [method(self._model, cr, uid, id, *args, **kwargs) for id in self.ids]
File "/home/hugo/Projets/Projets_TecLib/odoo/openerp/models.py", line 4697, in copy_data
seen_map = context.setdefault('__copy_data_seen', {})
File "/home/hugo/Projets/Projets_TecLib/odoo/openerp/tools/misc.py", line 1280, in setdefault
raise NotImplementedError("'setdefault' not supported on frozendict")
NotImplementedError: 'setdefault' not supported on frozendic

Avatar
Discard

I updated answer. BTW what is an error with "packaging_copy = self.copy_data()" ? it should work normally...

if you prefer so... try:
packaging_obj = self.env['product.packaging']
instead of: packaging_obj = self.pool.get('product.packaging')

do not pass only id, either you do NOT pass any arguments from cr, uid,id (new api style) or you pass all of them (if you're calling function in old style). the last error you posted here indicates that you called function in old style, then you should pass cr and uid as well. (2 given) arguments are id you passed and self passed automatically. to overcome this error you can add self._cr and self._uid here, just before self.id...

Author

Thanks a lot, I edited my post to answer you.

ok. try:
packaging_copy_data = self.with_context({}).copy_data()

Author

Still the same. But using "packaging_obj.copy_data(self._cr,self._uid,self.id)" is giving me something: an empty list

list [ ] or dictionary { } ?

Author

list []

it seems copy_data is not compatible with the new api. most probably in the new api frozendict is used for context, but copy_data uses setdefault() on context... actually it may be considered as a bug. So you've to continue with a second way with singleton and old api style call of copy_data... can you please add a full stacktrace of error of self.copy_data() call with new api style (no arguments)?

Author

Here is the stacktrace of error of self.copy_data() Traceback (most recent call last): File "/home/hugo/Projets/Projets_TecLib/odoo/openerp/http.py", line 530, in _handle_exception return super(JsonRequest, self)._handle_exception(exception) File "/home/hugo/Projets/Projets_TecLib/odoo/openerp/http.py", line 567, in dispatch result = self._call_function(**self.params) File "/home/hugo/Projets/Projets_TecLib/odoo/openerp/http.py", line 303, in _call_function return checked_call(self.db, *args, **kwargs) File "/home/hugo/Projets/Projets_TecLib/odoo/openerp/service/model.py", line 113, in wrapper return f(dbname, *args, **kwargs) File "/home/hugo/Projets/Projets_TecLib/odoo/openerp/http.py", line 300, in checked_call return self.endpoint(*a, **kw) File "/home/hugo/Projets/Projets_TecLib/odoo/openerp/http.py", line 796, in __call__ return self.method(*args, **kw) File "/home/hugo/Projets/Projets_TecLib/odoo/openerp/http.py", line 396, in response_wrap response = f(*args, **kw) File "/home/hugo/Projets/Projets_TecLib/odoo/addons/web/controllers/main.py", line 937, in call_kw return self._call_kw(model, method, args, kwargs) File "/home/hugo/Projets/Projets_TecLib/odoo/addons/web/controllers/main.py", line 929, in _call_kw return getattr(request.registry.get(model), method)(request.cr, request.uid, *args, **kwargs) File "/home/hugo/Projets/Projets_TecLib/odoo/openerp/api.py", line 241, in wrapper return old_api(self, *args, **kwargs) File "/home/hugo/Projets/Projets_TecLib/odoo/addons/product/product.py", line 772, in write res = super(product_template, self).write(cr, uid, ids, vals, context=context) File "/home/hugo/Projets/Projets_TecLib/odoo/openerp/api.py", line 241, in wrapper return old_api(self, *args, **kwargs) File "/home/hugo/Projets/Projets_TecLib/odoo/addons/mail/mail_thread.py", line 431, in write result = super(mail_thread, self).write(cr, uid, ids, values, context=context) File "/home/hugo/Projets/Projets_TecLib/odoo/openerp/api.py", line 241, in wrapper return old_api(self, *args, **kwargs) File "/home/hugo/Projets/Projets_TecLib/odoo/openerp/api.py", line 363, in old_api result = method(recs, *args, **kwargs) File "/home/hugo/Projets/Projets_TecLib/odoo_addons_community/linked/connector/producer.py", line 61, in write result = write_original(self, vals) File "/home/hugo/Projets/Projets_TecLib/odoo/openerp/api.py", line 239, in wrapper return new_api(self, *args, **kwargs) File "/home/hugo/Projets/Projets_TecLib/odoo/openerp/models.py", line 3774, in write self._write(old_vals) File "/home/hugo/Projets/Projets_TecLib/odoo/openerp/api.py", line 239, in wrapper return new_api(self, *args, **kwargs) File "/home/hugo/Projets/Projets_TecLib/odoo/openerp/api.py", line 546, in new_api result = method(self._model, cr, uid, self.ids, *args, **kwargs) File "/home/hugo/Projets/Projets_TecLib/odoo/openerp/models.py", line 3917, in _write result += self._columns[field].set(cr, self, id, field, vals[field], user, context=rel_context) or [] File "/home/hugo/Projets/Projets_TecLib/odoo/openerp/osv/fields.py", line 800, in set id_new = obj.create(cr, user, act[2], context=context) File "/home/hugo/Projets/Projets_TecLib/odoo/openerp/api.py", line 241, in wrapper return old_api(self, *args, **kwargs) File "/home/hugo/Projets/Projets_TecLib/odoo/openerp/api.py", line 336, in old_api result = method(recs, *args, **kwargs) File "/home/hugo/Projets/Projets_TecLib/odoo_addons_community/linked/connector/producer.py", line 47, in create record_id = create_original(self, vals) File "/home/hugo/Projets/Projets_TecLib/odoo/openerp/api.py", line 239, in wrapper return new_api(self, *args, **kwargs) File "/home/hugo/Projets/Projets_TecLib/odoo/openerp/models.py", line 4079, in create self._fields[key].determine_inverse(record) File "/home/hugo/Projets/Projets_TecLib/odoo/openerp/fields.py", line 935, in determine_inverse self.inverse(records) File "/home/hugo/Projets/Projets_TecLib/odoo/openerp/api.py", line 239, in wrapper return new_api(self, *args, **kwargs) File "/home/hugo/Projets/Projets_TecLib/odoo/openerp/api.py", line 397, in new_api result = [method(rec, *args, **kwargs) for rec in self] File "/home/hugo/Projets/Projets_TecLib/odoo_addons/auguria_scan_packaging/models/picking.py", line 42, in _set_product_tmpl_id_fnc packaging_copy_data = self.copy_data() File "/home/hugo/Projets/Projets_TecLib/odoo/openerp/api.py", line 239, in wrapper return new_api(self, *args, **kwargs) File "/home/hugo/Projets/Projets_TecLib/odoo/openerp/api.py", line 503, in new_api result = [method(self._model, cr, uid, id, *args, **kwargs) for id in self.ids] File "/home/hugo/Projets/Projets_TecLib/odoo/openerp/models.py", line 4697, in copy_data seen_map = context.setdefault('__copy_data_seen', {}) File "/home/hugo/Projets/Projets_TecLib/odoo/openerp/tools/misc.py", line 1280, in setdefault raise NotImplementedError("'setdefault' not supported on frozendict") NotImplementedError: 'setdefault' not supported on frozendict

Author

For more visibility, I edited the post.

now it's clear, as I supposed it's a bug of odoo, the copy_data() function is not compatible with new api style call...

packaging_copy = self.copy_data()
should work, but it will not work because of this bug. So now the only way is to get worked another option, with singletone instance that you started, I updated my answer with some suggestions for this approach, I don't know if it'll help you. good luck
Author

You helped me to understand many stuffs, even if I finally used another option, thanks Temur !

il n'y à pas de quoi

Best Answer

Try:

 @api.one
 def _set_product_tmpl_id_fnc(self):
     if len(self.product_tmpl_id.product_variant_ids) >= 1
     for product in self.product_tmpl_id.product_variant_ids
         packaging_copy = self.copy_data() # no arguments here, id should be passed automatically.
print "packaging_copy: ",packaging_copy ###
See what it looks like, then adapt next line to it. I've doubts about next line...
###
packaging_copy.write({'product_id':self.product_id})

...because, if packaging_copy is a record copy of self, then normally product_id should be same in packaging_copy as in the self... then what it changes to copy that field from original record to the copied record? at least check if such action is absolutely necessary. it may be a case that "product_id" considered as special field and is not copied with copy_data? then it's ok, otherwise no need for this line.

but if packaging_copy is a dictionary containing field values of self rather then the orm record, there will no write() method. in such a case you'll have to create duplicate record first, as follows:

         packaging_copy_record = self.create(packaging_copy)

so solution depends on the type of packaging_copy returned from copy_data... if it's a record, then you do not need the last line in your code fragment(of course if product_id is already copied and not skipped for some reason), but if it's a dictionary of field values then you'll need to add above create() statement...


UPDATE for code with singletone in your answer:

@api.one
 def _set_product_tmpl_id_fnc(self):
     packaging_obj = self.pool.get('product.packaging')
     if len(self.product_tmpl_id.product_variant_ids) >= 1
     for product in self.product_tmpl_id.product_variant_ids
         packaging_copy = packaging_obj.copy_data(self._cr,self._uid,self.id)
         ### packaging_copy.write({'product_id':self.product_id})

and with "default":
 
@api.one def _set_product_tmpl_id_fnc(self): packaging_obj = self.pool.get('product.packaging')
# packaging_obj = self.env['product.packaging'] ### also an option... if len(self.product_tmpl_id.product_variant_ids) >= 1 for product in self.product_tmpl_id.product_variant_ids packaging_copy = packaging_obj.copy_data(self._cr,self._uid,self.id, default={'product_id': product.id})
print "packaging_copy: ",packaging_copy
### ...


Avatar
Discard
Related Posts Replies Views Activity
2
Feb 22
5371
2
Aug 18
3876
1
Aug 17
5799
0
Jul 17
2531
2
Sep 15
4387