|
1 | 1 | # Grumpy: Go running Python
|
2 | 2 |
|
3 |
| -[](https://travis-ci.org/google/grumpy) |
| 3 | +[](https://travis-ci.org/alanjds/grumpy) |
| 4 | +[](https://gitter.im/grumpy-devel/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) |
4 | 5 |
|
5 | 6 | ## Overview
|
6 | 7 |
|
7 | 8 | Grumpy is a Python to Go source code transcompiler and runtime that is intended
|
8 |
| -to be a near drop in replacement for CPython 2.7. The key difference is that it |
| 9 | +to be a near drop-in replacement for CPython 2.7. The key difference is that it |
9 | 10 | compiles Python source code to Go source code which is then compiled to native
|
10 | 11 | code, rather than to bytecode. This means that Grumpy has no VM. The compiled Go
|
11 | 12 | source code is a series of calls to the Grumpy runtime, a Go library serving a
|
12 |
| -similar purpose to the Python C API (although the C API is not directly |
13 |
| -supported). |
| 13 | +similar purpose to the Python C API (although the API is incompatible with |
| 14 | +CPython's). |
14 | 15 |
|
15 | 16 | ## Limitations
|
16 | 17 |
|
17 | 18 | ### Things that will probably never be supported by Grumpy
|
18 | 19 |
|
19 | 20 | 1. `exec`, `eval` and `compile`: These dynamic features of CPython are not
|
20 |
| - supported by Grumpy because Grumpy modules consist of statically compiled Go |
| 21 | + supported by Grumpy because Grumpy modules consist of statically-compiled Go |
21 | 22 | code. Supporting dynamic execution would require bundling Grumpy programs
|
22 |
| - with the compilation toolchain which would be unwieldy and impractically |
| 23 | + with the compilation toolchain, which would be unwieldy and impractically |
23 | 24 | slow.
|
24 | 25 |
|
25 | 26 | 2. C extension modules: Grumpy has a different API and object layout than
|
26 | 27 | CPython and so supporting C extensions would be difficult. In principle it's
|
27 | 28 | possible to support them via an API bridge layer like the one that
|
28 |
| - [JyNI](http://jyni.org) provides for Jython but it would be hard to maintain and |
| 29 | + [JyNI](http://jyni.org) provides for Jython, but it would be hard to maintain and |
29 | 30 | would add significant overhead when calling into and out of extension
|
30 | 31 | modules.
|
31 | 32 |
|
32 | 33 | ### Things that Grumpy will support but doesn't yet
|
33 | 34 |
|
34 | 35 | There are three basic categories of incomplete functionality:
|
35 | 36 |
|
36 |
| -1. Language features: Most language features are implemented with the notable |
37 |
| - exception of decorators. There are also a handful of operators that aren't |
38 |
| - yet supported. |
| 37 | +1. [Language features](https://github.com/google/grumpy/wiki/Missing-features#language-features): |
| 38 | + Most language features are implemented with the notable exception of |
| 39 | + [old-style classes](http://stackoverflow.com/questions/54867/what-is-the-difference-between-old-style-and-new-style-classes-in-python). |
| 40 | + There are also a handful of operators that aren't yet supported. |
39 | 41 |
|
40 |
| -2. Builtin functions and types: There are a number of missing functions and |
41 |
| - types in `__builtins__` that have not been implemented. There are also a |
42 |
| - lot of methods on builtin types that are missing. |
| 42 | +2. [Builtin functions and types](https://github.com/google/grumpy/wiki/Missing-features#builtins): |
| 43 | + There are a number of missing functions and types in `__builtins__` that have |
| 44 | + not yet been implemented. There are also a lot of methods on builtin types |
| 45 | + that are missing. |
43 | 46 |
|
44 |
| -3. Standard library: The Python standard library is very large and much of it |
45 |
| - is pure Python, so as the language features and builtins get filled out, many |
46 |
| - modules will just work. But there are also a number of libraries in CPython |
47 |
| - that are C extension modules that need to be rewritten. |
48 |
| - |
49 |
| - To see the status of a particular feature or standard library module, click |
50 |
| - [here](https://github.com/google/grumpy/wiki/Missing-Features). |
| 47 | +3. [Standard library](https://github.com/google/grumpy/wiki/Missing-features#standard-libraries): |
| 48 | + The Python standard library is very large and much of it is pure Python, so |
| 49 | + as the language features and builtins get filled out, many modules will |
| 50 | + just work. But there are also a number of libraries in CPython that are C |
| 51 | + extension modules which will need to be rewritten. |
| 52 | + |
| 53 | +4. C locale support: Go doesn't support locales in the same way that C does. As such, |
| 54 | + some functionality that is locale-dependent may not currently work the same as in |
| 55 | + CPython. |
51 | 56 |
|
52 | 57 | ## Running Grumpy Programs
|
53 | 58 |
|
54 |
| -### Method 1: grumprun: |
| 59 | +### Pre-requisites |
| 60 | + |
| 61 | +The commands ahead assumes that you have Golang installed and a recent |
| 62 | +version of Python 2, `setuptools` and `pip`. |
| 63 | + |
| 64 | +### Method 1: binary package |
| 65 | + |
| 66 | +For convenience, a Python package is provided from the PyPI. During install, |
| 67 | +many Grumpy will be compiled and stored inside your Python installation. |
| 68 | + |
| 69 | +You need Golang preinstalled anyway for the installation to be successful. |
| 70 | + |
| 71 | +``` |
| 72 | +pip2 install -U grumpy-runtime -I --no-cache |
| 73 | +(wait about 5 minutes) |
| 74 | +echo "print 'hello, world'" | grumpy run |
| 75 | +``` |
| 76 | + |
| 77 | +### Method 1: make run: |
55 | 78 |
|
56 | 79 | The simplest way to execute a Grumpy program is to use `make run`, which wraps a
|
57 | 80 | shell script called grumprun that takes Python code on stdin and builds and runs
|
58 |
| -the code under Grumpy. All of the commands below are assumed to be run from the |
59 |
| -root directory of the Grumpy source code distribution: |
| 81 | +the code under Grumpy: |
60 | 82 |
|
61 | 83 | ```
|
| 84 | +cd grumpy-tools-src |
| 85 | +python2 setup.py develop |
| 86 | +cd ../grumpy-runtime-src |
62 | 87 | echo "print 'hello, world'" | make run
|
63 | 88 | ```
|
64 | 89 |
|
65 |
| -### Method 2: grumpc: |
| 90 | +### Method 2: grumpc and grumprun: |
66 | 91 |
|
67 |
| -For more complicated programs you'll want to compile your Python source code to |
| 92 | +For more complicated programs, you'll want to compile your Python source code to |
68 | 93 | Go using grumpc (the Grumpy compiler) and then build the Go code using `go
|
69 |
| -build`. First, write a simple .py script: |
70 |
| - |
71 |
| -``` |
72 |
| -echo 'print "hello, world"' > hello.py |
73 |
| -``` |
| 94 | +build`. Since Grumpy programs are statically linked, all the modules in a |
| 95 | +program must be findable by the Grumpy toolchain on the GOPATH. Grumpy looks for |
| 96 | +Go packages corresponding to Python modules in the \_\_python\_\_ subdirectory |
| 97 | +of the GOPATH. By convention, this subdirectory is also used for staging Python |
| 98 | +source code, making it similar to the PYTHONPATH. |
74 | 99 |
|
75 |
| -Next, build the toolchain and export some environment variables that make the |
76 |
| -toolchain work: |
| 100 | +The first step is to set up the shell so that the Grumpy toolchain and libraries |
| 101 | +can be found. From the root directory of the Grumpy source distribution run: |
77 | 102 |
|
78 | 103 | ```
|
| 104 | +cd grumpy-tools-src |
| 105 | +python2 setup.py develop |
| 106 | +cd ../grumpy-runtime-src |
79 | 107 | make
|
| 108 | +export PATH=$PWD/build/bin:$PATH |
80 | 109 | export GOPATH=$PWD/build
|
81 | 110 | export PYTHONPATH=$PWD/build/lib/python2.7/site-packages
|
82 | 111 | ```
|
83 | 112 |
|
84 |
| -Finally, compile the Python script and build a binary from it: |
| 113 | +You will know things are working if you see the expected output from this |
| 114 | +command: |
85 | 115 |
|
86 | 116 | ```
|
87 |
| -build/bin/grumpc hello.py > hello.go |
88 |
| -go build -o hello hello.go |
| 117 | +cd grumpy-runtime-src |
| 118 | +echo 'import sys; print sys.version' | grumprun |
89 | 119 | ```
|
90 | 120 |
|
91 |
| -Now execute the `./hello` binary to your heart's content. |
| 121 | +Next, we will write our simple Python module into the \_\_python\_\_ directory: |
| 122 | + |
| 123 | +``` |
| 124 | +cd grumpy-runtime-src |
| 125 | +echo 'def hello(): print "hello, world"' > $GOPATH/src/__python__/hello.py |
| 126 | +``` |
| 127 | + |
| 128 | +To build a Go package from our Python script, run the following: |
| 129 | + |
| 130 | +``` |
| 131 | +cd grumpy-runtime-src |
| 132 | +mkdir -p $GOPATH/src/__python__/hello |
| 133 | +grumpc -modname=hello $GOPATH/src/__python__/hello.py > \ |
| 134 | + $GOPATH/src/__python__/hello/module.go |
| 135 | +``` |
| 136 | + |
| 137 | +You should now be able to build a Go program that imports the package |
| 138 | +"\_\_python\_\_/hello". We can also import this module into Python programs |
| 139 | +that are built using grumprun: |
| 140 | + |
| 141 | +``` |
| 142 | +cd grumpy-runtime-src |
| 143 | +echo 'from hello import hello; hello()' | grumprun |
| 144 | +``` |
| 145 | + |
| 146 | +grumprun is doing a few things under the hood here: |
| 147 | + |
| 148 | +1. Compiles the given Python code to a dummy Go package, the same way we |
| 149 | + produced \_\_python\_\_/hello/module.go above |
| 150 | +2. Produces a main Go package that imports the Go package from step 1. and |
| 151 | + executes it as our \_\_main\_\_ Python package |
| 152 | +3. Executes `go run` on the main package generated in step 2. |
92 | 153 |
|
93 | 154 | ## Developing Grumpy
|
94 | 155 |
|
95 | 156 | There are three main components and depending on what kind of feature you're
|
96 | 157 | writing, you may need to change one or more of these.
|
97 | 158 |
|
98 |
| -### grumpc |
| 159 | +### Grumpy Tools |
99 | 160 |
|
100 |
| -Grumpy converts Python programs into Go programs and grumpc is the tool |
101 |
| -responsible for parsing Python code and generating Go code from it. grumpc is |
102 |
| -written in Python and uses the `ast` module to accomplish parsing. |
| 161 | +Grumpy converts Python programs into Go programs and |
| 162 | +`grumpy transpile` is the CLI tool responsible for parsing Python code |
| 163 | +and generating Go code from it. `grumpy transpile` is written in Python |
| 164 | +and uses the [`pythonparser`](https://github.com/m-labs/pythonparser) |
| 165 | +module to accomplish parsing. |
103 | 166 |
|
104 |
| -The grumpc script itself lives at tools/grumpc. It is supported by a number of |
105 |
| -Python modules in the compiler subdir. |
| 167 | +The CLI main entrypoint lives at `grumpy-tools-src/grumpy_tools/cli.py`. |
| 168 | +It is supported by a number of Python modules in the |
| 169 | +`grumpy-tools-src/grumpy_tools/compiler` subdir. |
106 | 170 |
|
107 | 171 | ### Grumpy Runtime
|
108 | 172 |
|
109 |
| -The Go code generated by grumpc performs operations on data structures that |
110 |
| -represent Python objects in running Grumpy programs. These data structures and |
111 |
| -operations are defined in the `grumpy` Go library (source is in the runtime |
112 |
| -subdir of the source distribution). This runtime is analogous to the Python C |
113 |
| -API and many of the structures and operations defined by `grumpy` have |
114 |
| -counterparts in CPython. |
| 173 | +The Go code generated by `grumpy transpile` performs operations |
| 174 | +on data structures that represent Python objects in running Grumpy programs. |
| 175 | +These data structures and operations are defined in the `grumpy` Go library |
| 176 | +(source is in the `grumpy-runtime-src/runtime` subdir of the source |
| 177 | +distribution). This runtime is analogous to the Python C API and many of the |
| 178 | +structures and operations defined by `grumpy` have counterparts in CPython. |
115 | 179 |
|
116 | 180 | ### Grumpy Standard Library
|
117 | 181 |
|
118 |
| -Much of the Python standard library is written in Python and so it "just works" |
| 182 | +Much of the Python standard library is written in Python and thus "just works" |
119 | 183 | in Grumpy. These parts of the standard library are copied from CPython 2.7
|
120 | 184 | (possibly with light modifications). For licensing reasons, these files are kept
|
121 |
| -in the third_party/stdlib subdir. |
| 185 | +in the `grumpy-runtime-src/third_party` subdir. |
122 | 186 |
|
123 | 187 | The parts of the standard library that cannot be written in pure Python, e.g.
|
124 |
| -file and directory operations, are kept in the lib subdir. In CPython these |
125 |
| -kinds of modules are written as C extensions. In Grumpy they are written in |
126 |
| -Python but they use native Go extensions to access facilities not otherwise |
127 |
| -available in Python. |
| 188 | +file and directory operations, are kept in the `grumpy-runtime-src/lib` subdir. |
| 189 | +In CPython these kinds of modules are written as C extensions. In Grumpy they |
| 190 | +are written in Python but they use native Go extensions to access facilities not |
| 191 | +otherwise available in Python. |
128 | 192 |
|
129 | 193 | ### Source Code Overview
|
130 | 194 |
|
131 |
| -- `compiler`: Python package implementating Python -> Go transcompilation logic. |
132 |
| -- `lib`: Grumpy-specific Python standard library implementation. |
133 |
| -- `runtime`: Go source code for the Grumpy runtime library. |
134 |
| -- `third_party/stdlib`: Pure Python standard libraries copied from CPython. |
135 |
| -- `tools`: Transcompilation and utility binaries. |
| 195 | +- `grumpy-tools-src/grumpy_tools/compiler`: Python package implementating Python -> Go transcompilation logic. |
| 196 | +- `grumpy-runtime-src/lib`: Grumpy-specific Python standard library implementation. |
| 197 | +- `grumpy-runtime-src/runtime`: Go source code for the Grumpy runtime library. |
| 198 | +- `grumpy-runtime-src/third_party/ouroboros`: Pure Python standard libraries copied from the |
| 199 | + [Ouroboros project](https://github.com/pybee/ouroboros). |
| 200 | +- `grumpy-runtime-src/third_party/pypy`: Pure Python standard libraries copied from PyPy. |
| 201 | +- `grumpy-runtime-src/third_party/stdlib`: Pure Python standard libraries copied from CPython. |
| 202 | +- `grumpy-tools-src/grumpy_tools/`: Transcompilation and utility CLI. |
136 | 203 |
|
137 | 204 | ## Contact
|
138 | 205 |
|
139 |
| -Questions? Comments? Drop us a line at [[email protected]](https://groups.google.com/forum/#!forum/grumpy-users). |
| 206 | +Questions? Comments? Drop us a line at [[email protected]](https://groups.google.com/forum/#!forum/grumpy-users) |
| 207 | +or join our [Gitter channel](https://gitter.im/grumpy-devel/Lobby) |
0 commit comments