Merge remote-tracking branch 'origin/master' into ttl
This commit is contained in:
		| @@ -256,6 +256,10 @@ class Integer(Column): | ||||
|         return self.validate(value) | ||||
|  | ||||
|  | ||||
| class BigInt(Integer): | ||||
|     db_type = 'bigint' | ||||
|  | ||||
|  | ||||
| class VarInt(Column): | ||||
|     db_type = 'varint' | ||||
|  | ||||
| @@ -332,11 +336,9 @@ class DateTime(Column): | ||||
|             else: | ||||
|                 raise ValidationError("'{}' is not a datetime object".format(value)) | ||||
|         epoch = datetime(1970, 1, 1, tzinfo=value.tzinfo) | ||||
|         offset = 0 | ||||
|         if epoch.tzinfo: | ||||
|             offset_delta = epoch.tzinfo.utcoffset(epoch) | ||||
|             offset = offset_delta.days*24*3600 + offset_delta.seconds | ||||
|         return long(((value  - epoch).total_seconds() - offset) * 1000) | ||||
|         offset = epoch.tzinfo.utcoffset(epoch).total_seconds() if epoch.tzinfo else 0 | ||||
|  | ||||
|         return long(((value - epoch).total_seconds() - offset) * 1000) | ||||
|  | ||||
|  | ||||
| class Date(Column): | ||||
| @@ -406,12 +408,7 @@ class TimeUUID(UUID): | ||||
|         global _last_timestamp | ||||
|  | ||||
|         epoch = datetime(1970, 1, 1, tzinfo=dt.tzinfo) | ||||
|  | ||||
|         offset = 0 | ||||
|         if epoch.tzinfo: | ||||
|             offset_delta = epoch.tzinfo.utcoffset(epoch) | ||||
|             offset = offset_delta.days*24*3600 + offset_delta.seconds | ||||
|  | ||||
|         offset = epoch.tzinfo.utcoffset(epoch).total_seconds() if epoch.tzinfo else 0 | ||||
|         timestamp = (dt  - epoch).total_seconds() - offset | ||||
|  | ||||
|         node = None | ||||
|   | ||||
| @@ -54,8 +54,10 @@ class MinTimeUUID(BaseQueryFunction): | ||||
|         super(MinTimeUUID, self).__init__(value) | ||||
|  | ||||
|     def get_value(self): | ||||
|         epoch = datetime(1970, 1, 1) | ||||
|         return long((self.value - epoch).total_seconds() * 1000) | ||||
|         epoch = datetime(1970, 1, 1, tzinfo=self.value.tzinfo) | ||||
|         offset = epoch.tzinfo.utcoffset(epoch).total_seconds() if epoch.tzinfo else 0 | ||||
|  | ||||
|         return long(((self.value - epoch).total_seconds() - offset) * 1000) | ||||
|  | ||||
|     def get_dict(self, column): | ||||
|         return {self.identifier: self.get_value()} | ||||
| @@ -79,8 +81,10 @@ class MaxTimeUUID(BaseQueryFunction): | ||||
|         super(MaxTimeUUID, self).__init__(value) | ||||
|  | ||||
|     def get_value(self): | ||||
|         epoch = datetime(1970, 1, 1) | ||||
|         return long((self.value - epoch).total_seconds() * 1000) | ||||
|         epoch = datetime(1970, 1, 1, tzinfo=self.value.tzinfo) | ||||
|         offset = epoch.tzinfo.utcoffset(epoch).total_seconds() if epoch.tzinfo else 0 | ||||
|  | ||||
|         return long(((self.value - epoch).total_seconds() - offset) * 1000) | ||||
|  | ||||
|     def get_dict(self, column): | ||||
|         return {self.identifier: self.get_value()} | ||||
|   | ||||
| @@ -15,6 +15,7 @@ from cqlengine.columns import Bytes | ||||
| from cqlengine.columns import Ascii | ||||
| from cqlengine.columns import Text | ||||
| from cqlengine.columns import Integer | ||||
| from cqlengine.columns import BigInt | ||||
| from cqlengine.columns import VarInt | ||||
| from cqlengine.columns import DateTime | ||||
| from cqlengine.columns import Date | ||||
| @@ -180,6 +181,16 @@ class TestInteger(BaseCassEngTestCase): | ||||
|         it = self.IntegerTest() | ||||
|         it.validate() | ||||
|  | ||||
| class TestBigInt(BaseCassEngTestCase): | ||||
|     class BigIntTest(Model): | ||||
|         test_id = UUID(primary_key=True, default=lambda:uuid4()) | ||||
|         value   = BigInt(default=0, required=True) | ||||
|  | ||||
|     def test_default_zero_fields_validate(self): | ||||
|         """ Tests that bigint columns with a default value of 0 validate """ | ||||
|         it = self.BigIntTest() | ||||
|         it.validate() | ||||
|  | ||||
| class TestText(BaseCassEngTestCase): | ||||
|  | ||||
|     def test_min_length(self): | ||||
|   | ||||
| @@ -95,6 +95,12 @@ class TestInteger(BaseColumnIOTest): | ||||
|     pkey_val = 5 | ||||
|     data_val = 6 | ||||
|  | ||||
| class TestBigInt(BaseColumnIOTest): | ||||
|  | ||||
|     column = columns.BigInt | ||||
|     pkey_val = 6 | ||||
|     data_val = pow(2, 63) - 1 | ||||
|  | ||||
| class TestDateTime(BaseColumnIOTest): | ||||
|  | ||||
|     column = columns.DateTime | ||||
|   | ||||
| @@ -11,6 +11,25 @@ from cqlengine.management import delete_table | ||||
| from cqlengine.models import Model | ||||
| from cqlengine import columns | ||||
| from cqlengine import query | ||||
| from datetime import timedelta | ||||
| from datetime import tzinfo | ||||
|  | ||||
|  | ||||
| class TzOffset(tzinfo): | ||||
|     """Minimal implementation of a timezone offset to help testing with timezone | ||||
|     aware datetimes. | ||||
|     """ | ||||
|     def __init__(self, offset): | ||||
|         self._offset = timedelta(hours=offset) | ||||
|  | ||||
|     def utcoffset(self, dt): | ||||
|         return self._offset | ||||
|  | ||||
|     def tzname(self, dt): | ||||
|         return 'TzOffset: {}'.format(self._offset.hours) | ||||
|  | ||||
|     def dst(self, dt): | ||||
|         return timedelta(0) | ||||
|  | ||||
| class TestModel(Model): | ||||
|     test_id = columns.Integer(primary_key=True) | ||||
| @@ -515,6 +534,49 @@ class TestMinMaxTimeUUIDFunctions(BaseCassEngTestCase): | ||||
|         super(TestMinMaxTimeUUIDFunctions, cls).tearDownClass() | ||||
|         delete_table(TimeUUIDQueryModel) | ||||
|  | ||||
|     def test_tzaware_datetime_support(self): | ||||
|         """Test that using timezone aware datetime instances works with the | ||||
|         MinTimeUUID/MaxTimeUUID functions. | ||||
|         """ | ||||
|         pk = uuid4() | ||||
|         midpoint_utc = datetime.utcnow().replace(tzinfo=TzOffset(0)) | ||||
|         midpoint_helsinki = midpoint_utc.astimezone(TzOffset(3)) | ||||
|  | ||||
|         # Assert pre-condition that we have the same logical point in time | ||||
|         assert midpoint_utc.utctimetuple() == midpoint_helsinki.utctimetuple() | ||||
|         assert midpoint_utc.timetuple() != midpoint_helsinki.timetuple() | ||||
|  | ||||
|         TimeUUIDQueryModel.create( | ||||
|             partition=pk, | ||||
|             time=columns.TimeUUID.from_datetime(midpoint_utc - timedelta(minutes=1)), | ||||
|             data='1') | ||||
|  | ||||
|         TimeUUIDQueryModel.create( | ||||
|             partition=pk, | ||||
|             time=columns.TimeUUID.from_datetime(midpoint_utc), | ||||
|             data='2') | ||||
|  | ||||
|         TimeUUIDQueryModel.create( | ||||
|             partition=pk, | ||||
|             time=columns.TimeUUID.from_datetime(midpoint_utc + timedelta(minutes=1)), | ||||
|             data='3') | ||||
|  | ||||
|         assert ['1', '2'] == [o.data for o in TimeUUIDQueryModel.filter( | ||||
|             TimeUUIDQueryModel.partition == pk, | ||||
|             TimeUUIDQueryModel.time <= functions.MaxTimeUUID(midpoint_utc))] | ||||
|  | ||||
|         assert ['1', '2'] == [o.data for o in TimeUUIDQueryModel.filter( | ||||
|             TimeUUIDQueryModel.partition == pk, | ||||
|             TimeUUIDQueryModel.time <= functions.MaxTimeUUID(midpoint_helsinki))] | ||||
|  | ||||
|         assert ['2', '3'] == [o.data for o in TimeUUIDQueryModel.filter( | ||||
|             TimeUUIDQueryModel.partition == pk, | ||||
|             TimeUUIDQueryModel.time >= functions.MinTimeUUID(midpoint_utc))] | ||||
|  | ||||
|         assert ['2', '3'] == [o.data for o in TimeUUIDQueryModel.filter( | ||||
|             TimeUUIDQueryModel.partition == pk, | ||||
|             TimeUUIDQueryModel.time >= functions.MinTimeUUID(midpoint_helsinki))] | ||||
|  | ||||
|     def test_success_case(self): | ||||
|         """ Test that the min and max time uuid functions work as expected """ | ||||
|         pk = uuid4() | ||||
|   | ||||
| @@ -38,10 +38,16 @@ Columns | ||||
|  | ||||
| .. class:: Integer() | ||||
|  | ||||
|     Stores an integer value :: | ||||
|     Stores a 32-bit signed integer value :: | ||||
|  | ||||
|         columns.Integer() | ||||
|  | ||||
| .. class:: BigInt() | ||||
|  | ||||
|     Stores a 64-bit signed long value :: | ||||
|  | ||||
|         columns.BigInt() | ||||
|  | ||||
| .. class:: VarInt() | ||||
|  | ||||
|     Stores an arbitrary-precision integer :: | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Jon Haddad
					Jon Haddad