def test_from_rfc3339_wo_fraction(): timestamp = "2016-12-20T21:13:47Z" expected = datetime_helpers.DatetimeWithNanoseconds( 2016, 12, 20, 21, 13, 47, tzinfo=pytz.UTC ) stamp = datetime_helpers.DatetimeWithNanoseconds.from_rfc3339(timestamp) assert stamp == expected
def test_from_rfc3339_w_partial_precision(): timestamp = "2016-12-20T21:13:47.1Z" expected = datetime_helpers.DatetimeWithNanoseconds( 2016, 12, 20, 21, 13, 47, microsecond=100000, tzinfo=pytz.UTC ) stamp = datetime_helpers.DatetimeWithNanoseconds.from_rfc3339(timestamp) assert stamp == expected
def test_from_rfc3339_w_full_precision(): timestamp = "2016-12-20T21:13:47.123456789Z" expected = datetime_helpers.DatetimeWithNanoseconds( 2016, 12, 20, 21, 13, 47, nanosecond=123456789, tzinfo=pytz.UTC ) stamp = datetime_helpers.DatetimeWithNanoseconds.from_rfc3339(timestamp) assert stamp == expected
def test_timestamp_pb_w_nanos(): stamp = datetime_helpers.DatetimeWithNanoseconds( 2016, 12, 20, 21, 13, 47, nanosecond=123456789, tzinfo=pytz.UTC ) delta = stamp - datetime_helpers._UTC_EPOCH timestamp = timestamp_pb2.Timestamp( seconds=int(delta.total_seconds()), nanos=123456789) assert stamp.timestamp_pb() == timestamp
def test_timestamp_pb_wo_nanos_naive(): stamp = datetime_helpers.DatetimeWithNanoseconds( 2016, 12, 20, 21, 13, 47, 123456) delta = stamp.replace(tzinfo=pytz.UTC) - datetime_helpers._UTC_EPOCH seconds = int(delta.total_seconds()) nanos = 123456000 timestamp = timestamp_pb2.Timestamp(seconds=seconds, nanos=nanos) assert stamp.timestamp_pb() == timestamp
def test_rfc3339_w_nanos_w_leading_zero_and_no_trailing_zeros(): stamp = datetime_helpers.DatetimeWithNanoseconds(2016, 12, 20, 21, 13, 47, nanosecond=1234500) assert stamp.rfc3339() == "2016-12-20T21:13:47.0012345Z"
def test_datetimewithnanos_rfc339_w_nanos(): stamp = datetime_helpers.DatetimeWithNanoseconds(2016, 12, 20, 21, 13, 47, nanosecond=123456789) assert stamp.rfc3339() == "2016-12-20T21:13:47.123456789Z"
def test_datetimewithnanos_rfc339_w_nanos_no_trailing_zeroes(): stamp = datetime_helpers.DatetimeWithNanoseconds(2016, 12, 20, 21, 13, 47, nanosecond=100000000) assert stamp.rfc3339() == "2016-12-20T21:13:47.1Z"
def test_ctor_wo_nanos(): stamp = datetime_helpers.DatetimeWithNanoseconds(2016, 12, 20, 21, 13, 47, 123456) assert stamp.year == 2016 assert stamp.month == 12 assert stamp.day == 20 assert stamp.hour == 21 assert stamp.minute == 13 assert stamp.second == 47 assert stamp.microsecond == 123456 assert stamp.nanosecond == 0
def test_ctor_w_micros_positional_and_nanos(): with pytest.raises(TypeError): datetime_helpers.DatetimeWithNanoseconds(2016, 12, 20, 21, 13, 47, 123456, nanosecond=123456789)
def test_datetimewithnanos_ctor_w_micros_keyword_and_nanos(): with pytest.raises(TypeError): datetime_helpers.DatetimeWithNanoseconds(2016, 12, 20, 21, 13, 47, microsecond=123456, nanosecond=123456789)
def get_timestamp_with_nanoseconds(timestamp_string): from google.api_core import datetime_helpers from datetime import datetime date_tmp = None if "." in timestamp_string: date_tmp = datetime.strptime(timestamp_string, '%Y-%m-%d %H:%M:%S.%f') else: date_tmp = datetime.strptime(timestamp_string, '%Y-%m-%d %H:%M:%S') timestamp=datetime_helpers.DatetimeWithNanoseconds(date_tmp.year, date_tmp.month, date_tmp.day, date_tmp.hour, date_tmp.minute, date_tmp.second, date_tmp.microsecond) return timestamp
def test_w_timestamp_w_nanos(self): import pytz from google.protobuf.struct_pb2 import Value from google.api_core import datetime_helpers when = datetime_helpers.DatetimeWithNanoseconds( 2016, 12, 20, 21, 13, 47, nanosecond=123456789, tzinfo=pytz.UTC ) value_pb = self._callFUT(when) self.assertIsInstance(value_pb, Value) self.assertEqual(value_pb.string_value, when.rfc3339())
def test_w_timestamp_w_nanos(self): import pytz from google.api_core import datetime_helpers from google.cloud.spanner_v1 import Type from google.cloud.spanner_v1 import TypeCode field_type = Type(code=TypeCode.TIMESTAMP) value = "2016-12-20T21:13:47.123456789Z" expected_value = datetime_helpers.DatetimeWithNanoseconds( 2016, 12, 20, 21, 13, 47, nanosecond=123456789, tzinfo=pytz.UTC) parsed = self._callFUT(value, field_type) self.assertIsInstance(parsed, datetime_helpers.DatetimeWithNanoseconds) self.assertEqual(parsed, expected_value)
def test_w_timestamp_w_nanos(self): import pytz from google.protobuf.struct_pb2 import Value from google.api_core import datetime_helpers from google.cloud.spanner_v1 import Type from google.cloud.spanner_v1 import TypeCode value = datetime_helpers.DatetimeWithNanoseconds( 2016, 12, 20, 21, 13, 47, nanosecond=123456789, tzinfo=pytz.UTC ) field_type = Type(code=TypeCode.TIMESTAMP) value_pb = Value(string_value=datetime_helpers.to_rfc3339(value)) parsed = self._callFUT(value_pb, field_type) self.assertIsInstance(parsed, datetime_helpers.DatetimeWithNanoseconds) self.assertEqual(parsed, value)
def test_rfc3339_wo_nanos(): stamp = datetime_helpers.DatetimeWithNanoseconds(2016, 12, 20, 21, 13, 47, 123456) assert stamp.rfc3339() == "2016-12-20T21:13:47.123456Z"
class ConditionTest( spanner_emulator_testlib.TestCase, parameterized.TestCase, ): def setUp(self): super().setUp() self.run_orm_migrations( os.path.join( os.path.dirname(os.path.abspath(__file__)), 'migrations_for_emulator_test', )) @parameterized.parameters( (True, type_pb2.Type(code=type_pb2.BOOL)), (0, type_pb2.Type(code=type_pb2.INT64)), (0.0, type_pb2.Type(code=type_pb2.FLOAT64)), ( datetime_helpers.DatetimeWithNanoseconds(2021, 1, 5), type_pb2.Type(code=type_pb2.TIMESTAMP), ), (datetime.datetime(2021, 1, 5), type_pb2.Type(code=type_pb2.TIMESTAMP)), (datetime.date(2021, 1, 5), type_pb2.Type(code=type_pb2.DATE)), (b'\x01', type_pb2.Type(code=type_pb2.BYTES)), ('foo', type_pb2.Type(code=type_pb2.STRING)), (decimal.Decimal('1.23'), type_pb2.Type(code=type_pb2.NUMERIC)), ( (0, 1), type_pb2.Type( code=type_pb2.ARRAY, array_element_type=type_pb2.Type(code=type_pb2.INT64), ), ), ( ['a', None, 'b'], type_pb2.Type( code=type_pb2.ARRAY, array_element_type=type_pb2.Type(code=type_pb2.STRING), ), ), ) def test_param_from_value(self, value, expected_type): param = condition.Param.from_value(value) self.assertEqual(expected_type, param.type) # Test that the value and inferred type are compatible. This will raise an # exception if they're not. self.assertEmpty( models.SmallTestModel.where( condition.ArbitraryCondition( '$param IS NULL', dict(param=param), segment=condition.Segment.WHERE, ))) @parameterized.parameters( (None, 'Cannot infer type of None'), ((0, 'some-string'), 'elements of exactly one type'), ((0, 'some-string', None), 'elements of exactly one type'), (object(), 'Unknown type'), ) def test_param_from_value_error(self, value, error_regex): with self.assertRaisesRegex(TypeError, error_regex): condition.Param.from_value(value) @parameterized.named_parameters( ( 'bytes', condition.ArbitraryCondition( '$param = b"\x01\x02"', dict(param=condition.Param.from_value(b'\x01\x02')), segment=condition.Segment.WHERE, ), ), ( 'array_of_bytes', condition.ArbitraryCondition( '${param}[OFFSET(0)] = b"\x01\x02"', dict(param=condition.Param.from_value([b'\x01\x02'])), segment=condition.Segment.WHERE, ), ), ( 'array_of_bytes_and_null', condition.ArbitraryCondition( '${param}[OFFSET(0)] IS NULL', dict(param=condition.Param.from_value((None, b'\x01\x02'))), segment=condition.Segment.WHERE, ), ), ) def test_param_from_value_correctly_encodes(self, tautology): test_model = models.SmallTestModel( dict( key='some-key', value_1='some-value', value_2='other-value', )) test_model.save() self.assertCountEqual((test_model,), models.SmallTestModel.where(tautology)) @parameterized.named_parameters( ( 'minimal', condition.ArbitraryCondition( 'FALSE', segment=condition.Segment.WHERE, ), {}, {}, 'FALSE', (), ), ( 'full', condition.ArbitraryCondition( '$key = IF($true_param, ${key_param}, $value_1)', dict( key=models.SmallTestModel.key, true_param=condition.Param.from_value(True), key_param=condition.Param.from_value('some-key'), value_1=condition.Column('value_1'), ), segment=condition.Segment.WHERE, ), dict( true_param0=True, key_param0='some-key', ), dict( true_param0=type_pb2.Type(code=type_pb2.BOOL), key_param0=type_pb2.Type(code=type_pb2.STRING), ), ('SmallTestModel.key = ' 'IF(@true_param0, @key_param0, SmallTestModel.value_1)'), ('some-key',), ), ) def test_arbitrary_condition( self, condition_, expected_params, expected_types, expected_sql, expected_row_keys, ): models.SmallTestModel( dict( key='some-key', value_1='some-value', value_2='other-value', )).save() rows = models.SmallTestModel.where(condition_) self.assertEqual(expected_params, condition_.params()) self.assertEqual(expected_types, condition_.types()) self.assertEqual(expected_sql, condition_.sql()) self.assertCountEqual(expected_row_keys, tuple(row.key for row in rows)) @parameterized.named_parameters( ('key_not_found', '$not_found', KeyError, 'not_found'), ('invalid_template', '$', ValueError, 'Invalid placeholder'), ) def test_arbitrary_condition_template_error( self, template, error_class, error_regex, ): with self.assertRaisesRegex(error_class, error_regex): condition.ArbitraryCondition(template, segment=condition.Segment.WHERE) @parameterized.named_parameters( ( 'field_from_wrong_model', models.ChildTestModel.key, 'does not belong to the Model', ), ( 'column_not_found', condition.Column('not_found'), 'does not exist in the Model', ), ) def test_arbitrary_condition_validation_error( self, substitution, error_regex, ): condition_ = condition.ArbitraryCondition( '$substitution', dict(substitution=substitution), segment=condition.Segment.WHERE, ) with self.assertRaisesRegex(error.ValidationError, error_regex): models.SmallTestModel.where(condition_) @parameterized.named_parameters( ( 'empty_or', condition.OrCondition(), {}, {}, 'FALSE', '', ), ( 'empty_and', condition.OrCondition([]), {}, {}, '(TRUE)', 'ab', ), ( 'single', condition.OrCondition( [condition.equal_to(models.SmallTestModel.key, 'a')]), dict(key0='a'), dict(key0=type_pb2.Type(code=type_pb2.STRING)), '((SmallTestModel.key = @key0))', 'a', ), ( 'multiple', condition.OrCondition( [ condition.equal_to(models.SmallTestModel.key, 'a'), condition.equal_to(models.SmallTestModel.value_1, 'a'), ], [ condition.equal_to(models.SmallTestModel.key, 'b'), condition.equal_to(models.SmallTestModel.value_1, 'b'), ], ), dict( key0='a', value_11='a', key2='b', value_13='b', ), dict( key0=type_pb2.Type(code=type_pb2.STRING), value_11=type_pb2.Type(code=type_pb2.STRING), key2=type_pb2.Type(code=type_pb2.STRING), value_13=type_pb2.Type(code=type_pb2.STRING), ), ('(' '(SmallTestModel.key = @key0 AND SmallTestModel.value_1 = @value_11)' ' OR ' '(SmallTestModel.key = @key2 AND SmallTestModel.value_1 = @value_13)' ')'), 'ab', ), ) def test_or_condition( self, condition_, expected_params, expected_types, expected_sql, expected_row_keys, ): models.SmallTestModel(dict(key='a', value_1='a', value_2='a')).save() models.SmallTestModel(dict(key='b', value_1='b', value_2='b')).save() rows = models.SmallTestModel.where(condition_) self.assertEqual(expected_params, condition_.params()) self.assertEqual(expected_types, condition_.types()) self.assertEqual(expected_sql, condition_.sql()) self.assertCountEqual(expected_row_keys, tuple(row.key for row in rows)) @parameterized.parameters( ('ABCD', 'BC', True), ('ABCD', 'bc', False), ('ABCD', 'CB', False), (b'ABCD', b'BC', True), (b'ABCD', b'bc', False), (b'ABCD', b'CB', False), ('ABCD', 'BC', True, dict(case_sensitive=False)), ('ABCD', 'bc', True, dict(case_sensitive=False)), ('ABCD', 'CB', False, dict(case_sensitive=False)), (b'ABCD', b'BC', True, dict(case_sensitive=False)), (b'ABCD', b'bc', True, dict(case_sensitive=False)), (b'ABCD', b'CB', False, dict(case_sensitive=False)), ) def test_contains( self, haystack, needle, expect_results, kwargs={}, ): test_model = models.SmallTestModel(dict(key='a', value_1='a', value_2='a')) test_model.save() self.assertCountEqual( ((test_model,) if expect_results else ()), models.SmallTestModel.where( spanner_orm.contains( condition.Param.from_value(haystack), condition.Param.from_value(needle), **kwargs, )), )
def test_rfc3339_wo_nanos_w_leading_zero(): stamp = datetime_helpers.DatetimeWithNanoseconds(2016, 12, 20, 21, 13, 47, 1234) assert stamp.rfc3339() == "2016-12-20T21:13:47.001234Z"