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
@@ -0,0 +1,22 @@
1
+ import pytest
2
+ from sqlobject import SQLObject
3
+ from sqlobject.tests.dbtest import setupClass, supports
4
+
5
+
6
+ class EmptyClass(SQLObject):
7
+
8
+ pass
9
+
10
+
11
+ def test_empty():
12
+ if not supports('emptyTable'):
13
+ pytest.skip("emptyTable isn't supported")
14
+ setupClass(EmptyClass)
15
+ e1 = EmptyClass()
16
+ e2 = EmptyClass()
17
+ assert e1 != e2
18
+ assert e1.id != e2.id
19
+ assert e1 in list(EmptyClass.select())
20
+ assert e2 in list(EmptyClass.select())
21
+ e1.destroySelf()
22
+ assert list(EmptyClass.select()) == [e2]
@@ -0,0 +1,75 @@
1
+ from sqlobject import EnumCol, SQLObject, UnicodeCol
2
+ from sqlobject.col import validators
3
+ from sqlobject.tests.dbtest import raises, setupClass
4
+
5
+
6
+ ########################################
7
+ # Enum test
8
+ ########################################
9
+
10
+
11
+ class Enum1(SQLObject):
12
+
13
+ cl = EnumCol(enumValues=['a', 'bcd', 'e'])
14
+
15
+
16
+ def testBad():
17
+ setupClass(Enum1)
18
+ for _l in ['a', 'bcd', 'a', 'e']:
19
+ Enum1(cl=_l)
20
+ raises(
21
+ (Enum1._connection.module.IntegrityError,
22
+ Enum1._connection.module.ProgrammingError,
23
+ validators.Invalid),
24
+ Enum1, cl='b')
25
+
26
+
27
+ class EnumWithNone(SQLObject):
28
+
29
+ cl = EnumCol(enumValues=['a', 'bcd', 'e', None])
30
+
31
+
32
+ def testNone():
33
+ setupClass(EnumWithNone)
34
+ for _l in [None, 'a', 'bcd', 'a', 'e', None]:
35
+ e = EnumWithNone(cl=_l)
36
+ assert e.cl == _l
37
+
38
+
39
+ class EnumWithDefaultNone(SQLObject):
40
+
41
+ cl = EnumCol(enumValues=['a', 'bcd', 'e', None], default=None)
42
+
43
+
44
+ def testDefaultNone():
45
+ setupClass(EnumWithDefaultNone)
46
+
47
+ e = EnumWithDefaultNone()
48
+ assert e.cl is None
49
+
50
+
51
+ class EnumWithDefaultOther(SQLObject):
52
+
53
+ cl = EnumCol(enumValues=['a', 'bcd', 'e', None], default='a')
54
+
55
+
56
+ def testDefaultOther():
57
+ setupClass(EnumWithDefaultOther)
58
+
59
+ e = EnumWithDefaultOther()
60
+ assert e.cl == 'a'
61
+
62
+
63
+ class EnumUnicode(SQLObject):
64
+
65
+ n = UnicodeCol()
66
+ cl = EnumCol(enumValues=['a', 'b'])
67
+
68
+
69
+ def testUnicode():
70
+ setupClass(EnumUnicode)
71
+
72
+ EnumUnicode(n=u'a', cl='a')
73
+ EnumUnicode(n=u'b', cl=u'b')
74
+ EnumUnicode(n=u'\u201c', cl='a')
75
+ EnumUnicode(n=u'\u201c', cl=u'b')
@@ -0,0 +1,142 @@
1
+ from __future__ import print_function
2
+
3
+ from sqlobject import IntCol, SQLObject, StringCol, events
4
+ from sqlobject.inheritance import InheritableSQLObject
5
+ from sqlobject.tests.dbtest import setupClass
6
+
7
+
8
+ class EventTester(SQLObject):
9
+ name = StringCol()
10
+
11
+
12
+ def make_watcher():
13
+ log = []
14
+
15
+ def watch(*args):
16
+ log.append(args)
17
+
18
+ watch.log = log
19
+ return watch
20
+
21
+
22
+ def make_listen(signal, cls=None):
23
+ if cls is None:
24
+ cls = EventTester
25
+ watcher = make_watcher()
26
+ events.listen(watcher, cls, signal)
27
+ return watcher
28
+
29
+
30
+ def test_create():
31
+ watcher = make_listen(events.ClassCreateSignal)
32
+
33
+ class EventTesterSub1(EventTester):
34
+ pass
35
+
36
+ class EventTesterSub2(EventTesterSub1):
37
+ pass
38
+
39
+ assert len(watcher.log) == 2
40
+ assert len(watcher.log[0]) == 5
41
+ assert watcher.log[0][0] == 'EventTesterSub1'
42
+ assert watcher.log[0][1] == (EventTester,)
43
+ assert isinstance(watcher.log[0][2], dict)
44
+ assert isinstance(watcher.log[0][3], list)
45
+
46
+
47
+ def test_row_create():
48
+ setupClass(EventTester)
49
+ watcher = make_listen(events.RowCreateSignal)
50
+ row1 = EventTester(name='foo')
51
+ row2 = EventTester(name='bar')
52
+ assert len(watcher.log) == 2
53
+ assert watcher.log == [
54
+ (row1, {'name': 'foo'}, []),
55
+ (row2, {'name': 'bar'}, [])]
56
+
57
+
58
+ def test_row_destroy():
59
+ setupClass(EventTester)
60
+ watcher = make_listen(events.RowDestroySignal)
61
+ f = EventTester(name='foo')
62
+ assert not watcher.log
63
+ f.destroySelf()
64
+ assert watcher.log == [(f, [])]
65
+
66
+
67
+ def test_row_destroyed():
68
+ setupClass(EventTester)
69
+ watcher = make_listen(events.RowDestroyedSignal)
70
+ f = EventTester(name='foo')
71
+ assert not watcher.log
72
+ f.destroySelf()
73
+ assert watcher.log == [(f, [])]
74
+
75
+
76
+ def test_row_update():
77
+ setupClass(EventTester)
78
+ watcher = make_listen(events.RowUpdateSignal)
79
+ f = EventTester(name='bar')
80
+ assert not watcher.log
81
+ f.name = 'bar2'
82
+ f.set(name='bar3')
83
+ assert watcher.log == [
84
+ (f, {'name': 'bar2'}),
85
+ (f, {'name': 'bar3'})]
86
+
87
+
88
+ def test_row_updated():
89
+ setupClass(EventTester)
90
+ watcher = make_listen(events.RowUpdatedSignal)
91
+ f = EventTester(name='bar')
92
+ assert not watcher.log
93
+ f.name = 'bar2'
94
+ f.set(name='bar3')
95
+ assert watcher.log == [(f, []), (f, [])]
96
+
97
+
98
+ def test_add_column():
99
+ setupClass(EventTester)
100
+ watcher = make_listen(events.AddColumnSignal)
101
+ events.summarize_events_by_sender()
102
+
103
+ class NewEventTester(EventTester):
104
+ name2 = StringCol()
105
+
106
+ expect = (
107
+ NewEventTester, None,
108
+ 'name2', NewEventTester.sqlmeta.columnDefinitions['name2'],
109
+ False, [])
110
+ print(zip(watcher.log[1], expect))
111
+ assert watcher.log[1] == expect
112
+
113
+
114
+ class InheritableEventTestA(InheritableSQLObject):
115
+ a = IntCol()
116
+
117
+
118
+ class InheritableEventTestB(InheritableEventTestA):
119
+ b = IntCol()
120
+
121
+
122
+ class InheritableEventTestC(InheritableEventTestB):
123
+ c = IntCol()
124
+
125
+
126
+ def _query(instance):
127
+ row = InheritableEventTestA.get(instance.id)
128
+ assert isinstance(row, InheritableEventTestC)
129
+ assert row.c == 3
130
+
131
+
132
+ def _signal(instance, kwargs, postfuncs):
133
+ postfuncs.append(_query)
134
+
135
+
136
+ def test_inheritance_row_created():
137
+ setupClass([InheritableEventTestA, InheritableEventTestB,
138
+ InheritableEventTestC])
139
+
140
+ events.listen(_signal, InheritableEventTestA, events.RowCreatedSignal)
141
+
142
+ InheritableEventTestC(a=1, b=2, c=3)
@@ -0,0 +1,40 @@
1
+ import pytest
2
+ from sqlobject import SQLObject, StringCol
3
+ from sqlobject.dberrors import DatabaseError, DuplicateEntryError, \
4
+ OperationalError, ProgrammingError
5
+ from sqlobject.tests.dbtest import getConnection, raises, setupClass, supports
6
+
7
+
8
+ ########################################
9
+ # Table aliases and self-joins
10
+ ########################################
11
+
12
+
13
+ class SOTestException(SQLObject):
14
+ name = StringCol(unique=True, length=100)
15
+
16
+
17
+ class SOTestExceptionWithNonexistingTable(SQLObject):
18
+ pass
19
+
20
+
21
+ def test_exceptions():
22
+ if not supports("exceptions"):
23
+ pytest.skip("exceptions aren't supported")
24
+ setupClass(SOTestException)
25
+ SOTestException(name="test")
26
+ raises(DuplicateEntryError, SOTestException, name="test")
27
+
28
+ connection = getConnection()
29
+ SOTestExceptionWithNonexistingTable.setConnection(connection)
30
+ try:
31
+ list(SOTestExceptionWithNonexistingTable.select())
32
+ except ProgrammingError as e:
33
+ assert e.args[0].code in (1146, '42P01')
34
+ except OperationalError:
35
+ assert connection.dbName == 'sqlite'
36
+ except DatabaseError:
37
+ assert connection.dbName == 'postgres' \
38
+ and connection.driver == 'pg8000'
39
+ else:
40
+ assert False, "DID NOT RAISE"
@@ -0,0 +1,29 @@
1
+ from sqlobject import SQLObject, StringCol
2
+ from sqlobject.tests.dbtest import setupClass
3
+
4
+
5
+ ########################################
6
+ # Expiring, syncing
7
+ ########################################
8
+
9
+
10
+ class SyncTest(SQLObject):
11
+ name = StringCol(length=50, alternateID=True, dbName='name_col')
12
+
13
+
14
+ def test_expire():
15
+ setupClass(SyncTest)
16
+ SyncTest(name='bob')
17
+ SyncTest(name='tim')
18
+
19
+ conn = SyncTest._connection
20
+ b = SyncTest.byName('bob')
21
+ conn.query("UPDATE sync_test SET name_col = 'robert' WHERE id = %i"
22
+ % b.id)
23
+ assert b.name == 'bob'
24
+ b.expire()
25
+ assert b.name == 'robert'
26
+ conn.query("UPDATE sync_test SET name_col = 'bobby' WHERE id = %i"
27
+ % b.id)
28
+ b.sync()
29
+ assert b.name == 'bobby'
@@ -0,0 +1,45 @@
1
+ from sqlobject import IntCol, SQLObject, StringCol
2
+ from sqlobject.sqlbuilder import Select, func
3
+ from sqlobject.tests.dbtest import getConnection, setupClass
4
+
5
+
6
+ ########################################
7
+ # groupBy
8
+ ########################################
9
+
10
+
11
+ class GroupbyTest(SQLObject):
12
+ name = StringCol()
13
+ so_value = IntCol()
14
+
15
+
16
+ def test_groupBy():
17
+ setupClass(GroupbyTest)
18
+ GroupbyTest(name='a', so_value=1)
19
+ GroupbyTest(name='a', so_value=2)
20
+ GroupbyTest(name='b', so_value=1)
21
+
22
+ connection = getConnection()
23
+ select = Select(
24
+ [GroupbyTest.q.name, func.COUNT(GroupbyTest.q.so_value)],
25
+ groupBy=GroupbyTest.q.name,
26
+ orderBy=GroupbyTest.q.name)
27
+ sql = connection.sqlrepr(select)
28
+ rows = list(connection.queryAll(sql))
29
+ assert [tuple(t) for t in rows] == [('a', 2), ('b', 1)]
30
+
31
+
32
+ def test_groupBy_list():
33
+ setupClass(GroupbyTest)
34
+ GroupbyTest(name='a', so_value=1)
35
+ GroupbyTest(name='a', so_value=2)
36
+ GroupbyTest(name='b', so_value=1)
37
+
38
+ connection = getConnection()
39
+ select = Select(
40
+ [GroupbyTest.q.name, GroupbyTest.q.so_value],
41
+ groupBy=[GroupbyTest.q.name, GroupbyTest.q.so_value],
42
+ orderBy=[GroupbyTest.q.name, GroupbyTest.q.so_value])
43
+ sql = connection.sqlrepr(select)
44
+ rows = list(connection.queryAll(sql))
45
+ assert [tuple(t) for t in rows] == [('a', 1), ('a', 2), ('b', 1)]
@@ -0,0 +1,29 @@
1
+ from sqlobject import IntCol, SQLObject
2
+ from sqlobject.tests.dbtest import getConnection, setupClass
3
+
4
+
5
+ ########################################
6
+ # Identity (MS SQL)
7
+ ########################################
8
+
9
+
10
+ class SOTestIdentity(SQLObject):
11
+ n = IntCol()
12
+
13
+
14
+ def test_identity():
15
+ # (re)create table
16
+ SOTestIdentity.dropTable(connection=getConnection(), ifExists=True)
17
+ setupClass(SOTestIdentity)
18
+
19
+ # insert without giving identity
20
+ SOTestIdentity(n=100) # i1
21
+ # verify result
22
+ i1get = SOTestIdentity.get(1)
23
+ assert (i1get.n == 100)
24
+
25
+ # insert while giving identity
26
+ SOTestIdentity(id=2, n=200) # i2
27
+ # verify result
28
+ i2get = SOTestIdentity.get(2)
29
+ assert (i2get.n == 200)
@@ -0,0 +1,100 @@
1
+ import pytest
2
+ from sqlobject import DatabaseIndex, ForeignKey, IntCol, MultipleJoin, \
3
+ SQLObject, StringCol
4
+ from sqlobject.dberrors import DatabaseError, IntegrityError, \
5
+ OperationalError, ProgrammingError
6
+ from sqlobject.tests.dbtest import raises, setupClass, supports
7
+
8
+
9
+ ########################################
10
+ # Indexes
11
+ ########################################
12
+
13
+
14
+ class SOIndex1(SQLObject):
15
+ name = StringCol(length=100)
16
+ number = IntCol()
17
+
18
+ nameIndex = DatabaseIndex('name', unique=True)
19
+ nameIndex2 = DatabaseIndex(name, number)
20
+ nameIndex3 = DatabaseIndex({'column': name,
21
+ 'length': 3})
22
+
23
+
24
+ class SOIndex2(SQLObject):
25
+ name = StringCol(length=100)
26
+ nameIndex = DatabaseIndex({'expression': 'lower(name)'})
27
+
28
+
29
+ def test_indexes_1():
30
+ setupClass(SOIndex1)
31
+ n = 0
32
+ for name in 'blah blech boring yep yort snort'.split():
33
+ n += 1
34
+ SOIndex1(name=name, number=n)
35
+ mod = SOIndex1._connection.module
36
+ raises(
37
+ (mod.ProgrammingError, mod.IntegrityError,
38
+ mod.OperationalError, mod.DatabaseError,
39
+ ProgrammingError, IntegrityError, OperationalError, DatabaseError),
40
+ SOIndex1, name='blah', number=0)
41
+
42
+
43
+ def test_indexes_2():
44
+ if not supports('expressionIndex'):
45
+ pytest.skip("expressionIndex isn't supported")
46
+ setupClass(SOIndex2)
47
+ SOIndex2(name='')
48
+
49
+
50
+ class PersonIndexGet(SQLObject):
51
+ firstName = StringCol(length=100)
52
+ lastName = StringCol(length=100)
53
+ age = IntCol(alternateID=True)
54
+ nameIndex = DatabaseIndex(firstName, lastName, unique=True)
55
+
56
+
57
+ def test_index_get_1():
58
+ setupClass(PersonIndexGet, force=True)
59
+
60
+ PersonIndexGet(firstName='Eric', lastName='Idle', age=62)
61
+ PersonIndexGet(firstName='Terry', lastName='Gilliam', age=65)
62
+ PersonIndexGet(firstName='John', lastName='Cleese', age=66)
63
+
64
+ PersonIndexGet.get(1)
65
+ PersonIndexGet.nameIndex.get('Terry', 'Gilliam')
66
+ PersonIndexGet.nameIndex.get(firstName='John', lastName='Cleese')
67
+
68
+ raises(Exception, PersonIndexGet.nameIndex.get,
69
+ firstName='Graham', lastName='Chapman')
70
+
71
+ raises(Exception, PersonIndexGet.nameIndex.get,
72
+ 'Terry', lastName='Gilliam')
73
+
74
+ raises(Exception, PersonIndexGet.nameIndex.get, 'Terry', 'Gilliam', 65)
75
+
76
+ raises(Exception, PersonIndexGet.nameIndex.get, 'Terry')
77
+
78
+
79
+ class PersonIndexGet2(SQLObject):
80
+ name = StringCol(alternateID=True, length=100)
81
+ age = IntCol()
82
+ addresses = MultipleJoin('AddressIndexGet2')
83
+
84
+
85
+ class AddressIndexGet2(SQLObject):
86
+ person = ForeignKey('PersonIndexGet2', notNone=True)
87
+ type = StringCol(notNone=True, length=100)
88
+ street = StringCol(notNone=True)
89
+ pk = DatabaseIndex(person, type, unique=True)
90
+
91
+
92
+ def test_index_get_2():
93
+ setupClass([PersonIndexGet2, AddressIndexGet2])
94
+
95
+ p = PersonIndexGet2(name='Terry Guilliam', age=64)
96
+ AddressIndexGet2(person=p, type='home', street='Terry Street 234')
97
+ AddressIndexGet2(person=p, type='work', street='Guilliam Street 234')
98
+
99
+ AddressIndexGet2.pk.get(p, 'work')
100
+ AddressIndexGet2.pk.get(person=p, type='work')
@@ -0,0 +1,35 @@
1
+ from sqlobject import SQLObject, StringCol
2
+ from sqlobject.tests.dbtest import setupClass
3
+
4
+
5
+ ########################################
6
+ # Inheritance
7
+ ########################################
8
+
9
+
10
+ class Super(SQLObject):
11
+
12
+ name = StringCol(length=10)
13
+
14
+
15
+ class Sub(Super):
16
+
17
+ name2 = StringCol(length=10)
18
+
19
+
20
+ def test_super():
21
+ setupClass(Super)
22
+ setupClass(Sub)
23
+ s1 = Super(name='one')
24
+ Super(name='two') # s2
25
+ s3 = Super.get(s1.id)
26
+ assert s1 == s3
27
+
28
+
29
+ def test_sub():
30
+ setupClass(Super)
31
+ setupClass(Sub)
32
+ s1 = Sub(name='one', name2='1')
33
+ Sub(name='two', name2='2') # s2
34
+ s3 = Sub.get(s1.id)
35
+ assert s1 == s3
@@ -0,0 +1,160 @@
1
+ from sqlobject import ForeignKey, MultipleJoin, RelatedJoin, SQLObject, \
2
+ StringCol
3
+ from sqlobject.tests.dbtest import setupClass
4
+
5
+
6
+ ########################################
7
+ # Joins
8
+ ########################################
9
+
10
+
11
+ class PersonJoiner(SQLObject):
12
+
13
+ name = StringCol(length=40, alternateID=True)
14
+ addressJoiners = RelatedJoin('AddressJoiner')
15
+
16
+
17
+ class AddressJoiner(SQLObject):
18
+
19
+ zip = StringCol(length=5, alternateID=True)
20
+ personJoiners = RelatedJoin('PersonJoiner')
21
+
22
+
23
+ class ImplicitJoiningSO(SQLObject):
24
+ foo = RelatedJoin('Bar')
25
+
26
+
27
+ class ExplicitJoiningSO(SQLObject):
28
+ foo = MultipleJoin('Bar', joinMethodName='foo')
29
+
30
+
31
+ class TestJoin:
32
+
33
+ def setup_method(self, meth):
34
+ setupClass(PersonJoiner)
35
+ setupClass(AddressJoiner)
36
+ for n in ['bob', 'tim', 'jane', 'joe', 'fred', 'barb']:
37
+ PersonJoiner(name=n)
38
+ for z in ['11111', '22222', '33333', '44444']:
39
+ AddressJoiner(zip=z)
40
+
41
+ def test_join(self):
42
+ b = PersonJoiner.byName('bob')
43
+ assert b.addressJoiners == []
44
+ z = AddressJoiner.byZip('11111')
45
+ b.addAddressJoiner(z)
46
+ self.assertZipsEqual(b.addressJoiners, ['11111'])
47
+ self.assertNamesEqual(z.personJoiners, ['bob'])
48
+ z2 = AddressJoiner.byZip('22222')
49
+ b.addAddressJoiner(z2)
50
+ self.assertZipsEqual(b.addressJoiners, ['11111', '22222'])
51
+ self.assertNamesEqual(z2.personJoiners, ['bob'])
52
+ b.removeAddressJoiner(z)
53
+ self.assertZipsEqual(b.addressJoiners, ['22222'])
54
+ self.assertNamesEqual(z.personJoiners, [])
55
+
56
+ def assertZipsEqual(self, zips, dest):
57
+ assert [a.zip for a in zips] == dest
58
+
59
+ def assertNamesEqual(self, people, dest):
60
+ assert [p.name for p in people] == dest
61
+
62
+ def test_joinAttributeWithUnderscores(self):
63
+ # Make sure that the implicit setting of joinMethodName works
64
+ assert hasattr(ImplicitJoiningSO, 'foo')
65
+ assert not hasattr(ImplicitJoiningSO, 'bars')
66
+
67
+ # And make sure explicit setting also works
68
+ assert hasattr(ExplicitJoiningSO, 'foo')
69
+ assert not hasattr(ExplicitJoiningSO, 'bars')
70
+
71
+
72
+ class PersonJoiner2(SQLObject):
73
+
74
+ name = StringCol('name', length=40, alternateID=True)
75
+ addressJoiner2s = MultipleJoin('AddressJoiner2')
76
+
77
+
78
+ class AddressJoiner2(SQLObject):
79
+
80
+ class sqlmeta:
81
+ defaultOrder = ['-zip', 'plus4']
82
+
83
+ zip = StringCol(length=5)
84
+ plus4 = StringCol(length=4, default=None)
85
+ personJoiner2 = ForeignKey('PersonJoiner2')
86
+
87
+
88
+ class TestJoin2:
89
+
90
+ def setup_method(self, meth):
91
+ setupClass([PersonJoiner2, AddressJoiner2])
92
+ p1 = PersonJoiner2(name='bob')
93
+ p2 = PersonJoiner2(name='sally')
94
+ for z in ['11111', '22222', '33333']:
95
+ AddressJoiner2(zip=z, personJoiner2=p1)
96
+ AddressJoiner2(zip='00000', personJoiner2=p2)
97
+
98
+ def test_basic(self):
99
+ bob = PersonJoiner2.byName('bob')
100
+ sally = PersonJoiner2.byName('sally')
101
+ assert len(bob.addressJoiner2s) == 3
102
+ assert len(sally.addressJoiner2s) == 1
103
+ bob.addressJoiner2s[0].destroySelf()
104
+ assert len(bob.addressJoiner2s) == 2
105
+ z = bob.addressJoiner2s[0]
106
+ z.zip = 'xxxxx'
107
+ id = z.id
108
+ del z
109
+ z = AddressJoiner2.get(id)
110
+ assert z.zip == 'xxxxx'
111
+
112
+ def test_defaultOrder(self):
113
+ p1 = PersonJoiner2.byName('bob')
114
+ assert ([i.zip for i in p1.addressJoiner2s]
115
+ == ['33333', '22222', '11111'])
116
+
117
+
118
+ _personJoiner3_getters = []
119
+ _personJoiner3_setters = []
120
+
121
+
122
+ class PersonJoiner3(SQLObject):
123
+
124
+ name = StringCol('name', length=40, alternateID=True)
125
+ addressJoiner3s = MultipleJoin('AddressJoiner3')
126
+
127
+
128
+ class AddressJoiner3(SQLObject):
129
+
130
+ zip = StringCol(length=5)
131
+ personJoiner3 = ForeignKey('PersonJoiner3')
132
+
133
+ def _get_personJoiner3(self):
134
+ value = self._SO_get_personJoiner3()
135
+ _personJoiner3_getters.append((self, value))
136
+ return value
137
+
138
+ def _set_personJoiner3(self, value):
139
+ self._SO_set_personJoiner3(value)
140
+ _personJoiner3_setters.append((self, value))
141
+
142
+
143
+ class TestJoin3:
144
+
145
+ def setup_method(self, meth):
146
+ setupClass([PersonJoiner3, AddressJoiner3])
147
+ p1 = PersonJoiner3(name='bob')
148
+ p2 = PersonJoiner3(name='sally')
149
+ for z in ['11111', '22222', '33333']:
150
+ AddressJoiner3(zip=z, personJoiner3=p1)
151
+ AddressJoiner3(zip='00000', personJoiner3=p2)
152
+
153
+ def test_accessors(self):
154
+ assert len(_personJoiner3_getters) == 0
155
+ assert len(_personJoiner3_setters) == 4
156
+ bob = PersonJoiner3.byName('bob')
157
+ for addressJoiner3 in bob.addressJoiner3s:
158
+ addressJoiner3.personJoiner3
159
+ assert len(_personJoiner3_getters) == 3
160
+ assert len(_personJoiner3_setters) == 4