Skip to content

Commit

Permalink
Merge changes that use separate the application of ast NodeTransforme…
Browse files Browse the repository at this point in the history
…rs (ipython#41)

* Reorder the hierarchy of the classes.
* Deprecate parameterize for execute
* Make the necessary changes for parameterize
* Replace docstrings in utils source
* Update the readme
  • Loading branch information
tonyfast authored May 28, 2018
1 parent edd776a commit e863de1
Show file tree
Hide file tree
Showing 26 changed files with 1,360 additions and 1,477 deletions.
18 changes: 9 additions & 9 deletions readme.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,7 @@
"metadata": {},
"outputs": [],
"source": [
" from importnb import Partial\n",
" with Partial():\n",
" with Notebook(exceptions=BaseException):\n",
" try: from . import readme\n",
" except: import readme"
]
Expand Down Expand Up @@ -215,8 +214,8 @@
"metadata": {},
"outputs": [],
"source": [
" from importnb import Parameterize\n",
" f = Parameterize(readme)\n",
" from importnb.execute import Parameterize\n",
" f = Parameterize().from_filename(readme.__file__)\n",
" "
]
},
Expand Down Expand Up @@ -374,7 +373,7 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 12,
"metadata": {},
"outputs": [
{
Expand All @@ -390,7 +389,7 @@
"test_imports (src.importnb.tests.test_unittests.TestRemote) ... skipped 'requires IP'\n",
"\n",
"----------------------------------------------------------------------\n",
"Ran 7 tests in 2.024s\n",
"Ran 7 tests in 2.019s\n",
"\n",
"OK (skipped=1, expected failures=1)\n"
]
Expand All @@ -404,26 +403,27 @@
" for path in Path(root).rglob(\"\"\"*.ipynb\"\"\"): \n",
" if 'checkpoint' not in str(path):\n",
" export(path, Path('src/importnb') / path.with_suffix('.py').relative_to(root))\n",
" \n",
" \n",
" __import__('unittest').main(module='src.importnb.tests.test_unittests', argv=\"discover --verbose\".split(), exit=False) \n"
]
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 13,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[NbConvertApp] Converting notebook readme.ipynb to markdown\n"
"[NbConvertApp] Converting notebook readme.ipynb to markdown\n",
"[NbConvertApp] Writing 7383 bytes to readme.md\n"
]
}
],
"source": [
" if __name__ == '__main__':\n",
" \n",
" !jupyter nbconvert --to markdown readme.ipynb"
]
},
Expand Down
16 changes: 9 additions & 7 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,7 @@ The [`importnb.loader.Partial`](src/notebooks/loader.ipynb#Partial-Loader) will


```python
from importnb import Partial
with Partial():
with Notebook(exceptions=BaseException):
try: from . import readme
except: import readme
```
Expand Down Expand Up @@ -118,8 +117,8 @@ In `readme`, `foo` is a parameter because it may be evaluated with ast.literal_v


```python
from importnb import Parameterize
f = Parameterize(readme)
from importnb.execute import Parameterize
f = Parameterize().from_filename(readme.__file__)

```

Expand Down Expand Up @@ -223,6 +222,7 @@ For example, create a file called `tricks.yaml` containing
for path in Path(root).rglob("""*.ipynb"""):
if 'checkpoint' not in str(path):
export(path, Path('src/importnb') / path.with_suffix('.py').relative_to(root))


__import__('unittest').main(module='src.importnb.tests.test_unittests', argv="discover --verbose".split(), exit=False)

Expand All @@ -237,20 +237,22 @@ For example, create a file called `tricks.yaml` containing
test_imports (src.importnb.tests.test_unittests.TestRemote) ... skipped 'requires IP'

----------------------------------------------------------------------
Ran 7 tests in 1.014s
Ran 7 tests in 1.011s

FAILED (skipped=1, unexpected successes=1)



```python
if __name__ == '__main__':

!jupyter nbconvert --to markdown readme.ipynb
```

[NbConvertApp] Converting notebook readme.ipynb to markdown
[NbConvertApp] Writing 7109 bytes to readme.md
[NbConvertApp] Support files will be in readme_files/
[NbConvertApp] Making directory readme_files
[NbConvertApp] Making directory readme_files
[NbConvertApp] Writing 8946 bytes to readme.md


if __name__ == '__main__':
Expand Down
12 changes: 3 additions & 9 deletions src/importnb/__init__.py
Original file line number Diff line number Diff line change
@@ -1,30 +1,24 @@

# coding: utf-8

__all__ = "Notebook", "Partial", "reload", "Parameterize", "Lazy", "NotebookTest", "testmod", "Execute"
__all__ = "Notebook", "reload", "Parameterize", "NotebookTest", "testmod", "Execute"

try:
from .loader import (
Notebook,
Partial,
load_ipython_extension,
unload_ipython_extension,
reload,
Lazy,
)
from .parameterize import Parameterize
from .nbtest import NotebookTest, testmod
from .execute import Execute
from .execute import Execute, Parameterize

except:
from loader import (
Notebook,
Partial,
load_ipython_extension,
unload_ipython_extension,
reload,
Lazy,
)
from parameterize import Parameterize
from execute import Execute
from execute import Execute, Parameterize
from nbtest import NotebookTest, testmod
12 changes: 10 additions & 2 deletions src/importnb/capture.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,18 @@
"""

try:
from IPython.utils.capture import capture_output
from IPython.utils.capture import capture_output, CapturedIO
from IPython import get_ipython

assert get_ipython(), """There is no interactive shell"""
except:
from contextlib import redirect_stdout, ExitStack
from io import StringIO
import sys

try:
from contextlib import redirect_stderr
except:
import sys

class redirect_stderr:

Expand Down Expand Up @@ -64,6 +64,14 @@ def stdout(self):
def stderr(self):
return self._stderr and self._stderr.getvalue() or ""

def show(self):
"""write my output to sys.stdout/err as appropriate"""
sys.stdout.write(self.stdout)
sys.stderr.write(self.stderr)
sys.stdout.flush()
sys.stderr.flush()


if __name__ == "__main__":
try:
from .utils.export import export
Expand Down
62 changes: 2 additions & 60 deletions src/importnb/decoder.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,11 @@
except:
from textwrap import dedent


def identity(*x):
return x[0]


class LineNumberDecoder(JSONDecoder):
"""A JSON Decoder to return a NotebookNode with lines numbers in the metadata."""

Expand Down Expand Up @@ -65,74 +67,15 @@ def _parse_object(
{"lineno": len(s_and_end[0][:next].rsplit('"source":', 1)[0].splitlines())}
)

if object["cell_type"] == "markdown":
object["source"] = codify_markdown(object["source"])
object["outputs"] = []
object["cell_type"] = "code"
object["execution_count"] = None

for key in ("source", "text"):
if key in object:
object[key] = "".join(object[key])

return object, next

@singledispatch
def codify_markdown(string_or_list):
raise TypeError("Markdown must be a string or a list.")


@codify_markdown.register(str)
def codify_markdown_string(str):
if '"""' in str:
str = "'''{}\n'''".format(str)
else:
str = '"""{}\n"""'.format(str)
return str


@codify_markdown.register(list)
def codify_markdown_list(str):
return list(map("{}\n".format, codify_markdown_string("".join(str)).splitlines()))


load = partial(_load, cls=LineNumberDecoder)
loads = partial(_loads, cls=LineNumberDecoder)

def cell_to_ast(object, transform=identity, prefix=False):
module = ast.increment_lineno(
ast.parse(transform("".join(object["source"]))), object["metadata"].get("lineno", 1)
)
prefix and module.body.insert(0, ast.Expr(ast.Ellipsis()))
return module

def transform_cells(object, transform=dedent):
for cell in object["cells"]:
if "source" in cell:
cell["source"] = transform("".join(cell["source"]))
return object


def ast_from_cells(object, transform=identity):
import ast

module = ast.Module(body=[])
for cell in object["cells"]:
module.body.extend(
ast.fix_missing_locations(
ast.increment_lineno(
ast.parse("".join(cell["source"])), cell["metadata"].get("lineno", 1)
)
).body
)
return module

def loads_ast(object, loads=loads, transform=dedent, ast_transform=identity):
if isinstance(object, str):
object = loads(object)
object = transform_cells(object, transform)
return ast_from_cells(object, ast_transform)

if __name__ == "__main__":
try:
from .utils.export import export
Expand All @@ -141,4 +84,3 @@ def loads_ast(object, loads=loads, transform=dedent, ast_transform=identity):
export("decoder.ipynb", "../decoder.py")

__import__("doctest").testmod()

Loading

0 comments on commit e863de1

Please sign in to comment.