Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit4f00dbb

Browse files
committed
improved setup.py, new enum for transaction isolation levels
1 parent18d6d79 commit4f00dbb

File tree

3 files changed

+85
-29
lines changed

3 files changed

+85
-29
lines changed

‎setup.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,16 @@
1-
fromdistutils.coreimportsetup
1+
importsys
2+
3+
try:
4+
fromsetuptoolsimportsetup
5+
exceptImportError:
6+
fromdistutils.coreimportsetup
7+
8+
# Basic dependencies
9+
install_requires= ["pg8000","six","port-for"]
10+
11+
# Add compatibility enum class
12+
ifsys.version_info< (3,4):
13+
install_requires.append("enum34")
214

315
setup(
416
name='testgres',
@@ -11,4 +23,4 @@
1123
url='https://github.com/postgrespro/testgres',
1224
keywords=['testing','postgresql'],
1325
classifiers=[],
14-
install_requires=["pg8000","six","port-for","enum34"])
26+
install_requires=install_requires)

‎testgres/testgres.py

Lines changed: 46 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -171,19 +171,12 @@ def stopped(self):
171171
returnself.stop_event.isSet()
172172

173173

174-
deflog_watch(node_name,pg_logname):
174+
classIsolationLevel(Enum):
175175
"""
176-
Starts thread for node that redirects
177-
postgresql logs to python logging system
176+
Transaction isolation level for NodeConnection
178177
"""
179178

180-
reader=TestgresLogger(node_name,open(pg_logname,'r'))
181-
reader.start()
182-
183-
globalutil_threads
184-
util_threads.append(reader)
185-
186-
returnreader
179+
ReadUncommitted,ReadCommitted,RepeatableRead,Serializable=range(4)
187180

188181

189182
classNodeConnection(object):
@@ -218,7 +211,7 @@ def __enter__(self):
218211
def__exit__(self,type,value,traceback):
219212
self.close()
220213

221-
defbegin(self,isolation_level=0):
214+
defbegin(self,isolation_level=IsolationLevel.ReadCommitted):
222215
# yapf: disable
223216
levels= [
224217
'read uncommitted',
@@ -227,40 +220,51 @@ def begin(self, isolation_level=0):
227220
'serializable'
228221
]
229222

230-
# Check if level is int [0..3]
231-
if (isinstance(isolation_level,int)and
232-
isolation_levelinrange(0,4)):
223+
# Check if level is an IsolationLevel
224+
if (isinstance(isolation_level,IsolationLevel)):
233225

234-
# Replace index with isolation level type
235-
isolation_level=levels[isolation_level]
226+
# Get index of isolation level
227+
level_idx=isolation_level.value
228+
assert(level_idxinrange(4))
236229

237-
# Or it might be a string
238-
elif (isinstance(isolation_level,six.text_type)and
239-
isolation_level.lower()inlevels):
230+
# Replace isolation level with its name
231+
isolation_level=levels[level_idx]
240232

241-
# Nothing to do here
242-
pass
243-
244-
# Something is wrong, emit exception
245233
else:
246-
raiseQueryException(
247-
'Invalid isolation level "{}"'.format(isolation_level))
234+
# Get name of isolation level
235+
level_str=str(isolation_level).lower()
236+
237+
# Validate level string
238+
iflevel_strnotinlevels:
239+
error='Invalid isolation level "{}"'
240+
raiseQueryException(error.format(level_str))
241+
242+
# Replace isolation level with its name
243+
isolation_level=level_str
248244

249-
self.cursor.execute(
250-
'SET TRANSACTION ISOLATION LEVEL {}'.format(isolation_level))
245+
# Set isolation level
246+
cmd='SET TRANSACTION ISOLATION LEVEL {}'
247+
self.cursor.execute(cmd.format(isolation_level))
248+
249+
returnself
251250

252251
defcommit(self):
253252
self.connection.commit()
254253

254+
returnself
255+
255256
defrollback(self):
256257
self.connection.rollback()
257258

259+
returnself
260+
258261
defexecute(self,query,*args):
259262
self.cursor.execute(query,args)
260263

261264
try:
262265
res=self.cursor.fetchall()
263266

267+
# pg8000 might return tuples
264268
ifisinstance(res,tuple):
265269
res= [tuple(t)fortinres]
266270

@@ -1311,3 +1315,18 @@ def configure_testgres(**options):
13111315

13121316
forkey,optioninoptions.items():
13131317
setattr(TestgresConfig,key,option)
1318+
1319+
1320+
deflog_watch(node_name,pg_logname):
1321+
"""
1322+
Start thread for node that redirects
1323+
PostgreSQL logs to python logging system.
1324+
"""
1325+
1326+
reader=TestgresLogger(node_name,open(pg_logname,'r'))
1327+
reader.start()
1328+
1329+
globalutil_threads
1330+
util_threads.append(reader)
1331+
1332+
returnreader

‎tests/test_simple.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
fromtestgresimportget_new_node,get_pg_config,configure_testgres
2424
fromtestgresimportbound_ports
2525
fromtestgresimportNodeStatus
26+
fromtestgresimportIsolationLevel
2627

2728

2829
classSimpleTest(unittest.TestCase):
@@ -442,6 +443,30 @@ def test_configure(self):
442443
# return to the base state
443444
configure_testgres(cache_initdb=True,cache_pg_config=True)
444445

446+
deftest_isolation_levels(self):
447+
withget_new_node('node').init().start()asnode:
448+
withnode.connect()ascon:
449+
# string levels
450+
con.begin('Read Uncommitted').commit()
451+
con.begin('Read Committed').commit()
452+
con.begin('Repeatable Read').commit()
453+
con.begin('Serializable').commit()
454+
455+
# enum levels
456+
con.begin(IsolationLevel.ReadUncommitted).commit()
457+
con.begin(IsolationLevel.ReadCommitted).commit()
458+
con.begin(IsolationLevel.RepeatableRead).commit()
459+
con.begin(IsolationLevel.Serializable).commit()
460+
461+
# check wrong level
462+
got_exception=False
463+
try:
464+
con.begin('Garbage').commit()
465+
exceptQueryException:
466+
got_exception=True
467+
468+
self.assertTrue(got_exception)
469+
445470

446471
if__name__=='__main__':
447472
unittest.main()

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp