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,101 @@
1
+ from __future__ import print_function
2
+ try:
3
+ from StringIO import StringIO
4
+ except ImportError:
5
+ from io import StringIO
6
+
7
+ from sqlobject import IntCol, SQLObject, StringCol
8
+ from sqlobject.util.csvexport import export_csv, export_csv_zip
9
+ from .dbtest import setupClass
10
+
11
+
12
+ def assert_export(result, *args, **kw):
13
+ f = StringIO()
14
+ kw['writer'] = f
15
+ export_csv(*args, **kw)
16
+ s = f.getvalue().replace('\r\n', '\n')
17
+ if result.strip() != s.strip():
18
+ print('**Expected:')
19
+ print(result)
20
+ print('**Got:')
21
+ print(s)
22
+ assert result.strip() == s.strip()
23
+
24
+
25
+ class SimpleCSV(SQLObject):
26
+
27
+ name = StringCol()
28
+ address = StringCol()
29
+ address.csvTitle = 'Street Address'
30
+ hidden = StringCol()
31
+ hidden.noCSV = True
32
+
33
+
34
+ class ComplexCSV(SQLObject):
35
+
36
+ fname = StringCol()
37
+ lname = StringCol()
38
+ age = IntCol()
39
+ extraCSVColumns = [('name', 'Full Name'), 'initials']
40
+ # initials should end up at the end then:
41
+ csvColumnOrder = ['name', 'fname', 'lname', 'age']
42
+
43
+ def _get_name(self):
44
+ return self.fname + ' ' + self.lname
45
+
46
+ def _get_initials(self):
47
+ return self.fname[0] + self.lname[0]
48
+
49
+
50
+ def test_simple():
51
+ setupClass(SimpleCSV)
52
+ SimpleCSV(name='Bob', address='432W', hidden='boo')
53
+ SimpleCSV(name='Joe', address='123W', hidden='arg')
54
+ assert_export("""\
55
+ name,Street Address
56
+ Bob,432W
57
+ Joe,123W
58
+ """, SimpleCSV, orderBy='name')
59
+ assert_export("""\
60
+ name,Street Address
61
+ Joe,123W
62
+ Bob,432W
63
+ """, SimpleCSV, orderBy='address')
64
+ assert_export("""\
65
+ name,Street Address
66
+ Joe,123W
67
+ """, SimpleCSV.selectBy(name='Joe'))
68
+
69
+
70
+ def test_complex():
71
+ setupClass(ComplexCSV)
72
+ ComplexCSV(fname='John', lname='Doe', age=40)
73
+ ComplexCSV(fname='Bob', lname='Dylan', age=60)
74
+ ComplexCSV(fname='Harriet', lname='Tubman', age=160)
75
+ assert_export("""\
76
+ Full Name,fname,lname,age,initials
77
+ John Doe,John,Doe,40,JD
78
+ Bob Dylan,Bob,Dylan,60,BD
79
+ Harriet Tubman,Harriet,Tubman,160,HT
80
+ """, ComplexCSV, orderBy='lname')
81
+ assert_export("""\
82
+ Full Name,fname,lname,age,initials
83
+ Bob Dylan,Bob,Dylan,60,BD
84
+ John Doe,John,Doe,40,JD
85
+ """, ComplexCSV.select(ComplexCSV.q.lname.startswith('D'), orderBy='fname'))
86
+
87
+
88
+ def test_zip():
89
+ # Just exercise tests, doesn't actually test results
90
+ setupClass(SimpleCSV)
91
+ SimpleCSV(name='Bob', address='432W', hidden='boo')
92
+ SimpleCSV(name='Joe', address='123W', hidden='arg')
93
+
94
+ setupClass(ComplexCSV)
95
+ ComplexCSV(fname='John', lname='Doe', age=40)
96
+ ComplexCSV(fname='Bob', lname='Dylan', age=60)
97
+ ComplexCSV(fname='Harriet', lname='Tubman', age=160)
98
+ s = export_csv_zip([SimpleCSV, ComplexCSV])
99
+ assert isinstance(s, bytes) and s
100
+ s = export_csv_zip([SimpleCSV.selectBy(name='Bob'),
101
+ (ComplexCSV, list(ComplexCSV.selectBy(fname='John')))])
@@ -0,0 +1,21 @@
1
+ import csv
2
+ from datetime import datetime
3
+ from sqlobject.util.csvimport import load_csv
4
+
5
+ csv_data = """\
6
+ name:str,age:datetime,value:int
7
+ Test,2000-01-01 21:44:33,42"""
8
+
9
+
10
+ def test_load_csv():
11
+ loaded = load_csv(csv.reader(csv_data.split('\n')),
12
+ default_class='SQLObject')
13
+ assert loaded == {
14
+ 'SQLObject': [
15
+ {
16
+ 'age': datetime(2000, 1, 1, 21, 44, 33),
17
+ 'name': 'Test',
18
+ 'value': 42
19
+ }
20
+ ]
21
+ }
@@ -0,0 +1,55 @@
1
+ import pytest
2
+ from sqlobject import BLOBCol, DateTimeCol, ForeignKey, IntCol, SQLObject, \
3
+ StringCol, sqlmeta
4
+ from sqlobject.tests.dbtest import getConnection, supports
5
+
6
+
7
+ class SOTestCyclicRefA(SQLObject):
8
+ class sqlmeta(sqlmeta):
9
+ idName = 'test_id_here'
10
+ table = 'test_cyclic_ref_a_table'
11
+ name = StringCol()
12
+ number = IntCol()
13
+ so_time = DateTimeCol()
14
+ short = StringCol(length=10)
15
+ blobcol = BLOBCol()
16
+ fkeyb = ForeignKey('SOTestCyclicRefB')
17
+
18
+
19
+ class SOTestCyclicRefB(SQLObject):
20
+ class sqlmeta(sqlmeta):
21
+ idName = 'test_id_here'
22
+ table = 'test_cyclic_ref_b_table'
23
+ name = StringCol()
24
+ number = IntCol()
25
+ so_time = DateTimeCol()
26
+ short = StringCol(length=10)
27
+ blobcol = BLOBCol()
28
+ fkeya = ForeignKey('SOTestCyclicRefA')
29
+
30
+
31
+ def test_cyclic_reference():
32
+ if not supports('dropTableCascade'):
33
+ pytest.skip("dropTableCascade isn't supported")
34
+ conn = getConnection()
35
+ SOTestCyclicRefA.setConnection(conn)
36
+ SOTestCyclicRefB.setConnection(conn)
37
+ SOTestCyclicRefA.dropTable(ifExists=True, cascade=True)
38
+ assert not conn.tableExists(SOTestCyclicRefA.sqlmeta.table)
39
+ SOTestCyclicRefB.dropTable(ifExists=True, cascade=True)
40
+ assert not conn.tableExists(SOTestCyclicRefB.sqlmeta.table)
41
+
42
+ constraints = SOTestCyclicRefA.createTable(ifNotExists=True,
43
+ applyConstraints=False)
44
+ assert conn.tableExists(SOTestCyclicRefA.sqlmeta.table)
45
+ constraints += SOTestCyclicRefB.createTable(ifNotExists=True,
46
+ applyConstraints=False)
47
+ assert conn.tableExists(SOTestCyclicRefB.sqlmeta.table)
48
+
49
+ for constraint in constraints:
50
+ conn.query(constraint)
51
+
52
+ SOTestCyclicRefA.dropTable(ifExists=True, cascade=True)
53
+ assert not conn.tableExists(SOTestCyclicRefA.sqlmeta.table)
54
+ SOTestCyclicRefB.dropTable(ifExists=True, cascade=True)
55
+ assert not conn.tableExists(SOTestCyclicRefB.sqlmeta.table)
@@ -0,0 +1,171 @@
1
+ from datetime import datetime, date, time
2
+ import pytest
3
+
4
+ from sqlobject import SQLObject
5
+ from sqlobject import col
6
+ from sqlobject.col import DateCol, DateTimeCol, TimeCol, use_microseconds, \
7
+ DATETIME_IMPLEMENTATION, MXDATETIME_IMPLEMENTATION, mxdatetime_available, \
8
+ ZOPE_DATETIME_IMPLEMENTATION, zope_datetime_available
9
+ from sqlobject.tests.dbtest import getConnection, setupClass
10
+ from sqlobject.converters import pendulumDateTimeType
11
+
12
+ ########################################
13
+ # Date/time columns
14
+ ########################################
15
+
16
+
17
+ col.default_datetime_implementation = DATETIME_IMPLEMENTATION
18
+
19
+
20
+ class DateTime1(SQLObject):
21
+ col1 = DateTimeCol()
22
+ col2 = DateCol()
23
+ col3 = TimeCol()
24
+
25
+
26
+ def test_dateTime():
27
+ setupClass(DateTime1)
28
+ _now = datetime.now().replace(microsecond=0)
29
+ dt1 = DateTime1(col1=_now, col2=_now, col3=_now.time())
30
+
31
+ assert isinstance(dt1.col1, datetime)
32
+ assert dt1.col1.year == _now.year
33
+ assert dt1.col1.month == _now.month
34
+ assert dt1.col1.day == _now.day
35
+ assert dt1.col1.hour == _now.hour
36
+ assert dt1.col1.minute == _now.minute
37
+ assert dt1.col1.second == _now.second
38
+
39
+ assert isinstance(dt1.col2, date)
40
+ assert not isinstance(dt1.col2, datetime)
41
+ assert dt1.col2.year == _now.year
42
+ assert dt1.col2.month == _now.month
43
+ assert dt1.col2.day == _now.day
44
+
45
+ assert isinstance(dt1.col3, time)
46
+ assert dt1.col3.hour == _now.hour
47
+ assert dt1.col3.minute == _now.minute
48
+ assert dt1.col3.second == _now.second
49
+
50
+
51
+ def test_microseconds():
52
+ connection = getConnection()
53
+ if not hasattr(connection, 'can_use_microseconds') or \
54
+ not connection.can_use_microseconds():
55
+ pytest.skip(
56
+ "The database doesn't support microseconds; "
57
+ "microseconds are supported by MariaDB since version 5.3.0, "
58
+ "by MySQL since version 5.6.4, "
59
+ "by MSSQL since MS SQL Server 2008.")
60
+
61
+ setupClass(DateTime1)
62
+ _now = datetime.now()
63
+ dt1 = DateTime1(col1=_now, col2=_now, col3=_now.time())
64
+
65
+ assert dt1.col1.microsecond == _now.microsecond
66
+ assert dt1.col3.microsecond == _now.microsecond
67
+
68
+ use_microseconds(False)
69
+ setupClass(DateTime1)
70
+ _now = datetime.now()
71
+ dt1 = DateTime1(col1=_now, col2=_now, col3=_now.time())
72
+
73
+ assert dt1.col1.microsecond == 0
74
+ assert dt1.col3.microsecond == 0
75
+
76
+ use_microseconds(True)
77
+ setupClass(DateTime1)
78
+ _now = datetime.now()
79
+ dt1 = DateTime1(col1=_now, col2=_now, col3=_now.time())
80
+
81
+ assert dt1.col1.microsecond == _now.microsecond
82
+ assert dt1.col3.microsecond == _now.microsecond
83
+
84
+ if mxdatetime_available:
85
+ col.default_datetime_implementation = MXDATETIME_IMPLEMENTATION
86
+ from mx.DateTime import now as mx_now, Time as mxTime
87
+
88
+ dateFormat = None # use default
89
+ try:
90
+ connection = getConnection()
91
+ except AttributeError:
92
+ # The module was imported during documentation building
93
+ pass
94
+ else:
95
+ if connection.dbName == "sqlite":
96
+ # mxDateTime sends and sqlite3 returns
97
+ # full date/time for dates
98
+ dateFormat = "%Y-%m-%d %H:%M:%S.%f"
99
+
100
+ class DateTime2(SQLObject):
101
+ col1 = DateTimeCol()
102
+ col2 = DateCol(dateFormat=dateFormat)
103
+ col3 = TimeCol()
104
+
105
+ def test_mxDateTime():
106
+ setupClass(DateTime2)
107
+ _now = mx_now()
108
+ dt2 = DateTime2(col1=_now, col2=_now.pydate(),
109
+ col3=mxTime(_now.hour, _now.minute, _now.second))
110
+
111
+ assert isinstance(dt2.col1, col.mxDateTimeType)
112
+ assert dt2.col1.year == _now.year
113
+ assert dt2.col1.month == _now.month
114
+ assert dt2.col1.day == _now.day
115
+ assert dt2.col1.hour == _now.hour
116
+ assert dt2.col1.minute == _now.minute
117
+ assert dt2.col1.second == int(_now.second)
118
+
119
+ assert isinstance(dt2.col2, col.mxDateTimeType)
120
+ assert dt2.col2.year == _now.year
121
+ assert dt2.col2.month == _now.month
122
+ assert dt2.col2.day == _now.day
123
+ assert dt2.col2.hour == 0
124
+ assert dt2.col2.minute == 0
125
+ assert dt2.col2.second == 0
126
+
127
+ assert isinstance(dt2.col3, (col.mxDateTimeType, col.mxTimeType))
128
+ assert dt2.col3.hour == _now.hour
129
+ assert dt2.col3.minute == _now.minute
130
+ assert dt2.col3.second == int(_now.second)
131
+
132
+ if pendulumDateTimeType:
133
+ col.default_datetime_implementation = DATETIME_IMPLEMENTATION
134
+ import pendulum
135
+
136
+ class DateTimePendulum(SQLObject):
137
+ col1 = DateTimeCol()
138
+
139
+ def test_PendulumDateTime():
140
+ setupClass(DateTimePendulum)
141
+ _now = pendulum.now()
142
+ dtp = DateTimePendulum(col1=_now)
143
+
144
+ assert isinstance(dtp.col1, datetime)
145
+ assert dtp.col1.year == _now.year
146
+ assert dtp.col1.month == _now.month
147
+ assert dtp.col1.day == _now.day
148
+ assert dtp.col1.hour == _now.hour
149
+ assert dtp.col1.minute == _now.minute
150
+ assert int(dtp.col1.second) == int(_now.second)
151
+
152
+
153
+ if zope_datetime_available:
154
+ col.default_datetime_implementation = ZOPE_DATETIME_IMPLEMENTATION
155
+ from DateTime import DateTime as zopeDateTime
156
+
157
+ class DateTime3(SQLObject):
158
+ col1 = DateTimeCol()
159
+
160
+ def test_ZopeDateTime():
161
+ setupClass(DateTime3)
162
+ _now = zopeDateTime()
163
+ dt3 = DateTime3(col1=_now)
164
+
165
+ assert isinstance(dt3.col1, col.zopeDateTimeType)
166
+ assert dt3.col1.year() == _now.year()
167
+ assert dt3.col1.month() == _now.month()
168
+ assert dt3.col1.day() == _now.day()
169
+ assert dt3.col1.hour() == _now.hour()
170
+ assert dt3.col1.minute() == _now.minute()
171
+ assert int(dt3.col1.second()) == int(_now.second())
@@ -0,0 +1,17 @@
1
+ from pytest import raises
2
+ from sqlobject.dbconnection import DBConnection
3
+
4
+
5
+ def test_name():
6
+ connection = DBConnection(name='test')
7
+ connection.close = lambda: True
8
+
9
+ with raises(AssertionError) as error:
10
+ DBConnection(name='test')
11
+ assert str(error.value) == 'An instance has already been registered ' \
12
+ 'with the name test'
13
+
14
+ with raises(AssertionError) as error:
15
+ DBConnection(name='test:test')
16
+ assert str(error.value) == "You cannot include ':' " \
17
+ "in your DB connection names ('test:test')"
@@ -0,0 +1,63 @@
1
+ from decimal import Decimal
2
+ import pytest
3
+ from sqlobject import DecimalCol, DecimalStringCol, SQLObject, UnicodeCol
4
+ from sqlobject.tests.dbtest import setupClass, supports
5
+
6
+
7
+ ########################################
8
+ # Decimal columns
9
+ ########################################
10
+
11
+
12
+ try:
13
+ support_decimal_column = supports('decimalColumn')
14
+ except NameError:
15
+ # The module was imported during documentation building
16
+ pass
17
+ else:
18
+ if not support_decimal_column:
19
+ pytestmark = pytest.mark.skip("These tests require Decimal support")
20
+
21
+
22
+ class DecimalTable(SQLObject):
23
+ name = UnicodeCol(length=255)
24
+ col1 = DecimalCol(size=6, precision=4)
25
+ col2 = DecimalStringCol(size=6, precision=4)
26
+ col3 = DecimalStringCol(size=6, precision=4, quantize=True)
27
+
28
+
29
+ def test_1_decimal():
30
+ setupClass(DecimalTable)
31
+ d = DecimalTable(name='test', col1=21.12, col2='10.01', col3='10.01')
32
+ # psycopg2 returns float as Decimal
33
+ if isinstance(d.col1, Decimal):
34
+ assert d.col1 == Decimal("21.12")
35
+ else:
36
+ assert d.col1 == 21.12
37
+ assert d.col2 == Decimal("10.01")
38
+ assert DecimalTable.sqlmeta.columns['col2'].to_python(
39
+ '10.01', d._SO_validatorState) == Decimal("10.01")
40
+ assert DecimalTable.sqlmeta.columns['col2'].from_python(
41
+ '10.01', d._SO_validatorState) == "10.01"
42
+ assert d.col3 == Decimal("10.01")
43
+ assert DecimalTable.sqlmeta.columns['col3'].to_python(
44
+ '10.01', d._SO_validatorState) == Decimal("10.01")
45
+ assert DecimalTable.sqlmeta.columns['col3'].from_python(
46
+ '10.01', d._SO_validatorState) == "10.0100"
47
+
48
+
49
+ def test_2_decimal():
50
+ setupClass(DecimalTable)
51
+ d = DecimalTable(name='test', col1=Decimal("21.12"),
52
+ col2=Decimal('10.01'), col3=Decimal('10.01'))
53
+ assert d.col1 == Decimal("21.12")
54
+ assert d.col2 == Decimal("10.01")
55
+ assert DecimalTable.sqlmeta.columns['col2'].to_python(
56
+ Decimal('10.01'), d._SO_validatorState) == Decimal("10.01")
57
+ assert DecimalTable.sqlmeta.columns['col2'].from_python(
58
+ Decimal('10.01'), d._SO_validatorState) == "10.01"
59
+ assert d.col3 == Decimal("10.01")
60
+ assert DecimalTable.sqlmeta.columns['col3'].to_python(
61
+ Decimal('10.01'), d._SO_validatorState) == Decimal("10.01")
62
+ assert DecimalTable.sqlmeta.columns['col3'].from_python(
63
+ Decimal('10.01'), d._SO_validatorState) == "10.0100"
@@ -0,0 +1,83 @@
1
+ from sqlobject.declarative import Declarative
2
+
3
+
4
+ class A1(Declarative):
5
+
6
+ a = 1
7
+ b = []
8
+
9
+
10
+ class A2(A1):
11
+
12
+ a = 5
13
+
14
+ A3 = A2(b=5)
15
+
16
+
17
+ def test_a_classes():
18
+ assert A1.a == 1
19
+ assert A1.singleton().a == 1
20
+ assert A1.b is A2.b
21
+ assert A3.b == 5
22
+ assert A1.declarative_count == A1.singleton().declarative_count
23
+ assert A1.declarative_count < A2.declarative_count
24
+ assert A2.singleton() is not A1.singleton()
25
+ assert A3.singleton().b == A3.b
26
+
27
+
28
+ class B1(Declarative):
29
+
30
+ attrs = []
31
+
32
+ def __classinit__(cls, new_attrs):
33
+ Declarative.__classinit__(cls, new_attrs)
34
+ cls.attrs = cls.add_attrs(cls.attrs, new_attrs)
35
+
36
+ def __instanceinit__(self, new_attrs):
37
+ Declarative.__instanceinit__(self, new_attrs)
38
+ self.attrs = self.add_attrs(self.attrs, new_attrs)
39
+
40
+ @staticmethod
41
+ def add_attrs(old_attrs, new_attrs):
42
+ old_attrs = old_attrs[:]
43
+ for name in new_attrs.keys():
44
+ if (name in old_attrs or name.startswith('_')
45
+ or name in ('add_attrs', 'declarative_count', 'attrs')):
46
+ continue
47
+ old_attrs.append(name)
48
+ old_attrs.sort()
49
+ return old_attrs
50
+
51
+ c = 1
52
+
53
+
54
+ class B2(B1):
55
+
56
+ g = 3
57
+
58
+ def __classinit__(cls, new_attrs):
59
+ new_attrs['test'] = 'whatever'
60
+ B1.__classinit__(cls, new_attrs)
61
+
62
+ B3 = B2(c=5, d=3)
63
+ B4 = B3(d=5)
64
+ B5 = B1(a=1)
65
+
66
+
67
+ def test_b_classes():
68
+ assert B1.attrs == ['c']
69
+ assert B1.c == 1
70
+ assert B2.attrs == ['c', 'g', 'test']
71
+ assert B3.d == 3
72
+ assert B4.d == 5
73
+ assert B5.a == 1
74
+ assert B5.attrs == ['a', 'c']
75
+ assert B3.attrs == ['c', 'd', 'g', 'test']
76
+ assert B4.attrs == ['c', 'd', 'g', 'test']
77
+ order = [B1, B1.singleton(), B2, B2.singleton(),
78
+ B3, B3.singleton(), B4, B4.singleton(),
79
+ B5, B5.singleton()]
80
+ last = 0
81
+ for obj in order:
82
+ assert obj.declarative_count >= last
83
+ last = obj.declarative_count
@@ -0,0 +1,65 @@
1
+ """
2
+ Test the default styles, to guarantee consistency.
3
+ """
4
+
5
+ from sqlobject import ForeignKey, MixedCaseStyle, MixedCaseUnderscoreStyle, \
6
+ SQLObject, StringCol, Style
7
+
8
+ # Hash of styles versus the database names resulting from 'columns' below.
9
+ columns = ["ABCUpper", "abc_lower", "ABCamelCaseColumn"]
10
+ styles = {
11
+ Style: columns,
12
+ MixedCaseUnderscoreStyle: ["abc_upper", "abc_lower",
13
+ "ab_camel_case_column"],
14
+ MixedCaseStyle: ["ABCUpper", "Abc_lower", "ABCamelCaseColumn"],
15
+ }
16
+
17
+ # Hash of styles versus the database names
18
+ # resulting from a foreign key named 'FKey'.
19
+ fkey = ForeignKey("DefaultStyleTest", name="FKey")
20
+ fkeys = {
21
+ Style: "FKeyID",
22
+ MixedCaseUnderscoreStyle: "f_key_id",
23
+ MixedCaseStyle: "FKeyID",
24
+ }
25
+
26
+
27
+ def make_columns():
28
+ global columns
29
+ columns = []
30
+ for col_name in columns:
31
+ columns.append(StringCol(name=col_name, length=10))
32
+
33
+
34
+ def do_col_test(DefaultStyleTest, style, dbnames):
35
+ DefaultStyleTest.sqlmeta.style = style()
36
+ for col, old_dbname in zip(columns, dbnames):
37
+ DefaultStyleTest.sqlmeta.addColumn(col)
38
+ try:
39
+ new_dbname = DefaultStyleTest.sqlmeta.columns[col.name].dbName
40
+ assert new_dbname == old_dbname
41
+ finally:
42
+ if col.name in DefaultStyleTest.sqlmeta.columns:
43
+ DefaultStyleTest.sqlmeta.delColumn(col)
44
+
45
+
46
+ def do_fkey_test(DefaultStyleTest, style, dbname):
47
+ DefaultStyleTest.sqlmeta.style = style()
48
+ DefaultStyleTest.sqlmeta.addColumn(fkey)
49
+ try:
50
+ assert list(DefaultStyleTest.sqlmeta.columns.keys())[0] == "FKeyID"
51
+ assert list(DefaultStyleTest.sqlmeta.columns.values())[0].dbName == \
52
+ dbname
53
+ finally:
54
+ DefaultStyleTest.sqlmeta.delColumn(fkey)
55
+
56
+
57
+ class DefaultStyleTest(SQLObject):
58
+ pass
59
+
60
+
61
+ def test_default_styles():
62
+ make_columns()
63
+ for style in styles:
64
+ do_col_test(DefaultStyleTest, style, styles[style])
65
+ do_fkey_test(DefaultStyleTest, style, fkeys[style])
@@ -0,0 +1,74 @@
1
+ from sqlobject import OR, RelatedJoin, SQLObject, StringCol, cache
2
+ from sqlobject.tests.dbtest import setupClass
3
+ from .test_basic import SOTestSO1, setupGetters
4
+
5
+
6
+ ########################################
7
+ # Delete during select
8
+ ########################################
9
+
10
+
11
+ def testSelect():
12
+ setupGetters(SOTestSO1)
13
+ for obj in SOTestSO1.select('all'):
14
+ obj.destroySelf()
15
+ assert list(SOTestSO1.select('all')) == []
16
+
17
+
18
+ ########################################
19
+ # Delete many rows at once
20
+ ########################################
21
+
22
+
23
+ def testDeleteMany():
24
+ setupGetters(SOTestSO1)
25
+ SOTestSO1.deleteMany(OR(SOTestSO1.q.name == "bob",
26
+ SOTestSO1.q.name == "fred"))
27
+ assert len(list(SOTestSO1.select('all'))) == 2
28
+
29
+
30
+ def testDeleteBy():
31
+ setupGetters(SOTestSO1)
32
+ SOTestSO1.deleteBy(name="dave")
33
+ assert len(list(SOTestSO1.select())) == 3
34
+
35
+
36
+ ########################################
37
+ # Delete without caching
38
+ ########################################
39
+
40
+
41
+ class NoCache(SQLObject):
42
+ name = StringCol()
43
+
44
+
45
+ def testDestroySelf():
46
+ setupClass(NoCache)
47
+ old = NoCache._connection.cache
48
+ NoCache._connection.cache = cache.CacheSet(cache=False)
49
+ value = NoCache(name='test')
50
+ value.destroySelf()
51
+ NoCache._connection.cache = old
52
+
53
+
54
+ ########################################
55
+ # Delete from related joins
56
+ ########################################
57
+
58
+
59
+ class Service(SQLObject):
60
+ groups = RelatedJoin("ServiceGroup")
61
+
62
+
63
+ class ServiceGroup(SQLObject):
64
+ services = RelatedJoin("Service")
65
+
66
+
67
+ def testDeleteRelatedJoins():
68
+ setupClass([Service, ServiceGroup])
69
+ service = Service()
70
+ service_group = ServiceGroup()
71
+ service.addServiceGroup(service_group)
72
+ service.destroySelf()
73
+ service_group = ServiceGroup.get(service_group.id)
74
+ assert len(service_group.services) == 0
@@ -0,0 +1,36 @@
1
+ from sqlobject import ForeignKey, IntCol, SQLObject
2
+ from sqlobject.tests.dbtest import setupClass
3
+
4
+
5
+ ########################################
6
+ # Distinct
7
+ ########################################
8
+
9
+
10
+ class Distinct1(SQLObject):
11
+ n = IntCol()
12
+
13
+
14
+ class Distinct2(SQLObject):
15
+ other = ForeignKey('Distinct1')
16
+
17
+
18
+ def count(select):
19
+ result = {}
20
+ for ob in select:
21
+ result[int(ob.n)] = result.get(int(ob.n), 0) + 1
22
+ return result
23
+
24
+
25
+ def test_distinct():
26
+ setupClass([Distinct1, Distinct2])
27
+ obs = [Distinct1(n=i) for i in range(3)]
28
+ Distinct2(other=obs[0])
29
+ Distinct2(other=obs[0])
30
+ Distinct2(other=obs[1])
31
+
32
+ query = (Distinct2.q.otherID == Distinct1.q.id)
33
+ sel = Distinct1.select(query)
34
+ assert count(sel) == {0: 2, 1: 1}
35
+ sel = Distinct1.select(query, distinct=True)
36
+ assert count(sel) == {0: 1, 1: 1}