Revision 3553
Added by Aaron Marcuse-Kubitza over 12 years ago
schemas/py_functions.sql | ||
---|---|---|
80 | 80 |
import datetime |
81 | 81 |
import dateutil.tz |
82 | 82 |
|
83 |
def e_str(e): |
|
84 |
msg = e.__class__.__name__+': '+e.args[0] |
|
85 |
return msg.rstrip() |
|
83 |
def e_msg(e): return e.args[0].rstrip() |
|
86 | 84 |
|
87 |
class ExceptionWithCause(Exception): |
|
88 |
def __init__(self, msg, cause): |
|
89 |
msg += '\nDETAIL: '+e_str(cause) |
|
90 |
Exception.__init__(self, msg) |
|
85 |
def e_str(e): return e.__class__.__name__+': '+e_msg(e) |
|
91 | 86 |
|
87 |
def raise_invalid_value(cause, value): |
|
88 |
raise ValueError('invalid input value: "'+str(value)+'"\nDETAIL: ' |
|
89 |
+e_str(cause)) |
|
90 |
|
|
92 | 91 |
utc = dateutil.tz.tzutc() |
93 | 92 |
|
94 | 93 |
def naive2utc(datetime_): |
... | ... | |
104 | 103 |
import dateutil.parser |
105 | 104 |
return dateutil.parser.parse(str_, default=default) |
106 | 105 |
|
107 |
class FormatException(ExceptionWithCause): |
|
108 |
def __init__(self, cause, value=None): |
|
109 |
msg = 'invalid input value' |
|
110 |
if value != None: msg += ': "'+str(value)+'"' |
|
111 |
ExceptionWithCause.__init__(self, msg, cause) |
|
112 |
|
|
113 | 106 |
if date != None: |
114 | 107 |
str_ = date |
115 | 108 |
try: year = float(str_) |
116 | 109 |
except ValueError: |
117 | 110 |
try: date = strtotime(str_) |
118 | 111 |
except ImportError: return str_ |
119 |
except ValueError, e: raise FormatException(e, str_)
|
|
112 |
except ValueError, e: raise_invalid_value(e, str_)
|
|
120 | 113 |
else: date = (datetime.date(int(year), 1, 1) + |
121 | 114 |
datetime.timedelta(round((year % 1.)*365))) |
122 | 115 |
else: |
123 | 116 |
# Year is required |
124 | 117 |
if year == None: |
125 | 118 |
if month == None and day == None: return None # entire date is empty |
126 |
else: raise FormatException(ValueError('Year is required')) |
|
119 |
else: raise AssertionError( |
|
120 |
'null value in column "year" violates not-null constraint') |
|
127 | 121 |
|
128 | 122 |
# Convert month name to number |
129 | 123 |
if month != None and not month.isdigit(): # month is name |
130 |
try: month = str(strtotime(month).month) |
|
131 |
except ValueError, e: raise FormatException(e) |
|
124 |
month = str(strtotime(month).month) |
|
132 | 125 |
|
133 | 126 |
if month == None: month = 1 |
134 | 127 |
if day == None: day = 1 |
... | ... | |
138 | 131 |
try: |
139 | 132 |
date = datetime.date(year, month, day) |
140 | 133 |
break |
141 |
except ValueError, e: |
|
142 |
if try_num > 0: raise FormatException(e) |
|
143 |
# exception still raised after retry |
|
144 |
msg = e_str(e) |
|
134 |
except ValueError: |
|
135 |
if try_num > 0: raise # exception still raised after retry |
|
136 |
msg = e_msg(e) |
|
145 | 137 |
if msg == 'month must be in 1..12': # try swapping month and day |
146 | 138 |
month, day = day, month |
147 |
else: raise FormatException(e)
|
|
139 |
else: raise |
|
148 | 140 |
|
149 | 141 |
return str(date) |
150 | 142 |
$$; |
Also available in: Unified diff
schemas/py_functions.sql: _date(): Raise (or pass through) ValueErrors directly instead of wrapping them in FormatExceptions, to simplify the code. This will also enable later translation of ValueErrors to data_exceptions. When year is required and missing, output a parsable 'null value in column year violates not-null constraint' error.