Package pyx12 :: Module codes
[hide private]

Source Code for Module pyx12.codes

  1  ###################################################################### 
  2  # Copyright (c) 2001-2005 Kalamazoo Community Mental Health Services, 
  3  #   John Holland <jholland@kazoocmh.org> <john@zoner.org> 
  4  # All rights reserved. 
  5  # 
  6  # This software is licensed as described in the file LICENSE.txt, which 
  7  # you should have received as part of this distribution. 
  8  # 
  9  ###################################################################### 
 10   
 11  #    $Id: codes.py 948 2007-03-22 17:28:37Z johnholland $ 
 12   
 13  """ 
 14  External Codes interface 
 15  """ 
 16   
 17  import os, os.path 
 18  #import sys 
 19  import cPickle 
 20  import libxml2 
 21  import datetime  
 22  #import pdb 
 23  from stat import ST_MTIME 
 24  #from stat import ST_SIZE 
 25   
 26  # Intrapackage imports 
 27  from pyx12.errors import EngineError, XML_Reader_Error 
 28   
29 -class CodesError(Exception):
30 """Class for code modules errors."""
31 32 NodeType = {'element_start': 1, 'element_end': 15, 'attrib': 2, 'text': 3, \ 33 'CData': 4, 'entity_ref': 5, 'entity_decl':6, 'pi': 7, 'comment': 8, \ 34 'doc': 9, 'dtd': 10, 'doc_frag': 11, 'notation': 12} 35 36
37 -class ExternalCodes(object):
38 """ 39 Validates an ID against an external list of codes 40 """ 41
42 - def __init__(self, base_path, exclude=None):
43 """ 44 Initialize the external list of codes 45 @param base_path: path to codes.xml 46 @type base_path: string 47 @param exclude: comma separated string of external codes to ignore 48 @type exclude: string 49 50 @note: self.codes - map of a tuple of two dates and a list of codes 51 {codeset_id: (eff_dte, exp_dte, [code_values])} 52 """ 53 54 self.codes = {} 55 code_file = base_path + '/codes.xml' 56 pickle_file = '%s.%s' % (os.path.splitext(code_file)[0], 'pkl') 57 #id1 = None 58 codeset_id = None 59 base_name = None 60 61 #print exclude 62 if exclude is None: 63 self.exclude_list = [] 64 else: 65 self.exclude_list = exclude.split(',') 66 67 base_level = 0 68 # init the map of codes from the pickled file codes.pkl 69 try: 70 if os.stat(code_file)[ST_MTIME] < os.stat(pickle_file)[ST_MTIME]: 71 self.codes = cPickle.load(open(pickle_file)) 72 else: 73 raise CodesError, "reload codes" 74 except: 75 try: 76 reader = libxml2.newTextReaderFilename(code_file) 77 except: 78 raise EngineError, 'Code file not found: %s' % (code_file) 79 try: 80 ret = reader.Read() 81 if ret == -1: 82 raise XML_Reader_Error, 'Read Error' 83 elif ret == 0: 84 raise XML_Reader_Error, 'End of Map File' 85 while ret == 1: 86 if reader.NodeType() == NodeType['element_start']: 87 cur_name = reader.Name() 88 if cur_name == 'codeset': 89 base_level = reader.Depth() 90 base_name = 'codeset' 91 elif cur_name == 'version': 92 code_list = [] 93 eff_dte = None 94 exp_dte = None 95 base_name = 'version' 96 elif reader.NodeType() == NodeType['element_end']: 97 if reader.Name() == 'codeset': 98 self.codes[codeset_id] = (eff_dte, exp_dte, \ 99 code_list) 100 #del code_list 101 # if reader.Depth() <= base_level: 102 # ret = reader.Read() 103 # if ret == -1: 104 # raise XML_Reader_Error, 'Read Error' 105 # elif ret == 0: 106 # raise XML_Reader_Error, 'End of Map File' 107 # break 108 cur_name = '' 109 elif reader.NodeType() == NodeType['text'] and \ 110 base_level + 1 <= reader.Depth(): 111 if cur_name == 'id': 112 if base_name == 'codeset': 113 codeset_id = reader.Value() 114 #id1 = reader.Value() 115 elif cur_name == 'code': 116 code_list.append(reader.Value()) 117 elif cur_name == 'eff_dte': 118 eff_dte = reader.Value() 119 elif cur_name == 'exp_dte': 120 exp_dte = reader.Value() 121 122 ret = reader.Read() 123 if ret == -1: 124 raise XML_Reader_Error, 'Read Error' 125 elif ret == 0: 126 raise XML_Reader_Error, 'End of Map File' 127 except XML_Reader_Error: 128 pass
129 # try: 130 # cPickle.dump(self.codes, open(pickle_file,'w')) 131 # except: 132 # pass 133 134
135 - def isValid(self, key, code, check_dte=None):
136 """ 137 Is the code in the list identified by key 138 @param key: the external codeset identifier 139 @type key: string 140 @param code: code to be verified 141 @type code: string 142 @param check_dte: YYYYMMDD - Date on which to 143 check code validity. eg 20040514 144 @type check_dte: string 145 @return: True if code is valid, False if not 146 @rtype: boolean 147 """ 148 149 #if not given a key, do not flag an error 150 if not key: 151 raise EngineError, 'bad key %s' % (key) 152 #return True 153 #check the code against the list indexed by key 154 else: 155 if key in self.exclude_list: 156 return True 157 if not self.codes.has_key(key): 158 raise EngineError, 'External Code "%s" is not defined' \ 159 % (key) 160 if check_dte is None: 161 code_list = self.codes[key][2] 162 if code in code_list: 163 return True 164 else: 165 if len(check_dte) != 8: 166 raise EngineError, 'Bad check date %s' & (check_dte) 167 dt_check_dte = datetime.date(int(check_dte[:4]), \ 168 int(check_dte[4:6]), int(check_dte[-2:])) 169 eff_dte = self.codes[key][0] 170 exp_dte = self.codes[key][1] 171 code_list = self.codes[key][2] 172 #print eff_dte, exp_dte 173 #pdb.set_trace() 174 if eff_dte != None: 175 dt_eff_dte = datetime.date(int(eff_dte[:4]), \ 176 int(eff_dte[4:6]), int(eff_dte[-2:])) 177 else: 178 dt_eff_dte = dt_check_dte.min 179 if exp_dte != None: 180 dt_exp_dte = datetime.date(int(exp_dte[:4]), \ 181 int(exp_dte[4:6]), int(exp_dte[-2:])) 182 else: 183 dt_exp_dte = dt_check_dte.max 184 if dt_check_dte >= dt_eff_dte and dt_check_dte <= dt_exp_dte: 185 if code in code_list: 186 return True 187 return False
188
189 - def debug_print(self):
190 for key in self.codes.keys(): 191 print self.codes[key][:10]
192