From ae253e0587fb3fdd1ac83904b7d53cc8797bb06c Mon Sep 17 00:00:00 2001 From: M1ha Date: Tue, 25 Jun 2019 18:10:04 +0500 Subject: [PATCH] =?UTF-8?q?=D0=91=D0=B0=D0=B3=D1=84=D0=B8=D0=BA=D1=81?= =?UTF-8?q?=D1=8B=20=D1=81=D0=BE=D0=B2=D0=BC=D0=B5=D1=81=D1=82=D0=B8=D0=BC?= =?UTF-8?q?=D0=BE=D1=81=D1=82=D0=B8=20=D1=81=20python=203.7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/django_clickhouse/clickhouse_models.py | 9 +++++++-- src/django_clickhouse/compatibility.py | 10 ++-------- src/django_clickhouse/utils.py | 2 +- tests/test_compatibility.py | 12 ++++++------ 4 files changed, 16 insertions(+), 17 deletions(-) diff --git a/src/django_clickhouse/clickhouse_models.py b/src/django_clickhouse/clickhouse_models.py index 2d11d37..80b0446 100644 --- a/src/django_clickhouse/clickhouse_models.py +++ b/src/django_clickhouse/clickhouse_models.py @@ -67,7 +67,7 @@ class ClickHouseModel(with_metaclass(ClickHouseModelMeta, InfiModel)): field_names = field_names or cls.fields(writable=False).keys() # Strange, but sometimes the columns are in different order... - field_names = tuple(sorted(field_names)) + field_names = sorted(field_names) if defaults: defaults_new = deepcopy(cls._defaults) @@ -75,7 +75,12 @@ class ClickHouseModel(with_metaclass(ClickHouseModelMeta, InfiModel)): else: defaults_new = cls._defaults - return namedtuple("%sTuple" % cls.__name__, field_names, defaults=defaults_new) + # defaults should be rightmost arguments + required_field_names = tuple(name for name in field_names if name not in defaults_new) + + default_field_names, default_values = zip(*defaults_new.items()) + + return namedtuple("%sTuple" % cls.__name__, required_field_names + default_field_names, defaults=default_values) @classmethod def objects_in(cls, database): # type: (Database) -> QuerySet diff --git a/src/django_clickhouse/compatibility.py b/src/django_clickhouse/compatibility.py index 8213afe..b35ce14 100644 --- a/src/django_clickhouse/compatibility.py +++ b/src/django_clickhouse/compatibility.py @@ -1,8 +1,5 @@ import sys -from collections import namedtuple as basenamedtuple, Mapping -from functools import lru_cache - -from copy import deepcopy +from collections import namedtuple as basenamedtuple def namedtuple(*args, **kwargs): @@ -16,10 +13,7 @@ def namedtuple(*args, **kwargs): defaults = kwargs.pop('defaults', {}) TupleClass = basenamedtuple(*args, **kwargs) TupleClass.__new__.__defaults__ = (None,) * len(TupleClass._fields) - if isinstance(defaults, Mapping): - prototype = TupleClass(**defaults) - else: - prototype = TupleClass(*defaults) + prototype = TupleClass(*defaults) TupleClass.__new__.__defaults__ = tuple(prototype) return TupleClass else: diff --git a/src/django_clickhouse/utils.py b/src/django_clickhouse/utils.py index 0ee57ec..a279d3a 100644 --- a/src/django_clickhouse/utils.py +++ b/src/django_clickhouse/utils.py @@ -159,7 +159,7 @@ def int_ranges(items: Iterable[int]) -> Iterator[Tuple[int, int]]: yield interval if interval_start is None: - raise StopIteration() + return else: yield interval_start, prev_item diff --git a/tests/test_compatibility.py b/tests/test_compatibility.py index e652ae0..0c0cd30 100644 --- a/tests/test_compatibility.py +++ b/tests/test_compatibility.py @@ -1,17 +1,17 @@ -from unittest import TestCase +from django.test import TestCase from django_clickhouse.compatibility import namedtuple class NamedTupleTest(TestCase): def test_defaults(self): - TestTuple = namedtuple('TestTuple', ('a', 'b', 'c'), defaults={'c': 3}) + TestTuple = namedtuple('TestTuple', ('a', 'b', 'c'), defaults=[3]) self.assertTupleEqual((1, 2, 3), tuple(TestTuple(1, b=2))) self.assertTupleEqual((1, 2, 4), tuple(TestTuple(1, 2, 4))) self.assertTupleEqual((1, 2, 4), tuple(TestTuple(a=1, b=2, c=4))) def test_exceptions(self): - TestTuple = namedtuple('TestTuple', ('a', 'b', 'c'), defaults={'c': 3}) + TestTuple = namedtuple('TestTuple', ('a', 'b', 'c'), defaults=[3]) # BUG On python < 3.7 this error is not raised, as not given defaults are filled by None # with self.assertRaises(TypeError): @@ -22,8 +22,8 @@ class NamedTupleTest(TestCase): def test_different_defaults(self): # Test that 2 tuple type defaults don't affect each other - TestTuple = namedtuple('TestTuple', ('a', 'b', 'c'), defaults={'c': 3}) - OtherTuple = namedtuple('TestTuple', ('a', 'b', 'c'), defaults={'c': 4}) + TestTuple = namedtuple('TestTuple', ('a', 'b', 'c'), defaults=[3]) + OtherTuple = namedtuple('TestTuple', ('a', 'b', 'c'), defaults=[4]) t1 = TestTuple(a=1, b=2) t2 = OtherTuple(a=3, b=4) self.assertTupleEqual((1, 2, 3), tuple(t1)) @@ -31,7 +31,7 @@ class NamedTupleTest(TestCase): def test_defaults_cache(self): # Test that 2 tuple instances don't affect each other's defaults - TestTuple = namedtuple('TestTuple', ('a', 'b', 'c'), defaults={'c': 3}) + TestTuple = namedtuple('TestTuple', ('a', 'b', 'c'), defaults=[3]) self.assertTupleEqual((1, 2, 4), tuple(TestTuple(a=1, b=2, c=4))) self.assertTupleEqual((1, 2, 3), tuple(TestTuple(a=1, b=2)))