Skip to content

Commit

Permalink
Merge pull request #94 from insightindustry/develop
Browse files Browse the repository at this point in the history
PR for v.0.6.0
  • Loading branch information
insightindustry committed Oct 13, 2020
2 parents 5d2e689 + 4b7ce7e commit 1d0232e
Show file tree
Hide file tree
Showing 12 changed files with 389 additions and 15 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Expand Up @@ -93,6 +93,8 @@ celerybeat-schedule
# virtualenv
.venv
venv/
.python38
.py38
.python37
.python36
.python27
Expand Down
29 changes: 29 additions & 0 deletions CHANGES.rst
@@ -1,5 +1,34 @@
-----------

Release 0.6.0
=========================================

.. image:: https://travis-ci.org/insightindustry/sqlathanor.svg?branch=v.0.6.0
:target: https://travis-ci.org/insightindustry/sqlathanor
:alt: Build Status (Travis CI)

.. image:: https://codecov.io/gh/insightindustry/sqlathanor/branch/v.0.6.0/graph/badge.svg
:target: https://codecov.io/gh/insightindustry/sqlathanor
:alt: Code Coverage Status (Codecov)

.. image:: https://readthedocs.org/projects/sqlathanor/badge/?version=v.0.6.0
:target: http://sqlathanor.readthedocs.io/en/latest/?badge=v.0.6.0
:alt: Documentation Status (ReadTheDocs)

Bug Fixes
-----------------

* #87: Fixed a longstanding bug that prevented one-to-one relationships from being
deserialized properly.

Other Changes
------------------

* #89: Implemented support for ``display_name`` on relationships.
* Updated test matrix to maintain test compability in the Python 3.4 environment.

-----------

Release 0.5.1
=========================================

Expand Down
14 changes: 14 additions & 0 deletions README.rst
Expand Up @@ -29,6 +29,20 @@ SQLAthanor
:target: http://sqlathanor.readthedocs.io/en/latest/?badge=latest
:alt: Documentation Status (ReadTheDocs)

* - `v.0.6 <https://github.com/insightindustry/sqlathanor/tree/v.0.6.0>`_
-
.. image:: https://travis-ci.org/insightindustry/sqlathanor.svg?branch=v.0.6.0
:target: https://travis-ci.org/insightindustry/sqlathanor
:alt: Build Status (Travis CI)

.. image:: https://codecov.io/gh/insightindustry/sqlathanor/branch/v.0.6.0/graph/badge.svg
:target: https://codecov.io/gh/insightindustry/sqlathanor
:alt: Code Coverage Status (Codecov)

.. image:: https://readthedocs.org/projects/sqlathanor/badge/?version=v.0.6.0
:target: http://sqlathanor.readthedocs.io/en/latest/?badge=v.0.6.0
:alt: Documentation Status (ReadTheDocs)

* - `v.0.5 <https://github.com/insightindustry/sqlathanor/tree/v.0.5.1>`_
-
.. image:: https://travis-ci.org/insightindustry/sqlathanor.svg?branch=v.0.5.1
Expand Down
20 changes: 17 additions & 3 deletions docs/_unit_tests_code_coverage.rst
Expand Up @@ -18,18 +18,32 @@
:target: http://sqlathanor.readthedocs.io/en/latest/?badge=latest
:alt: Documentation Status (ReadTheDocs)

* - `v.0.6 <https://github.com/insightindustry/sqlathanor/tree/v.0.6.0>`_
-
.. image:: https://travis-ci.org/insightindustry/sqlathanor.svg?branch=v.0.6.0
:target: https://travis-ci.org/insightindustry/sqlathanor
:alt: Build Status (Travis CI)

.. image:: https://codecov.io/gh/insightindustry/sqlathanor/branch/v.0.6.0/graph/badge.svg
:target: https://codecov.io/gh/insightindustry/sqlathanor
:alt: Code Coverage Status (Codecov)

.. image:: https://readthedocs.org/projects/sqlathanor/badge/?version=v.0.6.0
:target: http://sqlathanor.readthedocs.io/en/latest/?badge=v.0.6.0
:alt: Documentation Status (ReadTheDocs)

* - `v.0.5 <https://github.com/insightindustry/sqlathanor/tree/v.0.5.1>`_
-
.. image:: https://travis-ci.org/insightindustry/sqlathanor.svg?branch=v.0.5.1
:target: https://travis-ci.org/insightindustry/sqlathanor
:alt: Build Status (Travis CI)

.. image:: https://codecov.io/gh/insightindustry/sqlathanor/branch/v.0.4.0/graph/badge.svg
.. image:: https://codecov.io/gh/insightindustry/sqlathanor/branch/v.0.5.1/graph/badge.svg
:target: https://codecov.io/gh/insightindustry/sqlathanor
:alt: Code Coverage Status (Codecov)

.. image:: https://readthedocs.org/projects/sqlathanor/badge/?version=v.0.5.0
:target: http://sqlathanor.readthedocs.io/en/latest/?badge=v.0.5.0
.. image:: https://readthedocs.org/projects/sqlathanor/badge/?version=v.0.5.1
:target: http://sqlathanor.readthedocs.io/en/latest/?badge=v.0.5.1
:alt: Documentation Status (ReadTheDocs)

* - `v.0.4 <https://github.com/insightindustry/sqlathanor/tree/v.0.4.0>`_
Expand Down
2 changes: 1 addition & 1 deletion sqlathanor/__version__.py
@@ -1,2 +1,2 @@
# -*- coding: utf-8 -*-
__version__ = '0.5.1'
__version__ = '0.6.0'
19 changes: 15 additions & 4 deletions sqlathanor/declarative/base_model.py
Expand Up @@ -6,7 +6,9 @@
# there as needed.

import inspect as inspect_
import yaml

from sqlathanor._compat import json
from sqlathanor.attributes import validate_serialization_config
from sqlathanor.utilities import format_to_tuple
from sqlathanor.default_serializers import get_default_serializer
Expand Down Expand Up @@ -261,10 +263,19 @@ def _get_deserialized_value(cls,
resolved_class = None
if resolved_class:
# pylint: disable=W0212
return_value = [resolved_class(
**resolved_class._parse_dict(x,
format,
**kwargs)) for x in value]
if hasattr(resolved_class, 'new_from_json') and format == 'json' and isinstance(value, dict):
as_json = json.dumps(value)
return_value = resolved_class.new_from_json(as_json, **kwargs)
elif hasattr(resolved_class, 'new_from_yaml') and format == 'yaml' and isinstance(value, dict):
as_yaml = yaml.dump(value)
return_value = resolved_class.new_from_yaml(value, **kwargs)
elif hasattr(resolved_class, 'new_from_dict') and format == 'dict' and isinstance(value, dict):
return_value = resolved_class.new_from_dict(value, **kwargs)
else:
return_value = [resolved_class(
**resolved_class._parse_dict(x,
format,
**kwargs)) for x in value]
#pylint: enable=W0212
else:
return_value = value
Expand Down
8 changes: 7 additions & 1 deletion sqlathanor/schema.py
Expand Up @@ -193,6 +193,7 @@ def __init__(self,
supports_dict = False,
on_serialize = None,
on_deserialize = None,
display_name = None,
**kwargs):
"""Provide a relationship between two mapped classes.
Expand Down Expand Up @@ -353,6 +354,7 @@ def __init__(self,
self.supports_dict = supports_dict
self.on_serialize = on_serialize
self.on_deserialize = on_deserialize
self.display_name = display_name

comparator_factory = kwargs.pop('comparator_factory', RelationshipProperty.Comparator)

Expand Down Expand Up @@ -388,7 +390,11 @@ def on_serialize(self):

@property
def on_deserialize(self):
return self.prop.on_deserialize
return self.prop.on_deserialize\

@property
def display_name(self):
return self.prop.display_name


relationship = public_factory(RelationshipProperty, ".orm.relationship")
Expand Down
2 changes: 0 additions & 2 deletions sqlathanor/utilities.py
Expand Up @@ -437,8 +437,6 @@ def parse_yaml(input_data,
raise DeserializationError('input_data is not a valid string')

if not is_file:
print(type(input_data))
print(input_data)
from_yaml = yaml.safe_load(input_data, **kwargs)
else:
with open(input_data, 'r') as input_file:
Expand Down
104 changes: 103 additions & 1 deletion tests/fixtures.py
Expand Up @@ -485,6 +485,76 @@ class Address_Complex_PostgreSQL(BaseModel):
ForeignKey('users_complex_postgresql.id'))


# ISSUE 87: One-to-One relationship deserialization
class User_OneToOne_Nested(BaseModel):
"""Mocked class with a single primary key."""

__tablename__ = 'users_one_to_one'

__serialization__ = [
AttributeConfiguration(name = 'id',
supports_csv = True,
csv_sequence = 1,
supports_json = True,
supports_yaml = True,
supports_dict = True),
AttributeConfiguration(name = 'name',
supports_csv = True,
csv_sequence = 2,
supports_json = True,
supports_yaml = True,
supports_dict = True,
on_serialize = None,
on_deserialize = None),
AttributeConfiguration(name = 'address',
supports_json = True,
supports_yaml = (True, True),
supports_dict = (True, True)),
]

id = Column('id',
Integer,
primary_key = True)
name = Column('username',
String(50))
address = relationship('Address_Nested_OneToOne', backref = 'user', uselist = False)

class Address_Nested_OneToOne(BaseModel):
"""Mocked class with a single primary key."""

__tablename__ = 'addresses_nested_one_to_one'

__serialization__ = [
AttributeConfiguration(name = 'id',
supports_csv = True,
csv_sequence = 1,
supports_json = True,
supports_yaml = True,
supports_dict = True),
AttributeConfiguration(name = 'email',
supports_csv = True,
csv_sequence = 2,
supports_json = True,
supports_yaml = True,
supports_dict = True,
on_serialize = None,
on_deserialize = None),
]

id = Column('id',
Integer,
primary_key = True)
email = Column('email_address',
String(50),
supports_csv = True,
supports_json = True,
supports_yaml = True,
supports_dict = True,
on_serialize = validators.email,
on_deserialize = validators.email)
user_id = Column('user_id',
Integer,
ForeignKey('users_one_to_one.id'))

BaseModel.metadata.create_all(db_engine)

Expand All @@ -494,7 +564,8 @@ class Address_Complex_PostgreSQL(BaseModel):
'model_composite_pk': (User2, Address2),
'model_complex': (User_Complex, Address_Complex),
'model_complex_meta': (User_Complex_Meta, Address_Complex_Meta),
'model_complex_postgresql': (User_Complex_PostgreSQL, Address_Complex_PostgreSQL)
'model_complex_postgresql': (User_Complex_PostgreSQL, Address_Complex_PostgreSQL),
'model_user_one_to_one': (User_OneToOne_Nested, Address_Nested_OneToOne)
}

clear_mappers()
Expand Down Expand Up @@ -615,6 +686,13 @@ def model_complex_postgresql(request, tables):

return (User2, Address2)

@pytest.fixture(scope = 'session')
def model_nested_one_to_one(request, tables):
User3 = tables['model_user_one_to_one'][0]
Address3 = tables['model_user_one_to_one'][1]

return (User3, Address3)


@pytest.fixture
def instance_complex(request, model_complex):
Expand Down Expand Up @@ -692,6 +770,30 @@ def instance_postgresql(request, model_complex_postgresql):

return (instances, instance_values)

@pytest.fixture
def instance_nested_one_to_one(request, model_nested_one_to_one):
user_instance_values = {
'id': 1,
'name': 'test_username'
}
address_instance_values = {
'id': 1,
'email': 'test@domain.com',
'user_id': 1
}

user = model_nested_one_to_one[0]
address = model_nested_one_to_one[1]

user_instance = user(**user_instance_values)
address_instance = address(**address_instance_values)
user_instance.address = address_instance

instances = (user_instance, address_instance)
instance_values = (user_instance_values, address_instance_values)

return (instances, instance_values)


@pytest.fixture
def original_hybrid_config(request):
Expand Down

0 comments on commit 1d0232e

Please sign in to comment.