Skip to content

Commit 495ab66

Browse files
author
Scott Sanderson
authored
Merge pull request #31 from quantopian/add-fetch-script
ENH: Add command line script to fetch a notebook.
2 parents 5382165 + 9f224d3 commit 495ab66

File tree

1 file changed

+88
-0
lines changed

1 file changed

+88
-0
lines changed

bin/pgcontents

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,27 @@
11
#!/usr/bin/env python
2+
from __future__ import print_function
3+
24
from getpass import getuser
35
from os import getcwd
46
import subprocess
57
from textwrap import dedent
68

79
import click
810

11+
import nbformat
12+
from nbconvert.preprocessors.clearoutput import ClearOutputPreprocessor
913
from pgcontents.constants import (
1014
ALEMBIC_DIR_LOCATION,
1115
DB_URL_ENVVAR,
1216
)
17+
from pgcontents.crypto import single_password_crypto_factory
18+
from pgcontents.pgmanager import PostgresContentsManager
1319

1420
from pgcontents.utils.migrate import (
1521
temp_alembic_ini,
1622
upgrade,
1723
)
24+
from tornado.web import HTTPError
1825

1926

2027
@click.group(context_settings=dict(help_option_names=['-h', '--help']))
@@ -109,5 +116,86 @@ def gen_migration(db_url):
109116
)
110117

111118

119+
@main.command()
120+
@click.option(
121+
'-u', '--user',
122+
help='Owner of the notebook to be fetched.',
123+
)
124+
@click.option(
125+
'-f', '--filename',
126+
help='Name of the file to fetch in the DB.',
127+
)
128+
@click.option(
129+
'-o', '--output',
130+
help="Local filesystem destination.",
131+
type=click.Path(
132+
file_okay=True,
133+
dir_okay=False,
134+
writable=True,
135+
),
136+
)
137+
@click.option(
138+
'-k', '--key',
139+
help="Decryption key.",
140+
type=click.STRING,
141+
envvar='PGCONTENTS_DECRYPTION_KEY',
142+
)
143+
@click.option(
144+
'-t', '--type',
145+
help="Type of file to fetch (notebook or file).",
146+
default='notebook',
147+
type=click.Choice(['file', 'notebook']),
148+
show_default=True,
149+
)
150+
@click.option(
151+
'--clear-output',
152+
help="Clear notebook output before writing?",
153+
default=False,
154+
is_flag=True,
155+
)
156+
@_db_url
157+
def fetch(db_url, user, filename, key, output, type, clear_output):
158+
"""Fetch a notebook from the database to the local filesystem.
159+
"""
160+
if db_url is None:
161+
raise click.UsageError("-l/--db-url is required")
162+
if user is None:
163+
raise click.UsageError("-u/--user is required")
164+
if filename is None:
165+
raise click.UsageError("-f/--filename is required")
166+
if output is None:
167+
output = filename
168+
169+
crypto = single_password_crypto_factory(key)(user)
170+
171+
mgr = PostgresContentsManager(
172+
db_url=db_url,
173+
user_id=user,
174+
# User should already exist.
175+
create_directory_on_startup=False,
176+
create_user_on_startup=False,
177+
crypto=crypto,
178+
)
179+
180+
try:
181+
result = mgr.get(filename, content=True, type=type)
182+
except HTTPError as e:
183+
if e.status_code == 404:
184+
raise click.ClickException("No such file: {!r}".format(filename))
185+
elif e.status_code == 500:
186+
raise click.ClickException(
187+
"Failed to load file: {!r}. Is the decryption key correct?"
188+
.format(filename)
189+
)
190+
else:
191+
raise click.ClickException("Unknown error: %s" % e)
192+
193+
nb = nbformat.from_dict(result['content'])
194+
if clear_output:
195+
ClearOutputPreprocessor().preprocess(nb, resources=None)
196+
197+
nbformat.write(nb, open(output, 'w'), version=nbformat.NO_CONVERT)
198+
199+
112200
if __name__ == "__main__":
113201
main()

0 commit comments

Comments
 (0)