3 import os.path as _os_path
6 from django.template.defaultfilters import slugify as _slugify
8 from . import LOG as _LOG
11 CAS_REGEXP = _re.compile('\A[0-9]{2,}[-][0-9]{2}[-][0-9]\Z')
14 def valid_CASno(cas_string):
15 """Validate CAS numbers.
17 Check `N..NN-NN-N` format, and the `checksum digit`_ for valid CAS
21 N_n .. N_4 N_3 - N_2 N_1 - R
26 R = remainder([sum_{i=1}^n i N_i ] / 10 )
29 http://www.cas.org/expertise/cascontent/registry/checkdig.html
31 >>> valid_CASno('107-07-3')
33 >>> valid_CASno('107-08-3')
35 >>> valid_CASno('107-083')
38 Sometimes we don't have a CAS number, or a product will contain
39 secret, non-hazardous ingredients. Therefore we treat the strings
40 `na` and `+secret-non-hazardous` as valid CAS numbers.
44 >>> valid_CASno('+secret-non-hazardous')
47 if cas_string in [None, 'na', '+secret-non-hazardous']:
50 # \A matches the start of the string
51 # \Z matches the end of the string
52 if CAS_REGEXP.match(cas_string) == None:
53 _LOG.debug("invalid CAS# format: '%s'".format(cas_string))
55 # generate check digit
56 casdigs = [int(d) for d in ''.join(cas_string.split('-'))]
57 sumdigs = casdigs[:-1]
59 s = sum([(i+1)*d for i,d in enumerate(sumdigs)])
61 if check == casdigs[-1]:
63 _LOG.debug("invalid CAS# check: '{}' (expected {})".format(
67 def sanitize_path(string):
68 for a,b in [('..', '-')]:
69 string = string.replace(a, b)
70 return _slugify(string)
72 def chemical_upload_to(instance, filename, storage=None):
73 basename,extension = _os_path.splitext(filename)
74 if extension not in ['.pdf', '.html', '.txt']:
75 raise ValueError(filename)
76 return 'msds/{}{}'.format(sanitize_path(instance.abbrev), extension)