From c89cf80b256c444cdb88e9e2a11ee09e368a4be9 Mon Sep 17 00:00:00 2001 From: Julien Nakache Date: Tue, 18 Jun 2019 10:45:44 -0400 Subject: [PATCH] Fix `createConnectionField` deprecation warnings (#229) * Fix deprecation warnings * Release `2.2.1` * Add unrelated test to increase test coverage and unblock PR --- graphene_sqlalchemy/__init__.py | 2 +- graphene_sqlalchemy/fields.py | 21 ++++---- graphene_sqlalchemy/tests/test_types.py | 64 ++++++++++++++++--------- graphene_sqlalchemy/types.py | 5 +- 4 files changed, 58 insertions(+), 34 deletions(-) diff --git a/graphene_sqlalchemy/__init__.py b/graphene_sqlalchemy/__init__.py index d8eb010b..dc082689 100644 --- a/graphene_sqlalchemy/__init__.py +++ b/graphene_sqlalchemy/__init__.py @@ -2,7 +2,7 @@ from .fields import SQLAlchemyConnectionField from .utils import get_query, get_session -__version__ = "2.2.0" +__version__ = "2.2.1" __all__ = [ "__version__", diff --git a/graphene_sqlalchemy/fields.py b/graphene_sqlalchemy/fields.py index e29d87be..266b5f37 100644 --- a/graphene_sqlalchemy/fields.py +++ b/graphene_sqlalchemy/fields.py @@ -1,4 +1,4 @@ -import logging +import warnings from functools import partial from promise import Promise, is_thenable @@ -10,8 +10,6 @@ from .utils import get_query -log = logging.getLogger() - class UnsortedSQLAlchemyConnectionField(ConnectionField): @property @@ -100,7 +98,7 @@ def __init__(self, type, *args, **kwargs): def default_connection_field_factory(relationship, registry, **field_kwargs): model = relationship.mapper.entity model_type = registry.get_type_for_model(model) - return createConnectionField(model_type, **field_kwargs) + return __connectionFactory(model_type, **field_kwargs) # TODO Remove in next major version @@ -108,26 +106,29 @@ def default_connection_field_factory(relationship, registry, **field_kwargs): def createConnectionField(_type, **field_kwargs): - log.warning( + warnings.warn( 'createConnectionField is deprecated and will be removed in the next ' - 'major version. Use SQLAlchemyObjectType.Meta.connection_field_factory instead.' + 'major version. Use SQLAlchemyObjectType.Meta.connection_field_factory instead.', + DeprecationWarning, ) return __connectionFactory(_type, **field_kwargs) def registerConnectionFieldFactory(factoryMethod): - log.warning( + warnings.warn( 'registerConnectionFieldFactory is deprecated and will be removed in the next ' - 'major version. Use SQLAlchemyObjectType.Meta.connection_field_factory instead.' + 'major version. Use SQLAlchemyObjectType.Meta.connection_field_factory instead.', + DeprecationWarning, ) global __connectionFactory __connectionFactory = factoryMethod def unregisterConnectionFieldFactory(): - log.warning( + warnings.warn( 'registerConnectionFieldFactory is deprecated and will be removed in the next ' - 'major version. Use SQLAlchemyObjectType.Meta.connection_field_factory instead.' + 'major version. Use SQLAlchemyObjectType.Meta.connection_field_factory instead.', + DeprecationWarning, ) global __connectionFactory __connectionFactory = UnsortedSQLAlchemyConnectionField diff --git a/graphene_sqlalchemy/tests/test_types.py b/graphene_sqlalchemy/tests/test_types.py index bd5d5ae3..1c541f04 100644 --- a/graphene_sqlalchemy/tests/test_types.py +++ b/graphene_sqlalchemy/tests/test_types.py @@ -7,7 +7,7 @@ from ..converter import convert_sqlalchemy_composite from ..fields import (SQLAlchemyConnectionField, - UnsortedSQLAlchemyConnectionField, + UnsortedSQLAlchemyConnectionField, createConnectionField, registerConnectionFieldFactory, unregisterConnectionFieldFactory) from ..types import ORMField, SQLAlchemyObjectType, SQLAlchemyObjectTypeOptions @@ -224,6 +224,19 @@ class Meta: assert pets_field.type().description == 'Overridden' +def test_invalid_model_attr(): + err_msg = ( + "Cannot map ORMField to a model attribute.\n" + "Field: 'ReporterType.first_name'" + ) + with pytest.raises(ValueError, match=err_msg): + class ReporterType(SQLAlchemyObjectType): + class Meta: + model = Reporter + + first_name = ORMField(model_attr='does_not_exist') + + def test_only_fields(): class ReporterType(SQLAlchemyObjectType): class Meta: @@ -364,33 +377,40 @@ class Meta: def test_deprecated_registerConnectionFieldFactory(): - registerConnectionFieldFactory(_TestSQLAlchemyConnectionField) + with pytest.warns(DeprecationWarning): + registerConnectionFieldFactory(_TestSQLAlchemyConnectionField) - class ReporterType(SQLAlchemyObjectType): - class Meta: - model = Reporter - interfaces = (Node,) + class ReporterType(SQLAlchemyObjectType): + class Meta: + model = Reporter + interfaces = (Node,) - class ArticleType(SQLAlchemyObjectType): - class Meta: - model = Article - interfaces = (Node,) + class ArticleType(SQLAlchemyObjectType): + class Meta: + model = Article + interfaces = (Node,) - assert isinstance(ReporterType._meta.fields['articles'].type(), _TestSQLAlchemyConnectionField) + assert isinstance(ReporterType._meta.fields['articles'].type(), _TestSQLAlchemyConnectionField) def test_deprecated_unregisterConnectionFieldFactory(): - registerConnectionFieldFactory(_TestSQLAlchemyConnectionField) - unregisterConnectionFieldFactory() + with pytest.warns(DeprecationWarning): + registerConnectionFieldFactory(_TestSQLAlchemyConnectionField) + unregisterConnectionFieldFactory() - class ReporterType(SQLAlchemyObjectType): - class Meta: - model = Reporter - interfaces = (Node,) + class ReporterType(SQLAlchemyObjectType): + class Meta: + model = Reporter + interfaces = (Node,) + + class ArticleType(SQLAlchemyObjectType): + class Meta: + model = Article + interfaces = (Node,) + + assert not isinstance(ReporterType._meta.fields['articles'].type(), _TestSQLAlchemyConnectionField) - class ArticleType(SQLAlchemyObjectType): - class Meta: - model = Article - interfaces = (Node,) - assert not isinstance(ReporterType._meta.fields['articles'].type(), _TestSQLAlchemyConnectionField) +def test_deprecated_createConnectionField(): + with pytest.warns(DeprecationWarning): + createConnectionField(None) diff --git a/graphene_sqlalchemy/types.py b/graphene_sqlalchemy/types.py index f77cbc86..b79fd7c0 100644 --- a/graphene_sqlalchemy/types.py +++ b/graphene_sqlalchemy/types.py @@ -133,7 +133,10 @@ def construct_fields( for orm_field_name, orm_field in custom_orm_fields_items: attr_name = orm_field.kwargs.get('model_attr', orm_field_name) if attr_name not in all_model_attrs: - raise Exception('Cannot map ORMField "{}" to SQLAlchemy model property'.format(orm_field_name)) + raise ValueError(( + "Cannot map ORMField to a model attribute.\n" + "Field: '{}.{}'" + ).format(obj_type.__name__, orm_field_name,)) orm_field.kwargs['model_attr'] = attr_name # Merge automatic fields with custom ORM fields