Skip to content

Commit d60cdcb

Browse files
committed
Merge branch 'master' into logical
2 parents 4b279ef + 221df4f commit d60cdcb

File tree

6 files changed

+116
-31
lines changed

6 files changed

+116
-31
lines changed

hooks/pre-commit

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,23 @@
11
#!/bin/bash
22

3+
set -e
4+
35
# capture the changed files that have been staged
46
changed_files=$(git diff --staged --name-only)
57

68
for file in ${changed_files}
79
do
810
if [[ "${file##*.}" == "py" ]]; then
9-
echo "Yapfing ${file}"
10-
yapf ${file} -i
11-
git add ${file}
11+
if command -v yapf > /dev/null; then
12+
echo "Run yapf on ${file}"
13+
yapf ${file} -i
14+
git add ${file}
15+
fi
16+
17+
if command -v flake8 > /dev/null; then
18+
echo "Run flake8 on ${file}"
19+
flake8 ${file}
20+
fi
1221
fi
1322
done
23+

setup.py

100644100755
Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,18 @@
1616
if sys.version_info < (3, 3):
1717
install_requires.append("ipaddress")
1818

19+
# Get contents of README file
20+
with open('README.md', 'r') as f:
21+
readme = f.read()
22+
1923
setup(
20-
version='1.6.0',
24+
version='1.7.0',
2125
name='testgres',
2226
packages=['testgres'],
2327
description='Testing utility for PostgreSQL and its extensions',
2428
url='https://github.com/postgrespro/testgres',
29+
long_description=readme,
30+
long_description_content_type='text/markdown',
2531
license='PostgreSQL',
2632
author='Ildar Musin',
2733
author_email='[email protected]',

testgres/enums.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,3 +85,14 @@ def from_process(process):
8585

8686
# default
8787
return ProcessType.Unknown
88+
89+
90+
class DumpFormat(Enum):
91+
"""
92+
Available dump formats
93+
"""
94+
95+
Plain = 'plain'
96+
Custom = 'custom'
97+
Directory = 'directory'
98+
Tar = 'tar'

testgres/node.py

Lines changed: 55 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,10 @@
1010
from six import raise_from, iteritems
1111
from tempfile import mkstemp, mkdtemp
1212

13-
from .enums import NodeStatus, ProcessType
13+
from .enums import \
14+
NodeStatus, \
15+
ProcessType, \
16+
DumpFormat
1417

1518
from .cache import cached_initdb
1619

@@ -55,7 +58,8 @@
5558
StartNodeException, \
5659
TimeoutException, \
5760
InitNodeException, \
58-
TestgresException
61+
TestgresException, \
62+
BackupException
5963

6064
from .logger import TestgresLogger
6165

@@ -577,12 +581,13 @@ def get_control_data(self):
577581

578582
return out_dict
579583

580-
def start(self, params=[]):
584+
def start(self, params=[], wait=True):
581585
"""
582586
Start this node using pg_ctl.
583587
584588
Args:
585589
params: additional arguments for pg_ctl.
590+
wait: wait until operation completes.
586591
587592
Returns:
588593
This instance of :class:`.PostgresNode`.
@@ -592,7 +597,7 @@ def start(self, params=[]):
592597
get_bin_path("pg_ctl"),
593598
"-D", self.data_dir,
594599
"-l", self.pg_log_file,
595-
"-w", # wait
600+
"-w" if wait else '-W', # --wait or --no-wait
596601
"start"
597602
] + params # yapf: disable
598603

@@ -607,12 +612,13 @@ def start(self, params=[]):
607612

608613
return self
609614

610-
def stop(self, params=[]):
615+
def stop(self, params=[], wait=True):
611616
"""
612617
Stop this node using pg_ctl.
613618
614619
Args:
615620
params: additional arguments for pg_ctl.
621+
wait: wait until operation completes.
616622
617623
Returns:
618624
This instance of :class:`.PostgresNode`.
@@ -621,7 +627,7 @@ def stop(self, params=[]):
621627
_params = [
622628
get_bin_path("pg_ctl"),
623629
"-D", self.data_dir,
624-
"-w", # wait
630+
"-w" if wait else '-W', # --wait or --no-wait
625631
"stop"
626632
] + params # yapf: disable
627633

@@ -681,6 +687,8 @@ def reload(self, params=[]):
681687

682688
execute_utility(_params, self.utils_log_file)
683689

690+
return self
691+
684692
def pg_ctl(self, params):
685693
"""
686694
Invoke pg_ctl with params.
@@ -812,7 +820,11 @@ def safe_psql(self, query=None, **kwargs):
812820

813821
return out
814822

815-
def dump(self, filename=None, dbname=None, username=None):
823+
def dump(self,
824+
filename=None,
825+
dbname=None,
826+
username=None,
827+
format=DumpFormat.Plain):
816828
"""
817829
Dump database into a file using pg_dump.
818830
NOTE: the file is not removed automatically.
@@ -821,14 +833,27 @@ def dump(self, filename=None, dbname=None, username=None):
821833
filename: database dump taken by pg_dump.
822834
dbname: database name to connect to.
823835
username: database user name.
836+
format: format argument plain/custom/directory/tar.
824837
825838
Returns:
826839
Path to a file containing dump.
827840
"""
828841

842+
# Check arguments
843+
if not isinstance(format, DumpFormat):
844+
try:
845+
format = DumpFormat(format)
846+
except ValueError:
847+
msg = 'Invalid format "{}"'.format(format)
848+
raise BackupException(msg)
849+
850+
# Generate tmpfile or tmpdir
829851
def tmpfile():
830-
fd, fname = mkstemp(prefix=TMP_DUMP)
831-
os.close(fd)
852+
if format == DumpFormat.Directory:
853+
fname = mkdtemp(prefix=TMP_DUMP)
854+
else:
855+
fd, fname = mkstemp(prefix=TMP_DUMP)
856+
os.close(fd)
832857
return fname
833858

834859
# Set default arguments
@@ -842,7 +867,8 @@ def tmpfile():
842867
"-h", self.host,
843868
"-f", filename,
844869
"-U", username,
845-
"-d", dbname
870+
"-d", dbname,
871+
"-F", format.value
846872
] # yapf: disable
847873

848874
execute_utility(_params, self.utils_log_file)
@@ -854,12 +880,29 @@ def restore(self, filename, dbname=None, username=None):
854880
Restore database from pg_dump's file.
855881
856882
Args:
857-
filename: database dump taken by pg_dump.
883+
filename: database dump taken by pg_dump in custom/directory/tar formats.
858884
dbname: database name to connect to.
859885
username: database user name.
860886
"""
861887

862-
self.psql(filename=filename, dbname=dbname, username=username)
888+
# Set default arguments
889+
dbname = dbname or default_dbname()
890+
username = username or default_username()
891+
892+
_params = [
893+
get_bin_path("pg_restore"),
894+
"-p", str(self.port),
895+
"-h", self.host,
896+
"-U", username,
897+
"-d", dbname,
898+
filename
899+
] # yapf: disable
900+
901+
# try pg_restore if dump is binary formate, and psql if not
902+
try:
903+
execute_utility(_params, self.utils_log_name)
904+
except ExecUtilException:
905+
self.psql(filename=filename, dbname=dbname, username=username)
863906

864907
@method_decorator(positional_args_hack(['dbname', 'query']))
865908
def poll_query_until(self,

testgres/pubsub.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,9 +102,9 @@ def add_tables(self, tables, dbname=None, username=None):
102102

103103
class Subscription(object):
104104
def __init__(self,
105-
name,
106105
node,
107106
publication,
107+
name=None,
108108
dbname=None,
109109
username=None,
110110
**params):

tests/test_simple.py

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,8 @@
4646

4747
def util_exists(util):
4848
def good_properties(f):
49-
return (os.path.exists(f) and
50-
os.path.isfile(f) and
49+
return (os.path.exists(f) and # noqa: W504
50+
os.path.isfile(f) and # noqa: W504
5151
os.access(f, os.X_OK)) # yapf: disable
5252

5353
# try to resolve it
@@ -67,12 +67,14 @@ def removing(f):
6767
finally:
6868
if os.path.isfile(f):
6969
os.remove(f)
70+
elif os.path.isdir(f):
71+
rmtree(f, ignore_errors=True)
7072

7173

7274
class TestgresTests(unittest.TestCase):
7375
def test_node_repr(self):
7476
with get_new_node() as node:
75-
pattern = 'PostgresNode\(name=\'.+\', port=.+, base_dir=\'.+\'\)'
77+
pattern = r"PostgresNode\(name='.+', port=.+, base_dir='.+'\)"
7678
self.assertIsNotNone(re.match(pattern, str(node)))
7779

7880
def test_custom_init(self):
@@ -263,7 +265,7 @@ def test_psql(self):
263265
# check feeding input
264266
node.safe_psql('create table horns (w int)')
265267
node.safe_psql(
266-
'copy horns from stdin (format csv)', input=b"1\n2\n3\n\.\n")
268+
'copy horns from stdin (format csv)', input=b"1\n2\n3\n\\.\n")
267269
_sum = node.safe_psql('select sum(w) from horns')
268270
self.assertEqual(_sum, b'6\n')
269271

@@ -373,6 +375,18 @@ def test_backup_wrong_xlog_method(self):
373375
BackupException, msg='Invalid xlog_method "wrong"'):
374376
node.backup(xlog_method='wrong')
375377

378+
def test_pg_ctl_wait_option(self):
379+
with get_new_node() as node:
380+
node.init().start(wait=False)
381+
while True:
382+
try:
383+
node.stop(wait=False)
384+
break
385+
except ExecUtilException:
386+
# it's ok to get this exception here since node
387+
# could be not started yet
388+
pass
389+
376390
def test_replicate(self):
377391
with get_new_node() as node:
378392
node.init(allow_streaming=True).start()
@@ -515,16 +529,17 @@ def test_dump(self):
515529
with get_new_node().init().start() as node1:
516530

517531
node1.execute(query_create)
518-
519-
# take a new dump
520-
with removing(node1.dump()) as dump:
521-
with get_new_node().init().start() as node2:
522-
# restore dump
523-
self.assertTrue(os.path.isfile(dump))
524-
node2.restore(filename=dump)
525-
526-
res = node2.execute(query_select)
527-
self.assertListEqual(res, [(1, ), (2, )])
532+
for format in ['plain', 'custom', 'directory', 'tar']:
533+
with removing(node1.dump(format=format)) as dump:
534+
with get_new_node().init().start() as node3:
535+
if format == 'directory':
536+
self.assertTrue(os.path.isdir(dump))
537+
else:
538+
self.assertTrue(os.path.isfile(dump))
539+
# restore dump
540+
node3.restore(filename=dump)
541+
res = node3.execute(query_select)
542+
self.assertListEqual(res, [(1, ), (2, )])
528543

529544
def test_users(self):
530545
with get_new_node().init().start() as node:

0 commit comments

Comments
 (0)