py3: Update Shared.DC.ZRDB.{sqltest,sqlvar} monkey patches.
This supports both python2 and python3. For python3, this decode() properly arguments returned by string_literal() to have str(), otherwise the query string is an str() (DocumentTemplate) and the arguments are bytes(). In other places, bytes() is used directly but in this case this is not needed and would require monkey patching (at least) DocumentTemplate.
... | @@ -14,84 +14,99 @@ | ... | @@ -14,84 +14,99 @@ |
# dtml-sqlvar patch to convert None to NULL, and deal with DateTime | # dtml-sqlvar patch to convert None to NULL, and deal with DateTime | ||
from Shared.DC.ZRDB.sqlvar import SQLVar | from Shared.DC.ZRDB.sqlvar import * | ||
from Shared.DC.ZRDB import sqlvar | from Shared.DC.ZRDB import sqlvar | ||
from string import atoi,atof | |||
from DateTime import DateTime | from DateTime import DateTime | ||
def SQLVar_render(self, md): | if 1: # For easy diff with original (ZSQLMethods 3.14) | ||
args=self.args | def render(self, md): | ||
t=args['type'] | name = self.__name__ | ||
try: | args = self.args | ||
expr=self.expr | t = args['type'] | ||
if type(expr) is str: v=md[expr] | try: | ||
else: v=expr(md) | expr = self.expr | ||
except Exception: | if isinstance(expr, StringTypes): | ||
if args.get('optional'): | v = md[expr] | ||
else: | |||
v = expr(md) | |||
except Exception: | |||
if 'optional' in args and args['optional']: | |||
return 'null' | |||
if not isinstance(expr, StringTypes): | |||
raise | |||
raise ValueError('Missing input variable, <em>%s</em>' % name) | |||
if v is None: | |||
|
|||
return 'null' | return 'null' | ||
if type(expr) is not str: | |||
raise | |||
raise ValueError('Missing input variable, <em>%s</em>' % self.__name__) | |||
if v is None and args.get('optional'): | if t == 'int': | ||
return 'null' | try: | ||
if isinstance(v, StringTypes): | |||
if v[-1:] == 'L': | |||
v = v[:-1] | |||
int(v) | |||
else: | |||
v = str(int(v)) | |||
except Exception: | |||
if not v and 'optional' in args and args['optional']: | |||
return 'null' | |||
err = 'Invalid integer value for <em>%s</em>' % name | |||
raise ValueError(err) | |||
elif t == 'float': | |||
try: | |||
if isinstance(v, StringTypes): | |||
if v[-1:] == 'L': | |||
v = v[:-1] | |||
float(v) | |||
else: | |||
# ERP5 patch: We use repr that have better precision than str for | |||
# floats (on python2 only) | |||
v = repr(float(v)) | |||
except Exception: | |||
if not v and 'optional' in args and args['optional']: | |||
return 'null' | |||
err = 'Invalid floating-point value for <em>%s</em>' % name | |||
raise ValueError(err) | |||
if t=='int': | elif t.startswith('datetime'): | ||
try: | # For subsecond precision, use 'datetime(N)' MySQL type, | ||
if type(v) is str: | # where N is the number of digits after the decimal point. | ||
if v[-1:]=='L': | n = 0 if t == 'datetime' else int(t[9]) | ||
v=v[:-1] | try: | ||
atoi(v) | v = (v if isinstance(v, DateTime) else DateTime(v)).toZone('UTC') | ||
return v | return "'%s%s'" % (v.ISO(), | ||
return str(int(v)) | ('.%06u' % (v.micros() % 1000000))[:1+n] if n else '') | ||
except Exception: | except Exception: | ||
t = 'integer' | t = 'datetime' | ||
elif t=='float': | |||
try: | elif t=='nb' and not v: | ||
if type(v) is str: | t = 'empty string' | ||
if v[-1:]=='L': | |||
v=v[:-1] | |||
atof(v) | |||
return v | |||
# ERP5 patch, we use repr that have better precision than str for | |||
# floats | |||
return repr(float(v)) | |||
except Exception: | |||
t = 'floating-point' | |||
elif t.startswith('datetime'): | |||
# For subsecond precision, use 'datetime(N)' MySQL type, | |||
# where N is the number of digits after the decimal point. | |||
n = 0 if t == 'datetime' else int(t[9]) | |||
try: | |||
v = (v if isinstance(v, DateTime) else DateTime(v)).toZone('UTC') | |||
return "'%s%s'" % (v.ISO(), | |||
('.%06u' % (v.micros() % 1000000))[:1+n] if n else '') | |||
except Exception: | |||
t = 'datetime' | |||
elif t=='nb' and not v: | |||
t = 'empty string' | |||
else: | |||
v = md.getitem('sql_quote__',0)( | |||
v if isinstance(v, basestring) else str(v)) | |||
#if find(v,"\'") >= 0: v=join(split(v,"\'"),"''") | |||
#v="'%s'" % v | |||
return v | |||
if args.get('optional'): | else: | ||
return 'null' | if not isinstance(v, (str, StringTypes)): | ||
raise ValueError('Invalid %s value for <em>%s</em>: %r' | v = str(v) | ||
% (t, self.__name__, v)) | if not v and t == 'nb': | ||
if 'optional' in args and args['optional']: | |||
return 'null' | |||
else: | |||
err = 'Invalid empty string value for <em>%s</em>' % name | |||
raise ValueError(err) | |||
v = md.getitem('sql_quote__', 0)(v) | |||
# if v.find("\'") >= 0: v="''".join(v.split("\'")) | |||
# v="'%s'" % v | |||
return v | |||
# Patched by yo. datetime is added. | # Patched by yo. datetime is added. | ||
new_valid_types = 'int', 'float', 'string', 'nb', 'datetime' | new_valid_types = 'int', 'float', 'string', 'nb', 'datetime' | ||
new_valid_types += tuple(map('datetime(%s)'.__mod__, xrange(7))) | new_valid_types += tuple(map('datetime(%s)'.__mod__, range(7))) | ||
try: | try: | ||
# BBB | # BBB | ||
from Shared.DC.ZRDB.sqlvar import valid_type | from Shared.DC.ZRDB.sqlvar import valid_type | ||
sqlvar.valid_type = new_valid_types.__contains__ | sqlvar.valid_type = new_valid_types.__contains__ | ||
except ImportError: | except ImportError: | ||
sqlvar.valid_types = new_valid_types | sqlvar.valid_types = new_valid_types | ||
SQLVar.render = SQLVar_render | SQLVar.render = render | ||
SQLVar.__call__ = SQLVar_render | SQLVar.__call__ = render |