Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Type inference #12980

Merged
merged 11 commits into from
Aug 17, 2020
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@

from ._entity import EntityProperty, EdmType, TableEntity
from ._common_conversion import _decode_base64_to_bytes
from ._generated.models import TableProperties
from ._error import TableErrorCode

if TYPE_CHECKING:
Expand Down Expand Up @@ -62,11 +61,11 @@ def _deserialize_table_creation(response, _, headers):


def _from_entity_binary(value):
return EntityProperty(EdmType.BINARY, _decode_base64_to_bytes(value))
return EntityProperty(_decode_base64_to_bytes(value))


def _from_entity_int32(value):
return EntityProperty(EdmType.INT32, int(value))
return EntityProperty(int(value))


zero = datetime.timedelta(0) # same as 00:00
Expand Down
35 changes: 31 additions & 4 deletions sdk/tables/azure-data-tables/azure/data/tables/_entity.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
# license information.
# --------------------------------------------------------------------------
from enum import Enum
from datetime import datetime
from uuid import UUID
import six

from ._error import _ERROR_ATTRIBUTE_MISSING

Expand Down Expand Up @@ -75,17 +78,41 @@ class EntityProperty(object):
"""

def __init__(self,
type=None, # type: Union[str,EdmType] # pylint:disable=W0622
value=None # type: Any
):
value=None, # type: Any
type=None, # type: Union[str,EdmType] # pylint:disable=W0622
):
"""
Represents an Azure Table. Returned by list_tables.

:param Union[str, EdmType] type: The type of the property.
:param Any value: The value of the property.
"""
self.type = type
self.value = value
if type is not None:
self.type = type
elif isinstance(value, six.text_type):
try:
self.value = UUID(value)
seankane-msft marked this conversation as resolved.
Show resolved Hide resolved
self.type = EdmType.GUID
except ValueError:
self.type = EdmType.STRING
elif isinstance(value, six.binary_type):
self.type = EdmType.BINARY
elif isinstance(value, bool):
self.type = EdmType.BOOLEAN
elif isinstance(value, six.integer_types):
self.type = EdmType.INT64
elif isinstance(value, datetime):
self.type = EdmType.DATETIME
elif isinstance(value, float):
self.type = EdmType.DOUBLE
else:
raise ValueError(
"""Type of {} could not be inferred. Acceptable types are bytes, int, uuid.UUID,
datetime, string, int32, int64, float, and boolean. Refer to
azure.data.tables.EdmType for more information.
""".format(value)
)


class EdmType(str, Enum):
Expand Down
66 changes: 47 additions & 19 deletions sdk/tables/azure-data-tables/tests/test_table_batch.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
from azure.core import MatchConditions
from azure.core.exceptions import (
ResourceExistsError)
from azure.data.tables import EdmType, TableEntity, EntityProperty

from _shared.testcase import GlobalStorageAccountPreparer, TableTestCase, LogCaptured

Expand Down Expand Up @@ -78,7 +79,7 @@ def _create_random_entity_dict(self, pk=None, rk=None):
'Birthday': datetime(1973, 10, 4, tzinfo=tzutc()),
'birthday': datetime(1970, 10, 4, tzinfo=tzutc()),
'binary': b'binary',
'other': EntityProperty(EdmType.INT32, 20),
'other': EntityProperty(20, EdmType.INT32),
'clsid': uuid.UUID('c9da6455-213d-42c9-9a79-3e9149a57833')
}
return Entity(**properties)
Expand Down Expand Up @@ -148,6 +149,33 @@ def _assert_updated_entity(self, entity):
self.assertIsInstance(entity.timestamp, datetime)

#--Test cases for batch ---------------------------------------------

def test_inferred_types(self):
# Arrange
# Act
entity = TableEntity()
entity.PartitionKey = '003'
entity.RowKey = 'batch_all_operations_together-1'
entity.test = EntityProperty(True)
entity.test2 = EntityProperty(b'abcdef')
entity.test3 = EntityProperty(u'c9da6455-213d-42c9-9a79-3e9149a57833')
entity.test4 = EntityProperty(datetime(1973, 10, 4, tzinfo=tzutc()))
entity.test5 = EntityProperty(u"stringystring")
entity.test6 = EntityProperty(3.14159)
entity.test7 = EntityProperty(100)
entity.test8 = EntityProperty(10, EdmType.INT32)

# Assert
self.assertEqual(entity.test.type, EdmType.BOOLEAN)
self.assertEqual(entity.test2.type, EdmType.BINARY)
self.assertEqual(entity.test3.type, EdmType.GUID)
self.assertEqual(entity.test4.type, EdmType.DATETIME)
self.assertEqual(entity.test5.type, EdmType.STRING)
self.assertEqual(entity.test6.type, EdmType.DOUBLE)
self.assertEqual(entity.test7.type, EdmType.INT64)
self.assertEqual(entity.test8.type, EdmType.INT32)


@pytest.mark.skip("pending")
@GlobalStorageAccountPreparer()
def test_batch_insert(self, resource_group, location, storage_account, storage_account_key):
Expand All @@ -158,10 +186,10 @@ def test_batch_insert(self, resource_group, location, storage_account, storage_a
entity = Entity()
entity.PartitionKey = '001'
entity.RowKey = 'batch_insert'
entity.test = EntityProperty(EdmType.BOOLEAN, 'true')
entity.test = EntityProperty(True)
entity.test2 = 'value'
entity.test3 = 3
entity.test4 = EntityProperty(EdmType.INT64, '1234567890')
entity.test4 = EntityProperty(1234567890)
entity.test5 = datetime.utcnow()

batch = self.table.create_batch()
Expand All @@ -185,10 +213,10 @@ def test_batch_update(self, resource_group, location, storage_account, storage_a
entity = Entity()
entity.PartitionKey = '001'
entity.RowKey = 'batch_update'
entity.test = EntityProperty(EdmType.BOOLEAN, 'true')
entity.test = EntityProperty(True)
entity.test2 = 'value'
entity.test3 = 3
entity.test4 = EntityProperty(EdmType.INT64, '1234567890')
entity.test4 = EntityProperty(1234567890)
entity.test5 = datetime.utcnow()
self.table.create_item(entity)

Expand Down Expand Up @@ -218,10 +246,10 @@ def test_batch_merge(self, resource_group, location, storage_account, storage_ac
entity = Entity()
entity.PartitionKey = '001'
entity.RowKey = 'batch_merge'
entity.test = EntityProperty(EdmType.BOOLEAN, 'true')
entity.test = EntityProperty(True)
entity.test2 = 'value'
entity.test3 = 3
entity.test4 = EntityProperty(EdmType.INT64, '1234567890')
entity.test4 = EntityProperty(1234567890)
entity.test5 = datetime.utcnow()
self.table.create_item(entity)

Expand Down Expand Up @@ -313,7 +341,7 @@ def test_batch_insert_replace(self, resource_group, location, storage_account, s
entity.test = True
entity.test2 = 'value'
entity.test3 = 3
entity.test4 = EntityProperty(EdmType.INT64, '1234567890')
entity.test4 = EntityProperty(1234567890)
entity.test5 = datetime.utcnow()

batch = self.table.create_batch()
Expand Down Expand Up @@ -343,7 +371,7 @@ def test_batch_insert_merge(self, resource_group, location, storage_account, sto
entity.test = True
entity.test2 = 'value'
entity.test3 = 3
entity.test4 = EntityProperty(EdmType.INT64, '1234567890')
entity.test4 = EntityProperty(1234567890)
entity.test5 = datetime.utcnow()

batch = self.table.create_batch()
Expand All @@ -370,10 +398,10 @@ def test_batch_delete(self, resource_group, location, storage_account, storage_a
entity = Entity()
entity.PartitionKey = '001'
entity.RowKey = 'batch_delete'
entity.test = EntityProperty(EdmType.BOOLEAN, 'true')
entity.test = EntityProperty(True)
entity.test2 = 'value'
entity.test3 = 3
entity.test4 = EntityProperty(EdmType.INT64, '1234567890')
entity.test4 = EntityProperty(1234567890)
entity.test5 = datetime.utcnow()
self.table.create_item(entity)

Expand All @@ -399,10 +427,10 @@ def test_batch_inserts(self, resource_group, location, storage_account, storage_
# Act
entity = Entity()
entity.PartitionKey = 'batch_inserts'
entity.test = EntityProperty(EdmType.BOOLEAN, 'true')
entity.test = EntityProperty(True)
entity.test2 = 'value'
entity.test3 = 3
entity.test4 = EntityProperty(EdmType.INT64, '1234567890')
entity.test4 = EntityProperty(1234567890)

batch = self.table.create_batch()
for i in range(100):
Expand All @@ -428,10 +456,10 @@ def test_batch_all_operations_together(self, resource_group, location, storage_a
entity = Entity()
entity.PartitionKey = '003'
entity.RowKey = 'batch_all_operations_together-1'
entity.test = EntityProperty(EdmType.BOOLEAN, 'true')
entity.test = EntityProperty(True)
entity.test2 = 'value'
entity.test3 = 3
entity.test4 = EntityProperty(EdmType.INT64, '1234567890')
entity.test4 = EntityProperty(1234567890)
entity.test5 = datetime.utcnow()
self.table.create_item(entity)
entity.RowKey = 'batch_all_operations_together-2'
Expand Down Expand Up @@ -476,10 +504,10 @@ def test_batch_all_operations_together_context_manager(self, resource_group, loc
entity = Entity()
entity.PartitionKey = '003'
entity.RowKey = 'batch_all_operations_together-1'
entity.test = EntityProperty(EdmType.BOOLEAN, 'true')
entity.test = EntityProperty(True)
entity.test2 = 'value'
entity.test3 = 3
entity.test4 = EntityProperty(EdmType.INT64, '1234567890')
entity.test4 = EntityProperty(1234567890)
entity.test5 = datetime.utcnow()
self.table.create_item(entity)
entity.RowKey = 'batch_all_operations_together-2'
Expand Down Expand Up @@ -525,10 +553,10 @@ def test_batch_reuse(self, resource_group, location, storage_account, storage_ac
entity = Entity()
entity.PartitionKey = '003'
entity.RowKey = 'batch_all_operations_together-1'
entity.test = EntityProperty(EdmType.BOOLEAN, 'true')
entity.test = EntityProperty(True)
entity.test2 = 'value'
entity.test3 = 3
entity.test4 = EntityProperty(EdmType.INT64, '1234567890')
entity.test4 = EntityProperty(1234567890)
seankane-msft marked this conversation as resolved.
Show resolved Hide resolved
entity.test5 = datetime.utcnow()

batch = TableBatchClient()
Expand Down
22 changes: 11 additions & 11 deletions sdk/tables/azure-data-tables/tests/test_table_entity.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ def _create_random_entity_dict(self, pk=None, rk=None):
'Birthday': datetime(1973, 10, 4, tzinfo=tzutc()),
'birthday': datetime(1970, 10, 4, tzinfo=tzutc()),
'binary': b'binary',
'other': EntityProperty(type=EdmType.INT32, value=20),
'other': EntityProperty(value=20, type=EdmType.INT32),
'clsid': uuid.UUID('c9da6455-213d-42c9-9a79-3e9149a57833')
}
return TableEntity(**properties)
Expand Down Expand Up @@ -160,7 +160,7 @@ def _assert_default_entity(self, entity, headers=None):
self.assertEqual(entity['birthday'], datetime(1970, 10, 4, tzinfo=tzutc()))
self.assertEqual(entity['binary'].value, b'binary')
self.assertIsInstance(entity['other'], EntityProperty)
self.assertEqual(entity['other'].type, EdmType.INT32)
self.assertEqual(entity['other'].type, EdmType.INT64)
self.assertEqual(entity['other'].value, 20)
self.assertEqual(entity['clsid'], uuid.UUID('c9da6455-213d-42c9-9a79-3e9149a57833'))
# self.assertTrue('metadata' in entity.odata)
Expand Down Expand Up @@ -188,7 +188,7 @@ def _assert_default_entity_json_full_metadata(self, entity, headers=None):
self.assertEqual(entity['birthday'], datetime(1970, 10, 4, tzinfo=tzutc()))
self.assertEqual(entity['binary'].value, b'binary')
self.assertIsInstance(entity['other'], EntityProperty)
self.assertEqual(entity['other'].type, EdmType.INT32)
self.assertEqual(entity['other'].type, EdmType.INT64)
self.assertEqual(entity['other'].value, 20)
self.assertEqual(entity['clsid'], uuid.UUID('c9da6455-213d-42c9-9a79-3e9149a57833'))
# self.assertTrue('metadata' in entity.odata)
Expand Down Expand Up @@ -222,7 +222,7 @@ def _assert_default_entity_json_no_metadata(self, entity, headers=None):
self.assertTrue(entity['birthday'].endswith('00Z'))
self.assertEqual(entity['binary'], b64encode(b'binary').decode('utf-8'))
self.assertIsInstance(entity['other'], EntityProperty)
self.assertEqual(entity['other'].type, EdmType.INT32)
self.assertEqual(entity['other'].type, EdmType.INT64)
self.assertEqual(entity['other'].value, 20)
self.assertEqual(entity['clsid'], 'c9da6455-213d-42c9-9a79-3e9149a57833')
# self.assertIsNone(entity.odata)
Expand Down Expand Up @@ -273,7 +273,7 @@ def _assert_merged_entity(self, entity):
self.assertEqual(entity.Birthday, datetime(1973, 10, 4, tzinfo=tzutc()))
self.assertEqual(entity.birthday, datetime(1991, 10, 4, tzinfo=tzutc()))
self.assertIsInstance(entity.other, EntityProperty)
self.assertEqual(entity.other.type, EdmType.INT32)
self.assertEqual(entity.other.type, EdmType.INT64)
self.assertEqual(entity.other.value, 20)
self.assertIsInstance(entity.clsid, uuid.UUID)
self.assertEqual(str(entity.clsid), 'c9da6455-213d-42c9-9a79-3e9149a57833')
Expand Down Expand Up @@ -417,13 +417,13 @@ def test_insert_entity_with_large_int32_value_throws(self, resource_group, locat
try:
# Act
dict32 = self._create_random_base_entity_dict()
dict32['large'] = EntityProperty(EdmType.INT32, 2 ** 31)
dict32['large'] = EntityProperty(2 ** 31, EdmType.INT32)

# Assert
with self.assertRaises(TypeError):
self.table.create_entity(entity=dict32)

dict32['large'] = EntityProperty(EdmType.INT32, -(2 ** 31 + 1))
dict32['large'] = EntityProperty(-(2 ** 31 + 1), EdmType.INT32)
with self.assertRaises(TypeError):
self.table.create_entity(entity=dict32)
finally:
Expand All @@ -438,13 +438,13 @@ def test_insert_entity_with_large_int64_value_throws(self, resource_group, locat
try:
# Act
dict64 = self._create_random_base_entity_dict()
dict64['large'] = EntityProperty(EdmType.INT64, 2 ** 63)
dict64['large'] = EntityProperty(2 ** 63)

# Assert
with self.assertRaises(TypeError):
self.table.create_entity(entity=dict64)

dict64['large'] = EntityProperty(EdmType.INT64, -(2 ** 63 + 1))
dict64['large'] = EntityProperty(-(2 ** 63 + 1))
with self.assertRaises(TypeError):
self.table.create_entity(entity=dict64)
finally:
Expand Down Expand Up @@ -1304,10 +1304,10 @@ def test_query_entities_large(self, resource_group, location, storage_account, s
entity = Entity()
entity.PartitionKey = 'large'
entity.RowKey = 'batch{0}-item{1}'.format(j, i)
entity.test = EntityProperty(EdmType.BOOLEAN, 'true')
entity.test = EntityProperty(True)
entity.test2 = 'hello world;' * 100
entity.test3 = 3
entity.test4 = EntityProperty(EdmType.INT64, '1234567890')
entity.test4 = EntityProperty(1234567890)
entity.test5 = datetime(2016, 12, 31, 11, 59, 59, 0)
batch.create_entity(entity)
self.ts.commit_batch(table_name, batch)
Expand Down
Loading