def escape(data, toplevel=True): if data is None: return "" if isinstance(data, bytes): return "\\x%s" % binascii.hexlify(data).decode("ascii") elif isinstance(data, str): return '"%s"' % data.replace('"', '""') elif isinstance(data, datetime.datetime): # We escape twice to make sure the string generated by # isoformat gets escaped return escape(data.isoformat()) elif isinstance(data, dict): return escape(json.dumps(data)) elif isinstance(data, (list, tuple)): ret = "{%s}" % ",".join(escape(d, toplevel=False) for d in data) if toplevel: ret = '"%s"' % ret.replace("\\", "\\\\") return ret elif isinstance(data, psycopg2.extras.Range): # We escape twice here too, so that we make sure # everything gets passed to copy properly return escape( "%s%s,%s%s" % ( "[" if data.lower_inc else "(", "-infinity" if data.lower_inf else escape(data.lower), "infinity" if data.upper_inf else escape(data.upper), "]" if data.upper_inc else ")", ) ) elif isinstance(data, enum.IntEnum): return escape(int(data)) else: # We don't escape here to make sure we pass literals properly return str(data)