Loading AUTHORS +1 −0 Original line number Diff line number Diff line Loading @@ -57,6 +57,7 @@ answer newbie questions, and generally made Django that much better: Gisle Aas <gisle@aas.no> Chris Adams Mathieu Agopian <mathieu.agopian@gmail.com> Roberto Aguilar <roberto@baremetal.io> ajs <adi@sieker.info> alang@bright-green.com A S Alam <aalam@users.sf.net> Loading django/core/management/commands/dumpdata.py +4 −4 Original line number Diff line number Diff line Loading @@ -105,11 +105,11 @@ class Command(BaseCommand): # Check that the serialization format exists; this is a shortcut to # avoid collating all the objects and _then_ failing. if format not in serializers.get_public_serializer_formats(): raise CommandError("Unknown serialization format: %s" % format) try: serializers.get_serializer(format) except KeyError: except serializers.SerializerDoesNotExist: pass raise CommandError("Unknown serialization format: %s" % format) def get_objects(): Loading django/core/serializers/__init__.py +31 −8 Original line number Diff line number Diff line Loading @@ -26,17 +26,29 @@ BUILTIN_SERIALIZERS = { "xml" : "django.core.serializers.xml_serializer", "python" : "django.core.serializers.python", "json" : "django.core.serializers.json", "yaml" : "django.core.serializers.pyyaml", } # Check for PyYaml and register the serializer if it's available. try: import yaml BUILTIN_SERIALIZERS["yaml"] = "django.core.serializers.pyyaml" except ImportError: pass _serializers = {} class BadSerializer(object): """ Stub serializer to hold exception raised during registration This allows the serializer registration to cache serializers and if there is an error raised in the process of creating a serializer it will be raised and passed along to the caller when the serializer is used. """ internal_use_only = False def __init__(self, exception): self.exception = exception def __call__(self, *args, **kwargs): raise self.exception def register_serializer(format, serializer_module, serializers=None): """Register a new serializer. Loading @@ -52,12 +64,23 @@ def register_serializer(format, serializer_module, serializers=None): """ if serializers is None and not _serializers: _load_serializers() try: module = importlib.import_module(serializer_module) except ImportError, exc: bad_serializer = BadSerializer(exc) module = type('BadSerializerModule', (object,), { 'Deserializer': bad_serializer, 'Serializer': bad_serializer, }) if serializers is None: _serializers[format] = module else: serializers[format] = module def unregister_serializer(format): "Unregister a given serializer. This is not a thread-safe operation." if not _serializers: Loading tests/serializers/tests.py +116 −47 Original line number Diff line number Diff line # -*- coding: utf-8 -*- from __future__ import absolute_import, unicode_literals # -*- coding: utf-8 -*- import json from datetime import datetime from xml.dom import minidom try: import yaml HAS_YAML = True except ImportError: HAS_YAML = False from django.conf import settings from django.core import serializers from django.core import management, serializers from django.db import transaction, connection from django.test import TestCase, TransactionTestCase, Approximate from django.utils import six from django.utils.six import StringIO from django.utils import unittest from django.utils import importlib from .models import (Category, Author, Article, AuthorProfile, Actor, Movie, Score, Player, Team) Loading Loading @@ -420,11 +427,71 @@ class JsonSerializerTransactionTestCase(SerializersTransactionTestBase, Transact } }]""" try: import yaml except ImportError: pass else: YAML_IMPORT_ERROR_MESSAGE = r'No module named yaml' class YamlImportModuleMock(object): """Provides a wrapped import_module function to simulate yaml ImportError In order to run tests that verify the behavior of the YAML serializer when run on a system that has yaml installed (like the django CI server), mock import_module, so that it raises an ImportError when the yaml serializer is being imported. The importlib.import_module() call is being made in the serializers.register_serializer(). Refs: #12756 """ def __init__(self): self._import_module = importlib.import_module def import_module(self, module_path): if module_path == serializers.BUILTIN_SERIALIZERS['yaml']: raise ImportError(YAML_IMPORT_ERROR_MESSAGE) return self._import_module(module_path) class NoYamlSerializerTestCase(TestCase): """Not having pyyaml installed provides a misleading error Refs: #12756 """ @classmethod def setUpClass(cls): """Removes imported yaml and stubs importlib.import_module""" super(NoYamlSerializerTestCase, cls).setUpClass() cls._import_module_mock = YamlImportModuleMock() importlib.import_module = cls._import_module_mock.import_module # clear out cached serializers to emulate yaml missing serializers._serializers = {} @classmethod def tearDownClass(cls): """Puts yaml back if necessary""" super(NoYamlSerializerTestCase, cls).tearDownClass() importlib.import_module = cls._import_module_mock._import_module # clear out cached serializers to clean out BadSerializer instances serializers._serializers = {} def test_serializer_pyyaml_error_message(self): """Using yaml serializer without pyyaml raises ImportError""" jane = Author(name="Jane") self.assertRaises(ImportError, serializers.serialize, "yaml", [jane]) def test_deserializer_pyyaml_error_message(self): """Using yaml deserializer without pyyaml raises ImportError""" self.assertRaises(ImportError, serializers.deserialize, "yaml", "") def test_dumpdata_pyyaml_error_message(self): """Calling dumpdata produces an error when yaml package missing""" self.assertRaisesRegexp(management.CommandError, YAML_IMPORT_ERROR_MESSAGE, management.call_command, 'dumpdata', format='yaml') @unittest.skipUnless(HAS_YAML, "No yaml library detected") class YamlSerializerTestCase(SerializersTestBase, TestCase): serializer_name = "yaml" fwd_ref_str = """- fields: Loading Loading @@ -484,6 +551,8 @@ else: ret_list.append(str(field_value)) return ret_list @unittest.skipUnless(HAS_YAML, "No yaml library detected") class YamlSerializerTransactionTestCase(SerializersTransactionTestBase, TransactionTestCase): serializer_name = "yaml" fwd_ref_str = """- fields: Loading tests/serializers_regress/tests.py +4 −1 Original line number Diff line number Diff line Loading @@ -523,7 +523,10 @@ def streamTest(format, self): else: self.assertEqual(string_data, stream.content.decode('utf-8')) for format in serializers.get_serializer_formats(): for format in [ f for f in serializers.get_serializer_formats() if not isinstance(serializers.get_serializer(f), serializers.BadSerializer) ]: setattr(SerializerTests, 'test_' + format + '_serializer', curry(serializerTest, format)) setattr(SerializerTests, 'test_' + format + '_natural_key_serializer', curry(naturalKeySerializerTest, format)) setattr(SerializerTests, 'test_' + format + '_serializer_fields', curry(fieldsTest, format)) Loading Loading
AUTHORS +1 −0 Original line number Diff line number Diff line Loading @@ -57,6 +57,7 @@ answer newbie questions, and generally made Django that much better: Gisle Aas <gisle@aas.no> Chris Adams Mathieu Agopian <mathieu.agopian@gmail.com> Roberto Aguilar <roberto@baremetal.io> ajs <adi@sieker.info> alang@bright-green.com A S Alam <aalam@users.sf.net> Loading
django/core/management/commands/dumpdata.py +4 −4 Original line number Diff line number Diff line Loading @@ -105,11 +105,11 @@ class Command(BaseCommand): # Check that the serialization format exists; this is a shortcut to # avoid collating all the objects and _then_ failing. if format not in serializers.get_public_serializer_formats(): raise CommandError("Unknown serialization format: %s" % format) try: serializers.get_serializer(format) except KeyError: except serializers.SerializerDoesNotExist: pass raise CommandError("Unknown serialization format: %s" % format) def get_objects(): Loading
django/core/serializers/__init__.py +31 −8 Original line number Diff line number Diff line Loading @@ -26,17 +26,29 @@ BUILTIN_SERIALIZERS = { "xml" : "django.core.serializers.xml_serializer", "python" : "django.core.serializers.python", "json" : "django.core.serializers.json", "yaml" : "django.core.serializers.pyyaml", } # Check for PyYaml and register the serializer if it's available. try: import yaml BUILTIN_SERIALIZERS["yaml"] = "django.core.serializers.pyyaml" except ImportError: pass _serializers = {} class BadSerializer(object): """ Stub serializer to hold exception raised during registration This allows the serializer registration to cache serializers and if there is an error raised in the process of creating a serializer it will be raised and passed along to the caller when the serializer is used. """ internal_use_only = False def __init__(self, exception): self.exception = exception def __call__(self, *args, **kwargs): raise self.exception def register_serializer(format, serializer_module, serializers=None): """Register a new serializer. Loading @@ -52,12 +64,23 @@ def register_serializer(format, serializer_module, serializers=None): """ if serializers is None and not _serializers: _load_serializers() try: module = importlib.import_module(serializer_module) except ImportError, exc: bad_serializer = BadSerializer(exc) module = type('BadSerializerModule', (object,), { 'Deserializer': bad_serializer, 'Serializer': bad_serializer, }) if serializers is None: _serializers[format] = module else: serializers[format] = module def unregister_serializer(format): "Unregister a given serializer. This is not a thread-safe operation." if not _serializers: Loading
tests/serializers/tests.py +116 −47 Original line number Diff line number Diff line # -*- coding: utf-8 -*- from __future__ import absolute_import, unicode_literals # -*- coding: utf-8 -*- import json from datetime import datetime from xml.dom import minidom try: import yaml HAS_YAML = True except ImportError: HAS_YAML = False from django.conf import settings from django.core import serializers from django.core import management, serializers from django.db import transaction, connection from django.test import TestCase, TransactionTestCase, Approximate from django.utils import six from django.utils.six import StringIO from django.utils import unittest from django.utils import importlib from .models import (Category, Author, Article, AuthorProfile, Actor, Movie, Score, Player, Team) Loading Loading @@ -420,11 +427,71 @@ class JsonSerializerTransactionTestCase(SerializersTransactionTestBase, Transact } }]""" try: import yaml except ImportError: pass else: YAML_IMPORT_ERROR_MESSAGE = r'No module named yaml' class YamlImportModuleMock(object): """Provides a wrapped import_module function to simulate yaml ImportError In order to run tests that verify the behavior of the YAML serializer when run on a system that has yaml installed (like the django CI server), mock import_module, so that it raises an ImportError when the yaml serializer is being imported. The importlib.import_module() call is being made in the serializers.register_serializer(). Refs: #12756 """ def __init__(self): self._import_module = importlib.import_module def import_module(self, module_path): if module_path == serializers.BUILTIN_SERIALIZERS['yaml']: raise ImportError(YAML_IMPORT_ERROR_MESSAGE) return self._import_module(module_path) class NoYamlSerializerTestCase(TestCase): """Not having pyyaml installed provides a misleading error Refs: #12756 """ @classmethod def setUpClass(cls): """Removes imported yaml and stubs importlib.import_module""" super(NoYamlSerializerTestCase, cls).setUpClass() cls._import_module_mock = YamlImportModuleMock() importlib.import_module = cls._import_module_mock.import_module # clear out cached serializers to emulate yaml missing serializers._serializers = {} @classmethod def tearDownClass(cls): """Puts yaml back if necessary""" super(NoYamlSerializerTestCase, cls).tearDownClass() importlib.import_module = cls._import_module_mock._import_module # clear out cached serializers to clean out BadSerializer instances serializers._serializers = {} def test_serializer_pyyaml_error_message(self): """Using yaml serializer without pyyaml raises ImportError""" jane = Author(name="Jane") self.assertRaises(ImportError, serializers.serialize, "yaml", [jane]) def test_deserializer_pyyaml_error_message(self): """Using yaml deserializer without pyyaml raises ImportError""" self.assertRaises(ImportError, serializers.deserialize, "yaml", "") def test_dumpdata_pyyaml_error_message(self): """Calling dumpdata produces an error when yaml package missing""" self.assertRaisesRegexp(management.CommandError, YAML_IMPORT_ERROR_MESSAGE, management.call_command, 'dumpdata', format='yaml') @unittest.skipUnless(HAS_YAML, "No yaml library detected") class YamlSerializerTestCase(SerializersTestBase, TestCase): serializer_name = "yaml" fwd_ref_str = """- fields: Loading Loading @@ -484,6 +551,8 @@ else: ret_list.append(str(field_value)) return ret_list @unittest.skipUnless(HAS_YAML, "No yaml library detected") class YamlSerializerTransactionTestCase(SerializersTransactionTestBase, TransactionTestCase): serializer_name = "yaml" fwd_ref_str = """- fields: Loading
tests/serializers_regress/tests.py +4 −1 Original line number Diff line number Diff line Loading @@ -523,7 +523,10 @@ def streamTest(format, self): else: self.assertEqual(string_data, stream.content.decode('utf-8')) for format in serializers.get_serializer_formats(): for format in [ f for f in serializers.get_serializer_formats() if not isinstance(serializers.get_serializer(f), serializers.BadSerializer) ]: setattr(SerializerTests, 'test_' + format + '_serializer', curry(serializerTest, format)) setattr(SerializerTests, 'test_' + format + '_natural_key_serializer', curry(naturalKeySerializerTest, format)) setattr(SerializerTests, 'test_' + format + '_serializer_fields', curry(fieldsTest, format)) Loading