Skip to content
This repository has been archived by the owner on Jun 3, 2024. It is now read-only.

Little improvements #6

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
.DS_Store
*.pyc
*.pyc
*.egg-info
49 changes: 49 additions & 0 deletions run_tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#!/usr/bin/env python

import sys

try:
import django
except ImportError:
print("Error: missing test dependency:")
print(" django library is needed to run test suite")
print(" you can install it with 'pip install django'")
sys.exit(1)

from django.conf import settings


def main():
# Dynamically configure the Django settings with the minimum necessary to
# get Django running tests.

settings.configure(
INSTALLED_APPS=[
'versionfield',
],
DATABASE_ENGINE='django.db.backends.sqlite3',
DATABASES={
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': ':memory:',
}
},
DEBUG=True,
TEMPLATE_DEBUG=True,
)

if django.VERSION[:2] >= (1, 7):
django.setup()

apps = ['versionfield']

from django.test.utils import get_runner

DjangoTestRunner = get_runner(settings)

failures = DjangoTestRunner(verbosity=2, interactive=True).run_tests(apps)
sys.exit(failures)


if __name__ == '__main__':
main()
21 changes: 12 additions & 9 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,24 @@
from setuptools import setup, find_packages
except ImportError:
import ez_setup

ez_setup.use_setuptools()
from setuptools import setup, find_packages

import os

setup(
name = "django-versionfield",
version = "0.3.2",
url = 'https://github.com/mindsnacks/django-versionfield',
license = 'BSD',
description = "A DB Independent Custom Django Field for storing Version numbers for fast indexing",
author = 'Tom Hoddes',
packages = find_packages(),
include_package_data = True,
classifiers = [
name="django-versionfield",
version="0.3.2",
url='https://github.com/mindsnacks/django-versionfield',
license='BSD',
description="A DB Independent Custom Django Field for storing Version numbers for fast indexing",
author='Tom Hoddes',
packages=find_packages(),
include_package_data=True,
tests_require=['Django'],
test_suite='run_tests.main',
classifiers=[
'Development Status :: 3 - Alpha',
'Framework :: Django',
'Intended Audience :: Developers',
Expand Down
94 changes: 47 additions & 47 deletions versionfield/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,65 +5,65 @@
import forms


class VersionField(models.PositiveIntegerField):
"""
A Field where version numbers are input/output as strings (e.g. 3.0.1)
but stored in the db as converted integers for fast indexing
"""
description = "A version number (e.g. 3.0.1)"
class VersionField(models.BigIntegerField):
"""
A Field where version numbers are input/output as strings (e.g. 3.0.1)
but stored in the db as converted integers for fast indexing
"""
description = "A version number (e.g. 3.0.1)"

__metaclass__ = models.SubfieldBase
__metaclass__ = models.SubfieldBase

def __init__(self, number_bits=DEFAULT_NUMBER_BITS, *args, **kwargs):
self.number_bits = number_bits
super(VersionField, self).__init__(*args, **kwargs)
def __init__(self, number_bits=DEFAULT_NUMBER_BITS, *args, **kwargs):
self.number_bits = number_bits
super(VersionField, self).__init__(*args, **kwargs)

def to_python(self,value):
if isinstance(value, Version):
return value
def to_python(self, value):
if isinstance(value, Version):
return int(value)

if isinstance(value,basestring):
return Version(value,self.number_bits)
if isinstance(value, basestring):
return Version(value, self.number_bits)

if value is None:
return None
if value is None:
return None

return Version(convert_version_int_to_string(value,self.number_bits),self.number_bits)
return Version(convert_version_int_to_string(value, self.number_bits), self.number_bits)

def get_prep_value(self,value):
if isinstance(value,basestring):
return int(Version(value,self.number_bits))
def get_prep_value(self, value):
if isinstance(value, basestring):
return int(Version(value, self.number_bits))

if value is None:
return None
if value is None:
return None

return int(value)
return int(value)

def formfield(self, **kwargs):
defaults = {
'form_class': forms.VersionField,
'number_bits': self.number_bits
}
defaults.update(kwargs)
return super(VersionField, self).formfield(**defaults)

def __unicode__(self, value):
return unicode(value)
def formfield(self, **kwargs):
defaults = {
'form_class': forms.VersionField,
'number_bits': self.number_bits
}
defaults.update(kwargs)
return super(VersionField, self).formfield(**defaults)

def __unicode__(self, value):
return unicode(value)


try:
from south.modelsinspector import add_introspection_rules
rules = [
(
(VersionField,),
[],
{
"number_bits": ["number_bits", {"default": DEFAULT_NUMBER_BITS}],
},
)
]
add_introspection_rules(rules, ["^versionfield"])
from south.modelsinspector import add_introspection_rules

rules = [
(
(VersionField,),
[],
{
"number_bits": ["number_bits", {"default": DEFAULT_NUMBER_BITS}],
},
)
]
add_introspection_rules(rules, ["^versionfield"])
except ImportError:
# looks like we aren't using south
pass
# looks like we aren't using south
pass
2 changes: 1 addition & 1 deletion versionfield/constants.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
DEFAULT_NUMBER_BITS = (8,8,16)
DEFAULT_NUMBER_BITS = (8, 8, 16)
35 changes: 22 additions & 13 deletions versionfield/forms.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,30 @@
from django import forms
from django.forms.widgets import TextInput
from version import Version
from constants import DEFAULT_NUMBER_BITS
from utils import convert_version_string_to_int
from utils import convert_version_int_to_string


class VersionField(forms.IntegerField):
def __init__(self,number_bits=DEFAULT_NUMBER_BITS,**kwargs):
self.number_bits = number_bits
return super(VersionField, self).__init__(**kwargs)
widget = TextInput

def __init__(self, number_bits=DEFAULT_NUMBER_BITS, **kwargs):
self.number_bits = number_bits
return super(VersionField, self).__init__(**kwargs)

def to_python(self, value):
"""
Verifies that value can be converted to a Version object
"""
if not value:
return None

def to_python(self,value):
"""
Verifies that value can be converted to a Version object
"""
if not value:
return None
if isinstance(value, basestring):
return int(Version(value, self.number_bits))

if isinstance(value,basestring):
return Version(value,self.number_bits)
return Version(convert_version_int_to_string(value, self.number_bits), self.number_bits)

return Version(convert_version_int_to_string(value,self.number_bits),self.number_bits)
def widget_attrs(self, widget):
attrs = super(VersionField, self).widget_attrs(widget)
attrs['pattern'] = '^' + (r'(\d+\.)?' * (len(self.number_bits) - 1)) + r'(\*|\d+)$'
return attrs
57 changes: 1 addition & 56 deletions versionfield/tests/__init__.py
Original file line number Diff line number Diff line change
@@ -1,56 +1 @@
from django.test import TestCase
from django.db import models
from .. import VersionField

class DummyModel(models.Model):
version = VersionField()

class VersionFieldTest(TestCase):
def setUp(self):
DummyModel.objects.create(version="0.1")
DummyModel.objects.create(version="1.0")
DummyModel.objects.create(version="1.0.1")

def test_get_by_exact_version(self):
thing = DummyModel.objects.get(version="0.1")
self.assertEqual(thing.version,"0.1")
self.assertEqual(thing.version,"0.1.0")

def test_filter_by_greater_than_version(self):
things = DummyModel.objects.filter(version__gt="0.1")
self.assertEqual(len(things),2)

things = DummyModel.objects.filter(version__gt="1.0")
self.assertEqual(len(things),1)

things = DummyModel.objects.filter(version__gt="1.0.1")
self.assertEqual(len(things),0)

def test_filter_by_less_than_version(self):
things = DummyModel.objects.filter(version__lt="0.1")
self.assertEqual(len(things),0)

things = DummyModel.objects.filter(version__lt="1.0")
self.assertEqual(len(things),1)

things = DummyModel.objects.filter(version__lt="1.0.1")
self.assertEqual(len(things),2)

def test_overflow_number(self):
error_occured = False
try:
overflow = DummyModel.objects.create(version="1.999.1")
except ValueError:
error_occured = True
self.assertTrue(error_occured)

class DummyModelCustomBit(models.Model):
version = VersionField(number_bits=(8,16,8))

class VersionFieldCustomBitsTest(TestCase):
def setUp(self):
DummyModelCustomBit.objects.create(version="1.999.1")

def test_get_by_exact_version(self):
thing = DummyModelCustomBit.objects.get(version="1.999.1")
self.assertEqual(thing.version,"1.999.1")
# coding: utf8
60 changes: 60 additions & 0 deletions versionfield/tests/test_versionfield.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
from django.test import TestCase
from django.db import models
from .. import VersionField


class DummyModel(models.Model):
version = VersionField()


class VersionFieldTest(TestCase):
def setUp(self):
DummyModel.objects.create(version="0.1")
DummyModel.objects.create(version="1.0")
DummyModel.objects.create(version="1.0.1")

def test_get_by_exact_version(self):
thing = DummyModel.objects.get(version="0.1")
self.assertEqual(thing.version, "0.1")
self.assertEqual(thing.version, "0.1.0")

def test_filter_by_greater_than_version(self):
things = DummyModel.objects.filter(version__gt="0.1")
self.assertEqual(len(things), 2)

things = DummyModel.objects.filter(version__gt="1.0")
self.assertEqual(len(things), 1)

things = DummyModel.objects.filter(version__gt="1.0.1")
self.assertEqual(len(things), 0)

def test_filter_by_less_than_version(self):
things = DummyModel.objects.filter(version__lt="0.1")
self.assertEqual(len(things), 0)

things = DummyModel.objects.filter(version__lt="1.0")
self.assertEqual(len(things), 1)

things = DummyModel.objects.filter(version__lt="1.0.1")
self.assertEqual(len(things), 2)

def test_overflow_number(self):
error_occured = False
try:
overflow = DummyModel.objects.create(version="1.999.1")
except ValueError:
error_occured = True
self.assertTrue(error_occured)


class DummyModelCustomBit(models.Model):
version = VersionField(number_bits=(8, 16, 8))


class VersionFieldCustomBitsTest(TestCase):
def setUp(self):
DummyModelCustomBit.objects.create(version="1.999.1")

def test_get_by_exact_version(self):
thing = DummyModelCustomBit.objects.get(version="1.999.1")
self.assertEqual(thing.version, "1.999.1")
Loading