From cece3bc6389faedf6a1ffd760536cad77a470fd6 Mon Sep 17 00:00:00 2001 From: Scott Sanderson Date: Mon, 20 Jul 2015 04:07:27 -0400 Subject: [PATCH 1/7] MAINT: Add .travis.yml. --- .travis.yml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..2333b57 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,17 @@ +language: python +sudo: false +matrix: + include: + - python: 2.7 + - python: 3.4 +addons: + postgresql: "9.3" + +install: + - python setup.py install + - pip install -r requirements_dev.txt + +before_script: + - psql -c 'create database pgcontents_testing;' -U postgres +script: + nosetests pgcontents/tests From fa5447f18cedee8950fed47ad41799c2f7297729 Mon Sep 17 00:00:00 2001 From: Scott Sanderson Date: Mon, 20 Jul 2015 04:07:52 -0400 Subject: [PATCH 2/7] MAINT: Remove setup.py cruft and bump version. --- requirements.txt | 1 - setup.py | 25 ++++--------------------- 2 files changed, 4 insertions(+), 22 deletions(-) diff --git a/requirements.txt b/requirements.txt index 617387b..b502e29 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,7 +4,6 @@ MarkupSafe==0.23 Pygments==2.0.1 SQLAlchemy==1.0.5 alembic==0.7.6 -argparse==1.2.1 backports.ssl-match-hostname==3.4.0.2 certifi==14.05.14 fancycompleter==0.4 diff --git a/setup.py b/setup.py index 4188ce8..9b2b202 100644 --- a/setup.py +++ b/setup.py @@ -1,33 +1,16 @@ from __future__ import print_function from setuptools import setup -from os.path import join, dirname -import sys - - -def fail(msg): - print(msg, file=sys.stderr) - sys.exit(1) +from os.path import join, dirname, abspath def main(): - try: - import IPython - if IPython.version_info[0] < 3: - fail("PGContents requires IPython 3.0 or greater.") - except ImportError: - fail("PGContents requires IPython.") - - reqs_file = join(dirname(__file__), 'requirements.txt') + reqs_file = join(dirname(abspath(__file__)), 'requirements.txt') with open(reqs_file) as f: - requirements = [ - req.replace('==', '>=') - for req in f.readlines() - if not req.strip().startswith('-e') - ] + requirements = [req.strip() for req in f.readlines()] setup( name='pgcontents', - version='0.1', + version='0.2', description="A Postgres-backed ContentsManager for IPython.", author="Scott Sanderson", author_email="ssanderson@quantopian.com", From b13960773821d4ceb9533e719312d7a4676ad479 Mon Sep 17 00:00:00 2001 From: Scott Sanderson Date: Mon, 20 Jul 2015 04:40:44 -0400 Subject: [PATCH 3/7] DEV: Update README and examples. --- README.md | 19 ------------------- README.rst | 19 +++++++++++++++++++ examples/example_checkpoints_config.py | 10 ++++++++++ examples/example_ipython_notebook_config.py | 16 ++++++++++------ pgcontents/__init__.py | 7 +++++++ 5 files changed, 46 insertions(+), 25 deletions(-) delete mode 100644 README.md create mode 100644 README.rst create mode 100644 examples/example_checkpoints_config.py diff --git a/README.md b/README.md deleted file mode 100644 index 8420167..0000000 --- a/README.md +++ /dev/null @@ -1,19 +0,0 @@ -pgcontents -========== - -A PostgreSQL-backed implementation of [IPEP 27](https://github.com/ipython/ipython/wiki/IPEP-27:-Contents-Service). - -This repository is under development as part of the [Quantopian Research Environment](https://www.quantopian.com/research), currently in Alpha. - -Getting Started ---------------- -**Prerequisites:** - - Write access to an empty [PostgreSQL](http://www.postgresql.org) database. - - A Python installation with the latest master of [IPython Notebook](https://www.github.com/ipython/ipython). - -**Installation:** - -0. Install `pgcontents` from PyPI via `pip install pgcontents`. -1. Run `pgcontents init` to configure your database. You will be prompted for a database URL for pgcontents to use for storage. -2. Configure IPython Notebook to use `PostgresContentsManager` as its storage backend. This can be done from the command line or by modifying your `ipython_notebook_config.py` file. See `examples/example_ipython_notebook_config.py` for an example config file. -3. Enjoy your filesystem-free IPython experience! diff --git a/README.rst b/README.rst new file mode 100644 index 0000000..ea22008 --- /dev/null +++ b/README.rst @@ -0,0 +1,19 @@ +PGContents +========== + +PGContents is a PostgreSQL-backed implementation of `IPEP 27 `_. It aims to a be a transparent, drop-in replacement for IPython's standard filesystem-backed storage system. PGContents' `PostgresContentsManager` class can be used to replace all local filesystem storage with database-backed storage, while its `PostgresCheckpoints` class can be used to replace just IPython's checkpoint storage. These features are useful when running IPython in environments where you either don't have access to—or don't trust the reliability of—the local filesystem of your notebook server. + +This repository is under development as part of the `Quantopian Research Environment `_, currently in Open Beta. + +Getting Started +--------------- +**Prerequisites:** + - Write access to an empty `PostgreSQL `_ database. + - A Python installation with `IPython `_ 3.2.x. + +**Installation:** + +0. Install `pgcontents` from PyPI via `pip install pgcontents`. +1. Run `pgcontents init` to configure your database. You will be prompted for a database URL for pgcontents to use for storage. +2. Configure IPython Notebook to use pgcontents as its storage backend. This can be done from the command line or by modifying your `ipython_notebook_config.py` file. For a standard IPython installation on Unix-like systems, your profile will be located located at `~/.ipython/profile_default/ipython_notebook_config.py`. See the `examples` directory for example configuration files. +3. Enjoy your filesystem-free IPython experience! diff --git a/examples/example_checkpoints_config.py b/examples/example_checkpoints_config.py new file mode 100644 index 0000000..42ea066 --- /dev/null +++ b/examples/example_checkpoints_config.py @@ -0,0 +1,10 @@ +from pgcontents import PostgresCheckpoints +c = get_config() + +# Tell IPython to use PostgresCheckpoints for checkpoint storage. +c.NotebookApp.checkpoints_class = PostgresCheckpoints + +# Set the url for the database used to store files. See +# http://docs.sqlalchemy.org/en/rel_0_9/core/engines.html#postgresql +# for more info on db url formatting. +c.PostgresContentsManager.db_url = 'postgresql://ssanderson:secret_password@myhost.org:5432/pgcontents' diff --git a/examples/example_ipython_notebook_config.py b/examples/example_ipython_notebook_config.py index 2fc20f2..d82da51 100644 --- a/examples/example_ipython_notebook_config.py +++ b/examples/example_ipython_notebook_config.py @@ -1,15 +1,19 @@ +from pgcontents import PostgresContentsManager c = get_config() -# Tell IPython to use PostgresContentsManager. -c.NotebookApp.contents_manager_class = 'pgcontents.pgmanager.PostgresContentsManager' +# Tell IPython to use PostgresContentsManager for all storage. +c.NotebookApp.contents_manager_class = PostgresContentsManager # Set the url for the database used to store files. See # http://docs.sqlalchemy.org/en/rel_0_9/core/engines.html#postgresql # for more info on db url formatting. -# c.PostgresContentsManager.db_url = 'postgresql://ssanderson@/pgcontents' +c.PostgresContentsManager.db_url = 'postgresql://ssanderson@/pgcontents' -# Set a user ID. Defaults to the result of getpass.getuser() -# c.PostgresContentsManager.user_id = 'my_awesome_username' +# PGContents associates each running notebook server with a user, allowing +# multiple users to connect to the same database without trampling each other's +# notebooks. By default, we use the result of result of getpass.getuser(), but +# a username can be specified manually like so: +c.PostgresContentsManager.user_id = 'my_awesome_username' # Set a maximum file size, if desired. -# c.PostgresContentsManager.max_file_size_bytes = 1000000 # 1MB File cap +c.PostgresContentsManager.max_file_size_bytes = 1000000 # 1MB File cap diff --git a/pgcontents/__init__.py b/pgcontents/__init__.py index e69de29..08b8e87 100644 --- a/pgcontents/__init__.py +++ b/pgcontents/__init__.py @@ -0,0 +1,7 @@ +from .checkpoints import PostgresCheckpoints +from .pgmanager import PostgresContentsManager + +__all__ = [ + 'PostgresCheckpoints', + 'PostgresContentsManager', +] From 6b3d0fd17a39f986e549f80d7c6d8da3e33ce267 Mon Sep 17 00:00:00 2001 From: Scott Sanderson Date: Mon, 20 Jul 2015 05:21:53 -0400 Subject: [PATCH 4/7] MAINT: Run flake8 on travis. --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 2333b57..795b380 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,6 +12,7 @@ install: - pip install -r requirements_dev.txt before_script: + - flake8 pgcontents - psql -c 'create database pgcontents_testing;' -U postgres script: nosetests pgcontents/tests From 6b00310dba3360e3a6db35703b5283094a45f578 Mon Sep 17 00:00:00 2001 From: Scott Sanderson Date: Mon, 20 Jul 2015 05:22:07 -0400 Subject: [PATCH 5/7] BUG: Fix string encoding bug in test on py3. --- pgcontents/tests/test_pgmanager.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pgcontents/tests/test_pgmanager.py b/pgcontents/tests/test_pgmanager.py index c4ab3c6..a6e9e2c 100644 --- a/pgcontents/tests/test_pgmanager.py +++ b/pgcontents/tests/test_pgmanager.py @@ -183,7 +183,7 @@ def test_max_file_size(self): self.set_pgmgr_attribute('max_file_size_bytes', max_size) good = 'a' * 51 - self.assertEqual(len(b64encode(good)), max_size) + self.assertEqual(len(b64encode(good.encode('utf-8'))), max_size) cm.save( model={ 'content': good, @@ -196,7 +196,7 @@ def test_max_file_size(self): self.assertEqual(result['content'], good) bad = 'a' * 52 - self.assertGreater(bad, max_size) + self.assertGreater(len(b64encode(bad.encode('utf-8'))), max_size) with assertRaisesHTTPError(self, 413): cm.save( model={ From 7a159a42a1dc56c77571e312ff927f70fa8b7225 Mon Sep 17 00:00:00 2001 From: Scott Sanderson Date: Mon, 20 Jul 2015 13:58:09 -0400 Subject: [PATCH 6/7] MAINT: Don't peg versions in requirements.txt. --- requirements.txt | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/requirements.txt b/requirements.txt index b502e29..e007556 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,20 +1,20 @@ -Jinja2==2.7.3 -Mako==1.0.0 -MarkupSafe==0.23 -Pygments==2.0.1 -SQLAlchemy==1.0.5 -alembic==0.7.6 -backports.ssl-match-hostname==3.4.0.2 -certifi==14.05.14 -fancycompleter==0.4 -ipython==3.2.0 -jsonschema==2.4.0 -mistune==0.5.0 -psycopg2==2.6.1 -pyrepl==0.8.4 -pyzmq==14.4.1 -tornado==4.0.2 -wmctrl==0.1 -requests==2.7.0 -six==1.9.0 -click==3.3 +Jinja2>=2.7.3 +Mako>=1.0.0 +MarkupSafe>=0.23 +Pygments>=2.0.1 +SQLAlchemy>=1.0.5 +alembic>=0.7.6 +backports.ssl-match-hostname>=3.4.0.2 +certifi>=14.05.14 +fancycompleter>=0.4 +ipython>=3.2.0 +jsonschema>=2.4.0 +mistune>=0.5.0 +psycopg2>=2.6.1 +pyrepl>=0.8.4 +pyzmq>=14.4.1 +tornado>=4.0.2 +wmctrl>=0.1 +requests>=2.7.0 +six>=1.9.0 +click>=3.3 From 36567772fbe07c5325768254846768ec51d6e7ee Mon Sep 17 00:00:00 2001 From: Scott Sanderson Date: Mon, 20 Jul 2015 15:46:06 -0400 Subject: [PATCH 7/7] MAINT: Peg IPython version. Travis somehow managed to install 4.0-dev. --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index e007556..3bc8c80 100644 --- a/requirements.txt +++ b/requirements.txt @@ -7,7 +7,7 @@ alembic>=0.7.6 backports.ssl-match-hostname>=3.4.0.2 certifi>=14.05.14 fancycompleter>=0.4 -ipython>=3.2.0 +ipython==3.2.1 jsonschema>=2.4.0 mistune>=0.5.0 psycopg2>=2.6.1