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.
- sqlobject/__init__.py +15 -0
- sqlobject/__version__.py +8 -0
- sqlobject/boundattributes.py +124 -0
- sqlobject/cache.py +376 -0
- sqlobject/classregistry.py +138 -0
- sqlobject/col.py +2187 -0
- sqlobject/compat.py +59 -0
- sqlobject/conftest.py +64 -0
- sqlobject/constraints.py +77 -0
- sqlobject/converters.py +278 -0
- sqlobject/dbconnection.py +1137 -0
- sqlobject/dberrors.py +54 -0
- sqlobject/declarative.py +211 -0
- sqlobject/events.py +365 -0
- sqlobject/firebird/__init__.py +8 -0
- sqlobject/firebird/firebirdconnection.py +463 -0
- sqlobject/include/__init__.py +1 -0
- sqlobject/include/hashcol.py +109 -0
- sqlobject/include/tests/__init__.py +1 -0
- sqlobject/include/tests/test_hashcol.py +84 -0
- sqlobject/index.py +189 -0
- sqlobject/inheritance/__init__.py +551 -0
- sqlobject/inheritance/iteration.py +106 -0
- sqlobject/inheritance/tests/__init__.py +1 -0
- sqlobject/inheritance/tests/test_aggregates.py +23 -0
- sqlobject/inheritance/tests/test_asdict.py +48 -0
- sqlobject/inheritance/tests/test_deep_inheritance.py +114 -0
- sqlobject/inheritance/tests/test_destroy_cascade.py +23 -0
- sqlobject/inheritance/tests/test_foreignKey.py +94 -0
- sqlobject/inheritance/tests/test_indexes.py +42 -0
- sqlobject/inheritance/tests/test_inheritance.py +164 -0
- sqlobject/inheritance/tests/test_inheritance_tree.py +50 -0
- sqlobject/joins.py +656 -0
- sqlobject/main.py +1880 -0
- sqlobject/manager/__init__.py +1 -0
- sqlobject/manager/command.py +1309 -0
- sqlobject/maxdb/__init__.py +8 -0
- sqlobject/maxdb/maxdbconnection.py +320 -0
- sqlobject/maxdb/readme.txt +27 -0
- sqlobject/mssql/__init__.py +8 -0
- sqlobject/mssql/mssqlconnection.py +417 -0
- sqlobject/mysql/__init__.py +8 -0
- sqlobject/mysql/mysqlconnection.py +562 -0
- sqlobject/postgres/__init__.py +8 -0
- sqlobject/postgres/pgconnection.py +619 -0
- sqlobject/sqlbuilder.py +1655 -0
- sqlobject/sqlite/__init__.py +8 -0
- sqlobject/sqlite/sqliteconnection.py +418 -0
- sqlobject/sresults.py +377 -0
- sqlobject/styles.py +174 -0
- sqlobject/sybase/__init__.py +8 -0
- sqlobject/sybase/sybaseconnection.py +183 -0
- sqlobject/tests/__init__.py +1 -0
- sqlobject/tests/dbtest.py +363 -0
- sqlobject/tests/test_ForeignKey.py +133 -0
- sqlobject/tests/test_ForeignKey_cascade.py +150 -0
- sqlobject/tests/test_NoneValuedResultItem.py +33 -0
- sqlobject/tests/test_SQLMultipleJoin.py +65 -0
- sqlobject/tests/test_SQLRelatedJoin.py +114 -0
- sqlobject/tests/test_SingleJoin.py +30 -0
- sqlobject/tests/test_aggregates.py +75 -0
- sqlobject/tests/test_aliases.py +49 -0
- sqlobject/tests/test_asdict.py +18 -0
- sqlobject/tests/test_auto.py +218 -0
- sqlobject/tests/test_basic.py +359 -0
- sqlobject/tests/test_blob.py +34 -0
- sqlobject/tests/test_boundattributes.py +67 -0
- sqlobject/tests/test_cache.py +57 -0
- sqlobject/tests/test_class_hash.py +22 -0
- sqlobject/tests/test_columns_order.py +18 -0
- sqlobject/tests/test_combining_joins.py +47 -0
- sqlobject/tests/test_comparison.py +24 -0
- sqlobject/tests/test_compat.py +10 -0
- sqlobject/tests/test_complex_sorting.py +77 -0
- sqlobject/tests/test_constraints.py +43 -0
- sqlobject/tests/test_converters.py +276 -0
- sqlobject/tests/test_create_drop.py +29 -0
- sqlobject/tests/test_csvexport.py +101 -0
- sqlobject/tests/test_csvimport.py +21 -0
- sqlobject/tests/test_cyclic_reference.py +55 -0
- sqlobject/tests/test_datetime.py +171 -0
- sqlobject/tests/test_dbconnection.py +17 -0
- sqlobject/tests/test_decimal.py +63 -0
- sqlobject/tests/test_declarative.py +83 -0
- sqlobject/tests/test_default_style.py +65 -0
- sqlobject/tests/test_delete.py +74 -0
- sqlobject/tests/test_distinct.py +36 -0
- sqlobject/tests/test_empty.py +22 -0
- sqlobject/tests/test_enum.py +75 -0
- sqlobject/tests/test_events.py +142 -0
- sqlobject/tests/test_exceptions.py +40 -0
- sqlobject/tests/test_expire.py +29 -0
- sqlobject/tests/test_groupBy.py +45 -0
- sqlobject/tests/test_identity.py +29 -0
- sqlobject/tests/test_indexes.py +100 -0
- sqlobject/tests/test_inheritance.py +35 -0
- sqlobject/tests/test_joins.py +160 -0
- sqlobject/tests/test_joins_conditional.py +143 -0
- sqlobject/tests/test_jsonbcol.py +53 -0
- sqlobject/tests/test_jsoncol.py +56 -0
- sqlobject/tests/test_lazy.py +165 -0
- sqlobject/tests/test_md5.py +13 -0
- sqlobject/tests/test_mysql.py +50 -0
- sqlobject/tests/test_new_joins.py +165 -0
- sqlobject/tests/test_parse_uri.py +147 -0
- sqlobject/tests/test_paste.py +92 -0
- sqlobject/tests/test_perConnection.py +20 -0
- sqlobject/tests/test_pickle.py +42 -0
- sqlobject/tests/test_picklecol.py +44 -0
- sqlobject/tests/test_postgres.py +82 -0
- sqlobject/tests/test_reparent_sqlmeta.py +33 -0
- sqlobject/tests/test_schema.py +30 -0
- sqlobject/tests/test_select.py +218 -0
- sqlobject/tests/test_select_through.py +63 -0
- sqlobject/tests/test_setters.py +23 -0
- sqlobject/tests/test_slice.py +59 -0
- sqlobject/tests/test_sorting.py +80 -0
- sqlobject/tests/test_sqlbuilder.py +134 -0
- sqlobject/tests/test_sqlbuilder_dbspecific.py +66 -0
- sqlobject/tests/test_sqlbuilder_importproxy.py +55 -0
- sqlobject/tests/test_sqlbuilder_joins_instances.py +90 -0
- sqlobject/tests/test_sqlite.py +160 -0
- sqlobject/tests/test_sqlmeta_idName.py +52 -0
- sqlobject/tests/test_sqlobject_admin.py +38 -0
- sqlobject/tests/test_string_id.py +79 -0
- sqlobject/tests/test_style.py +36 -0
- sqlobject/tests/test_subqueries.py +142 -0
- sqlobject/tests/test_transactions.py +122 -0
- sqlobject/tests/test_unicode.py +84 -0
- sqlobject/tests/test_uuidcol.py +40 -0
- sqlobject/tests/test_validation.py +125 -0
- sqlobject/tests/test_views.py +159 -0
- sqlobject/util/__init__.py +1 -0
- sqlobject/util/csvexport.py +210 -0
- sqlobject/util/csvimport.py +366 -0
- sqlobject/util/moduleloader.py +35 -0
- sqlobject/util/threadinglocal.py +6 -0
- sqlobject/versioning/__init__.py +120 -0
- sqlobject/versioning/test/__init__.py +0 -0
- sqlobject/versioning/test/test_version.py +183 -0
- sqlobject/views.py +151 -0
- sqlobject/wsgi_middleware.py +109 -0
- sqlobject-3.13.1.data/scripts/sqlobject-admin +36 -0
- sqlobject-3.13.1.data/scripts/sqlobject-convertOldURI +19 -0
- sqlobject-3.13.1.dist-info/METADATA +177 -0
- sqlobject-3.13.1.dist-info/RECORD +149 -0
- sqlobject-3.13.1.dist-info/WHEEL +6 -0
- sqlobject-3.13.1.dist-info/entry_points.txt +4 -0
- sqlobject-3.13.1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
from datetime import datetime
|
|
2
|
+
from pytest import raises
|
|
3
|
+
|
|
4
|
+
from sqlobject import KeyCol, MultipleJoin, SQLObject, StringCol, \
|
|
5
|
+
classregistry, sqlmeta
|
|
6
|
+
from sqlobject.col import use_microseconds
|
|
7
|
+
from sqlobject.tests.dbtest import getConnection, setupClass
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
########################################
|
|
11
|
+
# Dynamic column tests
|
|
12
|
+
########################################
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
now = datetime.now
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class Person(SQLObject):
|
|
19
|
+
|
|
20
|
+
class sqlmeta:
|
|
21
|
+
defaultOrder = 'name'
|
|
22
|
+
name = StringCol(length=100, dbName='name_col')
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class Phone(SQLObject):
|
|
26
|
+
|
|
27
|
+
class sqlmeta:
|
|
28
|
+
defaultOrder = 'phone'
|
|
29
|
+
phone = StringCol(length=12)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class TestPeople:
|
|
33
|
+
|
|
34
|
+
def setup_method(self, meth):
|
|
35
|
+
setupClass(Person)
|
|
36
|
+
setupClass(Phone)
|
|
37
|
+
for n in ['jane', 'tim', 'bob', 'jake']:
|
|
38
|
+
Person(name=n)
|
|
39
|
+
for p in ['555-555-5555', '555-394-2930',
|
|
40
|
+
'444-382-4854']:
|
|
41
|
+
Phone(phone=p)
|
|
42
|
+
|
|
43
|
+
def test_defaultOrder(self):
|
|
44
|
+
assert list(Person.select('all')) == list(
|
|
45
|
+
Person.select('all', orderBy=Person.sqlmeta.defaultOrder))
|
|
46
|
+
|
|
47
|
+
def test_dynamicColumn(self):
|
|
48
|
+
nickname = StringCol('nickname', length=10)
|
|
49
|
+
Person.sqlmeta.addColumn(nickname, changeSchema=True)
|
|
50
|
+
Person(name='robert', nickname='bob')
|
|
51
|
+
assert ([p.name for p in Person.select('all')]
|
|
52
|
+
== ['bob', 'jake', 'jane', 'robert', 'tim'])
|
|
53
|
+
Person.sqlmeta.delColumn(nickname, changeSchema=True)
|
|
54
|
+
|
|
55
|
+
def test_dynamicJoin(self):
|
|
56
|
+
col = KeyCol('person', foreignKey='Person')
|
|
57
|
+
Phone.sqlmeta.addColumn(col, changeSchema=True)
|
|
58
|
+
join = MultipleJoin('Phone')
|
|
59
|
+
Person.sqlmeta.addJoin(join)
|
|
60
|
+
for phone in Phone.select('all'):
|
|
61
|
+
if phone.phone.startswith('555'):
|
|
62
|
+
phone.person = Person.selectBy(name='tim')[0]
|
|
63
|
+
else:
|
|
64
|
+
phone.person = Person.selectBy(name='bob')[0]
|
|
65
|
+
_l = [p.phone for p in Person.selectBy(name='tim')[0].phones]
|
|
66
|
+
_l.sort()
|
|
67
|
+
assert _l == ['555-394-2930', '555-555-5555']
|
|
68
|
+
Phone.sqlmeta.delColumn(col, changeSchema=True)
|
|
69
|
+
Person.sqlmeta.delJoin(join)
|
|
70
|
+
|
|
71
|
+
def _test_collidingName(self):
|
|
72
|
+
class CollidingName(SQLObject):
|
|
73
|
+
expire = StringCol()
|
|
74
|
+
|
|
75
|
+
def test_collidingName(self):
|
|
76
|
+
raises(AssertionError, Person.sqlmeta.addColumn,
|
|
77
|
+
StringCol(name="name"))
|
|
78
|
+
raises(AssertionError, Person.sqlmeta.addColumn,
|
|
79
|
+
StringCol(name="_init"))
|
|
80
|
+
raises(AssertionError, Person.sqlmeta.addColumn,
|
|
81
|
+
StringCol(name="expire"))
|
|
82
|
+
raises(AssertionError, Person.sqlmeta.addColumn,
|
|
83
|
+
StringCol(name="set"))
|
|
84
|
+
raises(AssertionError, self._test_collidingName)
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
########################################
|
|
88
|
+
# Auto class generation
|
|
89
|
+
########################################
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
class TestAuto:
|
|
93
|
+
|
|
94
|
+
mysqlCreate = """
|
|
95
|
+
CREATE TABLE IF NOT EXISTS auto_test (
|
|
96
|
+
auto_id INT AUTO_INCREMENT PRIMARY KEY,
|
|
97
|
+
first_name VARCHAR(100),
|
|
98
|
+
last_name VARCHAR(200) NOT NULL,
|
|
99
|
+
age INT DEFAULT NULL,
|
|
100
|
+
created DATETIME NOT NULL,
|
|
101
|
+
happy char(1) DEFAULT 'Y' NOT NULL,
|
|
102
|
+
long_field TEXT,
|
|
103
|
+
wannahavefun TINYINT DEFAULT 0 NOT NULL
|
|
104
|
+
)
|
|
105
|
+
"""
|
|
106
|
+
|
|
107
|
+
postgresCreate = """
|
|
108
|
+
CREATE TABLE auto_test (
|
|
109
|
+
auto_id SERIAL PRIMARY KEY,
|
|
110
|
+
first_name VARCHAR(100),
|
|
111
|
+
last_name VARCHAR(200) NOT NULL,
|
|
112
|
+
age INT DEFAULT 0,
|
|
113
|
+
created TIMESTAMP NOT NULL,
|
|
114
|
+
happy char(1) DEFAULT 'Y' NOT NULL,
|
|
115
|
+
long_field TEXT,
|
|
116
|
+
wannahavefun BOOL DEFAULT FALSE NOT NULL
|
|
117
|
+
)
|
|
118
|
+
"""
|
|
119
|
+
|
|
120
|
+
sqliteCreate = """
|
|
121
|
+
CREATE TABLE auto_test (
|
|
122
|
+
auto_id INTEGER PRIMARY KEY AUTOINCREMENT ,
|
|
123
|
+
first_name VARCHAR(100),
|
|
124
|
+
last_name VARCHAR(200) NOT NULL,
|
|
125
|
+
age INT DEFAULT NULL,
|
|
126
|
+
created DATETIME NOT NULL,
|
|
127
|
+
happy char(1) DEFAULT 'Y' NOT NULL,
|
|
128
|
+
long_field TEXT,
|
|
129
|
+
wannahavefun INT DEFAULT 0 NOT NULL
|
|
130
|
+
)
|
|
131
|
+
"""
|
|
132
|
+
|
|
133
|
+
sybaseCreate = """
|
|
134
|
+
CREATE TABLE auto_test (
|
|
135
|
+
auto_id integer,
|
|
136
|
+
first_name VARCHAR(100),
|
|
137
|
+
last_name VARCHAR(200) NOT NULL,
|
|
138
|
+
age INT DEFAULT 0,
|
|
139
|
+
created DATETIME NOT NULL,
|
|
140
|
+
happy char(1) DEFAULT 'Y' NOT NULL,
|
|
141
|
+
long_field TEXT,
|
|
142
|
+
wannahavefun BIT default(0) NOT NULL
|
|
143
|
+
)
|
|
144
|
+
"""
|
|
145
|
+
|
|
146
|
+
mssqlCreate = """
|
|
147
|
+
CREATE TABLE auto_test (
|
|
148
|
+
auto_id int identity(1,1),
|
|
149
|
+
first_name VARCHAR(100),
|
|
150
|
+
last_name VARCHAR(200) NOT NULL,
|
|
151
|
+
age INT DEFAULT 0,
|
|
152
|
+
created DATETIME NOT NULL,
|
|
153
|
+
happy char(1) DEFAULT 'Y' NOT NULL,
|
|
154
|
+
long_field TEXT,
|
|
155
|
+
wannahavefun BIT default(0) NOT NULL
|
|
156
|
+
)
|
|
157
|
+
"""
|
|
158
|
+
|
|
159
|
+
mysqlDrop = """
|
|
160
|
+
DROP TABLE IF EXISTS auto_test
|
|
161
|
+
"""
|
|
162
|
+
|
|
163
|
+
postgresDrop = """
|
|
164
|
+
DROP TABLE auto_test
|
|
165
|
+
"""
|
|
166
|
+
|
|
167
|
+
sqliteDrop = sybaseDrop = mssqlDrop = postgresDrop
|
|
168
|
+
|
|
169
|
+
def setup_method(self, meth):
|
|
170
|
+
conn = getConnection()
|
|
171
|
+
dbName = conn.dbName
|
|
172
|
+
creator = getattr(self, dbName + 'Create', None)
|
|
173
|
+
if creator:
|
|
174
|
+
conn.query(creator)
|
|
175
|
+
|
|
176
|
+
def teardown_method(self, meth):
|
|
177
|
+
conn = getConnection()
|
|
178
|
+
dbName = conn.dbName
|
|
179
|
+
dropper = getattr(self, dbName + 'Drop', None)
|
|
180
|
+
if dropper:
|
|
181
|
+
try:
|
|
182
|
+
conn.query(dropper)
|
|
183
|
+
except Exception: # Perhaps we don't have DROP permission
|
|
184
|
+
pass
|
|
185
|
+
|
|
186
|
+
def test_classCreate(self):
|
|
187
|
+
class AutoTest(SQLObject):
|
|
188
|
+
_connection = getConnection()
|
|
189
|
+
|
|
190
|
+
class sqlmeta(sqlmeta):
|
|
191
|
+
idName = 'auto_id'
|
|
192
|
+
fromDatabase = True
|
|
193
|
+
if AutoTest._connection.dbName == 'mssql':
|
|
194
|
+
use_microseconds(False)
|
|
195
|
+
john = AutoTest(firstName='john',
|
|
196
|
+
lastName='doe',
|
|
197
|
+
age=10,
|
|
198
|
+
created=now(),
|
|
199
|
+
wannahavefun=False,
|
|
200
|
+
longField='x' * 1000)
|
|
201
|
+
jane = AutoTest(firstName='jane',
|
|
202
|
+
lastName='doe',
|
|
203
|
+
happy='N',
|
|
204
|
+
created=now(),
|
|
205
|
+
wannahavefun=True,
|
|
206
|
+
longField='x' * 1000)
|
|
207
|
+
assert not john.wannahavefun
|
|
208
|
+
assert jane.wannahavefun
|
|
209
|
+
assert john.longField == 'x' * 1000
|
|
210
|
+
assert jane.longField == 'x' * 1000
|
|
211
|
+
del classregistry.registry(
|
|
212
|
+
AutoTest.sqlmeta.registry).classes['AutoTest']
|
|
213
|
+
|
|
214
|
+
columns = AutoTest.sqlmeta.columns
|
|
215
|
+
assert columns["lastName"].dbName == "last_name"
|
|
216
|
+
assert columns["wannahavefun"].dbName == "wannahavefun"
|
|
217
|
+
if AutoTest._connection.dbName == 'mssql':
|
|
218
|
+
use_microseconds(True)
|
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
import codecs
|
|
2
|
+
import pytest
|
|
3
|
+
from sqlobject import BoolCol, ForeignKey, IntCol, KeyCol, SQLObject, \
|
|
4
|
+
StringCol, connectionForURI, sqlhub
|
|
5
|
+
from sqlobject.tests.dbtest import inserts, raises, setupClass, supports
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class SOTestSO1(SQLObject):
|
|
9
|
+
|
|
10
|
+
name = StringCol(length=50, dbName='name_col')
|
|
11
|
+
name.title = 'Your Name'
|
|
12
|
+
name.foobar = 1
|
|
13
|
+
passwd = StringCol(length=10)
|
|
14
|
+
|
|
15
|
+
class sqlmeta:
|
|
16
|
+
cacheValues = False
|
|
17
|
+
|
|
18
|
+
def _set_passwd(self, passwd):
|
|
19
|
+
self._SO_set_passwd(codecs.encode(passwd, 'rot13'))
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def setupGetters(cls):
|
|
23
|
+
setupClass(cls)
|
|
24
|
+
inserts(cls, [('bob', 'god'), ('sally', 'sordid'),
|
|
25
|
+
('dave', 'dremel'), ('fred', 'forgo')],
|
|
26
|
+
'name passwd')
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def test_case1():
|
|
30
|
+
setupGetters(SOTestSO1)
|
|
31
|
+
bob = SOTestSO1.selectBy(name='bob')[0]
|
|
32
|
+
assert bob.name == 'bob'
|
|
33
|
+
assert bob.passwd == codecs.encode('god', 'rot13')
|
|
34
|
+
bobs = SOTestSO1.selectBy(name='bob')[:10]
|
|
35
|
+
assert len(list(bobs)) == 1
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def test_newline():
|
|
39
|
+
setupGetters(SOTestSO1)
|
|
40
|
+
bob = SOTestSO1.selectBy(name='bob')[0]
|
|
41
|
+
testString = 'hey\nyou\\can\'t you see me?\t'
|
|
42
|
+
bob.name = testString
|
|
43
|
+
bob.expire()
|
|
44
|
+
assert bob.name == testString
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def test_count():
|
|
48
|
+
setupGetters(SOTestSO1)
|
|
49
|
+
assert SOTestSO1.selectBy(name=None).count() == 0
|
|
50
|
+
assert SOTestSO1.selectBy(name='bob').count() == 1
|
|
51
|
+
assert SOTestSO1.select(SOTestSO1.q.name == 'bob').count() == 1
|
|
52
|
+
assert SOTestSO1.select().count() == len(list(SOTestSO1.select()))
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def test_getset():
|
|
56
|
+
setupGetters(SOTestSO1)
|
|
57
|
+
bob = SOTestSO1.selectBy(name='bob')[0]
|
|
58
|
+
assert bob.name == 'bob'
|
|
59
|
+
bob.name = 'joe'
|
|
60
|
+
assert bob.name == 'joe'
|
|
61
|
+
bob.set(name='joebob', passwd='testtest')
|
|
62
|
+
assert bob.name == 'joebob'
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def test_extra_vars():
|
|
66
|
+
setupGetters(SOTestSO1)
|
|
67
|
+
col = SOTestSO1.sqlmeta.columns['name']
|
|
68
|
+
assert col.title == 'Your Name'
|
|
69
|
+
assert col.foobar == 1
|
|
70
|
+
assert getattr(SOTestSO1.sqlmeta.columns['passwd'], 'title', None) is None
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
class SOTestSO2(SQLObject):
|
|
74
|
+
name = StringCol(length=50, dbName='name_col')
|
|
75
|
+
passwd = StringCol(length=10)
|
|
76
|
+
|
|
77
|
+
def _set_passwd(self, passwd):
|
|
78
|
+
self._SO_set_passwd(codecs.encode(passwd, 'rot13'))
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def test_case2():
|
|
82
|
+
setupGetters(SOTestSO2)
|
|
83
|
+
bob = SOTestSO2.selectBy(name='bob')[0]
|
|
84
|
+
assert bob.name == 'bob'
|
|
85
|
+
assert bob.passwd == codecs.encode('god', 'rot13')
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
class Student(SQLObject):
|
|
89
|
+
is_smart = BoolCol()
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def test_boolCol():
|
|
93
|
+
setupClass(Student)
|
|
94
|
+
student = Student(is_smart=False)
|
|
95
|
+
assert not student.is_smart
|
|
96
|
+
student2 = Student(is_smart=1)
|
|
97
|
+
assert student2.is_smart
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
class SOTestSO3(SQLObject):
|
|
101
|
+
name = StringCol(length=10, dbName='name_col')
|
|
102
|
+
other = ForeignKey('SOTestSO4', default=None)
|
|
103
|
+
other2 = KeyCol(foreignKey='SOTestSO4', default=None)
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
class SOTestSO4(SQLObject):
|
|
107
|
+
me = StringCol(length=10)
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def test_foreignKey():
|
|
111
|
+
setupClass([SOTestSO4, SOTestSO3])
|
|
112
|
+
test3_order = [col.name for col in SOTestSO3.sqlmeta.columnList]
|
|
113
|
+
assert test3_order == ['name', 'otherID', 'other2ID']
|
|
114
|
+
tc3 = SOTestSO3(name='a')
|
|
115
|
+
assert tc3.other is None
|
|
116
|
+
assert tc3.other2 is None
|
|
117
|
+
assert tc3.otherID is None
|
|
118
|
+
assert tc3.other2ID is None
|
|
119
|
+
tc4a = SOTestSO4(me='1')
|
|
120
|
+
tc3.other = tc4a
|
|
121
|
+
assert tc3.other == tc4a
|
|
122
|
+
assert tc3.otherID == tc4a.id
|
|
123
|
+
tc4b = SOTestSO4(me='2')
|
|
124
|
+
tc3.other = tc4b.id
|
|
125
|
+
assert tc3.other == tc4b
|
|
126
|
+
assert tc3.otherID == tc4b.id
|
|
127
|
+
tc4c = SOTestSO4(me='3')
|
|
128
|
+
tc3.other2 = tc4c
|
|
129
|
+
assert tc3.other2 == tc4c
|
|
130
|
+
assert tc3.other2ID == tc4c.id
|
|
131
|
+
tc4d = SOTestSO4(me='4')
|
|
132
|
+
tc3.other2 = tc4d.id
|
|
133
|
+
assert tc3.other2 == tc4d
|
|
134
|
+
assert tc3.other2ID == tc4d.id
|
|
135
|
+
tcc = SOTestSO3(name='b', other=tc4a)
|
|
136
|
+
assert tcc.other == tc4a
|
|
137
|
+
tcc2 = SOTestSO3(name='c', other=tc4a.id)
|
|
138
|
+
assert tcc2.other == tc4a
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
def test_selectBy():
|
|
142
|
+
setupClass([SOTestSO4, SOTestSO3])
|
|
143
|
+
tc4 = SOTestSO4(me='another')
|
|
144
|
+
tc3 = SOTestSO3(name='sel', other=tc4)
|
|
145
|
+
SOTestSO3(name='not joined')
|
|
146
|
+
assert tc3.other == tc4
|
|
147
|
+
assert list(SOTestSO3.selectBy(other=tc4)) == [tc3]
|
|
148
|
+
assert list(SOTestSO3.selectBy(otherID=tc4.id)) == [tc3]
|
|
149
|
+
assert SOTestSO3.selectBy(otherID=tc4.id)[0] == tc3
|
|
150
|
+
assert list(SOTestSO3.selectBy(otherID=tc4.id)[:10]) == [tc3]
|
|
151
|
+
assert list(SOTestSO3.selectBy(other=tc4)[:10]) == [tc3]
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
class SOTestSO5(SQLObject):
|
|
155
|
+
name = StringCol(length=10, dbName='name_col')
|
|
156
|
+
other = ForeignKey('SOTestSO6', default=None, cascade=True)
|
|
157
|
+
another = ForeignKey('SOTestSO7', default=None, cascade=True)
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
class SOTestSO6(SQLObject):
|
|
161
|
+
name = StringCol(length=10, dbName='name_col')
|
|
162
|
+
other = ForeignKey('SOTestSO7', default=None, cascade=True)
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
class SOTestSO7(SQLObject):
|
|
166
|
+
name = StringCol(length=10, dbName='name_col')
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
def test_foreignKeyDestroySelfCascade():
|
|
170
|
+
setupClass([SOTestSO7, SOTestSO6, SOTestSO5])
|
|
171
|
+
|
|
172
|
+
tc5 = SOTestSO5(name='a')
|
|
173
|
+
tc6a = SOTestSO6(name='1')
|
|
174
|
+
tc5.other = tc6a
|
|
175
|
+
tc7a = SOTestSO7(name='2')
|
|
176
|
+
tc6a.other = tc7a
|
|
177
|
+
tc5.another = tc7a
|
|
178
|
+
assert tc5.other == tc6a
|
|
179
|
+
assert tc5.otherID == tc6a.id
|
|
180
|
+
assert tc6a.other == tc7a
|
|
181
|
+
assert tc6a.otherID == tc7a.id
|
|
182
|
+
assert tc5.other.other == tc7a
|
|
183
|
+
assert tc5.other.otherID == tc7a.id
|
|
184
|
+
assert tc5.another == tc7a
|
|
185
|
+
assert tc5.anotherID == tc7a.id
|
|
186
|
+
assert tc5.other.other == tc5.another
|
|
187
|
+
assert SOTestSO5.select().count() == 1
|
|
188
|
+
assert SOTestSO6.select().count() == 1
|
|
189
|
+
assert SOTestSO7.select().count() == 1
|
|
190
|
+
tc6b = SOTestSO6(name='3')
|
|
191
|
+
tc6c = SOTestSO6(name='4')
|
|
192
|
+
tc7b = SOTestSO7(name='5')
|
|
193
|
+
tc6b.other = tc7b
|
|
194
|
+
tc6c.other = tc7b
|
|
195
|
+
assert SOTestSO5.select().count() == 1
|
|
196
|
+
assert SOTestSO6.select().count() == 3
|
|
197
|
+
assert SOTestSO7.select().count() == 2
|
|
198
|
+
tc6b.destroySelf()
|
|
199
|
+
assert SOTestSO5.select().count() == 1
|
|
200
|
+
assert SOTestSO6.select().count() == 2
|
|
201
|
+
assert SOTestSO7.select().count() == 2
|
|
202
|
+
tc7b.destroySelf()
|
|
203
|
+
assert SOTestSO5.select().count() == 1
|
|
204
|
+
assert SOTestSO6.select().count() == 1
|
|
205
|
+
assert SOTestSO7.select().count() == 1
|
|
206
|
+
tc7a.destroySelf()
|
|
207
|
+
assert SOTestSO5.select().count() == 0
|
|
208
|
+
assert SOTestSO6.select().count() == 0
|
|
209
|
+
assert SOTestSO7.select().count() == 0
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
def testForeignKeyDropTableCascade():
|
|
213
|
+
if not supports('dropTableCascade'):
|
|
214
|
+
pytest.skip("dropTableCascade isn't supported")
|
|
215
|
+
setupClass(SOTestSO7)
|
|
216
|
+
setupClass(SOTestSO6)
|
|
217
|
+
setupClass(SOTestSO5)
|
|
218
|
+
|
|
219
|
+
tc5a = SOTestSO5(name='a')
|
|
220
|
+
tc6a = SOTestSO6(name='1')
|
|
221
|
+
tc5a.other = tc6a
|
|
222
|
+
tc7a = SOTestSO7(name='2')
|
|
223
|
+
tc6a.other = tc7a
|
|
224
|
+
tc5a.another = tc7a
|
|
225
|
+
tc5b = SOTestSO5(name='b')
|
|
226
|
+
tc5c = SOTestSO5(name='c')
|
|
227
|
+
tc6b = SOTestSO6(name='3')
|
|
228
|
+
tc5c.other = tc6b
|
|
229
|
+
assert SOTestSO5.select().count() == 3
|
|
230
|
+
assert SOTestSO6.select().count() == 2
|
|
231
|
+
assert SOTestSO7.select().count() == 1
|
|
232
|
+
SOTestSO7.dropTable(cascade=True)
|
|
233
|
+
assert SOTestSO5.select().count() == 3
|
|
234
|
+
assert SOTestSO6.select().count() == 2
|
|
235
|
+
tc6a.destroySelf()
|
|
236
|
+
assert SOTestSO5.select().count() == 2
|
|
237
|
+
assert SOTestSO6.select().count() == 1
|
|
238
|
+
tc6b.destroySelf()
|
|
239
|
+
assert SOTestSO5.select().count() == 1
|
|
240
|
+
assert SOTestSO6.select().count() == 0
|
|
241
|
+
assert next(iter(SOTestSO5.select())) == tc5b
|
|
242
|
+
tc6c = SOTestSO6(name='3')
|
|
243
|
+
tc5b.other = tc6c
|
|
244
|
+
assert SOTestSO5.select().count() == 1
|
|
245
|
+
assert SOTestSO6.select().count() == 1
|
|
246
|
+
tc6c.destroySelf()
|
|
247
|
+
assert SOTestSO5.select().count() == 0
|
|
248
|
+
assert SOTestSO6.select().count() == 0
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
class SOTestSO8(SQLObject):
|
|
252
|
+
name = StringCol(length=10, dbName='name_col')
|
|
253
|
+
other = ForeignKey('SOTestSO9', default=None, cascade=False)
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
class SOTestSO9(SQLObject):
|
|
257
|
+
name = StringCol(length=10, dbName='name_col')
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
def testForeignKeyDestroySelfRestrict():
|
|
261
|
+
setupClass([SOTestSO9, SOTestSO8])
|
|
262
|
+
|
|
263
|
+
tc8a = SOTestSO8(name='a')
|
|
264
|
+
tc9a = SOTestSO9(name='1')
|
|
265
|
+
tc8a.other = tc9a
|
|
266
|
+
tc8b = SOTestSO8(name='b')
|
|
267
|
+
tc9b = SOTestSO9(name='2')
|
|
268
|
+
assert tc8a.other == tc9a
|
|
269
|
+
assert tc8a.otherID == tc9a.id
|
|
270
|
+
assert SOTestSO8.select().count() == 2
|
|
271
|
+
assert SOTestSO9.select().count() == 2
|
|
272
|
+
raises(Exception, tc9a.destroySelf)
|
|
273
|
+
tc9b.destroySelf()
|
|
274
|
+
assert SOTestSO8.select().count() == 2
|
|
275
|
+
assert SOTestSO9.select().count() == 1
|
|
276
|
+
tc8a.destroySelf()
|
|
277
|
+
tc8b.destroySelf()
|
|
278
|
+
tc9a.destroySelf()
|
|
279
|
+
assert SOTestSO8.select().count() == 0
|
|
280
|
+
assert SOTestSO9.select().count() == 0
|
|
281
|
+
|
|
282
|
+
|
|
283
|
+
class SOTestSO10(SQLObject):
|
|
284
|
+
name = StringCol()
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
class SOTestSO11(SQLObject):
|
|
288
|
+
name = StringCol()
|
|
289
|
+
other = ForeignKey('SOTestSO10', default=None, cascade='null')
|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
def testForeignKeySetNull():
|
|
293
|
+
setupClass([SOTestSO10, SOTestSO11])
|
|
294
|
+
obj1 = SOTestSO10(name='foo')
|
|
295
|
+
obj2 = SOTestSO10(name='bar')
|
|
296
|
+
dep1 = SOTestSO11(name='xxx', other=obj1)
|
|
297
|
+
dep2 = SOTestSO11(name='yyy', other=obj1)
|
|
298
|
+
dep3 = SOTestSO11(name='zzz', other=obj2)
|
|
299
|
+
for name in 'xxx', 'yyy', 'zzz':
|
|
300
|
+
assert len(list(SOTestSO11.selectBy(name=name))) == 1
|
|
301
|
+
obj1.destroySelf()
|
|
302
|
+
for name in 'xxx', 'yyy', 'zzz':
|
|
303
|
+
assert len(list(SOTestSO11.selectBy(name=name))) == 1
|
|
304
|
+
assert dep1.other is None
|
|
305
|
+
assert dep2.other is None
|
|
306
|
+
assert dep3.other is obj2
|
|
307
|
+
|
|
308
|
+
|
|
309
|
+
def testAsDict():
|
|
310
|
+
setupGetters(SOTestSO1)
|
|
311
|
+
bob = SOTestSO1.selectBy(name='bob')[0]
|
|
312
|
+
assert bob.sqlmeta.asDict() == {
|
|
313
|
+
'passwd': 'tbq', 'name': 'bob', 'id': bob.id}
|
|
314
|
+
|
|
315
|
+
|
|
316
|
+
def test_nonexisting_attr():
|
|
317
|
+
setupClass(Student)
|
|
318
|
+
raises(AttributeError, getattr, Student.q, 'nonexisting')
|
|
319
|
+
|
|
320
|
+
|
|
321
|
+
class SOTestSO12(SQLObject):
|
|
322
|
+
name = StringCol()
|
|
323
|
+
so_value = IntCol(defaultSQL='1')
|
|
324
|
+
|
|
325
|
+
|
|
326
|
+
def test_defaultSQL():
|
|
327
|
+
setupClass(SOTestSO12)
|
|
328
|
+
test = SOTestSO12(name="test")
|
|
329
|
+
assert test.so_value == 1
|
|
330
|
+
|
|
331
|
+
|
|
332
|
+
def test_connection_override():
|
|
333
|
+
sqlhub.processConnection = connectionForURI('sqlite:///db1')
|
|
334
|
+
|
|
335
|
+
class SOTestSO13(SQLObject):
|
|
336
|
+
_connection = connectionForURI('sqlite:///db2')
|
|
337
|
+
|
|
338
|
+
assert SOTestSO13._connection.uri() == 'sqlite:///db2'
|
|
339
|
+
del sqlhub.processConnection
|
|
340
|
+
|
|
341
|
+
|
|
342
|
+
def _test_wrong_sqlmeta_idType():
|
|
343
|
+
class SOTestSO13(SQLObject):
|
|
344
|
+
class sqlmeta:
|
|
345
|
+
idType = dict
|
|
346
|
+
|
|
347
|
+
|
|
348
|
+
def test_wrong_sqlmeta_idType():
|
|
349
|
+
pytest.raises(TypeError, _test_wrong_sqlmeta_idType)
|
|
350
|
+
|
|
351
|
+
|
|
352
|
+
def _test_wrong_sqlmeta_idSize():
|
|
353
|
+
class SOTestSO14(SQLObject):
|
|
354
|
+
class sqlmeta:
|
|
355
|
+
idSize = 'DEFAULT'
|
|
356
|
+
|
|
357
|
+
|
|
358
|
+
def test_wrong_sqlmeta_idSize():
|
|
359
|
+
pytest.raises(ValueError, _test_wrong_sqlmeta_idSize)
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
from sqlobject import BLOBCol, SQLObject
|
|
3
|
+
from sqlobject.compat import PY2
|
|
4
|
+
from sqlobject.tests.dbtest import setupClass, supports
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
########################################
|
|
8
|
+
# BLOB columns
|
|
9
|
+
########################################
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class ImageData(SQLObject):
|
|
13
|
+
image = BLOBCol(default=b'emptydata', length=256)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def test_BLOBCol():
|
|
17
|
+
if not supports('blobData'):
|
|
18
|
+
pytest.skip("blobData isn't supported")
|
|
19
|
+
setupClass(ImageData)
|
|
20
|
+
if PY2:
|
|
21
|
+
data = ''.join([chr(x) for x in range(256)])
|
|
22
|
+
else:
|
|
23
|
+
data = bytes(range(256))
|
|
24
|
+
|
|
25
|
+
prof = ImageData(image=data)
|
|
26
|
+
iid = prof.id
|
|
27
|
+
|
|
28
|
+
ImageData._connection.cache.clear()
|
|
29
|
+
|
|
30
|
+
prof2 = ImageData.get(iid)
|
|
31
|
+
assert prof2.image == data
|
|
32
|
+
|
|
33
|
+
ImageData(image=b'string')
|
|
34
|
+
assert ImageData.selectBy(image=b'string').count() == 1
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
|
|
3
|
+
from sqlobject import boundattributes
|
|
4
|
+
from sqlobject import declarative
|
|
5
|
+
|
|
6
|
+
pytestmark = pytest.mark.skipif(
|
|
7
|
+
True,
|
|
8
|
+
reason='The module "boundattributes" and its tests were not finished yet')
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class SOTestMe(object):
|
|
12
|
+
pass
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class AttrReplace(boundattributes.BoundAttribute):
|
|
16
|
+
|
|
17
|
+
__unpackargs__ = ('replace',)
|
|
18
|
+
|
|
19
|
+
replace = None
|
|
20
|
+
|
|
21
|
+
@declarative.classinstancemethod
|
|
22
|
+
def make_object(self, cls, added_class, attr_name, **attrs):
|
|
23
|
+
if not self:
|
|
24
|
+
return cls.singleton().make_object(
|
|
25
|
+
added_class, attr_name, **attrs)
|
|
26
|
+
self.replace.added_class = added_class
|
|
27
|
+
self.replace.name = attr_name
|
|
28
|
+
assert attrs['replace'] is self.replace
|
|
29
|
+
del attrs['replace']
|
|
30
|
+
self.replace.attrs = attrs
|
|
31
|
+
return self.replace
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class Holder:
|
|
35
|
+
def __init__(self, name):
|
|
36
|
+
self.holder_name = name
|
|
37
|
+
|
|
38
|
+
def __repr__(self):
|
|
39
|
+
return '<Holder %s>' % self.holder_name
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def test_1():
|
|
43
|
+
v1 = Holder('v1')
|
|
44
|
+
v2 = Holder('v2')
|
|
45
|
+
v3 = Holder('v3')
|
|
46
|
+
|
|
47
|
+
class V2Class(AttrReplace):
|
|
48
|
+
arg1 = 'nothing'
|
|
49
|
+
arg2 = ['something']
|
|
50
|
+
|
|
51
|
+
class A1(SOTestMe):
|
|
52
|
+
a = AttrReplace(v1)
|
|
53
|
+
v = V2Class(v2)
|
|
54
|
+
|
|
55
|
+
class inline(AttrReplace):
|
|
56
|
+
replace = v3
|
|
57
|
+
arg3 = 'again'
|
|
58
|
+
arg4 = 'so there'
|
|
59
|
+
for n in ('a', 'v', 'inline'):
|
|
60
|
+
assert getattr(A1, n).name == n
|
|
61
|
+
assert getattr(A1, n).added_class is A1
|
|
62
|
+
assert A1.a is v1
|
|
63
|
+
assert A1.a.attrs == {}
|
|
64
|
+
assert A1.v is v2
|
|
65
|
+
assert A1.v.attrs == {'arg1': 'nothing', 'arg2': ['something']}
|
|
66
|
+
assert A1.inline is v3
|
|
67
|
+
assert A1.inline.attrs == {'arg3': 'again', 'arg4': 'so there'}
|