/usr/lib/python3/dist-packages/stdnum/ismn.py is in python3-stdnum 1.2-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 | # ismn.py - functions for handling ISMNs
#
# Copyright (C) 2010, 2011, 2012, 2013 Arthur de Jong
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301 USA
"""ISMN (International Standard Music Number).
The ISMN (International Standard Music Number) is used to identify sheet
music. This module handles both numbers in the 10-digit 13-digit format.
>>> validate('979-0-3452-4680-5')
'9790345246805'
>>> validate('9790060115615')
'9790060115615'
>>> ismn_type(' M-2306-7118-7')
'ISMN10'
>>> validate('9790060115614')
Traceback (most recent call last):
...
InvalidChecksum: ...
>>> compact(' 979-0-3452-4680-5')
'9790345246805'
>>> format('9790060115615')
'979-0-060-11561-5'
>>> format('M230671187')
'979-0-2306-7118-7'
>>> to_ismn13('M230671187')
'9790230671187'
"""
from stdnum import ean
from stdnum.exceptions import *
from stdnum.util import clean
def compact(number):
"""Convert the ISMN to the minimal representation. This strips the number
of any valid ISMN separators and removes surrounding whitespace."""
return clean(number, ' -.').strip().upper()
def validate(number):
"""Checks to see if the number provided is a valid ISMN (either a legacy
10-digit one or a 13-digit one). This checks the length and the check
bit but does not check if the publisher is known."""
number = compact(number)
if len(number) == 10:
if number[0] != 'M':
raise InvalidFormat()
ean.validate('9790' + number[1:])
else:
ean.validate(number)
return number
def ismn_type(number):
"""Check the type of ISMN number passed and return 'ISMN13', 'ISMN10'
or None (for invalid)."""
try:
number = validate(number)
except ValidationError:
return None
if len(number) == 10:
return 'ISMN10'
else: # len(number) == 13:
return 'ISMN13'
def is_valid(number):
"""Checks to see if the number provided is a valid ISMN (either a legacy
10-digit one or a 13-digit one). This checks the length and the check
bit but does not check if the publisher is known."""
try:
return bool(validate(number))
except ValidationError:
return False
def to_ismn13(number):
"""Convert the number to ISMN13 (EAN) format."""
number = number.strip()
min_number = compact(number)
if len(min_number) == 13:
return number # nothing to do, already 13 digit format
# add prefix and strip the M
if ' ' in number:
return '979 0' + number[1:]
elif '-' in number:
return '979-0' + number[1:]
else:
return '9790' + number[1:]
# these are the ranges allocated to publisher codes
_ranges = (
(3, '000', '099'), (4, '1000', '3999'), (5, '40000', '69999'),
(6, '700000', '899999'), (7, '9000000', '9999999'))
def split(number):
"""Split the specified ISMN into a bookland prefix (979), an ISMN
prefix (0), a publisher element (3 to 7 digits), an item element (2 to
6 digits) and a check digit."""
# clean up number
number = to_ismn13(compact(number))
# rind the correct range and split the number
for length, low, high in _ranges:
if low <= number[4:4 + length] <= high:
return (number[:3], number[3], number[4:4 + length],
number[4 + length:-1], number[-1])
def format(number, separator='-'):
"""Reformat the passed number to the standard format with the
prefixes, the publisher element, the item element and the check-digit
separated by the specified separator. The number is converted to the
13-digit format silently."""
return separator.join(x for x in split(number) if x)
|