diff options
author | Rob Austein <sra@hactrn.net> | 2024-04-13 22:19:52 -0400 |
---|---|---|
committer | Rob Austein <sra@hactrn.net> | 2024-04-13 22:19:52 -0400 |
commit | d2c08cfed1d0d545da42a80c6deaf85fcd844cc6 (patch) | |
tree | 00345f34e9caf59fa9d92e1159ec66aa282a4a9e | |
parent | 42e215baae5ba124cf4aa66a79bf68d4fe2e29c1 (diff) |
doc
-rw-r--r-- | README.md | 30 | ||||
-rwxr-xr-x | rfc1982_serial_number.py | 35 |
2 files changed, 64 insertions, 1 deletions
diff --git a/README.md b/README.md new file mode 100644 index 0000000..3537697 --- /dev/null +++ b/README.md @@ -0,0 +1,30 @@ +# Implementation of RFC 1982 Serial Number Arithmetic. + +Run as a program, this takes start and finish serial values and tells +you what intermediate steps (if any) are needed to make the specified +change. + +Used as a module, this implements the `Serial` class and an iterator +which returns the intermediate steps (if any) needed between two +`Serial` values. + +Per the RFC, only two operations are defined on `Serial` objects: +addition and comparision, both within a restricted range specified +by the RFC. + +The default modulus is `2**32`, you can change this by subclassing the +`Serial` and overriding the class's `modulus` variable. The modulus +must be a power of two. + +See RFC 1982 for discussion of the ways in which serial numbers do not +work like normal integers. In particular, note that there's a corner +case in which one can have a pair of serial numbers `I1` and `I2` +where `I1` is neither equal to, less than, nor greater than `I2`. +This is deliberate and is not a bug in the code. See the RFC. + +The `find_intermediate()` iterator takes two `Serial` values `start` +and `finish` and yields the sequence of intermediate values (if any) +needed to step from `start` to `finish`. + +There are also a couple of test programs that use `random.randint()` +to generate test values. Maybe someday I'll recode with `unittest`. diff --git a/rfc1982_serial_number.py b/rfc1982_serial_number.py index e46974a..bb9988c 100755 --- a/rfc1982_serial_number.py +++ b/rfc1982_serial_number.py @@ -1,6 +1,34 @@ #!/usr/bin/env python3 +"""Implementation of RFC 1982 Serial Number Arithmetic. + +Run as a program, this takes start and finish serial values and tells +you what intermediate steps (if any) are needed to make the specified +change. + +Used as a module, this implements the Serial class and an iterator +which returns the intermediate steps (if any) needed between two +Serial values. +""" + class Serial: + """Implementation of RFC 1982 Serial Number Arithmetic. + + Per the RFC, only two operations are defined on Serial objects: + addition and comparision, both within a restricted range specified + by the RFC. + + The default modulus is 2**32, you can change this by subclassing + the Serial class and overriding the class's modulus variable. The + modulus must be a power of two. + + See RFC 1982 for discussion of the ways in which Serial numbers do + not work like normal integers. In particular, note that there's a + corner case in which one can have a pair of Serial numbers I1 and + I2 where I1 is neither equal to, less than, nor greater than I2. + This is deliberate and is not a bug in the code. See the RFC. + + """ modulus = 2 ** 32 @@ -40,6 +68,11 @@ class Serial: return f"{int(self):{len(str(self.modulus))}d}" def find_intermediate(start, finish): + """ + Find the sequence of intermediate values (if any) needed to step + from start to finish + """ + while not (start < finish): # sic: serial numbers are not (quite) integers start += ((Serial.modulus >> 1) - 1) yield start @@ -47,7 +80,7 @@ def find_intermediate(start, finish): def main(): from argparse import ArgumentParser - ap = ArgumentParser() + ap = ArgumentParser(description = __doc__) ap.add_argument("start", type = Serial) ap.add_argument("finish", type = Serial) args = ap.parse_args() |