sqlobject 3.13.1__py2.py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (149) hide show
  1. sqlobject/__init__.py +15 -0
  2. sqlobject/__version__.py +8 -0
  3. sqlobject/boundattributes.py +124 -0
  4. sqlobject/cache.py +376 -0
  5. sqlobject/classregistry.py +138 -0
  6. sqlobject/col.py +2187 -0
  7. sqlobject/compat.py +59 -0
  8. sqlobject/conftest.py +64 -0
  9. sqlobject/constraints.py +77 -0
  10. sqlobject/converters.py +278 -0
  11. sqlobject/dbconnection.py +1137 -0
  12. sqlobject/dberrors.py +54 -0
  13. sqlobject/declarative.py +211 -0
  14. sqlobject/events.py +365 -0
  15. sqlobject/firebird/__init__.py +8 -0
  16. sqlobject/firebird/firebirdconnection.py +463 -0
  17. sqlobject/include/__init__.py +1 -0
  18. sqlobject/include/hashcol.py +109 -0
  19. sqlobject/include/tests/__init__.py +1 -0
  20. sqlobject/include/tests/test_hashcol.py +84 -0
  21. sqlobject/index.py +189 -0
  22. sqlobject/inheritance/__init__.py +551 -0
  23. sqlobject/inheritance/iteration.py +106 -0
  24. sqlobject/inheritance/tests/__init__.py +1 -0
  25. sqlobject/inheritance/tests/test_aggregates.py +23 -0
  26. sqlobject/inheritance/tests/test_asdict.py +48 -0
  27. sqlobject/inheritance/tests/test_deep_inheritance.py +114 -0
  28. sqlobject/inheritance/tests/test_destroy_cascade.py +23 -0
  29. sqlobject/inheritance/tests/test_foreignKey.py +94 -0
  30. sqlobject/inheritance/tests/test_indexes.py +42 -0
  31. sqlobject/inheritance/tests/test_inheritance.py +164 -0
  32. sqlobject/inheritance/tests/test_inheritance_tree.py +50 -0
  33. sqlobject/joins.py +656 -0
  34. sqlobject/main.py +1880 -0
  35. sqlobject/manager/__init__.py +1 -0
  36. sqlobject/manager/command.py +1309 -0
  37. sqlobject/maxdb/__init__.py +8 -0
  38. sqlobject/maxdb/maxdbconnection.py +320 -0
  39. sqlobject/maxdb/readme.txt +27 -0
  40. sqlobject/mssql/__init__.py +8 -0
  41. sqlobject/mssql/mssqlconnection.py +417 -0
  42. sqlobject/mysql/__init__.py +8 -0
  43. sqlobject/mysql/mysqlconnection.py +562 -0
  44. sqlobject/postgres/__init__.py +8 -0
  45. sqlobject/postgres/pgconnection.py +619 -0
  46. sqlobject/sqlbuilder.py +1655 -0
  47. sqlobject/sqlite/__init__.py +8 -0
  48. sqlobject/sqlite/sqliteconnection.py +418 -0
  49. sqlobject/sresults.py +377 -0
  50. sqlobject/styles.py +174 -0
  51. sqlobject/sybase/__init__.py +8 -0
  52. sqlobject/sybase/sybaseconnection.py +183 -0
  53. sqlobject/tests/__init__.py +1 -0
  54. sqlobject/tests/dbtest.py +363 -0
  55. sqlobject/tests/test_ForeignKey.py +133 -0
  56. sqlobject/tests/test_ForeignKey_cascade.py +150 -0
  57. sqlobject/tests/test_NoneValuedResultItem.py +33 -0
  58. sqlobject/tests/test_SQLMultipleJoin.py +65 -0
  59. sqlobject/tests/test_SQLRelatedJoin.py +114 -0
  60. sqlobject/tests/test_SingleJoin.py +30 -0
  61. sqlobject/tests/test_aggregates.py +75 -0
  62. sqlobject/tests/test_aliases.py +49 -0
  63. sqlobject/tests/test_asdict.py +18 -0
  64. sqlobject/tests/test_auto.py +218 -0
  65. sqlobject/tests/test_basic.py +359 -0
  66. sqlobject/tests/test_blob.py +34 -0
  67. sqlobject/tests/test_boundattributes.py +67 -0
  68. sqlobject/tests/test_cache.py +57 -0
  69. sqlobject/tests/test_class_hash.py +22 -0
  70. sqlobject/tests/test_columns_order.py +18 -0
  71. sqlobject/tests/test_combining_joins.py +47 -0
  72. sqlobject/tests/test_comparison.py +24 -0
  73. sqlobject/tests/test_compat.py +10 -0
  74. sqlobject/tests/test_complex_sorting.py +77 -0
  75. sqlobject/tests/test_constraints.py +43 -0
  76. sqlobject/tests/test_converters.py +276 -0
  77. sqlobject/tests/test_create_drop.py +29 -0
  78. sqlobject/tests/test_csvexport.py +101 -0
  79. sqlobject/tests/test_csvimport.py +21 -0
  80. sqlobject/tests/test_cyclic_reference.py +55 -0
  81. sqlobject/tests/test_datetime.py +171 -0
  82. sqlobject/tests/test_dbconnection.py +17 -0
  83. sqlobject/tests/test_decimal.py +63 -0
  84. sqlobject/tests/test_declarative.py +83 -0
  85. sqlobject/tests/test_default_style.py +65 -0
  86. sqlobject/tests/test_delete.py +74 -0
  87. sqlobject/tests/test_distinct.py +36 -0
  88. sqlobject/tests/test_empty.py +22 -0
  89. sqlobject/tests/test_enum.py +75 -0
  90. sqlobject/tests/test_events.py +142 -0
  91. sqlobject/tests/test_exceptions.py +40 -0
  92. sqlobject/tests/test_expire.py +29 -0
  93. sqlobject/tests/test_groupBy.py +45 -0
  94. sqlobject/tests/test_identity.py +29 -0
  95. sqlobject/tests/test_indexes.py +100 -0
  96. sqlobject/tests/test_inheritance.py +35 -0
  97. sqlobject/tests/test_joins.py +160 -0
  98. sqlobject/tests/test_joins_conditional.py +143 -0
  99. sqlobject/tests/test_jsonbcol.py +53 -0
  100. sqlobject/tests/test_jsoncol.py +56 -0
  101. sqlobject/tests/test_lazy.py +165 -0
  102. sqlobject/tests/test_md5.py +13 -0
  103. sqlobject/tests/test_mysql.py +50 -0
  104. sqlobject/tests/test_new_joins.py +165 -0
  105. sqlobject/tests/test_parse_uri.py +147 -0
  106. sqlobject/tests/test_paste.py +92 -0
  107. sqlobject/tests/test_perConnection.py +20 -0
  108. sqlobject/tests/test_pickle.py +42 -0
  109. sqlobject/tests/test_picklecol.py +44 -0
  110. sqlobject/tests/test_postgres.py +82 -0
  111. sqlobject/tests/test_reparent_sqlmeta.py +33 -0
  112. sqlobject/tests/test_schema.py +30 -0
  113. sqlobject/tests/test_select.py +218 -0
  114. sqlobject/tests/test_select_through.py +63 -0
  115. sqlobject/tests/test_setters.py +23 -0
  116. sqlobject/tests/test_slice.py +59 -0
  117. sqlobject/tests/test_sorting.py +80 -0
  118. sqlobject/tests/test_sqlbuilder.py +134 -0
  119. sqlobject/tests/test_sqlbuilder_dbspecific.py +66 -0
  120. sqlobject/tests/test_sqlbuilder_importproxy.py +55 -0
  121. sqlobject/tests/test_sqlbuilder_joins_instances.py +90 -0
  122. sqlobject/tests/test_sqlite.py +160 -0
  123. sqlobject/tests/test_sqlmeta_idName.py +52 -0
  124. sqlobject/tests/test_sqlobject_admin.py +38 -0
  125. sqlobject/tests/test_string_id.py +79 -0
  126. sqlobject/tests/test_style.py +36 -0
  127. sqlobject/tests/test_subqueries.py +142 -0
  128. sqlobject/tests/test_transactions.py +122 -0
  129. sqlobject/tests/test_unicode.py +84 -0
  130. sqlobject/tests/test_uuidcol.py +40 -0
  131. sqlobject/tests/test_validation.py +125 -0
  132. sqlobject/tests/test_views.py +159 -0
  133. sqlobject/util/__init__.py +1 -0
  134. sqlobject/util/csvexport.py +210 -0
  135. sqlobject/util/csvimport.py +366 -0
  136. sqlobject/util/moduleloader.py +35 -0
  137. sqlobject/util/threadinglocal.py +6 -0
  138. sqlobject/versioning/__init__.py +120 -0
  139. sqlobject/versioning/test/__init__.py +0 -0
  140. sqlobject/versioning/test/test_version.py +183 -0
  141. sqlobject/views.py +151 -0
  142. sqlobject/wsgi_middleware.py +109 -0
  143. sqlobject-3.13.1.data/scripts/sqlobject-admin +36 -0
  144. sqlobject-3.13.1.data/scripts/sqlobject-convertOldURI +19 -0
  145. sqlobject-3.13.1.dist-info/METADATA +177 -0
  146. sqlobject-3.13.1.dist-info/RECORD +149 -0
  147. sqlobject-3.13.1.dist-info/WHEEL +6 -0
  148. sqlobject-3.13.1.dist-info/entry_points.txt +4 -0
  149. sqlobject-3.13.1.dist-info/top_level.txt +1 -0
sqlobject/compat.py ADDED
@@ -0,0 +1,59 @@
1
+ import os
2
+ import sys
3
+ import types
4
+
5
+ # Credit to six authors: https://pypi.org/project/six/
6
+ # License: MIT
7
+
8
+
9
+ def with_metaclass(meta, *bases):
10
+ """Create a base class with a metaclass."""
11
+ # This requires a bit of explanation: the basic idea is to make a dummy
12
+ # metaclass for one level of class instantiation that replaces itself with
13
+ # the actual metaclass.
14
+
15
+ class metaclass(meta):
16
+ def __new__(cls, name, this_bases, d):
17
+ return meta(name, bases, d)
18
+ return type.__new__(metaclass, 'temporary_class', (), {})
19
+
20
+ # Compatability definitions (inspired by six)
21
+ PY2 = sys.version_info[0] < 3
22
+ if PY2:
23
+ # disable flake8 checks on python 3
24
+ string_type = basestring # noqa
25
+ unicode_type = unicode # noqa
26
+ class_types = (type, types.ClassType)
27
+ buffer_type = buffer # noqa
28
+ else:
29
+ string_type = str
30
+ unicode_type = str
31
+ class_types = (type,)
32
+ buffer_type = memoryview
33
+
34
+ if PY2:
35
+ import imp
36
+
37
+ def load_module_from_file(base_name, module_name, filename):
38
+ fp, pathname, description = imp.find_module(
39
+ base_name, [os.path.dirname(filename)])
40
+ try:
41
+ module = imp.load_module(module_name, fp, pathname, description)
42
+ finally:
43
+ fp.close()
44
+ return module
45
+ else:
46
+ import importlib.util
47
+
48
+ def load_module_from_file(base_name, module_name, filename):
49
+ specs = importlib.util.spec_from_file_location(module_name, filename)
50
+ loader = specs.loader
51
+ if hasattr(loader, 'create_module'):
52
+ module = loader.create_module(specs)
53
+ else:
54
+ module = None
55
+ if module is None:
56
+ return specs.loader.load_module()
57
+ else:
58
+ loader.exec_module(module)
59
+ return module
sqlobject/conftest.py ADDED
@@ -0,0 +1,64 @@
1
+ """This module is used by pytest to configure testing"""
2
+
3
+ try:
4
+ import pkg_resources
5
+ except ImportError:
6
+ pass
7
+ else:
8
+ pkg_resources.require('SQLObject')
9
+
10
+ # Override some options (doesn't override command line):
11
+ verbose = 0
12
+ exitfirst = True
13
+
14
+ connectionShortcuts = {
15
+ 'mysql': 'mysql://test@localhost/test',
16
+ 'dbm': 'dbm:///data',
17
+ 'postgres': 'postgres:///test',
18
+ 'postgresql': 'postgres:///test',
19
+ 'pygresql': 'pygresql://localhost/test',
20
+ 'sqlite': 'sqlite:/:memory:',
21
+ 'sybase': 'sybase://test:test123@sybase/test?autoCommit=0',
22
+ 'firebird':
23
+ 'firebird://sysdba:masterkey@localhost/var/lib/firebird/data/test.gdb',
24
+ 'mssql': 'mssql://sa:@127.0.0.1/test'
25
+ }
26
+
27
+
28
+ def pytest_addoption(parser):
29
+ """Add the SQLObject options"""
30
+ parser.addoption(
31
+ '-D', '--Database',
32
+ action="store", dest="Database", default='sqlite',
33
+ help="The database to run the tests under (default sqlite). "
34
+ "Can also use an alias from: %s"
35
+ % (', '.join(connectionShortcuts.keys())))
36
+ parser.addoption(
37
+ '-S', '--SQL',
38
+ action="store_true", dest="show_sql", default=False,
39
+ help="Show SQL from statements (when capturing stdout the "
40
+ "SQL is only displayed when a test fails)")
41
+ parser.addoption(
42
+ '-O', '--SQL-output',
43
+ action="store_true", dest="show_sql_output", default=False,
44
+ help="Show output from SQL statements (when capturing "
45
+ "stdout the output is only displayed when a test fails)")
46
+ parser.addoption(
47
+ '-E', '--events',
48
+ action="store_true", dest="debug_events", default=False,
49
+ help="Debug events (print information about events as they are "
50
+ "sent)")
51
+
52
+ option = None
53
+
54
+
55
+ def pytest_configure(config):
56
+ """Make cmdline arguments available to dbtest"""
57
+ global option
58
+ option = config.option
59
+
60
+
61
+ def setup_tests():
62
+ if option.debug_events:
63
+ from sqlobject import events
64
+ events.debug_events()
@@ -0,0 +1,77 @@
1
+ """
2
+ Constraints
3
+ """
4
+
5
+ from sqlobject.compat import PY2
6
+
7
+ if not PY2:
8
+ # alias for python 3 compatability
9
+ long = int
10
+
11
+
12
+ class BadValue(ValueError):
13
+
14
+ def __init__(self, desc, obj, col, value, *args):
15
+ self.desc = desc
16
+ self.col = col
17
+
18
+ # I want these objects to be garbage-collectable, so
19
+ # I just keep their repr:
20
+ self.obj = repr(obj)
21
+ self.value = repr(value)
22
+ fullDesc = "%s.%s %s (you gave: %s)" \
23
+ % (obj, col.name, desc, value)
24
+ ValueError.__init__(self, fullDesc, *args)
25
+
26
+
27
+ def isString(obj, col, value):
28
+ if not isinstance(value, str):
29
+ raise BadValue("only allows strings", obj, col, value)
30
+
31
+
32
+ def notNull(obj, col, value):
33
+ if value is None:
34
+ raise BadValue("is defined NOT NULL", obj, col, value)
35
+
36
+
37
+ def isInt(obj, col, value):
38
+ if not isinstance(value, (int, long)):
39
+ raise BadValue("only allows integers", obj, col, value)
40
+
41
+
42
+ def isFloat(obj, col, value):
43
+ if not isinstance(value, (int, long, float)):
44
+ raise BadValue("only allows floating point numbers", obj, col, value)
45
+
46
+
47
+ def isBool(obj, col, value):
48
+ if not isinstance(value, bool):
49
+ raise BadValue("only allows booleans", obj, col, value)
50
+
51
+
52
+ class InList:
53
+
54
+ def __init__(self, _l):
55
+ self.list = _l
56
+
57
+ def __call__(self, obj, col, value):
58
+ if value not in self.list:
59
+ raise BadValue("accepts only values in %s" % repr(self.list),
60
+ obj, col, value)
61
+
62
+
63
+ class MaxLength:
64
+
65
+ def __init__(self, length):
66
+ self.length = length
67
+
68
+ def __call__(self, obj, col, value):
69
+ try:
70
+ length = len(value)
71
+ except TypeError:
72
+ raise BadValue("object does not have a length",
73
+ obj, col, value)
74
+ if length > self.length:
75
+ raise BadValue("must be shorter in length than %s"
76
+ % self.length,
77
+ obj, col, value)
@@ -0,0 +1,278 @@
1
+ from array import array
2
+ import datetime
3
+ from decimal import Decimal
4
+ import time
5
+ import sys
6
+ from .compat import PY2, buffer_type
7
+
8
+ if PY2:
9
+ from types import ClassType, InstanceType, NoneType
10
+ else:
11
+ # Use suitable aliases for now
12
+ ClassType = type
13
+ NoneType = type(None)
14
+ # This is may not be what we want in all cases, but will do for now
15
+ InstanceType = object
16
+
17
+
18
+ try:
19
+ from mx.DateTime import DateTimeType as mxDateTimeType, \
20
+ DateTimeDeltaType as mxDateTimeDeltaType
21
+ except ImportError:
22
+ mxDateTimeType = None
23
+ mxDateTimeDeltaType = None
24
+
25
+ try:
26
+ import pendulum
27
+ except ImportError:
28
+ pendulumDateTimeType = None
29
+ else:
30
+ pendulumDateTimeType = pendulum.DateTime
31
+
32
+ try:
33
+ from DateTime import DateTime as zopeDateTime
34
+ except ImportError:
35
+ zopeDateTimeType = None
36
+ else:
37
+ zopeDateTimeType = type(zopeDateTime())
38
+
39
+ try:
40
+ import Sybase
41
+ NumericType = Sybase.NumericType
42
+ except ImportError:
43
+ NumericType = None
44
+
45
+
46
+ ########################################
47
+ # Quoting
48
+ ########################################
49
+
50
+ sqlStringReplace = [
51
+ ("'", "''"),
52
+ ('\\', '\\\\'),
53
+ ('\000', '\\0'),
54
+ ('\b', '\\b'),
55
+ ('\n', '\\n'),
56
+ ('\r', '\\r'),
57
+ ('\t', '\\t'),
58
+ ]
59
+
60
+
61
+ class ConverterRegistry:
62
+
63
+ def __init__(self):
64
+ self.basic = {}
65
+ self.klass = {}
66
+
67
+ def registerConverter(self, typ, func):
68
+ if type(typ) is ClassType:
69
+ self.klass[typ] = func
70
+ else:
71
+ self.basic[typ] = func
72
+
73
+ if PY2:
74
+ def lookupConverter(self, value, default=None):
75
+ if type(value) is InstanceType:
76
+ # lookup on klasses dict
77
+ return self.klass.get(value.__class__, default)
78
+ return self.basic.get(type(value), default)
79
+ else:
80
+ def lookupConverter(self, value, default=None):
81
+ # python 3 doesn't have classic classes, so everything's
82
+ # in self.klass due to comparison order in registerConvertor
83
+ return self.klass.get(value.__class__, default)
84
+
85
+ converters = ConverterRegistry()
86
+ registerConverter = converters.registerConverter
87
+ lookupConverter = converters.lookupConverter
88
+
89
+
90
+ def StringLikeConverter(value, db):
91
+ if isinstance(value, array):
92
+ try:
93
+ value = value.tounicode()
94
+ except ValueError:
95
+ value = value.tostring()
96
+ elif isinstance(value, buffer_type):
97
+ value = str(value)
98
+
99
+ if db in ('mysql', 'postgres'):
100
+ for orig, repl in sqlStringReplace:
101
+ value = value.replace(orig, repl)
102
+ elif db in ('sqlite', 'firebird', 'sybase', 'maxdb', 'mssql'):
103
+ value = value.replace("'", "''")
104
+ else:
105
+ assert 0, "Database %s unknown" % db
106
+ if (db == 'postgres') and ('\\' in value):
107
+ return "E'%s'" % value
108
+ return "'%s'" % value
109
+
110
+ registerConverter(str, StringLikeConverter)
111
+ if PY2:
112
+ # noqa for flake8 & python3
113
+ registerConverter(unicode, StringLikeConverter) # noqa
114
+ registerConverter(array, StringLikeConverter)
115
+ if PY2:
116
+ registerConverter(bytearray, StringLikeConverter)
117
+ registerConverter(buffer_type, StringLikeConverter)
118
+ else:
119
+ registerConverter(memoryview, StringLikeConverter)
120
+
121
+
122
+ def IntConverter(value, db):
123
+ return repr(int(value))
124
+
125
+ registerConverter(int, IntConverter)
126
+
127
+
128
+ def LongConverter(value, db):
129
+ return str(value)
130
+
131
+ if sys.version_info[0] < 3:
132
+ # noqa for flake8 & python3
133
+ registerConverter(long, LongConverter) # noqa
134
+
135
+ if NumericType:
136
+ registerConverter(NumericType, IntConverter)
137
+
138
+
139
+ def BoolConverter(value, db):
140
+ if db == 'postgres':
141
+ if value:
142
+ return "'t'"
143
+ else:
144
+ return "'f'"
145
+ else:
146
+ if value:
147
+ return '1'
148
+ else:
149
+ return '0'
150
+
151
+ registerConverter(bool, BoolConverter)
152
+
153
+
154
+ def FloatConverter(value, db):
155
+ return repr(value)
156
+
157
+ registerConverter(float, FloatConverter)
158
+
159
+
160
+ def NoneConverter(value, db):
161
+ return "NULL"
162
+
163
+ registerConverter(NoneType, NoneConverter)
164
+
165
+
166
+ def SequenceConverter(value, db):
167
+ return "(%s)" % ", ".join([sqlrepr(v, db) for v in value])
168
+
169
+ registerConverter(tuple, SequenceConverter)
170
+ registerConverter(list, SequenceConverter)
171
+ registerConverter(dict, SequenceConverter)
172
+ registerConverter(set, SequenceConverter)
173
+ registerConverter(frozenset, SequenceConverter)
174
+
175
+ if hasattr(time, 'struct_time'):
176
+ def StructTimeConverter(value, db):
177
+ return time.strftime("'%Y-%m-%d %H:%M:%S'", value)
178
+
179
+ registerConverter(time.struct_time, StructTimeConverter)
180
+
181
+
182
+ def DateTimeConverter(value, db):
183
+ return "'%04d-%02d-%02d %02d:%02d:%02d'" % (
184
+ value.year, value.month, value.day,
185
+ value.hour, value.minute, value.second)
186
+
187
+
188
+ def DateTimeConverterMS(value, db):
189
+ return "'%04d-%02d-%02d %02d:%02d:%02d.%06d'" % (
190
+ value.year, value.month, value.day,
191
+ value.hour, value.minute, value.second, value.microsecond)
192
+
193
+ registerConverter(datetime.datetime, DateTimeConverterMS)
194
+
195
+
196
+ def DateConverter(value, db):
197
+ return "'%04d-%02d-%02d'" % (value.year, value.month, value.day)
198
+
199
+ registerConverter(datetime.date, DateConverter)
200
+
201
+
202
+ def TimeConverter(value, db):
203
+ return "'%02d:%02d:%02d'" % (value.hour, value.minute, value.second)
204
+
205
+
206
+ def TimeConverterMS(value, db):
207
+ return "'%02d:%02d:%02d.%06d'" % (value.hour, value.minute,
208
+ value.second, value.microsecond)
209
+
210
+ registerConverter(datetime.time, TimeConverterMS)
211
+
212
+
213
+ if mxDateTimeType:
214
+ def mxDateTimeConverter(value, db):
215
+ return "'%s'" % value.strftime("%Y-%m-%d %H:%M:%S")
216
+
217
+ registerConverter(mxDateTimeType, mxDateTimeConverter)
218
+
219
+ def mxTimeConverter(value, db):
220
+ return "'%s'" % value.strftime("%H:%M:%S")
221
+
222
+ registerConverter(mxDateTimeDeltaType, mxTimeConverter)
223
+
224
+
225
+ if pendulumDateTimeType:
226
+ def pendulumConverter(value, db):
227
+ return "'%s'" % value.to_datetime_string()
228
+
229
+ registerConverter(pendulum.DateTime, pendulumConverter)
230
+
231
+
232
+ if zopeDateTimeType:
233
+ def zopeDateTimeConverter(value, db):
234
+ return "'%s'" % value.strftime("%Y-%m-%d %H:%M:%S")
235
+
236
+ registerConverter(zopeDateTimeType, zopeDateTimeConverter)
237
+
238
+
239
+ def DecimalConverter(value, db):
240
+ return value.to_eng_string()
241
+
242
+ registerConverter(Decimal, DecimalConverter)
243
+
244
+
245
+ def TimedeltaConverter(value, db):
246
+
247
+ return """INTERVAL '%d days %d seconds'""" % \
248
+ (value.days, value.seconds)
249
+
250
+ registerConverter(datetime.timedelta, TimedeltaConverter)
251
+
252
+
253
+ def sqlrepr(obj, db=None):
254
+ try:
255
+ reprFunc = obj.__sqlrepr__
256
+ except AttributeError:
257
+ converter = lookupConverter(obj)
258
+ if converter is None:
259
+ raise ValueError("Unknown SQL builtin type: %s for %s" %
260
+ (type(obj), repr(obj)))
261
+ return converter(obj, db)
262
+ else:
263
+ return reprFunc(db)
264
+
265
+
266
+ def quote_str(s, db):
267
+ if (db == 'postgres') and ('\\' in s):
268
+ return "E'%s'" % s
269
+ return "'%s'" % s
270
+
271
+
272
+ def unquote_str(s):
273
+ if s[:2].upper().startswith("E'") and s.endswith("'"):
274
+ return s[2:-1]
275
+ elif s.startswith("'") and s.endswith("'"):
276
+ return s[1:-1]
277
+ else:
278
+ return s