├── .gitignore ├── setup.py ├── README.rst ├── LICENSE └── gvmagic.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Filename: .gitignore 2 | 3 | *.py[cod] 4 | build 5 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | # Filename: setup.py 2 | 3 | try: 4 | from setuptools import setup, Extension 5 | except ImportError: 6 | from distutils.core import setup, Extension 7 | 8 | with open('LICENSE') as fin: 9 | LICENSE = fin.read() 10 | 11 | MODULES = ['gvmagic'] 12 | 13 | setup( 14 | name='ipython-magic', 15 | version='0.1', 16 | 17 | author="Chris Drake", 18 | author_email="cjdrake AT gmail DOT com", 19 | description="IPython magic functions", 20 | license=LICENSE, 21 | url="https://github.com/cjdrake/ipython-magic", 22 | 23 | py_modules=MODULES, 24 | ) 25 | 26 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | *************************** 2 | IPython Magic Functions 3 | *************************** 4 | 5 | I am quite fond of IPython. 6 | If I tinker around with creating magic functions for the notebook, 7 | I will publish them here. 8 | 9 | Consult the source code for usage instructions. 10 | 11 | Contents: 12 | 13 | * Graphviz Magics (``gvmagic.py``): 14 | ``%dot``, ``%dotstr``, ``%dotobj``, ``%dotobjs`` 15 | ``%neato``, ``%neatostr``, ``%neatoobj``, ``%neatoobjs`` 16 | ``%circo``, ``%circostr``, ``%circoobj``, ``%circoobjs`` 17 | ``%fdp``, ``%fdpstr``, ``%fdpobj``, ``%fdpobjs`` 18 | ``%sfdp``, ``%sfdpstr``, ``%sfdpobj``, ``%sfdpobjs`` 19 | ``%twopi``, ``%twopistr``, ``%twopiobj``, ``%twopiobjs`` 20 | 21 | Thanks to contributors: 22 | 23 | * John B. Nelson (@jbn) 24 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013, Chris Drake 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 18 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 21 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | 25 | -------------------------------------------------------------------------------- /gvmagic.py: -------------------------------------------------------------------------------- 1 | """ 2 | Graphviz IPython magic extensions 3 | 4 | Magic methods: 5 | %dot 6 | %%dot 8 | %dotstr "" 9 | %dotobj obj.to_dot() 10 | %dotobjs obj[0].to_dot(), obj[1].to_dot(), ... 11 | 12 | also: %twopi, %neato, %sdp, %fsdp, and %circo magic families. 13 | 14 | Usage: 15 | %load_ext gvmagic 16 | """ 17 | 18 | 19 | from logging import info, error 20 | from subprocess import Popen, PIPE 21 | 22 | from IPython.core.display import display_svg 23 | from IPython.core.magic import Magics 24 | from IPython.core.magic import line_cell_magic 25 | from IPython.core.magic import line_magic 26 | from IPython.core.magic import magics_class 27 | 28 | 29 | def run_graphviz(s, layout_engine='dot'): 30 | """Execute dot with a layout and return a raw SVG image, or None.""" 31 | cmd = ['dot', '-Tsvg', '-K', layout_engine] 32 | 33 | dot = Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE) 34 | stdoutdata, stderrdata = dot.communicate(s.encode('utf-8')) 35 | status = dot.wait() 36 | if status == 0: 37 | return stdoutdata 38 | else: 39 | fstr = "dot returned {}\n[==== stderr ====]\n{}" 40 | error(fstr.format(status, stderrdata.decode('utf-8'))) 41 | return None 42 | 43 | 44 | @magics_class 45 | class GraphvizMagics(Magics): 46 | 47 | @line_cell_magic 48 | def dot(self, line, cell=None): 49 | self._from_cell(line, cell, 'dot') 50 | 51 | @line_magic 52 | def dotstr(self, line): 53 | self._from_str(line, 'dot') 54 | 55 | @line_magic 56 | def dotobj(self, line): 57 | self._from_obj(line, 'dot') 58 | 59 | @line_magic 60 | def dotobjs(self, line): 61 | self._from_objs(line, 'dot') 62 | 63 | @line_cell_magic 64 | def neato(self, line, cell=None): 65 | self._from_cell(line, cell, 'neato') 66 | 67 | @line_magic 68 | def neatostr(self, line): 69 | self._from_str(line, 'neato') 70 | 71 | @line_magic 72 | def neatoobj(self, line): 73 | self._from_obj(line, 'neato') 74 | 75 | @line_magic 76 | def neatoobjs(self, line): 77 | self._from_objs(line, 'neato') 78 | 79 | @line_cell_magic 80 | def sfdp(self, line, cell=None): 81 | self._from_cell(line, cell, 'sfdp') 82 | 83 | @line_magic 84 | def sfdpstr(self, line): 85 | self._from_str(line, 'sfdp') 86 | 87 | @line_magic 88 | def sfdpobj(self, line): 89 | self._from_obj(line, 'sfdp') 90 | 91 | @line_magic 92 | def sfdpobjs(self, line): 93 | self._from_objs(line, 'sfdp') 94 | 95 | @line_cell_magic 96 | def fdp(self, line, cell=None): 97 | self._from_cell(line, cell, 'fdp') 98 | 99 | @line_magic 100 | def fdpstr(self, line): 101 | self._from_str(line, 'fdp') 102 | 103 | @line_magic 104 | def fdpobj(self, line): 105 | self._from_obj(line, 'fdp') 106 | 107 | @line_magic 108 | def fdpobjs(self, line): 109 | self._from_objs(line, 'fdp') 110 | 111 | @line_cell_magic 112 | def twopi(self, line, cell=None): 113 | self._from_cell(line, cell, 'twopi') 114 | 115 | @line_magic 116 | def twopistr(self, line): 117 | self._from_str(line, 'twopi') 118 | 119 | @line_magic 120 | def twopiobj(self, line): 121 | self._from_obj(line, 'twopi') 122 | 123 | @line_magic 124 | def twopiobjs(self, line): 125 | self._from_objs(line, 'twopi') 126 | 127 | @line_cell_magic 128 | def circo(self, line, cell=None): 129 | self._from_cell(line, cell, 'circo') 130 | 131 | @line_magic 132 | def circostr(self, line): 133 | self._from_str(line, 'circo') 134 | 135 | @line_magic 136 | def circoobj(self, line): 137 | self._from_obj(line, 'circo') 138 | 139 | @line_magic 140 | def circoobjs(self, line): 141 | self._from_objs(line, 'circo') 142 | 143 | def _from_cell(self, line, cell, layout_engine): 144 | if cell is None: 145 | s = line 146 | else: 147 | s = line + '\n' + cell 148 | data = run_graphviz(s, layout_engine) 149 | if data: 150 | display_svg(data, raw=True) 151 | 152 | def _from_str(self, line, layout_engine): 153 | s = self.shell.ev(line) 154 | data = run_graphviz(s, layout_engine) 155 | if data: 156 | display_svg(data, raw=True) 157 | 158 | def _from_obj(self, line, layout_engine): 159 | obj = self.shell.ev(line) 160 | try: 161 | s = obj.to_dot() 162 | except AttributeError: 163 | error("expected object to implement 'to_dot()' method") 164 | except TypeError: 165 | error("expected to_dot method to be callable w/o args") 166 | else: 167 | data = run_graphviz(s, layout_engine) 168 | if data: 169 | display_svg(data, raw=True) 170 | 171 | def _from_objs(self, line, layout_engine): 172 | """dot objects magic""" 173 | objs = self.shell.ev(line) 174 | for i, obj in enumerate(objs): 175 | try: 176 | s = obj.to_dot() 177 | except AttributeError: 178 | error("expected object to implement 'to_dot()' method") 179 | except TypeError: 180 | error("expected to_dot method to be callable w/o args") 181 | else: 182 | data = run_graphviz(s, layout_engine) 183 | if data: 184 | info("object {}:".format(i)) 185 | display_svg(data, raw=True) 186 | 187 | 188 | def load_ipython_extension(ipython): 189 | """Load the extension in IPython.""" 190 | ipython.register_magics(GraphvizMagics) 191 | 192 | 193 | def unload_ipython_extension(ipython): 194 | """Unload the extension in IPython.""" 195 | pass 196 | --------------------------------------------------------------------------------