summaryrefslogtreecommitdiff
diff options
-rw-r--r--LICENSE202
-rw-r--r--MANIFEST.in5
-rw-r--r--PKG-INFO229
-rw-r--r--README.rst206
-rw-r--r--debian/.git-dpm11
-rw-r--r--debian/changelog5
-rw-r--r--debian/compat1
-rw-r--r--debian/control61
-rw-r--r--debian/copyright28
-rw-r--r--debian/patches/0001-From-Takeshi-KOMIYA-i.tkomiya-gmail.com.patch129
-rw-r--r--debian/patches/series1
-rwxr-xr-xdebian/rules12
-rw-r--r--debian/source/format1
-rw-r--r--debian/source/lintian-overrides2
-rw-r--r--debian/watch4
-rw-r--r--setup.cfg25
-rw-r--r--setup.py52
-rw-r--r--src/testing.postgresql.egg-info/PKG-INFO229
-rw-r--r--src/testing.postgresql.egg-info/SOURCES.txt14
-rw-r--r--src/testing.postgresql.egg-info/dependency_links.txt1
-rw-r--r--src/testing.postgresql.egg-info/namespace_packages.txt1
-rw-r--r--src/testing.postgresql.egg-info/requires.txt7
-rw-r--r--src/testing.postgresql.egg-info/top_level.txt1
-rw-r--r--src/testing/__init__.py16
-rw-r--r--src/testing/postgresql.py144
-rw-r--r--tests/test_postgresql.py282
26 files changed, 1669 insertions, 0 deletions
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/MANIFEST.in b/MANIFEST.in
new file mode 100644
index 0000000..e84d857
--- /dev/null
+++ b/MANIFEST.in
@@ -0,0 +1,5 @@
+include MANIFEST.in
+include LICENSE
+include README.rst
+recursive-include src *.py
+recursive-include tests *.py
diff --git a/PKG-INFO b/PKG-INFO
new file mode 100644
index 0000000..45dcb11
--- /dev/null
+++ b/PKG-INFO
@@ -0,0 +1,229 @@
+Metadata-Version: 1.1
+Name: testing.postgresql
+Version: 1.3.0
+Summary: automatically setups a postgresql instance in a temporary directory, and destroys it after testing
+Home-page: https://github.com/tk0miya/testing.postgresql
+Author: Takeshi Komiya
+Author-email: i.tkomiya at gmail.com
+License: Apache License 2.0
+Description: About
+ =====
+ ``testing.postgresql`` automatically setups a postgresql instance in a temporary directory, and destroys it after testing.
+
+ .. image:: https://travis-ci.org/tk0miya/testing.postgresql.svg?branch=master
+ :target: https://travis-ci.org/tk0miya/testing.postgresql
+
+ .. image:: https://coveralls.io/repos/tk0miya/testing.postgresql/badge.png?branch=master
+ :target: https://coveralls.io/r/tk0miya/testing.postgresql?branch=master
+
+ .. image:: https://codeclimate.com/github/tk0miya/testing.postgresql/badges/gpa.svg
+ :target: https://codeclimate.com/github/tk0miya/testing.postgresql
+
+
+ Documentation
+ https://github.com/tk0miya/testing.postgresql
+ Issues
+ https://github.com/tk0miya/testing.postgresql/issues
+ Download
+ https://pypi.python.org/pypi/testing.postgresql
+
+ Install
+ =======
+ Use pip::
+
+ $ pip install testing.postgresql
+
+ And ``testing.postgresql`` requires PostgreSQL server in your PATH.
+
+
+ Usage
+ =====
+ Create PostgreSQL instance using ``testing.postgresql.Postgresql``::
+
+ import testing.postgresql
+ from sqlalchemy import create_engine
+
+ # Lanuch new PostgreSQL server
+ with testing.postgresql.Postgresql() as postgresql:
+ # connect to PostgreSQL
+ engine = create_engine(postgresql.url())
+
+ # if you use postgresql or other drivers:
+ # import psycopg2
+ # db = psycopg2.connect(**postgresql.dsn())
+
+ #
+ # do any tests using PostgreSQL...
+ #
+
+ # PostgreSQL server is terminated here
+
+
+ ``testing.postgresql.Postgresql`` executes ``initdb`` and ``postgres`` on instantiation.
+ On deleting Postgresql object, it terminates PostgreSQL instance and removes temporary directory.
+
+ If you want a database including tables and any fixtures for your apps,
+ use ``copy_data_from`` keyword::
+
+ # uses a copy of specified data directory of PostgreSQL.
+ postgresql = testing.postgresql.Postgresql(copy_data_from='/path/to/your/database')
+
+
+ For example, you can setup new PostgreSQL server for each testcases on setUp() method::
+
+ import unittest
+ import testing.postgresql
+
+ class MyTestCase(unittest.TestCase):
+ def setUp(self):
+ self.postgresql = testing.postgresql.Postgresql()
+
+ def tearDown(self):
+ self.postgresql.stop()
+
+
+ To make your tests faster
+ -------------------------
+
+ ``testing.postgresql.Postgresql`` invokes ``initdb`` command on every instantiation.
+ That is very simple. But, in many cases, it is very waste that generating brandnew database for each testcase.
+
+ To optimize the behavior, use ``testing.postgresql.PostgresqlFactory``.
+ The factory class is able to cache the generated database beyond the testcases,
+ and it reduces the number of invocation of ``initdb`` command::
+
+ import unittest
+ import testing.postgresql
+
+ # Generate Postgresql class which shares the generated database
+ Postgresql = testing.postgresql.PostgresqlFactory(cache_initialized_db=True)
+
+
+ def tearDownModule(self):
+ # clear cached database at end of tests
+ Postgresql.clear_cache()
+
+
+ class MyTestCase(unittest.TestCase):
+ def setUp(self):
+ # Use the generated Postgresql class instead of testing.postgresql.Postgresql
+ self.postgresql = Postgresql()
+
+ def tearDown(self):
+ self.postgresql.stop()
+
+ If you want to insert fixtures to the cached database, use ``initdb_handler`` option::
+
+ # create initial data on create as fixtures into the database
+ def handler(postgresql):
+ conn = psycopg2.connect(**postgresql.dsn())
+ cursor = conn.cursor()
+ cursor.execute("CREATE TABLE hello(id int, value varchar(256))")
+ cursor.execute("INSERT INTO hello values(1, 'hello'), (2, 'ciao')")
+ cursor.close()
+ conn.commit()
+ conn.close()
+
+ # Use `handler()` on initialize database
+ Postgresql = testing.postgresql.PostgresqlFactory(cache_initialized_db=True,
+ on_initialized=handler)
+
+
+ Requirements
+ ============
+ * Python 2.6, 2.7, 3.2, 3.3, 3.4, 3.5
+ * pg8000 1.10
+
+ License
+ =======
+ Apache License 2.0
+
+
+ History
+ =======
+
+ 1.3.0 (2016-02-03)
+ -------------------
+ * Add testing.postgresql.PostgresqlFactory
+ * Depend on ``testing.common.database`` package
+
+ 1.2.1 (2015-08-22)
+ -------------------
+ * Fix bug:
+
+ - Close #3 Fix AttributeError on end of tests
+
+ 1.2.0 (2015-05-17)
+ -------------------
+ * Use `pg8000` for connector to create test database
+ * Connect to `postgres` to create test database (instead of `template1`)
+
+ 1.1.2 (2015-04-06)
+ -------------------
+ * Fix bugs:
+
+ - Do not call os.getpid() on destructor (if not needed)
+ - Raise detailed RuntimeError if initdb exits non-zero
+
+ 1.1.1 (2015-01-18)
+ -------------------
+ * Disable logging_collector feature (For Fedora)
+ * Fix bugs:
+
+ - MacPorts default path is /opt/local/lib/postgresql*, no dash
+
+ 1.1.0 (2014-12-20)
+ -------------------
+ * Invoke 'postgres' command instead of 'postmaster'
+
+ 1.0.6 (2014-07-19)
+ -------------------
+ * Fix #1 Dirty postmaster shut down
+
+ 1.0.5 (2014-07-19)
+ -------------------
+ * Fix path for PostgreSQL
+ * Use absolute path for which command
+
+ 1.0.4 (2014-06-19)
+ -------------------
+ * Fix timeout on terminating postgresql
+ * Support PostgreSQL on /usr/local/bin (cf. FreeBSD ports)
+ * Fix bugs
+
+ 1.0.3 (2014-06-11)
+ -------------------
+ * Fix ImportError if caught SIGINT on py3
+
+ 1.0.2 (2013-12-06)
+ -------------------
+ * Change behavior: Postgresql#stop() cleans workdir
+ * Fix caught AttributeError on object deletion
+
+ 1.0.1 (2013-12-05)
+ -------------------
+ * Add @skipIfNotInstalled decorator (alias of skipIfNotFound)
+ * Suport python 2.6 and 3.2
+
+ 1.0.0 (2013-12-04)
+ -------------------
+ * Add @skipIfNotFound decorator
+
+ 0.1.0 (2013-11-26)
+ -------------------
+ * First release
+
+Platform: UNKNOWN
+Classifier: Development Status :: 4 - Beta
+Classifier: Intended Audience :: Developers
+Classifier: License :: OSI Approved :: Apache Software License
+Classifier: Programming Language :: Python
+Classifier: Programming Language :: Python :: 2.6
+Classifier: Programming Language :: Python :: 2.7
+Classifier: Programming Language :: Python :: 3.2
+Classifier: Programming Language :: Python :: 3.3
+Classifier: Programming Language :: Python :: 3.4
+Classifier: Programming Language :: Python :: 3.5
+Classifier: Topic :: Database
+Classifier: Topic :: Software Development
+Classifier: Topic :: Software Development :: Testing
diff --git a/README.rst b/README.rst
new file mode 100644
index 0000000..b3cfc22
--- /dev/null
+++ b/README.rst
@@ -0,0 +1,206 @@
+About
+=====
+``testing.postgresql`` automatically setups a postgresql instance in a temporary directory, and destroys it after testing.
+
+.. image:: https://travis-ci.org/tk0miya/testing.postgresql.svg?branch=master
+ :target: https://travis-ci.org/tk0miya/testing.postgresql
+
+.. image:: https://coveralls.io/repos/tk0miya/testing.postgresql/badge.png?branch=master
+ :target: https://coveralls.io/r/tk0miya/testing.postgresql?branch=master
+
+.. image:: https://codeclimate.com/github/tk0miya/testing.postgresql/badges/gpa.svg
+ :target: https://codeclimate.com/github/tk0miya/testing.postgresql
+
+
+Documentation
+ https://github.com/tk0miya/testing.postgresql
+Issues
+ https://github.com/tk0miya/testing.postgresql/issues
+Download
+ https://pypi.python.org/pypi/testing.postgresql
+
+Install
+=======
+Use pip::
+
+ $ pip install testing.postgresql
+
+And ``testing.postgresql`` requires PostgreSQL server in your PATH.
+
+
+Usage
+=====
+Create PostgreSQL instance using ``testing.postgresql.Postgresql``::
+
+ import testing.postgresql
+ from sqlalchemy import create_engine
+
+ # Lanuch new PostgreSQL server
+ with testing.postgresql.Postgresql() as postgresql:
+ # connect to PostgreSQL
+ engine = create_engine(postgresql.url())
+
+ # if you use postgresql or other drivers:
+ # import psycopg2
+ # db = psycopg2.connect(**postgresql.dsn())
+
+ #
+ # do any tests using PostgreSQL...
+ #
+
+ # PostgreSQL server is terminated here
+
+
+``testing.postgresql.Postgresql`` executes ``initdb`` and ``postgres`` on instantiation.
+On deleting Postgresql object, it terminates PostgreSQL instance and removes temporary directory.
+
+If you want a database including tables and any fixtures for your apps,
+use ``copy_data_from`` keyword::
+
+ # uses a copy of specified data directory of PostgreSQL.
+ postgresql = testing.postgresql.Postgresql(copy_data_from='/path/to/your/database')
+
+
+For example, you can setup new PostgreSQL server for each testcases on setUp() method::
+
+ import unittest
+ import testing.postgresql
+
+ class MyTestCase(unittest.TestCase):
+ def setUp(self):
+ self.postgresql = testing.postgresql.Postgresql()
+
+ def tearDown(self):
+ self.postgresql.stop()
+
+
+To make your tests faster
+-------------------------
+
+``testing.postgresql.Postgresql`` invokes ``initdb`` command on every instantiation.
+That is very simple. But, in many cases, it is very waste that generating brandnew database for each testcase.
+
+To optimize the behavior, use ``testing.postgresql.PostgresqlFactory``.
+The factory class is able to cache the generated database beyond the testcases,
+and it reduces the number of invocation of ``initdb`` command::
+
+ import unittest
+ import testing.postgresql
+
+ # Generate Postgresql class which shares the generated database
+ Postgresql = testing.postgresql.PostgresqlFactory(cache_initialized_db=True)
+
+
+ def tearDownModule(self):
+ # clear cached database at end of tests
+ Postgresql.clear_cache()
+
+
+ class MyTestCase(unittest.TestCase):
+ def setUp(self):
+ # Use the generated Postgresql class instead of testing.postgresql.Postgresql
+ self.postgresql = Postgresql()
+
+ def tearDown(self):
+ self.postgresql.stop()
+
+If you want to insert fixtures to the cached database, use ``initdb_handler`` option::
+
+ # create initial data on create as fixtures into the database
+ def handler(postgresql):
+ conn = psycopg2.connect(**postgresql.dsn())
+ cursor = conn.cursor()
+ cursor.execute("CREATE TABLE hello(id int, value varchar(256))")
+ cursor.execute("INSERT INTO hello values(1, 'hello'), (2, 'ciao')")
+ cursor.close()
+ conn.commit()
+ conn.close()
+
+ # Use `handler()` on initialize database
+ Postgresql = testing.postgresql.PostgresqlFactory(cache_initialized_db=True,
+ on_initialized=handler)
+
+
+Requirements
+============
+* Python 2.6, 2.7, 3.2, 3.3, 3.4, 3.5
+* pg8000 1.10
+
+License
+=======
+Apache License 2.0
+
+
+History
+=======
+
+1.3.0 (2016-02-03)
+-------------------
+* Add testing.postgresql.PostgresqlFactory
+* Depend on ``testing.common.database`` package
+
+1.2.1 (2015-08-22)
+-------------------
+* Fix bug:
+
+ - Close #3 Fix AttributeError on end of tests
+
+1.2.0 (2015-05-17)
+-------------------
+* Use `pg8000` for connector to create test database
+* Connect to `postgres` to create test database (instead of `template1`)
+
+1.1.2 (2015-04-06)
+-------------------
+* Fix bugs:
+
+ - Do not call os.getpid() on destructor (if not needed)
+ - Raise detailed RuntimeError if initdb exits non-zero
+
+1.1.1 (2015-01-18)
+-------------------
+* Disable logging_collector feature (For Fedora)
+* Fix bugs:
+
+ - MacPorts default path is /opt/local/lib/postgresql*, no dash
+
+1.1.0 (2014-12-20)
+-------------------
+* Invoke 'postgres' command instead of 'postmaster'
+
+1.0.6 (2014-07-19)
+-------------------
+* Fix #1 Dirty postmaster shut down
+
+1.0.5 (2014-07-19)
+-------------------
+* Fix path for PostgreSQL
+* Use absolute path for which command
+
+1.0.4 (2014-06-19)
+-------------------
+* Fix timeout on terminating postgresql
+* Support PostgreSQL on /usr/local/bin (cf. FreeBSD ports)
+* Fix bugs
+
+1.0.3 (2014-06-11)
+-------------------
+* Fix ImportError if caught SIGINT on py3
+
+1.0.2 (2013-12-06)
+-------------------
+* Change behavior: Postgresql#stop() cleans workdir
+* Fix caught AttributeError on object deletion
+
+1.0.1 (2013-12-05)
+-------------------
+* Add @skipIfNotInstalled decorator (alias of skipIfNotFound)
+* Suport python 2.6 and 3.2
+
+1.0.0 (2013-12-04)
+-------------------
+* Add @skipIfNotFound decorator
+
+0.1.0 (2013-11-26)
+-------------------
+* First release
diff --git a/debian/.git-dpm b/debian/.git-dpm
new file mode 100644
index 0000000..846ade9
--- /dev/null
+++ b/debian/.git-dpm
@@ -0,0 +1,11 @@
+# see git-dpm(1) from git-dpm package
+659829a63f423c495e6fbcc7a053235426234513
+659829a63f423c495e6fbcc7a053235426234513
+b427257b8230a01eb8c01154fc1cc8f9f67a5419
+b427257b8230a01eb8c01154fc1cc8f9f67a5419
+python-testing.postgresql_1.3.0.orig.tar.gz
+0e08d0bc0b958f90bd30f2d75087a946912af012
+11000
+debianTag="debian/%e%v"
+patchedTag="patched/%e%v"
+upstreamTag="upstream/%e%u"
diff --git a/debian/changelog b/debian/changelog
new file mode 100644
index 0000000..dd953b5
--- /dev/null
+++ b/debian/changelog
@@ -0,0 +1,5 @@
+python-testing.postgresql (1.3.0-1) unstable; urgency=low
+
+ * Initial release. (Closes: #838582)
+
+ -- Dominik George <nik@naturalnet.de> Thu, 13 Oct 2016 13:56:54 +0200
diff --git a/debian/compat b/debian/compat
new file mode 100644
index 0000000..f599e28
--- /dev/null
+++ b/debian/compat
@@ -0,0 +1 @@
+10
diff --git a/debian/control b/debian/control
new file mode 100644
index 0000000..65f24b1
--- /dev/null
+++ b/debian/control
@@ -0,0 +1,61 @@
+Source: python-testing.postgresql
+Maintainer: Debian Python Modules Team <python-modules-team@lists.alioth.debian.org>
+Uploaders:
+ Dominik George <nik@naturalnet.de>,
+Section: python
+Priority: optional
+Build-Depends:
+ debhelper (>= 10),
+ dh-python,
+ postgresql,
+ python-all (>= 2.6.6-3),
+ python-nose,
+ python-pg8000 (>= 1.10),
+ python-psycopg2,
+ python-setuptools (>= 0.6b3),
+ python-sqlalchemy,
+ python-testing.common.database (>= 1.1.0),
+ python3-all,
+ python3-nose,
+ python3-pg8000 (>= 1.10),
+ python3-psycopg2,
+ python3-setuptools,
+ python3-sqlalchemy,
+ python3-testing.common.database (>= 1.1.0),
+Standards-Version: 3.9.8
+Homepage: https://github.com/tk0miya/testing.postgresql
+Testsuite: autopkgtest-pkg-python
+Vcs-Git: https://anonscm.debian.org/git/python-modules/packages/python-testing.postgresql.git
+Vcs-Browser: https://anonscm.debian.org/git/python-modules/packages/python-testing.postgresql.git
+
+Package: python-testing.postgresql
+Architecture: all
+Depends:
+ postgresql,
+ ${misc:Depends},
+ ${python:Depends},
+Description: Python testing.* framework - PostgreSQL helpers (Python 2)
+ The testing.* Python modules provide a framework for Python unit test suites
+ that need to run tests against servers, like network-based DBMSs.
+ .
+ testing.postgresql contains helper classes to work with a temporary
+ PostgreSQL server. It automatically sets up a PostgreSQL instance in a
+ temporary directory, and destroys it after testing.
+ .
+ This package contains the Python 2 version.
+
+Package: python3-testing.postgresql
+Architecture: all
+Depends:
+ postgresql,
+ ${misc:Depends},
+ ${python3:Depends},
+Description: Python testing.* framework - PostgreSQL helpers (Python 3)
+ The testing.* Python modules provide a framework for Python unit test suites
+ that need to run tests against servers, like network-based DBMSs.
+ .
+ testing.postgresql contains helper classes to work with a temporary
+ PostgreSQL server. It automatically sets up a PostgreSQL instance in a
+ temporary directory, and destroys it after testing.
+ .
+ This package contains the Python 3 version.
diff --git a/debian/copyright b/debian/copyright
new file mode 100644
index 0000000..2402168
--- /dev/null
+++ b/debian/copyright
@@ -0,0 +1,28 @@
+Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
+Upstream-Name: testing.postgresql
+Upstream-Contact: Takeshi KOMIYA <i.tkomiya@gmail.com>
+Source: https://github.com/tk0miya/testing.postgresql
+
+Files: *
+Copyright: 2013 Takeshi KOMIYA <i.tkomiya@gmail.com>
+License: Apache-2.0
+
+Files: debian/*
+Copyright: 2016 Dominik George <nik@naturalnet.de>
+License: Apache-2.0
+
+License: Apache-2.0
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+ .
+ http://www.apache.org/licenses/LICENSE-2.0
+ .
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ .
+ On Debian systems, you can find the Apache-2.0 license under
+ /usr/share/common-licenses/Apache-2.0 .
diff --git a/debian/patches/0001-From-Takeshi-KOMIYA-i.tkomiya-gmail.com.patch b/debian/patches/0001-From-Takeshi-KOMIYA-i.tkomiya-gmail.com.patch
new file mode 100644
index 0000000..2dd13b7
--- /dev/null
+++ b/debian/patches/0001-From-Takeshi-KOMIYA-i.tkomiya-gmail.com.patch
@@ -0,0 +1,129 @@
+From 659829a63f423c495e6fbcc7a053235426234513 Mon Sep 17 00:00:00 2001
+From: Dominik George <nik@naturalnet.de>
+Date: Thu, 13 Oct 2016 13:40:10 +0200
+Subject: =?UTF-8?q?From:=20Takeshi=20KOMIYA=20<i.tkomiya@gmail.com>=0ADate?=
+ =?UTF-8?q?:=20Fri,=205=20Feb=202016=2021:56:57=20+0900=0ASubject:=20[PATC?=
+ =?UTF-8?q?H]=20Use=20utility=20methods=20of=20testing.common.database=20>?=
+ =?UTF-8?q?=3D=201.1.0=0AOrigin:=20upstream,=20https://github.com/tk0miya/?=
+ =?UTF-8?q?testing.postgresql/commit/738c8eb19a4b064dd74ff851c379dd1cbf11b?=
+ =?UTF-8?q?c65.patch=0AApplied-Upstream:=20commit:738c8eb19a4b064dd74ff851?=
+ =?UTF-8?q?c379dd1cbf11bc65?=
+
+---
+ setup.py | 2 +-
+ tests/test_postgresql.py | 41 ++++++++++++++---------------------------
+ 2 files changed, 15 insertions(+), 28 deletions(-)
+
+diff --git a/setup.py b/setup.py
+index 08095cd..9e95298 100644
+--- a/setup.py
++++ b/setup.py
+@@ -18,7 +18,7 @@ classifiers = [
+ "Topic :: Software Development :: Testing",
+ ]
+
+-install_requires = ['testing.common.database', 'pg8000 >= 1.10']
++install_requires = ['testing.common.database >= 1.1.0', 'pg8000 >= 1.10']
+ if sys.version_info < (2, 7):
+ install_requires.append('unittest2')
+
+diff --git a/tests/test_postgresql.py b/tests/test_postgresql.py
+index 29e2b7e..b3603a2 100644
+--- a/tests/test_postgresql.py
++++ b/tests/test_postgresql.py
+@@ -47,38 +47,31 @@ class TestPostgresql(unittest.TestCase):
+ conn.close()
+ finally:
+ # shutting down
+- pid = pgsql.pid
+- self.assertTrue(pid)
+- os.kill(pid, 0) # process is alive
++ pid = pgsql.server_pid
++ self.assertTrue(pgsql.is_alive())
+
+ pgsql.stop()
+ sleep(1)
+
+- self.assertIsNone(pgsql.pid)
++ self.assertFalse(pgsql.is_alive())
+ with self.assertRaises(OSError):
+ os.kill(pid, 0) # process is down
+
+ def test_stop(self):
+ # start postgresql server
+ pgsql = testing.postgresql.Postgresql()
+- self.assertIsNotNone(pgsql.pid)
+ self.assertTrue(os.path.exists(pgsql.base_dir))
+- pid = pgsql.pid
+- os.kill(pid, 0) # process is alive
++ self.assertTrue(pgsql.is_alive())
+
+ # call stop()
+ pgsql.stop()
+- self.assertIsNone(pgsql.pid)
+ self.assertFalse(os.path.exists(pgsql.base_dir))
+- with self.assertRaises(OSError):
+- os.kill(pid, 0) # process is down
++ self.assertFalse(pgsql.is_alive())
+
+ # call stop() again
+ pgsql.stop()
+- self.assertIsNone(pgsql.pid)
+ self.assertFalse(os.path.exists(pgsql.base_dir))
+- with self.assertRaises(OSError):
+- os.kill(pid, 0) # process is down
++ self.assertFalse(pgsql.is_alive())
+
+ # delete postgresql object after stop()
+ del pgsql
+@@ -98,20 +91,17 @@ class TestPostgresql(unittest.TestCase):
+ self.assertIsNotNone(conn)
+ conn.close()
+
+- pid = pgsql.pid
+- os.kill(pid, 0) # process is alive
++ self.assertTrue(pgsql.is_alive())
+
+- self.assertIsNone(pgsql.pid)
+- with self.assertRaises(OSError):
+- os.kill(pid, 0) # process is down
++ self.assertFalse(pgsql.is_alive())
+
+ def test_multiple_postgresql(self):
+ pgsql1 = testing.postgresql.Postgresql()
+ pgsql2 = testing.postgresql.Postgresql()
+- self.assertNotEqual(pgsql1.pid, pgsql2.pid)
++ self.assertNotEqual(pgsql1.server_pid, pgsql2.server_pid)
+
+- os.kill(pgsql1.pid, 0) # process is alive
+- os.kill(pgsql2.pid, 0) # process is alive
++ self.assertTrue(pgsql1.is_alive())
++ self.assertTrue(pgsql2.is_alive())
+
+ def test_postgresql_is_not_found(self):
+ try:
+@@ -135,21 +125,18 @@ class TestPostgresql(unittest.TestCase):
+ else:
+ os.wait()
+ sleep(1)
+- self.assertTrue(pgsql.pid)
+- os.kill(pgsql.pid, 0) # process is alive (delete pgsql obj in child does not effect)
++ self.assertTrue(pgsql.is_alive()) # process is alive (delete pgsql obj in child does not effect)
+
+ def test_stop_on_child_process(self):
+ pgsql = testing.postgresql.Postgresql()
+ if os.fork() == 0:
+ pgsql.stop()
+- self.assertTrue(pgsql.pid)
+- os.kill(pgsql.pid, 0) # process is alive (calling stop() is ignored)
++ os.kill(pgsql.server_pid, 0) # process is alive (calling stop() is ignored)
+ os.kill(os.getpid(), signal.SIGTERM) # exit tests FORCELY
+ else:
+ os.wait()
+ sleep(1)
+- self.assertTrue(pgsql.pid)
+- os.kill(pgsql.pid, 0) # process is alive (calling stop() in child is ignored)
++ self.assertTrue(pgsql.is_alive()) # process is alive (calling stop() in child is ignored)
+
+ def test_copy_data_from(self):
+ try:
diff --git a/debian/patches/series b/debian/patches/series
new file mode 100644
index 0000000..7bddafa
--- /dev/null
+++ b/debian/patches/series
@@ -0,0 +1 @@
+0001-From-Takeshi-KOMIYA-i.tkomiya-gmail.com.patch
diff --git a/debian/rules b/debian/rules
new file mode 100755
index 0000000..5a940b1
--- /dev/null
+++ b/debian/rules
@@ -0,0 +1,12 @@
+#!/usr/bin/make -f
+
+export PYBUILD_NAME=testing.postgresql
+%:
+ dh $@ --with python2,python3 --buildsystem=pybuild
+
+override_dh_installchangelogs:
+ csplit README.rst '%^History$$%'
+ dh_installchangelogs xx00
+
+override_dh_clean:
+ dh_clean xx00
diff --git a/debian/source/format b/debian/source/format
new file mode 100644
index 0000000..163aaf8
--- /dev/null
+++ b/debian/source/format
@@ -0,0 +1 @@
+3.0 (quilt)
diff --git a/debian/source/lintian-overrides b/debian/source/lintian-overrides
new file mode 100644
index 0000000..32d5859
--- /dev/null
+++ b/debian/source/lintian-overrides
@@ -0,0 +1,2 @@
+# Upstream does not sign tarballs. Discussing that, though.
+python-testing.postgresql source: debian-watch-may-check-gpg-signature
diff --git a/debian/watch b/debian/watch
new file mode 100644
index 0000000..b932fb2
--- /dev/null
+++ b/debian/watch
@@ -0,0 +1,4 @@
+# please also check http://pypi.debian.net/testing.postgresql/watch
+version=3
+opts="uversionmangle=s/(rc|a|b|c)/~$1/" \
+http://pypi.debian.net/testing.postgresql/testing.postgresql-(.+)\.(?:zip|tgz|tbz|txz|(?:tar\.(?:gz|bz2|xz)))
diff --git a/setup.cfg b/setup.cfg
new file mode 100644
index 0000000..fe6c155
--- /dev/null
+++ b/setup.cfg
@@ -0,0 +1,25 @@
+[egg_info]
+tag_build =
+tag_date = 0
+tag_svn_revision = 0
+
+[build]
+build-base = _build
+
+[sdist]
+formats = gztar
+
+[wheel]
+universal = 1
+
+[aliases]
+release = check -r -s register sdist bdist_wheel upload
+
+[check]
+strict = 1
+restructuredtext = 1
+
+[flake8]
+max-line-length = 120
+ignore = _
+
diff --git a/setup.py b/setup.py
new file mode 100644
index 0000000..08095cd
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,52 @@
+# -*- coding: utf-8 -*-
+import sys
+from setuptools import setup, find_packages
+
+classifiers = [
+ "Development Status :: 4 - Beta",
+ "Intended Audience :: Developers",
+ "License :: OSI Approved :: Apache Software License",
+ "Programming Language :: Python",
+ "Programming Language :: Python :: 2.6",
+ "Programming Language :: Python :: 2.7",
+ "Programming Language :: Python :: 3.2",
+ "Programming Language :: Python :: 3.3",
+ "Programming Language :: Python :: 3.4",
+ "Programming Language :: Python :: 3.5",
+ "Topic :: Database",
+ "Topic :: Software Development",
+ "Topic :: Software Development :: Testing",
+]
+
+install_requires = ['testing.common.database', 'pg8000 >= 1.10']
+if sys.version_info < (2, 7):
+ install_requires.append('unittest2')
+
+
+setup(
+ name='testing.postgresql',
+ version='1.3.0',
+ description='automatically setups a postgresql instance in a temporary '
+ 'directory, and destroys it after testing',
+ long_description=open('README.rst').read(),
+ classifiers=classifiers,
+ keywords=[],
+ author='Takeshi Komiya',
+ author_email='i.tkomiya at gmail.com',
+ url='https://github.com/tk0miya/testing.postgresql',
+ license='Apache License 2.0',
+ packages=find_packages('src'),
+ package_dir={'': 'src'},
+ package_data={'': ['buildout.cfg']},
+ include_package_data=True,
+ install_requires=install_requires,
+ extras_require=dict(
+ testing=[
+ 'nose',
+ 'psycopg2',
+ 'SQLAlchemy',
+ ],
+ ),
+ test_suite='nose.collector',
+ namespace_packages=['testing'],
+)
diff --git a/src/testing.postgresql.egg-info/PKG-INFO b/src/testing.postgresql.egg-info/PKG-INFO
new file mode 100644
index 0000000..45dcb11
--- /dev/null
+++ b/src/testing.postgresql.egg-info/PKG-INFO
@@ -0,0 +1,229 @@
+Metadata-Version: 1.1
+Name: testing.postgresql
+Version: 1.3.0
+Summary: automatically setups a postgresql instance in a temporary directory, and destroys it after testing
+Home-page: https://github.com/tk0miya/testing.postgresql
+Author: Takeshi Komiya
+Author-email: i.tkomiya at gmail.com
+License: Apache License 2.0
+Description: About
+ =====
+ ``testing.postgresql`` automatically setups a postgresql instance in a temporary directory, and destroys it after testing.
+
+ .. image:: https://travis-ci.org/tk0miya/testing.postgresql.svg?branch=master
+ :target: https://travis-ci.org/tk0miya/testing.postgresql
+
+ .. image:: https://coveralls.io/repos/tk0miya/testing.postgresql/badge.png?branch=master
+ :target: https://coveralls.io/r/tk0miya/testing.postgresql?branch=master
+
+ .. image:: https://codeclimate.com/github/tk0miya/testing.postgresql/badges/gpa.svg
+ :target: https://codeclimate.com/github/tk0miya/testing.postgresql
+
+
+ Documentation
+ https://github.com/tk0miya/testing.postgresql
+ Issues
+ https://github.com/tk0miya/testing.postgresql/issues
+ Download
+ https://pypi.python.org/pypi/testing.postgresql
+
+ Install
+ =======
+ Use pip::
+
+ $ pip install testing.postgresql
+
+ And ``testing.postgresql`` requires PostgreSQL server in your PATH.
+
+
+ Usage
+ =====
+ Create PostgreSQL instance using ``testing.postgresql.Postgresql``::
+
+ import testing.postgresql
+ from sqlalchemy import create_engine
+
+ # Lanuch new PostgreSQL server
+ with testing.postgresql.Postgresql() as postgresql:
+ # connect to PostgreSQL
+ engine = create_engine(postgresql.url())
+
+ # if you use postgresql or other drivers:
+ # import psycopg2
+ # db = psycopg2.connect(**postgresql.dsn())
+
+ #
+ # do any tests using PostgreSQL...
+ #
+
+ # PostgreSQL server is terminated here
+
+
+ ``testing.postgresql.Postgresql`` executes ``initdb`` and ``postgres`` on instantiation.
+ On deleting Postgresql object, it terminates PostgreSQL instance and removes temporary directory.
+
+ If you want a database including tables and any fixtures for your apps,
+ use ``copy_data_from`` keyword::
+
+ # uses a copy of specified data directory of PostgreSQL.
+ postgresql = testing.postgresql.Postgresql(copy_data_from='/path/to/your/database')
+
+
+ For example, you can setup new PostgreSQL server for each testcases on setUp() method::
+
+ import unittest
+ import testing.postgresql
+
+ class MyTestCase(unittest.TestCase):
+ def setUp(self):
+ self.postgresql = testing.postgresql.Postgresql()
+
+ def tearDown(self):
+ self.postgresql.stop()
+
+
+ To make your tests faster
+ -------------------------
+
+ ``testing.postgresql.Postgresql`` invokes ``initdb`` command on every instantiation.
+ That is very simple. But, in many cases, it is very waste that generating brandnew database for each testcase.
+
+ To optimize the behavior, use ``testing.postgresql.PostgresqlFactory``.
+ The factory class is able to cache the generated database beyond the testcases,
+ and it reduces the number of invocation of ``initdb`` command::
+
+ import unittest
+ import testing.postgresql
+
+ # Generate Postgresql class which shares the generated database
+ Postgresql = testing.postgresql.PostgresqlFactory(cache_initialized_db=True)
+
+
+ def tearDownModule(self):
+ # clear cached database at end of tests
+ Postgresql.clear_cache()
+
+
+ class MyTestCase(unittest.TestCase):
+ def setUp(self):
+ # Use the generated Postgresql class instead of testing.postgresql.Postgresql
+ self.postgresql = Postgresql()
+
+ def tearDown(self):
+ self.postgresql.stop()
+
+ If you want to insert fixtures to the cached database, use ``initdb_handler`` option::
+
+ # create initial data on create as fixtures into the database
+ def handler(postgresql):
+ conn = psycopg2.connect(**postgresql.dsn())
+ cursor = conn.cursor()
+ cursor.execute("CREATE TABLE hello(id int, value varchar(256))")
+ cursor.execute("INSERT INTO hello values(1, 'hello'), (2, 'ciao')")
+ cursor.close()
+ conn.commit()
+ conn.close()
+
+ # Use `handler()` on initialize database
+ Postgresql = testing.postgresql.PostgresqlFactory(cache_initialized_db=True,
+ on_initialized=handler)
+
+
+ Requirements
+ ============
+ * Python 2.6, 2.7, 3.2, 3.3, 3.4, 3.5
+ * pg8000 1.10
+
+ License
+ =======
+ Apache License 2.0
+
+
+ History
+ =======
+
+ 1.3.0 (2016-02-03)
+ -------------------
+ * Add testing.postgresql.PostgresqlFactory
+ * Depend on ``testing.common.database`` package
+
+ 1.2.1 (2015-08-22)
+ -------------------
+ * Fix bug:
+
+ - Close #3 Fix AttributeError on end of tests
+
+ 1.2.0 (2015-05-17)
+ -------------------
+ * Use `pg8000` for connector to create test database
+ * Connect to `postgres` to create test database (instead of `template1`)
+
+ 1.1.2 (2015-04-06)
+ -------------------
+ * Fix bugs:
+
+ - Do not call os.getpid() on destructor (if not needed)
+ - Raise detailed RuntimeError if initdb exits non-zero
+
+ 1.1.1 (2015-01-18)
+ -------------------
+ * Disable logging_collector feature (For Fedora)
+ * Fix bugs:
+
+ - MacPorts default path is /opt/local/lib/postgresql*, no dash
+
+ 1.1.0 (2014-12-20)
+ -------------------
+ * Invoke 'postgres' command instead of 'postmaster'
+
+ 1.0.6 (2014-07-19)
+ -------------------
+ * Fix #1 Dirty postmaster shut down
+
+ 1.0.5 (2014-07-19)
+ -------------------
+ * Fix path for PostgreSQL
+ * Use absolute path for which command
+
+ 1.0.4 (2014-06-19)
+ -------------------
+ * Fix timeout on terminating postgresql
+ * Support PostgreSQL on /usr/local/bin (cf. FreeBSD ports)
+ * Fix bugs
+
+ 1.0.3 (2014-06-11)
+ -------------------
+ * Fix ImportError if caught SIGINT on py3
+
+ 1.0.2 (2013-12-06)
+ -------------------
+ * Change behavior: Postgresql#stop() cleans workdir
+ * Fix caught AttributeError on object deletion
+
+ 1.0.1 (2013-12-05)
+ -------------------
+ * Add @skipIfNotInstalled decorator (alias of skipIfNotFound)
+ * Suport python 2.6 and 3.2
+
+ 1.0.0 (2013-12-04)
+ -------------------
+ * Add @skipIfNotFound decorator
+
+ 0.1.0 (2013-11-26)
+ -------------------
+ * First release
+
+Platform: UNKNOWN
+Classifier: Development Status :: 4 - Beta
+Classifier: Intended Audience :: Developers
+Classifier: License :: OSI Approved :: Apache Software License
+Classifier: Programming Language :: Python
+Classifier: Programming Language :: Python :: 2.6
+Classifier: Programming Language :: Python :: 2.7
+Classifier: Programming Language :: Python :: 3.2
+Classifier: Programming Language :: Python :: 3.3
+Classifier: Programming Language :: Python :: 3.4
+Classifier: Programming Language :: Python :: 3.5
+Classifier: Topic :: Database
+Classifier: Topic :: Software Development
+Classifier: Topic :: Software Development :: Testing
diff --git a/src/testing.postgresql.egg-info/SOURCES.txt b/src/testing.postgresql.egg-info/SOURCES.txt
new file mode 100644
index 0000000..7d599dc
--- /dev/null
+++ b/src/testing.postgresql.egg-info/SOURCES.txt
@@ -0,0 +1,14 @@
+LICENSE
+MANIFEST.in
+README.rst
+setup.cfg
+setup.py
+src/testing/__init__.py
+src/testing/postgresql.py
+src/testing.postgresql.egg-info/PKG-INFO
+src/testing.postgresql.egg-info/SOURCES.txt
+src/testing.postgresql.egg-info/dependency_links.txt
+src/testing.postgresql.egg-info/namespace_packages.txt
+src/testing.postgresql.egg-info/requires.txt
+src/testing.postgresql.egg-info/top_level.txt
+tests/test_postgresql.py \ No newline at end of file
diff --git a/src/testing.postgresql.egg-info/dependency_links.txt b/src/testing.postgresql.egg-info/dependency_links.txt
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/src/testing.postgresql.egg-info/dependency_links.txt
@@ -0,0 +1 @@
+
diff --git a/src/testing.postgresql.egg-info/namespace_packages.txt b/src/testing.postgresql.egg-info/namespace_packages.txt
new file mode 100644
index 0000000..038d718
--- /dev/null
+++ b/src/testing.postgresql.egg-info/namespace_packages.txt
@@ -0,0 +1 @@
+testing
diff --git a/src/testing.postgresql.egg-info/requires.txt b/src/testing.postgresql.egg-info/requires.txt
new file mode 100644
index 0000000..033c513
--- /dev/null
+++ b/src/testing.postgresql.egg-info/requires.txt
@@ -0,0 +1,7 @@
+testing.common.database
+pg8000 >= 1.10
+
+[testing]
+nose
+psycopg2
+SQLAlchemy
diff --git a/src/testing.postgresql.egg-info/top_level.txt b/src/testing.postgresql.egg-info/top_level.txt
new file mode 100644
index 0000000..038d718
--- /dev/null
+++ b/src/testing.postgresql.egg-info/top_level.txt
@@ -0,0 +1 @@
+testing
diff --git a/src/testing/__init__.py b/src/testing/__init__.py
new file mode 100644
index 0000000..c4fb22e
--- /dev/null
+++ b/src/testing/__init__.py
@@ -0,0 +1,16 @@
+# -*- coding: utf-8 -*-
+# Copyright 2013 Takeshi KOMIYA
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+__import__('pkg_resources').declare_namespace(__name__)
diff --git a/src/testing/postgresql.py b/src/testing/postgresql.py
new file mode 100644
index 0000000..948fc3c
--- /dev/null
+++ b/src/testing/postgresql.py
@@ -0,0 +1,144 @@
+# -*- coding: utf-8 -*-
+# Copyright 2013 Takeshi KOMIYA
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import os
+import pg8000
+import signal
+import subprocess
+from glob import glob
+from contextlib import closing
+
+from testing.common.database import (
+ Database, DatabaseFactory, get_path_of, SkipIfNotInstalledDecorator
+)
+
+
+__all__ = ['Postgresql', 'skipIfNotFound']
+
+SEARCH_PATHS = (['/usr/local/pgsql', '/usr/local'] +
+ glob('/usr/lib/postgresql/*') + # for Debian/Ubuntu
+ glob('/opt/local/lib/postgresql*')) # for MacPorts
+
+
+class Postgresql(Database):
+ DEFAULT_SETTINGS = dict(auto_start=2,
+ base_dir=None,
+ initdb=None,
+ initdb_args='-U postgres -A trust',
+ postgres=None,
+ postgres_args='-h 127.0.0.1 -F -c logging_collector=off',
+ pid=None,
+ port=None,
+ copy_data_from=None)
+ subdirectories = ['data', 'tmp']
+
+ def initialize(self):
+ self.initdb = self.settings.pop('initdb')
+ if self.initdb is None:
+ self.initdb = find_program('initdb', ['bin'])
+
+ self.postgres = self.settings.pop('postgres')
+ if self.postgres is None:
+ self.postgres = find_program('postgres', ['bin'])
+
+ def dsn(self, **kwargs):
+ # "database=test host=localhost user=postgres"
+ params = dict(kwargs)
+ params.setdefault('port', self.settings['port'])
+ params.setdefault('host', '127.0.0.1')
+ params.setdefault('user', 'postgres')
+ params.setdefault('database', 'test')
+
+ return params
+
+ def url(self, **kwargs):
+ params = self.dsn(**kwargs)
+
+ url = ('postgresql://%s@%s:%d/%s' %
+ (params['user'], params['host'], params['port'], params['database']))
+
+ return url
+
+ def get_data_directory(self):
+ return os.path.join(self.base_dir, 'data')
+
+ def initialize_database(self):
+ if not os.path.exists(os.path.join(self.base_dir, 'data', 'PG_VERSION')):
+ args = ([self.initdb, '-D', os.path.join(self.base_dir, 'data'), '--lc-messages=C'] +
+ self.settings['initdb_args'].split())
+
+ try:
+ p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ output, err = p.communicate()
+ if p.returncode != 0:
+ raise RuntimeError("initdb failed: %r" % err)
+ except OSError as exc:
+ raise RuntimeError("failed to spawn initdb: %s" % exc)
+
+ def get_server_commandline(self):
+ return ([self.postgres,
+ '-p', str(self.settings['port']),
+ '-D', os.path.join(self.base_dir, 'data'),
+ '-k', os.path.join(self.base_dir, 'tmp')] +
+ self.settings['postgres_args'].split())
+
+ def poststart(self):
+ with closing(pg8000.connect(**self.dsn(database='postgres'))) as conn:
+ conn.autocommit = True
+ with closing(conn.cursor()) as cursor:
+ cursor.execute("SELECT COUNT(*) FROM pg_database WHERE datname='test'")
+ if cursor.fetchone()[0] <= 0:
+ cursor.execute('CREATE DATABASE test')
+
+ def is_server_available(self):
+ try:
+ with closing(pg8000.connect(**self.dsn(database='template1'))):
+ pass
+ except pg8000.Error:
+ return False
+ else:
+ return True
+
+ def terminate(self, *args):
+ # send SIGINT instead of SIGTERM
+ super(Postgresql, self).terminate(signal.SIGINT)
+
+
+class PostgresqlFactory(DatabaseFactory):
+ target_class = Postgresql
+
+
+class PostgresqlSkipIfNotInstalledDecorator(SkipIfNotInstalledDecorator):
+ name = 'PostgreSQL'
+
+ def search_server(self):
+ find_program('postgres', ['bin'])
+
+
+skipIfNotFound = skipIfNotInstalled = PostgresqlSkipIfNotInstalledDecorator()
+
+
+def find_program(name, subdirs):
+ path = get_path_of(name)
+ if path:
+ return path
+
+ for base_dir in SEARCH_PATHS:
+ for subdir in subdirs:
+ path = os.path.join(base_dir, subdir, name)
+ if os.path.exists(path):
+ return path
+
+ raise RuntimeError("command not found: %s" % name)
diff --git a/tests/test_postgresql.py b/tests/test_postgresql.py
new file mode 100644
index 0000000..29e2b7e
--- /dev/null
+++ b/tests/test_postgresql.py
@@ -0,0 +1,282 @@
+# -*- coding: utf-8 -*-
+
+import os
+import sys
+import signal
+import tempfile
+import testing.postgresql
+from time import sleep
+from shutil import rmtree
+import pg8000
+import psycopg2
+import sqlalchemy
+from contextlib import closing
+
+if sys.version_info < (2, 7):
+ import unittest2 as unittest
+else:
+ import unittest
+
+
+class TestPostgresql(unittest.TestCase):
+ def test_basic(self):
+ try:
+ # start postgresql server
+ pgsql = testing.postgresql.Postgresql()
+ self.assertIsNotNone(pgsql)
+ params = pgsql.dsn()
+ self.assertEqual('test', params['database'])
+ self.assertEqual('127.0.0.1', params['host'])
+ self.assertEqual(pgsql.settings['port'], params['port'])
+ self.assertEqual('postgres', params['user'])
+
+ # connect to postgresql (w/ psycopg2)
+ conn = psycopg2.connect(**pgsql.dsn())
+ self.assertIsNotNone(conn)
+ self.assertRegexpMatches(pgsql.read_bootlog(), 'is ready to accept connections')
+ conn.close()
+
+ # connect to postgresql (w/ sqlalchemy)
+ engine = sqlalchemy.create_engine(pgsql.url())
+ self.assertIsNotNone(engine)
+
+ # connect to postgresql (w/ pg8000)
+ conn = pg8000.connect(**pgsql.dsn())
+ self.assertIsNotNone(conn)
+ self.assertRegexpMatches(pgsql.read_bootlog(), 'is ready to accept connections')
+ conn.close()
+ finally:
+ # shutting down
+ pid = pgsql.pid
+ self.assertTrue(pid)
+ os.kill(pid, 0) # process is alive
+
+ pgsql.stop()
+ sleep(1)
+
+ self.assertIsNone(pgsql.pid)
+ with self.assertRaises(OSError):
+ os.kill(pid, 0) # process is down
+
+ def test_stop(self):
+ # start postgresql server
+ pgsql = testing.postgresql.Postgresql()
+ self.assertIsNotNone(pgsql.pid)
+ self.assertTrue(os.path.exists(pgsql.base_dir))
+ pid = pgsql.pid
+ os.kill(pid, 0) # process is alive
+
+ # call stop()
+ pgsql.stop()
+ self.assertIsNone(pgsql.pid)
+ self.assertFalse(os.path.exists(pgsql.base_dir))
+ with self.assertRaises(OSError):
+ os.kill(pid, 0) # process is down
+
+ # call stop() again
+ pgsql.stop()
+ self.assertIsNone(pgsql.pid)
+ self.assertFalse(os.path.exists(pgsql.base_dir))
+ with self.assertRaises(OSError):
+ os.kill(pid, 0) # process is down
+
+ # delete postgresql object after stop()
+ del pgsql
+
+ def test_dsn_and_url(self):
+ pgsql = testing.postgresql.Postgresql(port=12345, auto_start=0)
+ self.assertEqual({'database': 'test', 'host': '127.0.0.1', 'port': 12345, 'user': 'postgres'},
+ pgsql.dsn())
+ self.assertEqual("postgresql://postgres@127.0.0.1:12345/test", pgsql.url())
+
+ def test_with_statement(self):
+ with testing.postgresql.Postgresql() as pgsql:
+ self.assertIsNotNone(pgsql)
+
+ # connect to postgresql
+ conn = pg8000.connect(**pgsql.dsn())
+ self.assertIsNotNone(conn)
+ conn.close()
+
+ pid = pgsql.pid
+ os.kill(pid, 0) # process is alive
+
+ self.assertIsNone(pgsql.pid)
+ with self.assertRaises(OSError):
+ os.kill(pid, 0) # process is down
+
+ def test_multiple_postgresql(self):
+ pgsql1 = testing.postgresql.Postgresql()
+ pgsql2 = testing.postgresql.Postgresql()
+ self.assertNotEqual(pgsql1.pid, pgsql2.pid)
+
+ os.kill(pgsql1.pid, 0) # process is alive
+ os.kill(pgsql2.pid, 0) # process is alive
+
+ def test_postgresql_is_not_found(self):
+ try:
+ search_paths = testing.postgresql.SEARCH_PATHS
+ testing.postgresql.SEARCH_PATHS = []
+ path_env = os.environ['PATH']
+ os.environ['PATH'] = ''
+
+ with self.assertRaises(RuntimeError):
+ testing.postgresql.Postgresql()
+ finally:
+ testing.postgresql.SEARCH_PATHS = search_paths
+ os.environ['PATH'] = path_env
+
+ def test_fork(self):
+ pgsql = testing.postgresql.Postgresql()
+ if os.fork() == 0:
+ del pgsql
+ pgsql = None
+ os.kill(os.getpid(), signal.SIGTERM) # exit tests FORCELY
+ else:
+ os.wait()
+ sleep(1)
+ self.assertTrue(pgsql.pid)
+ os.kill(pgsql.pid, 0) # process is alive (delete pgsql obj in child does not effect)
+
+ def test_stop_on_child_process(self):
+ pgsql = testing.postgresql.Postgresql()
+ if os.fork() == 0:
+ pgsql.stop()
+ self.assertTrue(pgsql.pid)
+ os.kill(pgsql.pid, 0) # process is alive (calling stop() is ignored)
+ os.kill(os.getpid(), signal.SIGTERM) # exit tests FORCELY
+ else:
+ os.wait()
+ sleep(1)
+ self.assertTrue(pgsql.pid)
+ os.kill(pgsql.pid, 0) # process is alive (calling stop() in child is ignored)
+
+ def test_copy_data_from(self):
+ try:
+ tmpdir = tempfile.mkdtemp()
+
+ # create new database
+ with testing.postgresql.Postgresql(base_dir=tmpdir) as pgsql:
+ conn = pg8000.connect(**pgsql.dsn())
+ with closing(conn.cursor()) as cursor:
+ cursor.execute("CREATE TABLE hello(id int, value varchar(256))")
+ cursor.execute("INSERT INTO hello values(1, 'hello'), (2, 'ciao')")
+ conn.commit()
+ conn.close()
+
+ # create another database from first one
+ data_dir = os.path.join(tmpdir, 'data')
+ with testing.postgresql.Postgresql(copy_data_from=data_dir) as pgsql:
+ conn = pg8000.connect(**pgsql.dsn())
+ with closing(conn.cursor()) as cursor:
+ cursor.execute('SELECT * FROM hello ORDER BY id')
+ self.assertEqual(cursor.fetchall(), ([1, 'hello'], [2, 'ciao']))
+ conn.close()
+ finally:
+ rmtree(tmpdir)
+
+ def test_skipIfNotInstalled_found(self):
+ try:
+ search_paths = testing.postgresql.SEARCH_PATHS
+ testing.postgresql.SEARCH_PATHS = []
+ path_env = os.environ['PATH']
+ os.environ['PATH'] = ''
+
+ @testing.postgresql.skipIfNotInstalled
+ def testcase():
+ pass
+
+ self.assertEqual(True, hasattr(testcase, '__unittest_skip__'))
+ self.assertEqual(True, hasattr(testcase, '__unittest_skip_why__'))
+ self.assertEqual(True, testcase.__unittest_skip__)
+ self.assertEqual("PostgreSQL not found", testcase.__unittest_skip_why__)
+ finally:
+ testing.postgresql.SEARCH_PATHS = search_paths
+ os.environ['PATH'] = path_env
+
+ def test_skipIfNotInstalled_notfound(self):
+ @testing.postgresql.skipIfNotInstalled
+ def testcase():
+ pass
+
+ self.assertEqual(False, hasattr(testcase, '__unittest_skip__'))
+ self.assertEqual(False, hasattr(testcase, '__unittest_skip_why__'))
+
+ def test_skipIfNotInstalled_with_args_found(self):
+ path = testing.postgresql.find_program('postgres', ['bin'])
+
+ @testing.postgresql.skipIfNotInstalled(path)
+ def testcase():
+ pass
+
+ self.assertEqual(False, hasattr(testcase, '__unittest_skip__'))
+ self.assertEqual(False, hasattr(testcase, '__unittest_skip_why__'))
+
+ def test_skipIfNotInstalled_with_args_notfound(self):
+ @testing.postgresql.skipIfNotInstalled("/path/to/anywhere")
+ def testcase():
+ pass
+
+ self.assertEqual(True, hasattr(testcase, '__unittest_skip__'))
+ self.assertEqual(True, hasattr(testcase, '__unittest_skip_why__'))
+ self.assertEqual(True, testcase.__unittest_skip__)
+ self.assertEqual("PostgreSQL not found", testcase.__unittest_skip_why__)
+
+ def test_skipIfNotFound_found(self):
+ try:
+ search_paths = testing.postgresql.SEARCH_PATHS
+ testing.postgresql.SEARCH_PATHS = []
+ path_env = os.environ['PATH']
+ os.environ['PATH'] = ''
+
+ @testing.postgresql.skipIfNotFound
+ def testcase():
+ pass
+
+ self.assertEqual(True, hasattr(testcase, '__unittest_skip__'))
+ self.assertEqual(True, hasattr(testcase, '__unittest_skip_why__'))
+ self.assertEqual(True, testcase.__unittest_skip__)
+ self.assertEqual("PostgreSQL not found", testcase.__unittest_skip_why__)
+ finally:
+ testing.postgresql.SEARCH_PATHS = search_paths
+ os.environ['PATH'] = path_env
+
+ def test_skipIfNotFound_notfound(self):
+ @testing.postgresql.skipIfNotFound
+ def testcase():
+ pass
+
+ self.assertEqual(False, hasattr(testcase, '__unittest_skip__'))
+ self.assertEqual(False, hasattr(testcase, '__unittest_skip_why__'))
+
+ def test_PostgresqlFactory(self):
+ Postgresql = testing.postgresql.PostgresqlFactory(cache_initialized_db=True)
+ with Postgresql() as pgsql1:
+ self.assertTrue(pgsql1.settings['copy_data_from'])
+ copy_data_from1 = pgsql1.settings['copy_data_from']
+ self.assertTrue(os.path.exists(copy_data_from1))
+ with Postgresql() as pgsql2:
+ self.assertEqual(copy_data_from1, pgsql2.settings['copy_data_from'])
+ Postgresql.clear_cache()
+ self.assertFalse(os.path.exists(copy_data_from1))
+
+ def test_PostgresqlFactory_with_initialized_handler(self):
+ def handler(pgsql):
+ conn = pg8000.connect(**pgsql.dsn())
+ with closing(conn.cursor()) as cursor:
+ cursor.execute("CREATE TABLE hello(id int, value varchar(256))")
+ cursor.execute("INSERT INTO hello values(1, 'hello'), (2, 'ciao')")
+ conn.commit()
+ conn.close()
+
+ Postgresql = testing.postgresql.PostgresqlFactory(cache_initialized_db=True,
+ on_initialized=handler)
+ try:
+ with Postgresql() as pgsql:
+ conn = pg8000.connect(**pgsql.dsn())
+ with closing(conn.cursor()) as cursor:
+ cursor.execute('SELECT * FROM hello ORDER BY id')
+ self.assertEqual(cursor.fetchall(), ([1, 'hello'], [2, 'ciao']))
+ conn.close()
+ finally:
+ Postgresql.clear_cache()