Skip to content

Commit

Permalink
Update documentation with API help
Browse files Browse the repository at this point in the history
  • Loading branch information
tonybaloney committed Nov 17, 2020
1 parent 7462c9f commit c37ffc2
Show file tree
Hide file tree
Showing 8 changed files with 110 additions and 10 deletions.
10 changes: 6 additions & 4 deletions .github/workflows/master.yml
Original file line number Diff line number Diff line change
Expand Up @@ -96,14 +96,16 @@ jobs:
- name: Run unit tests
working-directory: ${{runner.workspace}}/build
shell: bash
run: |
./unit_tests
gcov .
run: ./unit_tests

- name: Run gcov
shell: bash
run: gcov Tests/

- name: Codecov
uses: codecov/codecov-action@v1.0.15
with:
directory: ${{runner.workspace}}/build
directory: Tests/

- name: Run smoke tests
shell: bash
Expand Down
7 changes: 7 additions & 0 deletions Docs/source/api.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Pyjion Python API
=================

.. automodule:: pyjion



1 change: 1 addition & 0 deletions Docs/source/building.rst
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ Prerequisites:
- .NET 5

.. code-block::
$ git clone git@github.com:Microsoft/pyjion --recurse-submodules
$ cd pyjion
$ python -m pip install .
20 changes: 15 additions & 5 deletions Docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,16 @@
# documentation root, use os.path.abspath to make it absolute, like shown here.
#sys.path.insert(0, os.path.abspath('.'))

# Get the project root dir, which is the parent dir of this
cwd = os.getcwd()
project_root = os.path.dirname(cwd)

# Insert the project root dir as the first element in the PYTHONPATH.
# This lets us ensure that the source package is imported, and that its
# version is used.
sys.path.insert(0, project_root)
import pyjion

# -- General configuration ------------------------------------------------

# If your documentation needs a minimal Sphinx version, state it here.
Expand All @@ -30,7 +40,7 @@
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = []
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.viewcode']

# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
Expand All @@ -48,17 +58,17 @@

# General information about the project.
project = 'Pyjion'
copyright = '2016, Brett Cannon, Dino Viehland'
author = 'Brett Cannon, Dino Viehland'
copyright = '2020, Brett Cannon, Dino Viehland, Anthony Shaw'
author = 'Brett Cannon, Dino Viehland, Anthony Shaw'

# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
version = '1.0'
version = pyjion.__version__
# The full version, including alpha/beta/rc tags.
release = '1.0'
release = pyjion.__version__

# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
Expand Down
1 change: 1 addition & 0 deletions Docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,4 @@ Main
gettingstarted
building
using
api
71 changes: 71 additions & 0 deletions Docs/source/using.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,75 @@ Using Pyjion

After following the installation steps, pyjion is a python module that you can import a Python 3.9 environment.

To get started, you need to have .NET 5 installed, with Python 3.9 and the Pyjion package (I also recommend using a virtual environment).

After importing pyjion, enable it by calling `pyjion.enable()` which sets a compilation threshold to 0 (the code only needs to be run once to be compiled by the JIT):

.. code-snippet::

>>> import pyjion
>>> pyjion.enable()


Any Python code you define or import after enabling pyjion will be JIT compiled. You don't need to execute functions in any special API, its completely transparent:

.. code-snippet::

>>> def half(x):
... return x/2
>>> half(2)
1.0

Pyjion will have compiled the `half` function into machine code on-the-fly and stored a cached version of that compiled function inside the function object.
You can see some basic stats by running `pyjion.info(f)`, where `f` is the function object:

.. code-snippet::

>>> pyjion.info(half)
{'failed': False, 'compiled': True, 'run_count': 1}


You can see the machine code for the compiled function by disassembling it in the Python REPL.
Pyjion has essentially compiled your small Python function into a small, standalone application.
Install `distorm3` first to disassemble x86-64 assembly and run `pyjion.dis.dis_native(f)`:

.. code-snippet::

>>> import pyjion.dis
>>> pyjion.dis.dis_native(half)
00000000: PUSH RBP
00000001: MOV RBP, RSP
00000004: PUSH R14
00000006: PUSH RBX
00000007: MOV RBX, RSI
0000000a: MOV R14, [RDI+0x40]
0000000e: CALL 0x1b34
00000013: CMP DWORD [RAX+0x30], 0x0
00000017: JZ 0x31
00000019: CMP QWORD [RAX+0x40], 0x0
0000001e: JZ 0x31
00000020: MOV RDI, RAX
00000023: MOV RSI, RBX
00000026: XOR EDX, EDX
00000028: POP RBX
00000029: POP R14
...

The complex logic of converting a portable instruction set into low-level machine instructions is done by .NET's CLR JIT compiler.

All Python code executed after the JIT is enabled will be compiled into native machine code at runtime and cached on disk. For example, to enable the JIT on a simple `app.py` for a Flask web app:

.. code-snippet:: python

import pyjion
pyjion.enable()

from flask import Flask
app = Flask(__name__)

@app.route('/')
def hello_world():
return 'Hello, World!'

app.run()

8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,15 @@ A JIT extension for CPython that compiles your Python code into native CIL and e

![Compile and test C++ package](https://github.com/tonybaloney/Pyjion/workflows/Compile%20and%20test%20C++%20package/badge.svg)
[![Documentation Status](https://readthedocs.org/projects/pyjion/badge/?version=latest)](https://pyjion.readthedocs.io/en/latest/?badge=latest)
[![PyPI](https://img.shields.io/pypi/v/pyjion?label=pypi%20package)](https://pypi.org/p/pyjion)

## Installing

## Installing
```console
$ pip install pyjion
```

## Compiling from source

Prerequisites:

Expand Down
2 changes: 2 additions & 0 deletions pyjion/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import os
import platform

__version__ = '0.0.2'


def _no_dotnet(path):
print(f"Can't find a .NET 5 installation in {path}, "
Expand Down

0 comments on commit c37ffc2

Please sign in to comment.