diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | src/semantic_version/django_fields.py | 74 | ||||
-rw-r--r-- | tests/django_test_app/__init__.py | 0 | ||||
-rw-r--r-- | tests/django_test_app/models.py | 16 | ||||
-rw-r--r-- | tests/test_django.py | 117 |
5 files changed, 208 insertions, 0 deletions
@@ -2,3 +2,4 @@ .*.swp .coverage htmlcov/ +tests/db/ diff --git a/src/semantic_version/django_fields.py b/src/semantic_version/django_fields.py new file mode 100644 index 0000000..17184bc --- /dev/null +++ b/src/semantic_version/django_fields.py @@ -0,0 +1,74 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2012 Raphaël Barrois + +from django.db import models +from django.utils.translation import ugettext_lazy as _ + +from . import base + + +class VersionField(models.CharField): + default_error_messages = { + 'invalid': _(u"Enter a valid version number in X.Y.Z format."), + } + description = _(u"Version") + + __metaclass__ = models.SubfieldBase + + def __init__(self, *args, **kwargs): + self.partial = kwargs.pop('partial', False) + kwargs.setdefault('max_length', 40) + super(VersionField, self).__init__(*args, **kwargs) + + def to_python(self, value): + """Converts any value to a base.SemanticVersion field.""" + if value is None or value == '': + return value + if isinstance(value, base.SemanticVersion): + return value + return base.SemanticVersion(value, partial=self.partial) + + def get_prep_value(self, obj): + return str(obj) + + def get_db_prep_value(self, value, connection, prepared=False): + if not prepared: + value = self.get_prep_value(value) + return value + + def value_to_string(self, obj): + value = self.to_python(self._get_val_from_obj(obj)) + return str(value) + + +class SpecField(models.CharField): + default_error_messages = { + 'invalid': _(u"Enter a valid version number spec in ==X.Y.Z format."), + } + description = _(u"Version specification") + + __metaclass__ = models.SubfieldBase + + def __init__(self, *args, **kwargs): + kwargs.setdefault('max_length', 42) + return super(SpecField, self).__init__(*args, **kwargs) + + def to_python(self, value): + """Converts any value to a base.SemanticVersion field.""" + if value is None or value == '': + return value + if isinstance(value, base.Spec): + return value + return base.Spec(value) + + def get_prep_value(self, obj): + return str(obj) + + def get_db_prep_value(self, value, connection, prepared=False): + if not prepared: + value = self.get_prep_value(value) + return value + + def value_to_string(self, obj): + value = self.to_python(self._get_val_from_obj(obj)) + return str(value) diff --git a/tests/django_test_app/__init__.py b/tests/django_test_app/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/tests/django_test_app/__init__.py diff --git a/tests/django_test_app/models.py b/tests/django_test_app/models.py new file mode 100644 index 0000000..53ed874 --- /dev/null +++ b/tests/django_test_app/models.py @@ -0,0 +1,16 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2012 Raphaël Barrois + +from django.db import models +from semantic_version import django_fields as semver_fields + + +class VersionModel(models.Model): + version = semver_fields.VersionField(verbose_name='my version') + spec = semver_fields.SpecField(verbose_name='my spec') + + +class PartialVersionModel(models.Model): + partial = semver_fields.VersionField(partial=True, verbose_name='partial version') + optional = semver_fields.VersionField(verbose_name='optional version', blank=True, null=True) + optional_spec = semver_fields.SpecField(verbose_name='optional spec', blank=True, null=True) diff --git a/tests/test_django.py b/tests/test_django.py new file mode 100644 index 0000000..72f7964 --- /dev/null +++ b/tests/test_django.py @@ -0,0 +1,117 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# Copyright (c) 2012 Raphaël Barrois + +try: # pragma: no cover + import unittest2 as unittest +except ImportError: # pragma: no cover + import unittest + +import semantic_version + +try: # pragma: no cover + from django.conf import settings + django_loaded = True +except ImportError: # pragma: no cover + django_loaded = False + +if django_loaded: # pragma: no cover + if not settings.configured: + settings.configure( + DATABASES={ + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': 'tests/db/test.sqlite', + } + }, + INSTALLED_APPS=[ + 'tests.django_test_app', + ] + ) + from django_test_app import models + from django.core import serializers + + +@unittest.skipIf(not django_loaded, "Django not installed") +class DjangoFieldTestCase(unittest.TestCase): + def test_version(self): + obj = models.VersionModel(version='0.1.1', spec='>0.1.0') + + self.assertEqual(semantic_version.SemanticVersion('0.1.1'), obj.version) + self.assertEqual(semantic_version.Spec('>0.1.0'), obj.spec) + + alt_obj = models.VersionModel(version=obj.version, spec=obj.spec) + + self.assertEqual(semantic_version.SemanticVersion('0.1.1'), alt_obj.version) + self.assertEqual(semantic_version.Spec('>0.1.0'), alt_obj.spec) + self.assertEqual(obj.spec, alt_obj.spec) + self.assertEqual(obj.version, alt_obj.version) + + def test_invalid_input(self): + self.assertRaises(ValueError, models.VersionModel, version='0.1.1', spec='blah') + self.assertRaises(ValueError, models.VersionModel, version='0.1', spec='>0.1.1') + + def test_partial(self): + obj = models.PartialVersionModel(partial='0.1') + + self.assertEqual(semantic_version.SemanticVersion('0.1', partial=True), obj.partial) + self.assertIsNone(obj.optional) + self.assertIsNone(obj.optional_spec) + + alt_obj = models.PartialVersionModel(partial=obj.partial, optional=obj.optional, + optional_spec=obj.optional_spec) + self.assertEqual(semantic_version.SemanticVersion('0.1', partial=True), alt_obj.partial) + self.assertEqual(obj.partial, alt_obj.partial) + self.assertIsNone(obj.optional) + self.assertIsNone(obj.optional_spec) + + def test_serialization(self): + o1 = models.VersionModel(version='0.1.1', spec='<0.2.4-rc42') + o2 = models.VersionModel(version='0.4.3-rc3+build3', spec='~0.4') + + data = serializers.serialize('json', [o1, o2]) + + obj1, obj2 = serializers.deserialize('json', data) + self.assertEqual(o1, obj1.object) + self.assertEqual(o2, obj2.object) + + def test_serialization_partial(self): + o1 = models.PartialVersionModel(partial='0.1.1', optional='0.2.4-rc42', optional_spec=None) + o2 = models.PartialVersionModel(partial='0.4.3-rc3+build3', optional='', optional_spec='~1.1') + + data = serializers.serialize('json', [o1, o2]) + + obj1, obj2 = serializers.deserialize('json', data) + self.assertEqual(o1, obj1.object) + self.assertEqual(o2, obj2.object) + + +if django_loaded: + from django.test import TestCase + from django.test.simple import DjangoTestSuiteRunner + + class DbInteractingTestCase(TestCase): + + @classmethod + def setUpClass(cls): + cls.old_state = DjangoTestSuiteRunner().setup_databases() + + @classmethod + def tearDownClass(cls): + DjangoTestSuiteRunner().teardown_databases(cls.old_state) + + def test_db_interaction(self): + o1 = models.VersionModel(version='0.1.1', spec='<0.2.4-rc42') + o2 = models.VersionModel(version='0.4.3-rc3+build3', spec='~0.4') + + o1.save() + o2.save() + + obj1 = models.VersionModel.objects.get(pk=o1.pk) + self.assertEqual(o1.version, obj1.version) + + obj2 = models.VersionModel.objects.get(pk=o2.pk) + self.assertEqual(o2.version, obj2.version) + +else: # pragma: no cover + pass |