Commit c9479eaf authored by Arnaud Fontaine's avatar Arnaud Fontaine

zope4py3: 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.
parent b9322fae
...@@ -18,53 +18,61 @@ from DateTime import DateTime ...@@ -18,53 +18,61 @@ from DateTime import DateTime
list_type_list = list, tuple, set, frozenset, dict list_type_list = list, tuple, set, frozenset, dict
if 1: # For easy diff with original if 1: # For easy diff with original (ZSQLMethods 3.14)
def render(self, md): def render(self, md):
name=self.__name__ name = self.__name__
t=self.type t = self.type
args=self.args args = self.args
try: try:
expr=self.expr expr = self.expr
if type(expr) is type(''): if isinstance(expr, StringTypes):
v=md[expr] v = md[expr]
else: else:
v=expr(md) v = expr(md)
except (KeyError, NameError): except (KeyError, NameError):
if 'optional' in args and args['optional']: if 'optional' in args and args['optional']:
return '' return ''
raise ValueError('Missing input variable, <em>%s</em>' % name) raise ValueError('Missing input variable, <em>%s</em>' % name)
# PATCH: use isinstance instead of type comparison, to allow
# subclassing.
if isinstance(v, list_type_list): if isinstance(v, list_type_list):
if len(v) > 1 and not self.multiple: if len(v) > 1 and not self.multiple:
raise ValueError( msg = 'multiple values are not allowed for <em>%s</em>' % name
'multiple values are not allowed for <em>%s</em>' raise ValueError(msg)
% name) else:
else: v=[v] v = [v]
vs=[] vs = []
for v in v: for v in v:
if not v and isinstance(v, str) and t != 'string': continue if not v and isinstance(v, StringTypes) and t != 'string':
if t=='int': continue
if t == 'int':
try: try:
if isinstance(v, str): if isinstance(v, StringTypes):
if v[-1:]=='L': if six.PY3 and isinstance(v, bytes):
v=v[:-1] v = v.decode(self.encoding or 'UTF-8')
if v[-1:] == 'L':
v = v[:-1]
int(v) int(v)
else: v=str(int(v)) else:
except ValueError: v = str(int(v))
raise ValueError( except (TypeError, ValueError):
'Invalid integer value for <em>%s</em>' % name) msg = 'Invalid integer value for <em>%s</em>' % name
elif t=='float': raise ValueError(msg)
if not v and isinstance(v, str): continue elif t == 'float':
if not v and isinstance(v, StringTypes):
continue
try: try:
if isinstance(v, str): float(v) if six.PY3 and isinstance(v, bytes):
else: v=str(float(v)) v = v.decode(self.encoding or 'UTF-8')
except ValueError: if isinstance(v, StringTypes):
raise ValueError( float(v)
'Invalid floating-point value for <em>%s</em>' % name) else:
v = str(float(v))
except (TypeError, ValueError):
msg = 'Invalid floating-point value for <em>%s</em>' % name
raise ValueError(msg)
elif t.startswith('datetime'): elif t.startswith('datetime'):
# For subsecond precision, use 'datetime(N)' MySQL type, # For subsecond precision, use 'datetime(N)' MySQL type,
# where N is the number of digits after the decimal point. # where N is the number of digits after the decimal point.
...@@ -74,35 +82,41 @@ if 1: # For easy diff with original ...@@ -74,35 +82,41 @@ if 1: # For easy diff with original
('.%06u' % (v.micros() % 1000000))[:1+n] if n else '') ('.%06u' % (v.micros() % 1000000))[:1+n] if n else '')
else: else:
if not isinstance(v, str): if not isinstance(v, StringTypes):
v = str(v) v = str(v)
v=md.getitem('sql_quote__',0)(v) if isinstance(v, six.binary_type):
#if find(v,"\'") >= 0: v=join(split(v,"\'"),"''") v = v.decode('utf-8')
#v="'%s'" % v # The call to sql_quote__ can return something that is not
# a native string anymore!
v = md.getitem('sql_quote__', 0)(v)
if isinstance(v, six.binary_type):
v = v.decode('utf-8')
# if v.find("\'") >= 0: v="''".(v.split("\'"))
# v="'%s'" % v
vs.append(v) vs.append(v)
if not vs and t=='nb': if not vs and t == 'nb':
if 'optional' in args and args['optional']: if 'optional' in args and args['optional']:
return '' return ''
else: else:
raise ValueError( err = 'Invalid empty string value for <em>%s</em>' % name
'Invalid empty string value for <em>%s</em>' % name) raise ValueError(err)
if not vs: if not vs:
if self.optional: return '' if self.optional:
raise ValueError( return ''
'No input was provided for <em>%s</em>' % name) raise ValueError('No input was provided for <em>%s</em>' % name)
if len(vs) > 1: if len(vs) > 1:
vs = ', '.join(map(str, vs)) vs = ', '.join(map(str, vs))
if self.op == '<>': if self.op == '<>':
## Do the equivalent of 'not-equal' for a list, # Do the equivalent of 'not-equal' for a list,
## "a not in (b,c)" # "a not in (b,c)"
return "%s not in (%s)" % (self.column, vs) return '%s not in (%s)' % (self.column, vs)
else: else:
## "a in (b,c)" # "a in (b,c)"
return "%s in (%s)" % (self.column, vs) return '%s in (%s)' % (self.column, vs)
return "%s %s %s" % (self.column, self.op, vs[0]) return '%s %s %s' % (self.column, self.op, vs[0])
SQLTest.render = SQLTest.__call__ = render SQLTest.render = SQLTest.__call__ = render
from builtins import range from builtins import range
......
...@@ -16,52 +16,61 @@ ...@@ -16,52 +16,61 @@
from builtins import str from builtins import str
from builtins import map from builtins import map
#from builtins import str
from builtins import range from builtins import range
from past.builtins import basestring from Shared.DC.ZRDB.sqlvar import *
from Shared.DC.ZRDB.sqlvar import SQLVar
from Shared.DC.ZRDB import sqlvar from Shared.DC.ZRDB import sqlvar
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__
args = self.args
t = args['type']
try: try:
expr=self.expr expr = self.expr
if isinstance(expr, basestring): v=md[expr] if isinstance(expr, StringTypes):
else: v=expr(md) v = md[expr]
else:
v = expr(md)
except Exception: except Exception:
if args.get('optional'): if 'optional' in args and args['optional']:
return 'null' return 'null'
if not isinstance(expr, basestring): if not isinstance(expr, StringTypes):
raise raise
raise ValueError('Missing input variable, <em>%s</em>' % self.__name__) raise ValueError('Missing input variable, <em>%s</em>' % name)
if v is None and args.get('optional'): if v is None:
return 'null' return 'null'
if t=='int': if t == 'int':
try: try:
if isinstance(v, basestring): if isinstance(v, StringTypes):
if v[-1:]=='L': if v[-1:] == 'L':
v=v[:-1] v = v[:-1]
int(v) int(v)
return v else:
return str(int(v)) v = str(int(v))
except Exception: except Exception:
t = 'integer' if not v and 'optional' in args and args['optional']:
elif t=='float': return 'null'
err = 'Invalid integer value for <em>%s</em>' % name
raise ValueError(err)
elif t == 'float':
try: try:
if isinstance(v, basestring): if isinstance(v, StringTypes):
if v[-1:]=='L': if v[-1:] == 'L':
v=v[:-1] v = v[:-1]
float(v) float(v)
return v else:
# ERP5 patch, we use repr that have better precision than str for # ERP5 patch: We use repr that have better precision than str for
# floats # floats (on python2 only)
return repr(float(v)) v = repr(float(v))
except Exception: except Exception:
t = 'floating-point' 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)
elif t.startswith('datetime'): elif t.startswith('datetime'):
# For subsecond precision, use 'datetime(N)' MySQL type, # For subsecond precision, use 'datetime(N)' MySQL type,
# where N is the number of digits after the decimal point. # where N is the number of digits after the decimal point.
...@@ -72,19 +81,25 @@ def SQLVar_render(self, md): ...@@ -72,19 +81,25 @@ def SQLVar_render(self, md):
('.%06u' % (v.micros() % 1000000))[:1+n] if n else '') ('.%06u' % (v.micros() % 1000000))[:1+n] if n else '')
except Exception: except Exception:
t = 'datetime' t = 'datetime'
elif t=='nb' and not v: elif t=='nb' and not v:
t = 'empty string' 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:
if not isinstance(v, (str, StringTypes)):
v = str(v)
if not v and t == 'nb':
if 'optional' in args and args['optional']:
return 'null' return 'null'
raise ValueError('Invalid %s value for <em>%s</em>: %r' else:
% (t, self.__name__, v)) 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'
...@@ -97,5 +112,5 @@ except ImportError: ...@@ -97,5 +112,5 @@ 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
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment