Permalink
Browse files

Created "madebidderids" command and removed from mod11codes. Added un…

…ittests for this.
  • Loading branch information...
1 parent 2c87c0a commit fe6e1f57480cf6d3678e292541ef3c6b2d28c1bb @chmarr committed Mar 18, 2013
Showing with 78 additions and 83 deletions.
  1. +45 −0 artshow/management/commands/makebidderids.py
  2. +12 −83 artshow/mod11codes.py
  3. +21 −0 artshow/tests.py
@@ -0,0 +1,45 @@
+from optparse import make_option
+
+from django.core.management.base import BaseCommand, CommandError
+
+from artshow.mod11codes import make_check
+
+
+class Command(BaseCommand):
+ args = "firstcode numcodes"
+ help = "Generate a list of valid BidderID codes"
+ option_list = BaseCommand.option_list + (
+ make_option("--digits", type="int", default=3, help="pad to this many digits [%default]"),
+ make_option("--allow-x", action="store_true", default=False, help="allow X checkdigit"),
+ make_option("--prefix", type="str", default="", help="prefix characters [%default]"),
+ make_option("--suffix", type="str", default="", help="suffix characters [%default]"),
+ make_option("--offset", type="int", default=0, help="offset checkdigit [%default]"),
+ )
+
+ def handle(self, *args, **options):
+ try:
+ first_code, num_codes = args
+ except ValueError:
+ raise CommandError("incorrect number of parameters")
+ try:
+ first_code = int(first_code)
+ except ValueError:
+ raise CommandError("firstcode is not an integer")
+ try:
+ num_codes = int(num_codes)
+ except ValueError:
+ raise CommandError("numcodes is not an integer")
+ value = first_code
+ digits = options['digits']
+ allow_x = options['allow_x']
+ prefix = options['prefix']
+ suffix = options['suffix']
+ offset = options['offset']
+ while num_codes > 0:
+ code = "%0*d" % (digits, value)
+ value += 1
+ check = make_check(code,offset=offset)
+ if check=="X" and not allow_x:
+ continue
+ print prefix + code + check + suffix
+ num_codes -= 1
View
@@ -3,101 +3,30 @@
# Copyright (C) 2009, 2010 Chris Cogdon
# See file COPYING for licence details
-import optparse
-import sys
-
+# The first element must be 1 for check-digit calculation to be correct
default_factors = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
class CheckDigitError(ValueError):
pass
-def make_check(s, check10="X", factors=default_factors):
- tally = 0
+def make_check(s, check10="X", factors=default_factors, offset=0):
+ tally = -offset
for i in range(len(s)):
tally += int(s[-1 - i]) * factors[(1 + i) % len(factors)]
check = (-tally) % 11
- if check == 10:
- return check10
- else:
- return str(check)
+ return str(check) if check != 10 else check10
-def check(s, check10="X", start=0, end=None, factors=default_factors):
- s2 = s[start:end]
- tally = 0
- for i in range(len(s2)):
- c = s2[-1 - i]
- c = (c == check10) and 10 or int(c)
+def check(s, check10="X", factors=default_factors, offset=0):
+ tally = -offset
+ for i in range(len(s)):
+ c = s[-1 - i]
+ try:
+ c = int(c) if c != check10 else 10
+ except ValueError:
+ raise CheckDigitError("invalid character: %s" % c)
tally += c * factors[i % len(factors)]
if tally % 11 != 0:
raise CheckDigitError("check digit failed for " + s)
-
-
-def make_codes(num, first=0, count=1, min_digits=3, check10=False, factors=default_factors):
- i = 0
- bare_code = first
- while i < num:
- bare_code_str = "%0*d" % (min_digits, bare_code)
- bare_code += 1
- check = make_check(bare_code_str, factors=factors)
- if check == "X":
- if not check10:
- continue
- check = check10
- for c in range(count):
- yield bare_code_str + check
- i += 1
-
-
-def _get_options():
- # noinspection PyUnusedLocal
- def factors_callback(option, opt, value, parser):
- try:
- factors = value.split(",")
- factors = [int(x) for x in factors]
- parser.values.factors = factors
- except ValueError, x:
- raise optparse.OptionValueError(str(x))
-
- parser = optparse.OptionParser()
- parser.add_option("-c", "--count", type="int", default=1)
- parser.add_option("--min_digits", type="int", default=3)
- parser.add_option("--check10", type="str", default="")
- parser.add_option("--prefix", type="str", default="")
- parser.add_option("--suffix", type="str", default="")
- parser.add_option("--factors", type="str", action="callback", callback=factors_callback, default=default_factors)
- parser.add_option("--check", action="store_true", default=False)
- opts, args = parser.parse_args()
-
- if opts.check:
- opts.sample = args[0]
- else:
- opts.num = int(args[0])
- try:
- opts.first = int(args[1])
- except IndexError:
- opts.first = 0
-
- return opts
-
-
-def _main():
- opts = _get_options()
- if opts.check:
- try:
- check(opts.sample, check10=opts.check10, start=len(opts.prefix), end=len(opts.suffix) or None,
- factors=opts.factors)
- except ValueError, x:
- print >> sys.stderr, x
- raise SystemExit(1)
- else:
- for c in make_codes(opts.num, opts.first, opts.count, min_digits=opts.min_digits, check10=opts.check10,
- factors=opts.factors):
- print opts.prefix + c + opts.suffix
-
-
-if __name__ == "__main__":
- _main()
-
View
@@ -1,6 +1,7 @@
from django.test import TestCase
from artshow.utils import artshow_settings
from django.conf import settings
+from artshow import mod11codes
class AttributeFilterTest (TestCase):
@@ -15,3 +16,23 @@ def get_secret_key():
self.assertRaisesRegexp(AttributeError,
"AttributeFilter blocked access to 'SECRET_KEY'.*",
get_secret_key)
+
+
+class Mod11Test (TestCase):
+ def test_generation(self):
+ self.assertEqual(mod11codes.make_check("196"), "1")
+ self.assertEqual(mod11codes.make_check("197"), "X")
+ self.assertEqual(mod11codes.make_check("197", check10="@"), "@")
+ self.assertEqual(mod11codes.make_check("197", offset=4), "3")
+
+ def test_check_passes(self):
+ self.assertIsNone(mod11codes.check("1961"))
+ self.assertIsNone(mod11codes.check("197X"))
+ self.assertIsNone(mod11codes.check("197@", check10="@"))
+ self.assertIsNone(mod11codes.check("1973", offset=4))
+
+ def test_check_failures(self):
+ self.assertRaises(mod11codes.CheckDigitError, mod11codes.check, "196X")
+ self.assertRaises(mod11codes.CheckDigitError, mod11codes.check, "1970")
+ self.assertRaises(mod11codes.CheckDigitError, mod11codes.check, "197X", check10="@")
+ self.assertRaises(mod11codes.CheckDigitError, mod11codes.check, "197X", offset=4)

0 comments on commit fe6e1f5

Please sign in to comment.