Add pairwise_longest tools
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
# this repository contains the full copyright notices and license terms.
|
||||
from itertools import tee, zip_longest
|
||||
|
||||
from dateutil.relativedelta import relativedelta
|
||||
|
||||
@@ -18,15 +17,10 @@ from trytond.modules.currency.fields import Monetary
|
||||
from trytond.modules.product import price_digits
|
||||
from trytond.pool import Pool
|
||||
from trytond.pyson import Eval, If
|
||||
from trytond.tools import pairwise_longest
|
||||
from trytond.transaction import Transaction
|
||||
|
||||
|
||||
def pairwise(iterable):
|
||||
a, b = tee(iterable)
|
||||
next(b, None)
|
||||
return zip_longest(a, b)
|
||||
|
||||
|
||||
class Agent(ModelView, ModelSQL):
|
||||
"Commission Reporting per Agent"
|
||||
__name__ = 'commission.reporting.agent'
|
||||
@@ -121,7 +115,7 @@ class Agent(ModelView, ModelSQL):
|
||||
@property
|
||||
def time_series_all(self):
|
||||
delta = self._period_delta()
|
||||
for ts, next_ts in pairwise(self.time_series or []):
|
||||
for ts, next_ts in pairwise_longest(self.time_series or []):
|
||||
yield ts
|
||||
if delta and next_ts:
|
||||
date = ts.date + delta
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
# this repository contains the full copyright notices and license terms.
|
||||
from itertools import tee, zip_longest
|
||||
|
||||
try:
|
||||
import pygal
|
||||
@@ -17,15 +16,10 @@ from trytond.model import ModelSQL, ModelView, fields
|
||||
from trytond.modules.currency.fields import Monetary
|
||||
from trytond.pool import Pool
|
||||
from trytond.pyson import Eval, If
|
||||
from trytond.tools import pairwise_longest
|
||||
from trytond.transaction import Transaction
|
||||
|
||||
|
||||
def pairwise(iterable):
|
||||
a, b = tee(iterable)
|
||||
next(b, None)
|
||||
return zip_longest(a, b)
|
||||
|
||||
|
||||
class Abstract(ModelSQL):
|
||||
|
||||
company = fields.Many2One(
|
||||
@@ -122,7 +116,7 @@ class Abstract(ModelSQL):
|
||||
@property
|
||||
def time_series_all(self):
|
||||
delta = self._period_delta()
|
||||
for ts, next_ts in pairwise(self.time_series or []):
|
||||
for ts, next_ts in pairwise_longest(self.time_series or []):
|
||||
yield ts
|
||||
if delta and next_ts:
|
||||
date = ts.date + delta
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
# this repository contains the full copyright notices and license terms.
|
||||
from collections import defaultdict
|
||||
from decimal import Decimal
|
||||
from itertools import tee, zip_longest
|
||||
|
||||
try:
|
||||
import pygal
|
||||
@@ -20,17 +19,11 @@ from trytond.model import ModelSQL, ModelView, UnionMixin, fields, sum_tree
|
||||
from trytond.modules.currency.fields import Monetary
|
||||
from trytond.pool import Pool
|
||||
from trytond.pyson import Eval, If
|
||||
from trytond.tools import grouped_slice, reduce_ids
|
||||
from trytond.tools import grouped_slice, pairwise_longest, reduce_ids
|
||||
from trytond.transaction import Transaction
|
||||
from trytond.wizard import StateAction, StateTransition, Wizard
|
||||
|
||||
|
||||
def pairwise(iterable):
|
||||
a, b = tee(iterable)
|
||||
next(b, None)
|
||||
return zip_longest(a, b)
|
||||
|
||||
|
||||
class Abstract(ModelSQL):
|
||||
|
||||
company = fields.Many2One(
|
||||
@@ -190,7 +183,7 @@ class Abstract(ModelSQL):
|
||||
@property
|
||||
def time_series_all(self):
|
||||
delta = self._period_delta()
|
||||
for ts, next_ts in pairwise(self.time_series or []):
|
||||
for ts, next_ts in pairwise_longest(self.time_series or []):
|
||||
yield ts
|
||||
if delta and next_ts:
|
||||
date = ts.date + delta
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
# this repository contains the full copyright notices and license terms.
|
||||
|
||||
from itertools import tee, zip_longest
|
||||
|
||||
from dateutil.relativedelta import relativedelta
|
||||
from sql import Literal, Null, With
|
||||
from sql.aggregate import Count, Min, Sum
|
||||
@@ -19,15 +17,10 @@ from trytond.model import ModelSQL, ModelView, fields
|
||||
from trytond.modules.currency.fields import Monetary
|
||||
from trytond.pool import Pool
|
||||
from trytond.pyson import Eval, If
|
||||
from trytond.tools import pairwise_longest
|
||||
from trytond.transaction import Transaction
|
||||
|
||||
|
||||
def pairwise(iterable):
|
||||
a, b = tee(iterable)
|
||||
next(b, None)
|
||||
return zip_longest(a, b)
|
||||
|
||||
|
||||
class Abstract(ModelSQL):
|
||||
|
||||
company = fields.Many2One(
|
||||
@@ -201,7 +194,7 @@ class Abstract(ModelSQL):
|
||||
@property
|
||||
def time_series_all(self):
|
||||
delta = self._period_delta()
|
||||
for ts, next_ts in pairwise(self.time_series or []):
|
||||
for ts, next_ts in pairwise_longest(self.time_series or []):
|
||||
yield ts
|
||||
if delta and next_ts:
|
||||
date = ts.date + delta
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
|
||||
from collections import defaultdict
|
||||
from decimal import Decimal
|
||||
from itertools import tee, zip_longest
|
||||
|
||||
from sql import Literal, Null, With
|
||||
from sql.aggregate import Max, Min, Sum
|
||||
@@ -21,16 +20,10 @@ from trytond.model import ModelSQL, ModelView, fields, sum_tree
|
||||
from trytond.modules.currency.fields import Monetary
|
||||
from trytond.pool import Pool
|
||||
from trytond.pyson import Eval, If
|
||||
from trytond.tools import grouped_slice, reduce_ids
|
||||
from trytond.tools import grouped_slice, pairwise_longest, reduce_ids
|
||||
from trytond.transaction import Transaction
|
||||
|
||||
|
||||
def pairwise(iterable):
|
||||
a, b = tee(iterable)
|
||||
next(b, None)
|
||||
return zip_longest(a, b)
|
||||
|
||||
|
||||
class Abstract(ModelSQL, ModelView):
|
||||
|
||||
company = fields.Many2One(
|
||||
@@ -211,7 +204,7 @@ class Abstract(ModelSQL, ModelView):
|
||||
@property
|
||||
def time_series_all(self):
|
||||
delta = self._period_delta()
|
||||
for ts, next_ts in pairwise(self.time_series or []):
|
||||
for ts, next_ts in pairwise_longest(self.time_series or []):
|
||||
yield ts
|
||||
if delta and next_ts:
|
||||
date = ts.date + delta
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
* Add pairwise_longest tools
|
||||
* Add support for Python 3.12
|
||||
* Support default values for autocomplete
|
||||
* Support default value from context
|
||||
|
||||
@@ -16,6 +16,14 @@ Miscellaneous
|
||||
|
||||
Return the path of the named directory in subdir from root directory.
|
||||
|
||||
.. function:: pairwise_longest(iterable)
|
||||
|
||||
Return successive overlapping pairs taken from the input iterable.
|
||||
|
||||
The number of 2-tuples in the output iterator will be the number of inputs
|
||||
and ends with the ``None``.
|
||||
It will be empty if the input iterable has fewer than two values.
|
||||
|
||||
.. function:: resolve(name)
|
||||
|
||||
Resolve a dotted name to a global object.
|
||||
|
||||
@@ -13,9 +13,10 @@ import sql.operators
|
||||
|
||||
from trytond.tools import (
|
||||
decimal_, escape_wildcard, file_open, firstline, grouped_slice,
|
||||
is_full_text, is_instance_method, likify, lstrip_wildcard, reduce_domain,
|
||||
reduce_ids, remove_forbidden_chars, rstrip_wildcard, slugify,
|
||||
sortable_values, strip_wildcard, timezone, unescape_wildcard)
|
||||
is_full_text, is_instance_method, likify, lstrip_wildcard,
|
||||
pairwise_longest, reduce_domain, reduce_ids, remove_forbidden_chars,
|
||||
rstrip_wildcard, slugify, sortable_values, strip_wildcard, timezone,
|
||||
unescape_wildcard)
|
||||
from trytond.tools.domain_inversion import (
|
||||
canonicalize, concat, domain_inversion, eval_domain,
|
||||
extract_reference_models, localize_domain, merge, parse,
|
||||
@@ -128,6 +129,15 @@ class ToolsTestCase(unittest.TestCase):
|
||||
list(map(list, grouped_slice((x for x in range(10)), 5))),
|
||||
[[0, 1, 2, 3, 4], [5, 6, 7, 8, 9]])
|
||||
|
||||
def test_pairwise_longest(self):
|
||||
"Test pairwise_longest"
|
||||
self.assertEqual(
|
||||
list(pairwise_longest(range(3))), [(0, 1), (1, 2), (2, None)])
|
||||
|
||||
def test_pairwise_longest_empty(self):
|
||||
"Test pairwise_longest empty"
|
||||
self.assertEqual(list(pairwise_longest([])), [])
|
||||
|
||||
def test_is_instance_method(self):
|
||||
'Test is_instance_method'
|
||||
|
||||
|
||||
@@ -16,9 +16,9 @@ from .decimal_ import decistmt
|
||||
from .misc import (
|
||||
escape_wildcard, file_open, find_dir, find_path, firstline,
|
||||
get_smtp_server, grouped_slice, is_full_text, is_instance_method, likify,
|
||||
lstrip_wildcard, reduce_domain, reduce_ids, remove_forbidden_chars,
|
||||
resolve, rstrip_wildcard, slugify, sortable_values, sql_pairing,
|
||||
strip_wildcard, unescape_wildcard)
|
||||
lstrip_wildcard, pairwise_longest, reduce_domain, reduce_ids,
|
||||
remove_forbidden_chars, resolve, rstrip_wildcard, slugify, sortable_values,
|
||||
sql_pairing, strip_wildcard, unescape_wildcard)
|
||||
|
||||
|
||||
class ClassProperty(property):
|
||||
@@ -52,6 +52,7 @@ __all__ = [
|
||||
is_instance_method,
|
||||
likify,
|
||||
lstrip_wildcard,
|
||||
pairwise_longest,
|
||||
reduce_domain,
|
||||
reduce_ids,
|
||||
remove_forbidden_chars,
|
||||
|
||||
@@ -14,7 +14,7 @@ import warnings
|
||||
from array import array
|
||||
from collections.abc import Sized
|
||||
from functools import wraps
|
||||
from itertools import islice
|
||||
from itertools import islice, tee, zip_longest
|
||||
|
||||
from sql import Literal
|
||||
from sql.conditionals import Case
|
||||
@@ -174,6 +174,12 @@ def grouped_slice(records, count=None):
|
||||
yield islice(records, i, i + count)
|
||||
|
||||
|
||||
def pairwise_longest(iterable):
|
||||
a, b = tee(iterable)
|
||||
next(b, None)
|
||||
return zip_longest(a, b)
|
||||
|
||||
|
||||
def is_instance_method(cls, method):
|
||||
for klass in cls.__mro__:
|
||||
type_ = klass.__dict__.get(method)
|
||||
|
||||
Reference in New Issue
Block a user