Add django fields for SemanticVersion and Spec.
Signed-off-by: Raphaël Barrois <raphael.barrois@polyconseil.fr>
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -2,3 +2,4 @@
|
||||
.*.swp
|
||||
.coverage
|
||||
htmlcov/
|
||||
tests/db/
|
||||
|
||||
74
src/semantic_version/django_fields.py
Normal file
74
src/semantic_version/django_fields.py
Normal file
@@ -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)
|
||||
0
tests/django_test_app/__init__.py
Normal file
0
tests/django_test_app/__init__.py
Normal file
16
tests/django_test_app/models.py
Normal file
16
tests/django_test_app/models.py
Normal file
@@ -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)
|
||||
117
tests/test_django.py
Normal file
117
tests/test_django.py
Normal file
@@ -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
|
||||
Reference in New Issue
Block a user