import os
import os.path
import time
+import types
def valid_CASno(cas_string, debug=False):
"""
else :
os.mkdir(self.dir)
def basepath(self, id) :
- assert type(id) == type(1), 'id must be an integer, not %s (%s)' \
+ assert type(id) == types.IntType, 'id must be an integer, not %s (%s)' \
% (type(id), str(id))
return os.path.join(self.dir, "%d" % id)
def local_basepath(self, id) : # for symbolic links
- assert type(id) == type(1), 'id must be an integer, not %s (%s)' \
+ assert type(id) == types.IntType, 'id must be an integer, not %s (%s)' \
% (type(id), str(id))
return "./%d" % id
def MIME_ext(self, mime) :
path = os.path.join('./docs/', target_file)
os.system('cp ./docs/main.pdf %s' % path)
return path
- def inventory(self, namewidth='a') :
- "Create a pdf list of all currently owned chemicals."
+ def inventory(self, title=None,
+ namewidth='a', sort_field='db_id',
+ valid_record=lambda r: r['Disposed'] == '') :
+ """Create a pdf list of all maching chemicals. The default is to
+ match all currently owned chemicals. Matching chemicals can be sorted
+ by any field (defaults to 'ID')."""
+ if title == None:
+ title == 'Inventory'
pp = db_pretty_printer(self.db)
active_ids = []
for record in self.db.records() :
- if record['Disposed'] == '' : # get ids for chemicals we still have
+ if valid_record(record) : # get ids for matching chemicals
active_ids.append(record['db_id'])
+ active_ids.sort(cmp=lambda a,b: cmp(self.db.record(a)[sort_field],
+ self.db.record(b)[sort_field]))
active_fields = ['ID', 'Name', 'Amount',
'H', 'F', 'R', 'O', 'M', 'C', 'T']
width = {}
self._latex_safe(record['C']),
self._latex_safe(record['T']))
string += "\\end{longtable}\n"
+ print >> file('./docs/inventory_title.tex', 'w'), title
print >> file('./docs/inventory_data.tex', 'w'), string
## alter main.tex to point to the inventory template.
self._set_main_target('inventory_template')
ofile.close()
-if __name__ == "__main__" :
+if __name__ == '__main__' :
from optparse import OptionParser
- parser = OptionParser(usage="usage: %prog [options]", version="%prog 0.1")
+ parser = OptionParser(usage='usage: %prog [options]', version='%prog 0.1')
- parser.add_option('-f', '--input-file', dest="ifilename",
- help="Read input from FILE (default stdin)",
- type='string', metavar="FILE")
- parser.add_option('-o', '--output-file', dest="ofilename",
- help="Write output to FILE (default stdout)",
- type='string', metavar="FILE")
- parser.add_option('-d', '--delimiter', dest="FS", # field seperator
+ parser.add_option('-f', '--input-file', dest='ifilename',
+ help='Read input from FILE (default stdin)',
+ type='string', metavar='FILE')
+ parser.add_option('-o', '--output-file', dest='ofilename',
+ help='Write output to FILE (default stdout)',
+ type='string', metavar='FILE')
+ parser.add_option('-d', '--delimiter', dest='FS', # field seperator
help="Set field delimiter (default '%default')",
- type='string', metavar="DELIM", default='\t')
- parser.add_option('-p', '--print-fields', dest="print_fields",
- help="Only print certain fields (e.g. 0,3,4,2)",
- type='string', metavar="FIELDS")
- parser.add_option('-r', '--print-records', dest="print_records",
- help="Only print certain records (e.g. 0:3)",
- type='string', metavar="RECORDS")
- parser.add_option('-w', '--column-width', dest="width",
- help="Set column width for short-format output.",
- type='string', metavar="WIDTH")
- parser.add_option('-L', '--long-format', dest="long_format",
- help="Print long format (several lines per record)",
+ type='string', metavar='DELIM', default='\t')
+ parser.add_option('-p', '--print-fields', dest='print_fields',
+ help='Only print certain fields (e.g. 0,3,4,2)',
+ type='string', metavar='FIELDS')
+ parser.add_option('-r', '--print-records', dest='print_records',
+ help='Only print certain records (e.g. 0:3)',
+ type='string', metavar='RECORDS')
+ parser.add_option('-w', '--column-width', dest='width',
+ help='Set column width for short-format output.',
+ type='string', metavar='WIDTH')
+ parser.add_option('-L', '--long-format', dest='long_format',
+ help='Print long format (several lines per record)',
action='store_true', default=False)
- parser.add_option('-l', '--short-format', dest="long_format",
- help="Print short format (default) (one lines per record)",
+ parser.add_option('-l', '--short-format', dest='long_format',
+ help='Print short format (default) (one lines per record)',
action='store_false', default=False)
- parser.add_option('-t', '--test', dest="test",
- help="Run docutils tests on db.py",
- action="store_true", default=False)
- parser.add_option('-V', '--validate', dest="validate",
- help="Validate CAS#s (no other output)",
- action="store_true", default=False)
- parser.add_option('-v', '--verbose', dest="verbose",
- help="Print lots of debugging information",
- action="store_true", default=False)
+ parser.add_option('--valid-record', dest='valid_record',
+ help="Select fields where True == lambda r : eval(EXPRESSION). default '%default'",
+ type='string', metavar='EXPRESSION', default="r['Disposed'] == ''")
+ parser.add_option('--sort-field', dest='sort_field',
+ help="Sort matching records by FIELD (defauly '%default')",
+ type='string', metavar='FIELD', default='db_id')
+ parser.add_option('--pdf-title', dest='pdf_title',
+ help='Override the default PDF title',
+ type='string', metavar='TITLE')
+ parser.add_option('--inventory', dest='inventory',
+ help='Output a PDF inventory of matching records',
+ action='store_true', default=False)
+ parser.add_option('--door-warning', dest='door_warning',
+ help='Output a PDF door warning of matching records',
+ action='store_true', default=False)
+ parser.add_option('-t', '--test', dest='test',
+ help='Run docutils tests on db.py',
+ action='store_true', default=False)
+ parser.add_option('--list-locations', dest='locations',
+ help='List all currently used locations (no other output)',
+ action='store_true', default=False)
+ parser.add_option('-V', '--validate', dest='validate',
+ help='Validate CAS#s (no other output)',
+ action='store_true', default=False)
+ parser.add_option('-A', '--audit', dest='audit',
+ help='Search for troublesome entries (no other output)',
+ action='store_true', default=False)
+ parser.add_option('-v', '--verbose', dest='verbose',
+ help='Print lots of debugging information',
+ action='store_true', default=False)
(options, args) = parser.parse_args()
parser.destroy()
if options.test :
_test()
+ elif options.locations :
+ db = text_db(filename=None)
+ pp = db_pretty_printer(db)
+
+ # read in and parse the file
+ db._parse(ifile.read())
+
+ locations = []
+ for record in db.records():
+ if len(record['Location']) > 0 and record['Location'] not in locations:
+ locations.append(record['Location'])
+ locations.sort()
+ print >> ofile, '\n'.join(locations)
elif options.validate :
db = text_db(filename=None)
pp = db_pretty_printer(db)
if not valid :
print >> ofile, "in record %s: %s" % (record['ID'], record['Name'])
#pp.full_record_string(record)
+ elif options.audit :
+ db = text_db(filename=None)
+ pp = db_pretty_printer(db)
+
+ # read in and parse the file
+ db._parse(ifile.read())
+
+ for record in db.records():
+ # check for extra spaces
+ for key,value in record.items():
+ if type(value) in types.StringTypes and value.strip() != value:
+ print >> ofile, "Extra whitespace for %s - %s field %s : '%s'" % (record['ID'], record['Name'], key, value)
+ # make sure we know the location of all current chemicals
+ if len(record['Disposed']) == 0 and len(record['Location']) == 0:
+ print >> ofile, "Misplaced record: %s - %s" % (record['ID'], record['Name'])
+ elif options.inventory:
+ db = text_db(filename=None)
+ pp = db_pretty_printer(db)
+ # read in and parse the file
+ db._parse(ifile.read())
+
+ dgen = docgen(db)
+ def valid_record(r) :
+ return eval(options.valid_record, # expression
+ {'__builtins__':None}, # globals
+ {'r':r}) # locals
+ path = dgen.inventory(title=options.pdf_title,
+ namewidth=40,
+ sort_field=options.sort_field,
+ valid_record=valid_record)
+ print >> ofile, '\n', path
+ elif options.door_warning:
+ db = text_db(filename=None)
+ pp = db_pretty_printer(db)
+
+ # read in and parse the file
+ db._parse(ifile.read())
+
+ dgen = docgen(db)
+ def valid_record(r) :
+ return eval(options.valid_record, # expression
+ {'__builtins__':None}, # globals
+ {'r':r}) # locals
+ path = dgen.door_warning(valid_record=valid_record)
+ print >> ofile, '\n', path
else :
db = text_db(filename=None)
string = pp.full_record_string_id(id)
else :
# pythonize the width option
- if (options.width != None
- and options.width != 'a'
- and len(options.width.split(':')) == 1
- ) :
+ if options.width == None or options.width == 'a':
+ width = options.width
+ elif len(options.width.split(':')) == 1 :
width = int(options.width)
elif len(options.width.split(':')) > 1 :
width = {}