def _website_price(self): qty = self._context.get('quantity', 1.0) partner = self.env.user.partner_id current_website = self.env['website'].get_current_website() pricelist = current_website.get_current_pricelist() company_id = current_website.company_id context = dict(self._context, pricelist=pricelist.id, partner=partner) self2 = self.with_context( context) if self._context != context else self ret = self.env.user.has_group( 'sale.group_show_price_subtotal' ) and 'total_excluded' or 'total_included' for p, p2 in pycompat.izip(self, self2): taxes = partner.property_account_position_id.map_tax( p.sudo().taxes_id.filtered( lambda x: x.company_id == company_id)) p.website_price = taxes.compute_all(p2.price, pricelist.currency_id, quantity=qty, product=p2, partner=partner)[ret] price_without_pricelist = taxes.compute_all( p.list_price, pricelist.currency_id)[ret] p.website_price_difference = False if float_is_zero( price_without_pricelist - p.website_price, precision_rounding=pricelist.currency_id.rounding) else True p.website_public_price = taxes.compute_all(p2.lst_price, quantity=qty, product=p2, partner=partner)[ret]
def _compute_full_name(self): # Important: value must be stored in environment of group, not group1! for group, group1 in pycompat.izip(self, self.sudo()): if group1.category_id: group.full_name = '%s / %s' % (group1.category_id.name, group1.name) else: group.full_name = group1.name
def test_multiple(self): """ With two "concurrent" o2ms, exports the first line combined, then exports the rows for the first o2m, then the rows for the second o2m. """ fields = ['const', 'child1/value', 'child2/value'] child1 = [(0, False, { 'value': v, 'str': 'record%.02d' % index }) for index, v in pycompat.izip(itertools.count(), [4, 42, 36, 4, 13]) ] child2 = [(0, False, { 'value': v, 'str': 'record%.02d' % index }) for index, v in pycompat.izip(itertools.count(10), [8, 12, 8, 55, 33, 13])] self.assertEqual( self.export(child1=child1, child2=False, fields=fields), [ [u'36', u'4', False], ['', u'42', ''], ['', u'36', ''], ['', u'4', ''], ['', u'13', ''], ]) self.assertEqual( self.export(child1=False, child2=child2, fields=fields), [ [u'36', False, u'8'], ['', '', u'12'], ['', '', u'8'], ['', '', u'55'], ['', '', u'33'], ['', '', u'13'], ]) self.assertEqual( self.export(child1=child1, child2=child2, fields=fields), [ [u'36', u'4', u'8'], ['', u'42', ''], ['', u'36', ''], ['', u'4', ''], ['', u'13', ''], ['', '', u'12'], ['', '', u'8'], ['', '', u'55'], ['', '', u'33'], ['', '', u'13'], ])
def write(self, values): res = super(GroupsImplied, self).write(values) if values.get('users') or values.get('implied_ids'): # add all implied groups (to all users of each group) for group in self: vals = {'users': list(pycompat.izip(repeat(4), group.with_context(active_test=False).users.ids))} super(GroupsImplied, group.trans_implied_ids).write(vals) return res
def load_information_from_description_file(module, mod_path=None): """ :param module: The name of the module (sale, purchase, ...) :param mod_path: Physical path of module, if not providedThe name of the module (sale, purchase, ...) """ if not mod_path: mod_path = get_module_path(module, downloaded=True) manifest_file = module_manifest(mod_path) if manifest_file: # default values for descriptor info = { 'application': False, 'author': 'GECOERP S.A.', 'auto_install': False, 'category': 'Uncategorized', 'depends': [], 'description': '', 'icon': get_module_icon(module), 'installable': True, 'license': 'LGPL-3', 'post_load': None, 'version': '1.0', 'web': False, 'website': 'https://www.gecoerp.com', 'sequence': 100, 'summary': '', } info.update( pycompat.izip( 'depends data demo test init_xml update_xml demo_xml'.split(), iter(list, None))) f = tools.file_open(manifest_file, mode='rb') try: info.update(ast.literal_eval(pycompat.to_native(f.read()))) finally: f.close() if not info.get('description'): readme_path = [ opj(mod_path, x) for x in README if os.path.isfile(opj(mod_path, x)) ] if readme_path: readme_text = tools.file_open(readme_path[0]).read() info['description'] = readme_text if 'active' in info: # 'active' has been renamed 'auto_install' info['auto_install'] = info['active'] info['version'] = adapt_version(info['version']) return info _logger.debug('module %s: no manifest file found %s', module, MANIFEST_NAMES) return {}
def iter_tax_codes(self): keys = [c.value for c in self.sheet_tax_codes.row(0)] yield keys for i in range(1, self.sheet_tax_codes.nrows): row = (c.value for c in self.sheet_tax_codes.row(i)) d = OrderedDict(pycompat.izip(keys, row)) d['sign'] = int(d['sign']) d['sequence'] = int(d['sequence']) yield d
def chk(lst, verbose=False): pvs = [] for v in lst: pv = parse_version(v) pvs.append(pv) if verbose: print(v, pv) for a, b in pycompat.izip(pvs, pvs[1:]): assert a < b, '%s < %s == %s' % (a, b, a < b)
def _website_price(self): # First filter out the ones that have no variant: # This makes sure that every template below has a corresponding product in the zipped result. self = self.filtered('product_variant_id') # use mapped who returns a recordset with only itself to prefetch (and don't prefetch every product_variant_ids) for template, product in pycompat.izip( self, self.mapped('product_variant_id')): template.website_price = product.website_price template.website_public_price = product.website_public_price template.website_price_difference = product.website_price_difference
def _remove_reified_groups(self, values): """ return `values` without reified group fields """ add, rem = [], [] values1 = {} for key, val in values.items(): if is_boolean_group(key): (add if val else rem).append(get_boolean_group(key)) elif is_selection_groups(key): rem += get_selection_groups(key) if val: add.append(val) else: values1[key] = val if 'groups_id' not in values and (add or rem): # remove group ids in `rem` and add group ids in `add` values1['groups_id'] = list(itertools.chain( pycompat.izip(repeat(3), rem), pycompat.izip(repeat(4), add) )) return values1
def _inverse_display_name(self): names = self.display_name.split('/') # determine sequence of categories categories = [] for name in names[:-1]: category = self.search([('name', 'ilike', name.strip())]) categories.append(category[0]) categories.append(self) # assign parents following sequence for parent, child in pycompat.izip(categories, categories[1:]): if parent and child: child.parent = parent # assign name of last category, and reassign display_name (to normalize it) self.name = names[-1].strip()
def get_attribute_value_ids(self, product): res = super(WebsiteSale, self).get_attribute_value_ids(product) variant_ids = [r[0] for r in res] # recordsets conserve the order for r, variant in izip( res, request.env['product.product'].sudo().browse(variant_ids)): r.extend([{ 'virtual_available': variant.virtual_available, 'product_type': variant.type, 'inventory_availability': variant.inventory_availability, 'available_threshold': variant.available_threshold, 'custom_message': variant.custom_message, 'product_template': variant.product_tmpl_id.id, 'cart_qty': variant.cart_qty, 'uom_name': variant.uom_id.name, }]) return res
def test_spaces(self): """ Create translations where value has surrounding spaces. """ archf = '<form string="%s"><div>%s</div><div>%s</div></form>' terms_en = ('Knife', 'Fork', 'Spoon') terms_fr = (' Couteau', 'Fourchette ', ' Cuiller ') view0 = self.env['ir.ui.view'].create({ 'name': 'test', 'model': 'res.partner', 'arch': archf % terms_en, }) for src, value in list(pycompat.izip(terms_en, terms_fr)): self.env['ir.translation'].create({ 'type': 'model', 'name': 'ir.ui.view,arch_db', 'lang': 'fr_FR', 'res_id': view0.id, 'src': src, 'value': value, })
def test_copy(self): """ Create a simple view, fill in translations, and copy it. """ env_en = self.env(context={}) env_fr = self.env(context={'lang': 'fr_FR'}) archf = '<form string="%s"><div>%s</div><div>%s</div></form>' terms_en = ('Knife', 'Fork', 'Spoon') terms_fr = ('Couteau', 'Fourchette', 'Cuiller') view0 = self.env['ir.ui.view'].create({ 'name': 'test', 'model': 'res.partner', 'arch': archf % terms_en, }) for src, value in list(pycompat.izip(terms_en, terms_fr)): self.env['ir.translation'].create({ 'type': 'model', 'name': 'ir.ui.view,arch_db', 'lang': 'fr_FR', 'res_id': view0.id, 'src': src, 'value': value, }) # check translated field self.assertEqual(view0.with_env(env_en).arch_db, archf % terms_en) self.assertEqual(view0.with_env(env_fr).arch_db, archf % terms_fr) # copy without lang view1 = view0.with_env(env_en).copy({}) self.assertEqual(view1.with_env(env_en).arch_db, archf % terms_en) self.assertEqual(view1.with_env(env_fr).arch_db, archf % terms_fr) # copy with lang='fr_FR' view2 = view0.with_env(env_fr).copy({}) self.assertEqual(view2.with_env(env_en).arch_db, archf % terms_en) self.assertEqual(view2.with_env(env_fr).arch_db, archf % terms_fr) # copy with lang='fr_FR' and translate=html_translate self.patch( type(self.env['ir.ui.view']).arch_db, 'translate', html_translate) view3 = view0.with_env(env_fr).copy({}) self.assertEqual(view3.with_env(env_en).arch_db, archf % terms_en) self.assertEqual(view3.with_env(env_fr).arch_db, archf % terms_fr)
global count, errors count += 1 result = float_repr(float_round(amount, precision_digits=precision_digits), precision_digits=precision_digits) if result != expected: errors += 1 print('###!!! Rounding error: got %s , expected %s' % (result, expected)) # Extended float range test, inspired by Cloves Almeida's test on bug #882036. fractions = [.0, .015, .01499, .675, .67499, .4555, .4555, .45555] expecteds = ['.00', '.02', '.01', '.68', '.67', '.46', '.456', '.4556'] precisions = [2, 2, 2, 2, 2, 2, 3, 4] for magnitude in range(7): for frac, exp, prec in pycompat.izip(fractions, expecteds, precisions): for sign in [-1, 1]: for x in range(0, 10000, 97): n = x * 10**magnitude f = sign * (n + frac) f_exp = ('-' if f != 0 and sign == -1 else '') + str(n) + exp try_round(f, f_exp, precision_digits=prec) stop = time.time() # Micro-bench results: # 47130 round calls in 0.422306060791 secs, with Python 2.6.7 on Core i3 x64 # with decimal: # 47130 round calls in 6.612248100021 secs, with Python 2.6.7 on Core i3 x64 print(count, " round calls, ", errors, "errors, done in ", (stop - start),
def _compute_location_description(self): for operation, operation_sudo in izip(self, self.sudo()): operation.from_loc = '%s%s' % (operation_sudo.location_id.name, operation.product_id and operation_sudo.package_id.name or '') operation.to_loc = '%s%s' % (operation_sudo.location_dest_id.name, operation_sudo.result_package_id.name or '')
def iter_fiscal_pos_map(self): keys = [c.value for c in self.sheet_fiscal_pos_map.row(0)] yield keys for i in range(1, self.sheet_fiscal_pos_map.nrows): row = (c.value for c in self.sheet_fiscal_pos_map.row(i)) yield OrderedDict(pycompat.izip(keys, row))
def iter_taxes(self): keys = [c.value for c in self.sheet_taxes.row(0)] yield keys for i in range(1, self.sheet_taxes.nrows): row = (c.value for c in self.sheet_taxes.row(i)) yield OrderedDict(pycompat.izip(keys, row))
def _compute_params(self): self_bin = self.with_context(bin_size=False, bin_size_params_store=False) for record, record_bin in pycompat.izip(self, self_bin): record.params = record_bin.params_store and safe_eval( record_bin.params_store, {'uid': self._uid})
def test_rounding_03(self): """ Test rounding methods with 3 digits. """ def try_round(amount, expected, digits=3, method='HALF-UP'): value = float_round(amount, precision_digits=digits, rounding_method=method) result = float_repr(value, precision_digits=digits) self.assertEqual( result, expected, 'Rounding error: got %s, expected %s' % (result, expected)) try_round(2.6745, '2.675') try_round(-2.6745, '-2.675') try_round(2.6744, '2.674') try_round(-2.6744, '-2.674') try_round(0.0004, '0.000') try_round(-0.0004, '-0.000') try_round(357.4555, '357.456') try_round(-357.4555, '-357.456') try_round(457.4554, '457.455') try_round(-457.4554, '-457.455') # Try some rounding value with rounding method UP instead of HALF-UP # We use 8.175 because when normalizing 8.175 with precision_digits=3 it gives # us 8175,0000000001234 as value, and if not handle correctly the rounding UP # value will be incorrect (should be 8,175 and not 8,176) try_round(8.175, '8.175', method='UP') try_round(8.1751, '8.176', method='UP') try_round(-8.175, '-8.175', method='UP') try_round(-8.1751, '-8.176', method='UP') try_round(-6.000, '-6.000', method='UP') try_round(1.8, '2', 0, method='UP') try_round(-1.8, '-2', 0, method='UP') # Try some rounding value with rounding method DOWN instead of HALF-UP # We use 2.425 because when normalizing 2.425 with precision_digits=3 it gives # us 2424.9999999999995 as value, and if not handle correctly the rounding DOWN # value will be incorrect (should be 2.425 and not 2.424) try_round(2.425, '2.425', method='DOWN') try_round(2.4249, '2.424', method='DOWN') try_round(-2.425, '-2.425', method='DOWN') try_round(-2.4249, '-2.424', method='DOWN') try_round(-2.500, '-2.500', method='DOWN') try_round(1.8, '1', 0, method='DOWN') try_round(-1.8, '-1', 0, method='DOWN') # Extended float range test, inspired by Cloves Almeida's test on bug #882036. fractions = [.0, .015, .01499, .675, .67499, .4555, .4555, .45555] expecteds = ['.00', '.02', '.01', '.68', '.67', '.46', '.456', '.4556'] precisions = [2, 2, 2, 2, 2, 2, 3, 4] # Note: max precision for double floats is 53 bits of precision or # 17 significant decimal digits for magnitude in range(7): for frac, exp, prec in pycompat.izip(fractions, expecteds, precisions): for sign in [-1, 1]: for x in range(0, 10000, 97): n = x * 10**magnitude f = sign * (n + frac) f_exp = ('-' if f != 0 and sign == -1 else '') + str(n) + exp try_round(f, f_exp, digits=prec) def try_zero(amount, expected): self.assertEqual(float_is_zero(amount, precision_digits=3), expected, "Rounding error: %s should be zero!" % amount) try_zero(0.0002, True) try_zero(-0.0002, True) try_zero(0.00034, True) try_zero(0.0005, False) try_zero(-0.0005, False) try_zero(0.0008, False) try_zero(-0.0008, False) def try_compare(amount1, amount2, expected): self.assertEqual( float_compare(amount1, amount2, precision_digits=3), expected, "Rounding error, compare_amounts(%s,%s) should be %s" % (amount1, amount2, expected)) try_compare(0.0003, 0.0004, 0) try_compare(-0.0003, -0.0004, 0) try_compare(0.0002, 0.0005, -1) try_compare(-0.0002, -0.0005, 1) try_compare(0.0009, 0.0004, 1) try_compare(-0.0009, -0.0004, -1) try_compare(557.4555, 557.4556, 0) try_compare(-557.4555, -557.4556, 0) try_compare(657.4444, 657.445, -1) try_compare(-657.4444, -657.445, 1) # Rounding to unusual rounding units (e.g. coin values) def try_round(amount, expected, precision_rounding=None, method='HALF-UP'): value = float_round(amount, precision_rounding=precision_rounding, rounding_method=method) result = float_repr(value, precision_digits=2) self.assertEqual( result, expected, 'Rounding error: got %s, expected %s' % (result, expected)) try_round(-457.4554, '-457.45', precision_rounding=0.05) try_round(457.444, '457.50', precision_rounding=0.5) try_round(457.3, '455.00', precision_rounding=5) try_round(457.5, '460.00', precision_rounding=5) try_round(457.1, '456.00', precision_rounding=3) try_round(2.5, '2.50', precision_rounding=0.05, method='DOWN') try_round(-2.5, '-2.50', precision_rounding=0.05, method='DOWN')