diff --git a/addons/account/models/account.py b/addons/account/models/account.py index 75ff8987154..797e48e0d8a 100644 --- a/addons/account/models/account.py +++ b/addons/account/models/account.py @@ -641,7 +641,7 @@ class AccountTax(models.Model): if tax.amount_type == 'group': ret = tax.children_tax_ids.compute_all(price_unit, currency, quantity, product, partner) total_excluded = ret['total_excluded'] - base = ret['total_excluded'] + base = ret['base'] total_included = ret['total_included'] tax_amount = total_included - total_excluded taxes += ret['taxes'] @@ -677,6 +677,7 @@ class AccountTax(models.Model): 'taxes': sorted(taxes, key=lambda k: k['sequence']), 'total_excluded': currency.round(total_excluded), 'total_included': currency.round(total_included), + 'base': base, } @api.v7 diff --git a/addons/account/models/account_invoice.py b/addons/account/models/account_invoice.py index 418038915f0..f7e2ca4fc3d 100644 --- a/addons/account/models/account_invoice.py +++ b/addons/account/models/account_invoice.py @@ -5,8 +5,8 @@ from lxml import etree from datetime import datetime from dateutil.relativedelta import relativedelta -from openerp import api, fields, models, _, SUPERUSER_ID -from openerp.tools import float_is_zero +from openerp import api, fields, models, _ +from openerp.tools import float_is_zero, float_compare from openerp.tools.misc import formatLang from openerp.exceptions import UserError, RedirectWarning, ValidationError @@ -1093,13 +1093,16 @@ class AccountInvoiceLine(models.Model): taxes = self.product_id.taxes_id or self.account_id.tax_ids else: taxes = self.product_id.supplier_taxes_id or self.account_id.tax_ids - if self.env.uid == SUPERUSER_ID: - taxes = taxes.filtered(lambda r: r.company_id == self.company_id) + + # Keep only taxes of the company + company_id = self.company_id or self.env.user.company_id + taxes = taxes.filtered(lambda r: r.company_id == company_id) + self.invoice_line_tax_ids = fp_taxes = self.invoice_id.fiscal_position_id.map_tax(taxes) fix_price = self.env['account.tax']._fix_tax_included_price - if type in ('in_invoice', 'in_refund'): - if not self.price_unit or self.price_unit == self.product_id.standard_price: + if self.invoice_id.type in ('in_invoice', 'in_refund'): + if not self.price_unit or float_compare(self.price_unit, self.product_id.standard_price, precision_digits=self.currency_id.rounding) == 0: self.price_unit = fix_price(self.product_id.standard_price, taxes, fp_taxes) else: self.price_unit = fix_price(self.product_id.lst_price, taxes, fp_taxes) diff --git a/addons/account/tests/test_product_id_change.py b/addons/account/tests/test_product_id_change.py index a2008b64bc7..9458a8618de 100644 --- a/addons/account/tests/test_product_id_change.py +++ b/addons/account/tests/test_product_id_change.py @@ -38,10 +38,10 @@ class TestProductIdChange(AccountingTestCase): amount='0.00')) product_tmpl = self.product_tmpl_model.create(dict(name="Voiture", list_price='121', - standard_price='121', taxes_id=[(6, 0, [tax_include_sale.id])], supplier_taxes_id=[(6, 0, [tax_include_purchase.id])])) - product = self.product_model.create(dict(product_tmpl_id=product_tmpl.id)) + product = self.product_model.create(dict(product_tmpl_id=product_tmpl.id, + standard_price='242')) fp = self.fiscal_position_model.create(dict(name="fiscal position", sequence=1)) fp_tax_sale = self.fiscal_position_tax_model.create(dict(position_id=fp.id, tax_src_id=tax_include_sale.id, @@ -80,7 +80,7 @@ class TestProductIdChange(AccountingTestCase): in_line = self.invoice_line_model.create({ 'product_id': product.id, 'quantity': 1, - 'price_unit': 121.0, + 'price_unit': 242.0, 'invoice_id': in_invoice.id, 'name': 'something in', 'account_id': self.account_revenue.id, @@ -88,4 +88,4 @@ class TestProductIdChange(AccountingTestCase): out_line._onchange_product_id() self.assertEquals(100, out_line.price_unit, "The included tax must be subtracted to the price") in_line._onchange_product_id() - self.assertEquals(100, in_line.price_unit, "The included tax must be subtracted to the price") + self.assertEquals(200, in_line.price_unit, "The included tax must be subtracted to the price") diff --git a/addons/mail/static/src/js/chat_manager.js b/addons/mail/static/src/js/chat_manager.js index 5e37bf237d8..a1272cea1ec 100644 --- a/addons/mail/static/src/js/chat_manager.js +++ b/addons/mail/static/src/js/chat_manager.js @@ -694,6 +694,9 @@ var chat_manager = { } }, + get_message: function (id) { + return _.findWhere(messages, {id: id}); + }, get_messages: function (options) { var channel; diff --git a/addons/mail/static/src/js/chat_window.js b/addons/mail/static/src/js/chat_window.js index 0e0289c394e..1a9c0fa93ea 100644 --- a/addons/mail/static/src/js/chat_window.js +++ b/addons/mail/static/src/js/chat_window.js @@ -29,6 +29,7 @@ return Widget.extend({ this.folded = is_folded; this.options = _.defaults(options || {}, { display_stars: true, + display_reply_icon: false, placeholder: _t("Say something"), input_less: false, }); diff --git a/addons/mail/static/src/js/client_action.js b/addons/mail/static/src/js/client_action.js index a2b4a400a1b..7b4024f66d0 100644 --- a/addons/mail/static/src/js/client_action.js +++ b/addons/mail/static/src/js/client_action.js @@ -116,7 +116,7 @@ var ChatAction = Widget.extend(ControlPanelMixin, { chat_manager.undo_mark_as_read(msgs_ids, channel); }); }, - "click .o_mail_annoying_notification_bar .fa-close": function (event) { + "click .o_mail_annoying_notification_bar .fa-close": function () { this.$(".o_mail_annoying_notification_bar").slideUp(); }, "click .o_mail_request_permission": function (event) { @@ -124,6 +124,11 @@ var ChatAction = Widget.extend(ControlPanelMixin, { this.$(".o_mail_annoying_notification_bar").slideUp(); window.Notification.requestPermission(); }, + "keydown": function (event) { + if (event.which === $.ui.keyCode.ESCAPE && this.selected_message) { + this.unselect_message(); + } + }, }, on_attach_callback: function () { @@ -144,6 +149,7 @@ var ChatAction = Widget.extend(ControlPanelMixin, { this.channels_scrolltop = {}; this.throttled_render_sidebar = _.throttle(this.render_sidebar.bind(this), 100, { leading: false }); this.notification_bar = (window.Notification && window.Notification.permission === "default"); + this.selected_message = null; }, willStart: function () { @@ -206,6 +212,9 @@ var ChatAction = Widget.extend(ControlPanelMixin, { this.thread.on('toggle_star_status', this, function (message_id) { chat_manager.toggle_star_status(message_id); }); + this.thread.on('select_message', this, this.select_message); + this.thread.on('unselect_message', this, this.unselect_message); + this.basic_composer.on('post_message', this, this.on_post_message); this.basic_composer.on('input_focused', this, this.on_composer_input_focused); this.extended_composer.on('post_message', this, this.on_post_message); @@ -241,6 +250,31 @@ var ChatAction = Widget.extend(ControlPanelMixin, { }); }, + select_message: function(message_id) { + this.$el.addClass('o_mail_selection_mode'); + var message = chat_manager.get_message(message_id); + this.selected_message = message; + var subject = "Re: " + message.record_name; + this.extended_composer.set_subject(subject); + if (this.channel.type !== 'static') { + this.basic_composer.toggle(false); + } + this.extended_composer.toggle(true); + this.thread.scroll_to({id: message_id, duration: 200, only_if_necessary: true}); + this.extended_composer.focus('body'); + }, + + unselect_message: function() { + if (this.channel.type !== 'static' && !this.channel.mass_mailing) { + this.basic_composer.toggle(true); + this.basic_composer.focus(); + } + this.$el.removeClass('o_mail_selection_mode'); + this.extended_composer.toggle(this.channel.mass_mailing); + this.thread.unselect(); + this.selected_message = null; + }, + render_sidebar: function () { var self = this; var $sidebar = $(QWeb.render("mail.chat.Sidebar", { @@ -299,14 +333,16 @@ var ChatAction = Widget.extend(ControlPanelMixin, { }); }, - render_snackbar: function (nb_needactions) { - this.$snackbar = $(QWeb.render('mail.chat.UndoSnackbar', { - nb_needactions: nb_needactions, - })); + render_snackbar: function (template, context, timeout) { + if (this.$snackbar) { + this.$snackbar.remove(); + } + timeout = timeout || 20000; + this.$snackbar = $(QWeb.render(template, context)); this.$('.o_mail_chat_content').append(this.$snackbar); - // Hide snackbar after 20s + // Hide snackbar after [timeout] milliseconds (by default, 20s) var $snackbar = this.$snackbar; - setTimeout(function() { $snackbar.fadeOut(); }, 20000); + setTimeout(function() { $snackbar.fadeOut(); }, timeout); }, do_search_channel: function(search_val){ @@ -349,7 +385,9 @@ var ChatAction = Widget.extend(ControlPanelMixin, { if (channel.type !== 'static') { // Display snackbar if needactions have been cleared if (channel.needaction_counter > 0) { - self.render_snackbar(channel.needaction_counter); + self.render_snackbar('mail.chat.MessageSentSnackbar', { + nb_needactions: channel.needaction_counter, + }); } chat_manager.mark_channel_as_seen(channel); self.clear_needactions_def = chat_manager.mark_all_as_read(channel); @@ -374,6 +412,7 @@ var ChatAction = Widget.extend(ControlPanelMixin, { self.basic_composer.toggle(channel.type !== 'static' && !channel.mass_mailing); self.extended_composer.toggle(channel.type !== 'static' && channel.mass_mailing); + self.$el.removeClass('o_mail_selection_mode'); self.$('.o_mail_chat_channel_item') .removeClass('o_active') @@ -439,6 +478,7 @@ var ChatAction = Widget.extend(ControlPanelMixin, { display_empty_channel: !messages.length && !this.domain.length, display_no_match: !messages.length && this.domain.length, display_subject: this.channel.mass_mailing || this.channel.id === "channel_inbox", + display_reply_icon: true, }; }, @@ -512,11 +552,25 @@ var ChatAction = Widget.extend(ControlPanelMixin, { on_post_message: function (message) { var self = this; - var options = {channel_id: this.channel.id}; + var options = this.selected_message ? {} : {channel_id: this.channel.id}; + if (this.selected_message) { + message.subtype = 'mail.mt_comment'; + message.subtype_id = false; + message.message_type = 'comment'; + message.content_subtype = 'html'; + + options.model = this.selected_message.model; + options.res_id = this.selected_message.res_id; + } chat_manager .post_message(message, options) .then(function() { - self.thread.scroll_to(); + if (self.selected_message) { + self.render_snackbar('mail.chat.MessageSentSnackbar', {record_name: self.selected_message.record_name}, 5000); + self.unselect_message(); + } else { + self.thread.scroll_to(); + } }) .fail(function () { // todo: display notification diff --git a/addons/mail/static/src/js/composer.js b/addons/mail/static/src/js/composer.js index 92bac153267..6ffd2bc63c3 100644 --- a/addons/mail/static/src/js/composer.js +++ b/addons/mail/static/src/js/composer.js @@ -698,9 +698,15 @@ var ExtendedComposer = BasicComposer.extend({ should_send: function () { return false; }, - - focus: function () { - this.$subject_input.focus(); + focus: function (target) { + if (target === 'body') { + this.$input.focus(); + } else { + this.$subject_input.focus(); + } + }, + set_subject: function(subject) { + this.$('.o_composer_subject input').val(subject); }, }); diff --git a/addons/mail/static/src/js/thread.js b/addons/mail/static/src/js/thread.js index aee712ea905..dc2467d3862 100644 --- a/addons/mail/static/src/js/thread.js +++ b/addons/mail/static/src/js/thread.js @@ -21,27 +21,36 @@ var Thread = Widget.extend({ "click strong": "on_click_redirect", "click .o_thread_show_more": "on_click_show_more", "click .o_thread_message_needaction": function (event) { - event.stopPropagation(); var message_id = $(event.currentTarget).data('message-id'); this.trigger("mark_as_read", message_id); }, "click .o_thread_message_star": function (event) { - event.stopPropagation(); var message_id = $(event.currentTarget).data('message-id'); this.trigger("toggle_star_status", message_id); }, - "click .o_thread_message": function (event) { - var selected = $(event.currentTarget).hasClass('o_thread_selected_message'); + "click .o_thread_message_reply": function (event) { + this.selected_id = $(event.currentTarget).data('message-id'); this.$('.o_thread_message').removeClass('o_thread_selected_message'); - $(event.currentTarget).toggleClass('o_thread_selected_message', !selected); + this.$('.o_thread_message[data-message-id=' + this.selected_id + ']') + .addClass('o_thread_selected_message'); + this.trigger('select_message', this.selected_id); + event.stopPropagation(); }, "click .oe_mail_expand": function (event) { event.preventDefault(); - event.stopPropagation(); var $message = $(event.currentTarget).parents('.o_thread_message'); $message.addClass('o_message_expanded'); this.expanded_msg_ids.push($message.data('message-id')); }, + "click .o_thread_message": function (event) { + $(event.currentTarget).toggleClass('o_thread_selected_message'); + }, + "click": function () { + if (this.selected_id) { + this.unselect(); + this.trigger('unselect_message'); + } + }, }, init: function (parent, options) { @@ -54,8 +63,10 @@ var Thread = Widget.extend({ display_avatar: true, shorten_messages: true, squash_close_messages: true, + display_reply_icon: false, }); this.expanded_msg_ids = []; + this.selected_id = null; }, render: function (messages, options) { @@ -69,11 +80,14 @@ var Thread = Widget.extend({ // Hide avatar and info of a message if that message and the previous // one are both comments wrote by the same author at the same minute + // and in the same document (users can now post message in documents + // directly from a channel that follows it) var prev_msg; _.each(msgs, function (msg) { if (!prev_msg || (Math.abs(msg.date.diff(prev_msg.date)) > 60000) || prev_msg.message_type !== 'comment' || msg.message_type !== 'comment' || - (prev_msg.author_id[0] !== msg.author_id[0])) { + (prev_msg.author_id[0] !== msg.author_id[0]) || prev_msg.model !== msg.model || + prev_msg.res_id !== msg.res_id) { msg.display_author = true; } else { msg.display_author = !options.squash_close_messages; @@ -138,6 +152,7 @@ var Thread = Widget.extend({ } msg.display_subject = message.subject && !message.is_system_notification; + msg.is_selected = msg.id === this.selected_id; return msg; }, @@ -159,18 +174,23 @@ var Thread = Widget.extend({ /** * Scrolls the thread to a given message or offset if any, to bottom otherwise - * @param {int} [target.id] optional: the id of the message to scroll to - * @param {int} [target.offset] optional: the number of pixels to scroll + * @param {int} [options.id] optional: the id of the message to scroll to + * @param {int} [options.offset] optional: the number of pixels to scroll */ - scroll_to: function (target) { - target = target || {}; - if (target.id !== undefined) { - var $target = this.$('.o_thread_message[data-message-id=' + target.id + ']'); - if ($target.length) { + scroll_to: function (options) { + options = options || {}; + if (options.id !== undefined) { + var $target = this.$('.o_thread_message[data-message-id=' + options.id + ']'); + if (options.only_if_necessary) { + var delta = $target.parent().height() - $target.height(); + var offset = delta < 0 ? 0 : delta - ($target.offset().top - $target.offsetParent().offset().top); + offset = - Math.min(offset, 0); + this.$el.scrollTo("+=" + offset + "px", options); + } else if ($target.length) { this.$el.scrollTo($target); } - } else if (target.offset !== undefined) { - this.$el.scrollTop(target.offset); + } else if (options.offset !== undefined) { + this.$el.scrollTop(options.offset); } else { this.$el.scrollTop(this.el.scrollHeight); } @@ -181,6 +201,10 @@ var Thread = Widget.extend({ is_at_bottom: function () { return this.el.scrollHeight - this.$el.scrollTop() - this.$el.outerHeight() < 5; }, + unselect: function () { + this.$('.o_thread_message').removeClass('o_thread_selected_message'); + this.selected_id = null; + }, }); Thread.ORDER = ORDER; diff --git a/addons/mail/static/src/less/client_action.less b/addons/mail/static/src/less/client_action.less index c4b28874358..ecf4785f03e 100644 --- a/addons/mail/static/src/less/client_action.less +++ b/addons/mail/static/src/less/client_action.less @@ -112,6 +112,9 @@ height: 100%; margin-left: @mail-chat-sidebar-width; position: relative; + @media (min-width: @screen-sm-min) { + overflow: auto; + } @media (max-width: @screen-xs-max) { margin-left: 0; @@ -120,8 +123,7 @@ .o_mail_thread { .o-flex(1, 0, 0); overflow: auto; - .o-webclient-padding(); - padding-bottom: 15px; + padding: 0 0 15px 0; .o_chat_help_message { padding: 25px 0; @@ -253,6 +255,17 @@ } } } + + &.o_mail_selection_mode { + .o_thread_message { + opacity: 0.5; + &.o_thread_selected_message { + padding: 4px @odoo-horizontal-padding; + opacity: 1; + background-color: lightgray; + } + } + } } // User status bullet (in Discuss sidebar and Invite dialog) diff --git a/addons/mail/static/src/less/thread.less b/addons/mail/static/src/less/thread.less index 7f0f144ffd8..7da1a13802e 100644 --- a/addons/mail/static/src/less/thread.less +++ b/addons/mail/static/src/less/thread.less @@ -40,7 +40,8 @@ .o_thread_message { .o-flex-display(); - padding: 4px 0; + padding: 4px @odoo-horizontal-padding; + margin-bottom: 0px; .o_thread_message_sidebar { .o-flex(0, 0, @mail-thread-avatar-size); @@ -69,7 +70,7 @@ } } - i.o_thread_message_star, i.o_thread_message_needaction { + i.o_thread_message_star, i.o_thread_message_needaction, i.o_thread_message_reply { cursor: pointer; opacity: 0; &.fa-star { @@ -83,7 +84,7 @@ opacity: @mail-thread-side-date-opacity; } - i.o_thread_message_star, i.o_thread_message_needaction { + i.o_thread_message_star, i.o_thread_message_needaction, i.o_thread_message_reply { opacity: @mail-thread-icon-opacity; &:hover { opacity: 1; @@ -141,7 +142,7 @@ } } - .o_thread_message_star, .o_thread_message_needaction { + .o_thread_message_star, .o_thread_message_needaction, .o_thread_message_reply { padding: 4px; } } diff --git a/addons/mail/static/src/xml/client_action.xml b/addons/mail/static/src/xml/client_action.xml index 78371340e36..15eadb00626 100644 --- a/addons/mail/static/src/xml/client_action.xml +++ b/addons/mail/static/src/xml/client_action.xml @@ -118,6 +118,13 @@ + + + + +
diff --git a/addons/mail/static/src/xml/thread.xml b/addons/mail/static/src/xml/thread.xml index ca863d9ad8f..6ed0700be11 100644 --- a/addons/mail/static/src/xml/thread.xml +++ b/addons/mail/static/src/xml/thread.xml @@ -46,7 +46,7 @@ -
+
+

diff --git a/addons/product_visible_discount/product_visible_discount.py b/addons/product_visible_discount/product_visible_discount.py index 077ec1efa21..5d77144e4cf 100644 --- a/addons/product_visible_discount/product_visible_discount.py +++ b/addons/product_visible_discount/product_visible_discount.py @@ -57,7 +57,7 @@ class sale_order_line(osv.osv): if line.product_id.company_id and line.order_id.pricelist_id.currency_id.id != line.product_id.company_id.currency_id.id: # new_list_price is in company's currency while price in pricelist currency ctx = dict(context_partner, date=self.order_id.date_order) - new_list_price = self.env['res.currency'].browse(currency_id).with_context(ctx).compute(new_list_price, line.order_id.pricelist_id.currency_id.id) + new_list_price = self.env['res.currency'].browse(currency_id).with_context(ctx).compute(new_list_price, line.order_id.pricelist_id.currency_id) discount = (new_list_price - line.price_unit) / new_list_price * 100 if discount > 0: line.price_unit = new_list_price @@ -86,7 +86,7 @@ class sale_order_line(osv.osv): if self.product_id.company_id and self.order_id.pricelist_id.currency_id.id != self.product_id.company_id.currency_id.id: # new_list_price is in company's currency while price in pricelist currency ctx = dict(context_partner, date=self.order_id.date_order) - new_list_price = self.env['res.currency'].browse(currency_id).with_context(ctx).compute(new_list_price, self.order_id.pricelist_id.currency_id.id) + new_list_price = self.env['res.currency'].browse(currency_id).with_context(ctx).compute(new_list_price, self.order_id.pricelist_id.currency_id) discount = (new_list_price - self.price_unit) / new_list_price * 100 if discount > 0: self.price_unit = new_list_price diff --git a/addons/stock/stock.py b/addons/stock/stock.py index 75ba0d6de6b..ae220f8a947 100644 --- a/addons/stock/stock.py +++ b/addons/stock/stock.py @@ -3877,7 +3877,7 @@ class stock_warehouse(osv.osv): for pull in route.pull_ids: pull_obj.write(cr, uid, pull.id, {'name': pull.name.replace(warehouse.name, name, 1)}, context=context) for push in route.push_ids: - push_obj.write(cr, uid, push.id, {'name': pull.name.replace(warehouse.name, name, 1)}, context=context) + push_obj.write(cr, uid, push.id, {'name': push.name.replace(warehouse.name, name, 1)}, context=context) #change the mto procurement rule name if warehouse.mto_pull_id.id: pull_obj.write(cr, uid, warehouse.mto_pull_id.id, {'name': warehouse.mto_pull_id.name.replace(warehouse.name, name, 1)}, context=context) diff --git a/addons/stock/stock_view.xml b/addons/stock/stock_view.xml index d3b7497206d..5d7929ff7cb 100644 --- a/addons/stock/stock_view.xml +++ b/addons/stock/stock_view.xml @@ -1000,7 +1000,7 @@ stock.picking ir.actions.act_window form - tree,form,calendar + tree,kanban,form,calendar { 'search_default_picking_type_id': [active_id], @@ -1023,7 +1023,7 @@ stock.picking ir.actions.act_window form - tree,form,calendar + tree,kanban,form,calendar { 'search_default_picking_type_id': [active_id], @@ -1047,7 +1047,7 @@ stock.picking ir.actions.act_window form - tree,form,calendar + tree,kanban,form,calendar { 'search_default_picking_type_id': [active_id], @@ -1071,7 +1071,7 @@ stock.picking ir.actions.act_window form - tree,form,calendar + tree,kanban,form,calendar { 'search_default_picking_type_id': [active_id], @@ -1096,7 +1096,7 @@ stock.picking ir.actions.act_window form - tree,form,calendar + tree,kanban,form,calendar { 'search_default_picking_type_id': [active_id], @@ -1120,7 +1120,7 @@ stock.picking ir.actions.act_window form - tree,form,calendar + tree,kanban,form,calendar { 'search_default_picking_type_id': [active_id], @@ -1145,7 +1145,7 @@ stock.picking ir.actions.act_window form - tree,form,calendar + tree,kanban,form,calendar { 'search_default_picking_type_id': [active_id], @@ -1170,7 +1170,7 @@ stock.picking ir.actions.act_window form - tree,form,calendar + tree,kanban,form,calendar { 'search_default_picking_type_id': [active_id], diff --git a/addons/website_sale/controllers/main.py b/addons/website_sale/controllers/main.py index acdffa7dba5..7001a4d30d0 100644 --- a/addons/website_sale/controllers/main.py +++ b/addons/website_sale/controllers/main.py @@ -1054,5 +1054,5 @@ class website_sale(http.Controller): pricelist_id = request.website.get_current_pricelist(context=context).id else: pricelist_id = partner.property_product_pricelist.id - prices = pool['product.pricelist'].price_rule_get_multi(cr, uid, [], [(product, add_qty, partner) for product in products], context=context) + prices = pool['product.pricelist'].price_rule_get_multi(cr, uid, [pricelist_id], [(product, add_qty, partner) for product in products], context=context) return {product_id: prices[product_id][pricelist_id][0] for product_id in product_ids} diff --git a/openerp/tools/misc.py b/openerp/tools/misc.py index c6a8eec4643..1d6c369da3a 100644 --- a/openerp/tools/misc.py +++ b/openerp/tools/misc.py @@ -1111,11 +1111,15 @@ consteq = getattr(passlib.utils, 'consteq', _consteq) class Pickle(object): @classmethod - def load(cls, stream): + def load(cls, stream, errors=False): unpickler = cPickle.Unpickler(stream) # pickle builtins: str/unicode, int/long, float, bool, tuple, list, dict, None unpickler.find_global = None - return unpickler.load() + try: + return unpickler.load() + except Exception: + _logger.warning('Failed unpickling data, returning default: %r', errors, exc_info=True) + return errors @classmethod def loads(cls, text):