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,150 @@
1
+ from sqlobject import ForeignKey, SQLObject, StringCol, \
2
+ SQLObjectIntegrityError, SQLObjectNotFound
3
+ from sqlobject.tests.dbtest import raises, setupClass
4
+
5
+
6
+ class SOTestPerson1(SQLObject):
7
+ name = StringCol()
8
+
9
+
10
+ class SOTestMessageCascadeTrue(SQLObject):
11
+ sender = ForeignKey('SOTestPerson1', cascade=True)
12
+ recipient = ForeignKey('SOTestPerson1', cascade=True)
13
+ body = StringCol()
14
+
15
+
16
+ def test1():
17
+ setupClass([SOTestPerson1, SOTestMessageCascadeTrue])
18
+
19
+ john = SOTestPerson1(name='john')
20
+ emily = SOTestPerson1(name='emily')
21
+ message = SOTestMessageCascadeTrue(
22
+ sender=emily, recipient=john, body='test1'
23
+ )
24
+
25
+ SOTestPerson1.delete(emily.id)
26
+ john.expire()
27
+ message.expire()
28
+
29
+ john.sync()
30
+ raises(SQLObjectNotFound, emily.sync)
31
+ raises(SQLObjectNotFound, message.sync)
32
+
33
+
34
+ class SOTestPerson2(SQLObject):
35
+ name = StringCol()
36
+
37
+
38
+ class SOTestMessageCascadeFalse(SQLObject):
39
+ sender = ForeignKey('SOTestPerson2', cascade=False)
40
+ recipient = ForeignKey('SOTestPerson2', cascade=False)
41
+ body = StringCol()
42
+
43
+
44
+ def test2():
45
+ setupClass([SOTestPerson2, SOTestMessageCascadeFalse])
46
+
47
+ john = SOTestPerson2(name='john')
48
+ emily = SOTestPerson2(name='emily')
49
+ message = SOTestMessageCascadeFalse(
50
+ sender=emily, recipient=john, body='test2'
51
+ )
52
+
53
+ raises(SQLObjectIntegrityError, SOTestPerson2.delete, emily.id)
54
+ john.expire()
55
+ emily.expire()
56
+ message.expire()
57
+
58
+ john.sync()
59
+ emily.sync()
60
+ message.sync()
61
+
62
+ assert message.sender == emily
63
+ assert message.recipient == john
64
+
65
+
66
+ class SOTestPerson3(SQLObject):
67
+ name = StringCol()
68
+
69
+
70
+ class SOTestMessageCascadeNull(SQLObject):
71
+ sender = ForeignKey('SOTestPerson3', cascade='null')
72
+ recipient = ForeignKey('SOTestPerson3', cascade='null')
73
+ body = StringCol()
74
+
75
+
76
+ def test3():
77
+ setupClass([SOTestPerson3, SOTestMessageCascadeNull])
78
+
79
+ john = SOTestPerson3(name='john')
80
+ emily = SOTestPerson3(name='emily')
81
+ message = SOTestMessageCascadeNull(
82
+ sender=emily, recipient=john, body='test3'
83
+ )
84
+
85
+ SOTestPerson3.delete(emily.id)
86
+ john.expire()
87
+ message.expire()
88
+
89
+ john.sync()
90
+ message.sync()
91
+ raises(SQLObjectNotFound, emily.sync)
92
+
93
+ assert message.sender is None
94
+ assert message.recipient == john
95
+
96
+ SOTestPerson3.delete(john.id)
97
+ john.expire()
98
+ message.expire()
99
+
100
+ message.sync()
101
+ raises(SQLObjectNotFound, john.sync)
102
+
103
+ assert message.recipient is None
104
+
105
+
106
+ class SOTestPerson4(SQLObject):
107
+ name = StringCol()
108
+
109
+
110
+ class SOTestMessageCascadeMixed(SQLObject):
111
+ sender = ForeignKey('SOTestPerson4', cascade=True)
112
+ recipient = ForeignKey('SOTestPerson4', cascade='null')
113
+ body = StringCol()
114
+
115
+
116
+ def test4():
117
+ setupClass([SOTestPerson4, SOTestMessageCascadeMixed])
118
+
119
+ john = SOTestPerson4(name='john')
120
+ emily = SOTestPerson4(name='emily')
121
+ message = SOTestMessageCascadeMixed(
122
+ sender=emily, recipient=john, body='test4'
123
+ )
124
+
125
+ SOTestPerson4.delete(emily.id)
126
+ john.expire()
127
+ message.expire()
128
+
129
+ john.sync()
130
+ raises(SQLObjectNotFound, message.sync)
131
+
132
+
133
+ def test5():
134
+ setupClass([SOTestPerson4, SOTestMessageCascadeMixed])
135
+
136
+ john = SOTestPerson4(name='john')
137
+ emily = SOTestPerson4(name='emily')
138
+ message = SOTestMessageCascadeMixed(
139
+ sender=emily, recipient=john, body='test5'
140
+ )
141
+
142
+ john.destroySelf()
143
+ emily.expire()
144
+ message.expire()
145
+
146
+ emily.sync()
147
+ message.sync()
148
+
149
+ assert message.recipient is None
150
+ assert message.sender == emily
@@ -0,0 +1,33 @@
1
+ # Test that selectResults handle NULL values from, for example, outer joins.
2
+
3
+ from sqlobject import ForeignKey, SQLObject, StringCol, sqlbuilder
4
+ from sqlobject.tests.dbtest import setupClass
5
+
6
+
7
+ class SOTestComposer(SQLObject):
8
+ name = StringCol()
9
+
10
+
11
+ class SOTestWork(SQLObject):
12
+ class sqlmeta:
13
+ idName = "work_id"
14
+
15
+ composer = ForeignKey('SOTestComposer')
16
+ title = StringCol()
17
+
18
+
19
+ def test1():
20
+ setupClass([SOTestComposer,
21
+ SOTestWork])
22
+
23
+ c = SOTestComposer(name='Mahler, Gustav')
24
+ w = SOTestWork(composer=c, title='Symphony No. 9')
25
+ SOTestComposer(name='Bruckner, Anton')
26
+ # but don't add any works for Bruckner
27
+
28
+ # do a left join, a common use case that often involves NULL results
29
+ s = SOTestWork.select(
30
+ join=sqlbuilder.LEFTJOINOn(
31
+ SOTestComposer, SOTestWork,
32
+ SOTestComposer.q.id == SOTestWork.q.composerID))
33
+ assert tuple(s) == (w, None)
@@ -0,0 +1,65 @@
1
+ import pytest
2
+ from sqlobject import ForeignKey, IntCol, MultipleJoin, SQLMultipleJoin, \
3
+ SQLObject, StringCol
4
+ from sqlobject.tests.dbtest import setupClass, supports
5
+
6
+
7
+ class Race(SQLObject):
8
+ name = StringCol()
9
+ fightersAsList = MultipleJoin('RFighter', joinColumn="rf_id")
10
+ fightersAsSResult = SQLMultipleJoin('RFighter', joinColumn="rf_id")
11
+
12
+
13
+ class RFighter(SQLObject):
14
+ name = StringCol()
15
+ race = ForeignKey('Race', dbName="rf_id")
16
+ power = IntCol()
17
+
18
+
19
+ def createAllTables():
20
+ setupClass([Race, RFighter])
21
+
22
+
23
+ def test_1():
24
+ createAllTables()
25
+ # create some races
26
+ human = Race(name='human')
27
+ saiyajin = Race(name='saiyajin')
28
+ hibrid = Race(name='hibrid (human with sayajin)')
29
+ namek = Race(name='namekuseijin')
30
+ # create some fighters
31
+ RFighter(name='Gokou (Kakaruto)', race=saiyajin, power=10)
32
+ RFighter(name='Vegeta', race=saiyajin, power=9)
33
+ RFighter(name='Krilim', race=human, power=3)
34
+ RFighter(name='Yancha', race=human, power=2)
35
+ RFighter(name='Jackie Chan', race=human, power=2)
36
+ RFighter(name='Gohan', race=hibrid, power=8)
37
+ RFighter(name='Goten', race=hibrid, power=7)
38
+ trunks = RFighter(name='Trunks', race=hibrid, power=8)
39
+ picollo = RFighter(name='Picollo', race=namek, power=6)
40
+ RFighter(name='Neil', race=namek, power=5)
41
+
42
+ # testing the SQLMultipleJoin stuff
43
+ for i, j in zip(human.fightersAsList, human.fightersAsSResult):
44
+ assert i is j # the 2 ways should give the same result
45
+ assert namek.fightersAsSResult.count() == len(namek.fightersAsList)
46
+ assert saiyajin.fightersAsSResult.max('power') == 10
47
+ assert trunks in hibrid.fightersAsSResult
48
+ assert picollo not in hibrid.fightersAsSResult
49
+ assert str(hibrid.fightersAsSResult.sum('power')) == '23'
50
+
51
+
52
+ def test_multiple_join_transaction():
53
+ if not supports('transactions'):
54
+ pytest.skip("Transactions aren't supported")
55
+ createAllTables()
56
+ trans = Race._connection.transaction()
57
+ try:
58
+ namek = Race(name='namekuseijin', connection=trans)
59
+ RFighter(name='Gokou (Kakaruto)', race=namek, power=10,
60
+ connection=trans)
61
+ assert namek.fightersAsSResult.count() == 1
62
+ assert namek.fightersAsSResult[0]._connection == trans
63
+ finally:
64
+ trans.commit(True)
65
+ Race._connection.autoCommit = True
@@ -0,0 +1,114 @@
1
+ import pytest
2
+ from sqlobject import RelatedJoin, SQLObject, SQLRelatedJoin, StringCol, \
3
+ ForeignKey
4
+ from sqlobject.sqlbuilder import Alias
5
+ from sqlobject.tests.dbtest import setupClass, supports
6
+
7
+
8
+ class Fighter(SQLObject):
9
+ class sqlmeta:
10
+ idName = 'fighter_id' # test on a non-standard way
11
+ name = StringCol()
12
+ tourtments = RelatedJoin('Tourtment')
13
+
14
+
15
+ class Tourtment(SQLObject):
16
+ class sqlmeta:
17
+ table = 'competition' # test on a non-standard way
18
+ name = StringCol()
19
+ fightersAsList = RelatedJoin('Fighter')
20
+ fightersAsSResult = SQLRelatedJoin('Fighter')
21
+
22
+
23
+ def createAllTables():
24
+ setupClass(Fighter)
25
+ setupClass(Tourtment)
26
+
27
+
28
+ def createData():
29
+ createAllTables()
30
+ # create some tourtments
31
+ t1 = Tourtment(name='Tourtment #1')
32
+ t2 = Tourtment(name='Tourtment #2')
33
+ t3 = Tourtment(name='Tourtment #3')
34
+ # create some fighters
35
+ gokou = Fighter(name='gokou')
36
+ vegeta = Fighter(name='vegeta')
37
+ gohan = Fighter(name='gohan')
38
+ trunks = Fighter(name='trunks')
39
+ # relating them
40
+ t1.addFighter(gokou)
41
+ t1.addFighter(vegeta)
42
+ t1.addFighter(gohan)
43
+ t2.addFighter(gokou)
44
+ t2.addFighter(vegeta)
45
+ t2.addFighter(trunks)
46
+ t3.addFighter(gohan)
47
+ t3.addFighter(trunks)
48
+ return t1, t2, t3, gokou, vegeta, gohan, trunks
49
+
50
+
51
+ def test_1():
52
+ t1, t2, t3, gokou, vegeta, gohan, trunks = createData()
53
+ for i, j in zip(t1.fightersAsList, t1.fightersAsSResult):
54
+ assert i is j
55
+ assert len(t2.fightersAsList) == t2.fightersAsSResult.count()
56
+
57
+
58
+ def test_related_join_transaction():
59
+ if not supports('transactions'):
60
+ pytest.skip("Transactions aren't supported")
61
+ createAllTables()
62
+ trans = Tourtment._connection.transaction()
63
+ try:
64
+ t1 = Tourtment(name='Tourtment #1', connection=trans)
65
+ t1.addFighter(Fighter(name='Jim', connection=trans))
66
+ assert t1.fightersAsSResult.count() == 1
67
+ assert t1.fightersAsSResult[0]._connection == trans
68
+ finally:
69
+ trans.commit(True)
70
+ Tourtment._connection.autoCommit = True
71
+
72
+
73
+ def test_related_join_filter():
74
+ t1, t2, t3, gokou, vegeta, gohan, trunks = createData()
75
+ filteredFighters = t1.fightersAsSResult.filter(
76
+ Fighter.q.name.startswith('go')
77
+ ).orderBy('id')
78
+ for i, j in zip(filteredFighters, [gokou, gohan]):
79
+ assert i is j
80
+
81
+
82
+ class RecursiveGroup(SQLObject):
83
+ name = StringCol(length=255, unique=True)
84
+ subgroups = SQLRelatedJoin(
85
+ 'RecursiveGroup',
86
+ otherColumn='group_id',
87
+ intermediateTable='rec_group_map',
88
+ createRelatedTable=False,
89
+ )
90
+
91
+
92
+ class RecGroupMap(SQLObject):
93
+ recursive_group = ForeignKey('RecursiveGroup')
94
+ group = ForeignKey('RecursiveGroup')
95
+
96
+
97
+ def test_rec_group():
98
+ setupClass([RecursiveGroup, RecGroupMap])
99
+ a = RecursiveGroup(name='a')
100
+ a1 = RecursiveGroup(name='a1')
101
+ a.addRecursiveGroup(a1)
102
+ a2 = RecursiveGroup(name='a2')
103
+ a.addRecursiveGroup(a2)
104
+
105
+ assert sorted(a.subgroups, key=lambda x: x.name) == [a1, a2]
106
+
107
+ pytest.raises(
108
+ ValueError,
109
+ a.subgroups.filter,
110
+ RecursiveGroup.q.name == 'a1',
111
+ )
112
+
113
+ rgroupAlias = Alias(RecursiveGroup, '_SO_SQLRelatedJoin_OtherTable')
114
+ assert list(a.subgroups.filter(rgroupAlias.q.name == 'a1')) == [a1]
@@ -0,0 +1,30 @@
1
+ from sqlobject import ForeignKey, SQLObject, SingleJoin, StringCol
2
+ from sqlobject.tests.dbtest import setupClass
3
+
4
+
5
+ class PersonWithAlbum(SQLObject):
6
+ name = StringCol()
7
+ # albumNone returns the album or none
8
+ albumNone = SingleJoin('PhotoAlbum', joinColumn='test_person_id')
9
+ # albumInstance returns the album or an default album instance
10
+ albumInstance = SingleJoin('PhotoAlbum', makeDefault=True,
11
+ joinColumn='test_person_id')
12
+
13
+
14
+ class PhotoAlbum(SQLObject):
15
+ color = StringCol(default='red')
16
+ person = ForeignKey('PersonWithAlbum', dbName='test_person_id')
17
+
18
+
19
+ def test_1():
20
+ setupClass([PersonWithAlbum, PhotoAlbum])
21
+
22
+ person = PersonWithAlbum(name='Gokou (Kakarouto)')
23
+ # We didn't create an album, this way it returns None
24
+ assert not person.albumNone
25
+ assert isinstance(person.albumInstance, PhotoAlbum)
26
+
27
+ PhotoAlbum(person=person)
28
+ assert person.albumNone
29
+ assert isinstance(person.albumNone, PhotoAlbum)
30
+ assert isinstance(person.albumInstance, PhotoAlbum)
@@ -0,0 +1,75 @@
1
+ from sqlobject import FloatCol, IntCol, SQLObject
2
+ from sqlobject.tests.dbtest import setupClass
3
+
4
+
5
+ # Test MIN, AVG, MAX, COUNT, SUM
6
+
7
+
8
+ class IntAccumulator(SQLObject):
9
+ so_value = IntCol()
10
+
11
+
12
+ class FloatAccumulator(SQLObject):
13
+ so_value = FloatCol()
14
+
15
+
16
+ def test_integer():
17
+ setupClass(IntAccumulator)
18
+ IntAccumulator(so_value=1)
19
+ IntAccumulator(so_value=2)
20
+ IntAccumulator(so_value=3)
21
+
22
+ assert IntAccumulator.select().min(IntAccumulator.q.so_value) == 1
23
+ assert IntAccumulator.select().avg(IntAccumulator.q.so_value) == 2
24
+ assert IntAccumulator.select().max(IntAccumulator.q.so_value) == 3
25
+ assert IntAccumulator.select().sum(IntAccumulator.q.so_value) == 6
26
+
27
+ assert IntAccumulator.select(IntAccumulator.q.so_value > 1).\
28
+ max(IntAccumulator.q.so_value) == 3
29
+ assert IntAccumulator.select(IntAccumulator.q.so_value > 1).\
30
+ sum(IntAccumulator.q.so_value) == 5
31
+
32
+
33
+ def floatcmp(f1, f2):
34
+ if abs(f1 - f2) < 0.1:
35
+ return 0
36
+ if f1 < f2:
37
+ return 1
38
+ return -1
39
+
40
+
41
+ def test_float():
42
+ setupClass(FloatAccumulator)
43
+ FloatAccumulator(so_value=1.2)
44
+ FloatAccumulator(so_value=2.4)
45
+ FloatAccumulator(so_value=3.8)
46
+
47
+ assert floatcmp(
48
+ FloatAccumulator.select().min(FloatAccumulator.q.so_value), 1.2) == 0
49
+ assert floatcmp(
50
+ FloatAccumulator.select().avg(FloatAccumulator.q.so_value), 2.5) == 0
51
+ assert floatcmp(
52
+ FloatAccumulator.select().max(FloatAccumulator.q.so_value), 3.8) == 0
53
+ assert floatcmp(
54
+ FloatAccumulator.select().sum(FloatAccumulator.q.so_value), 7.4) == 0
55
+
56
+
57
+ def test_many():
58
+ setupClass(IntAccumulator)
59
+ IntAccumulator(so_value=1)
60
+ IntAccumulator(so_value=1)
61
+ IntAccumulator(so_value=2)
62
+ IntAccumulator(so_value=2)
63
+ IntAccumulator(so_value=3)
64
+ IntAccumulator(so_value=3)
65
+
66
+ attribute = IntAccumulator.q.so_value
67
+ assert list(IntAccumulator.select().accumulateMany(
68
+ ("MIN", attribute), ("AVG", attribute), ("MAX", attribute),
69
+ ("COUNT", attribute), ("SUM", attribute)
70
+ )) == [1, 2, 3, 6, 12]
71
+
72
+ assert list(IntAccumulator.select(distinct=True).accumulateMany(
73
+ ("MIN", attribute), ("AVG", attribute), ("MAX", attribute),
74
+ ("COUNT", attribute), ("SUM", attribute)
75
+ )) == [1, 2, 3, 3, 6]
@@ -0,0 +1,49 @@
1
+ from sqlobject import SQLObject, StringCol
2
+ from sqlobject.sqlbuilder import Alias, LEFTJOINOn
3
+ from sqlobject.tests.dbtest import setupClass
4
+
5
+
6
+ ########################################
7
+ # Table aliases and self-joins
8
+ ########################################
9
+
10
+
11
+ class JoinAlias(SQLObject):
12
+ name = StringCol()
13
+ parent = StringCol()
14
+
15
+
16
+ def test_1syntax():
17
+ setupClass(JoinAlias)
18
+ alias = Alias(JoinAlias)
19
+ select = JoinAlias.select(JoinAlias.q.parent == alias.q.name)
20
+ assert str(select) == \
21
+ "SELECT join_alias.id, join_alias.name, join_alias.parent " \
22
+ "FROM join_alias, join_alias join_alias_alias1 " \
23
+ "WHERE ((join_alias.parent) = (join_alias_alias1.name))"
24
+
25
+
26
+ def test_2perform_join():
27
+ setupClass(JoinAlias)
28
+ JoinAlias(name="grandparent", parent=None)
29
+ JoinAlias(name="parent", parent="grandparent")
30
+ JoinAlias(name="child", parent="parent")
31
+ alias = Alias(JoinAlias)
32
+ select = JoinAlias.select(JoinAlias.q.parent == alias.q.name)
33
+ assert select.count() == 2
34
+
35
+
36
+ def test_3joins():
37
+ setupClass(JoinAlias)
38
+ alias = Alias(JoinAlias)
39
+ select = JoinAlias.select(
40
+ (JoinAlias.q.name == 'a') & (alias.q.name == 'b'),
41
+ join=LEFTJOINOn(None, alias, alias.q.name == 'c')
42
+ )
43
+ assert str(select) == \
44
+ "SELECT join_alias.id, join_alias.name, join_alias.parent " \
45
+ "FROM join_alias " \
46
+ "LEFT JOIN join_alias join_alias_alias3 " \
47
+ "ON ((join_alias_alias3.name) = ('c')) " \
48
+ "WHERE (((join_alias.name) = ('a')) AND " \
49
+ "((join_alias_alias3.name) = ('b')))"
@@ -0,0 +1,18 @@
1
+ from sqlobject import SQLObject, StringCol
2
+ from sqlobject.tests.dbtest import setupClass
3
+
4
+
5
+ ########################################
6
+ # sqlmeta.asDict()
7
+ ########################################
8
+
9
+
10
+ class SOTestAsDict(SQLObject):
11
+ name = StringCol(length=10)
12
+ name2 = StringCol(length=10)
13
+
14
+
15
+ def test_asDict():
16
+ setupClass(SOTestAsDict, force=True)
17
+ t1 = SOTestAsDict(name='one', name2='1')
18
+ assert t1.sqlmeta.asDict() == dict(name='one', name2='1', id=1)