cyper 1.0
Cython performed inline: compile and run your Cython snippets on the fly.
License: MIT License
Keywords: cython

# cyper

**Cy**thon **per**formed inline: compile and run your Cython snippets on the fly.

It is aiming to provide a flexible alternative to the IPython Cython magic command outside the IPython/Jupyter environment.

## Features

- Simple, get rid of the tedious setup files or makefile.
- Smart, auto-detect and set compiler flags for Numpy and OpenMP.
- Highly customizable, allow one to set Cython directives, environment variables and compiler options.

## Usage

### Basic usage

- Basic usage
  ```python
  import cyper
  code = r'''
  def func(x):
      return 2.0 * x
  '''
  pyx = cyper.inline(code)
  pyx.func(1)
  # 2.0
  ```
  Raw string is recommended to avoid breaking escape character.

- It is convenient (though usually not encouraged) to export the variables from compiled module to the current namespace
  ```python
  cyper.inline(code, globals())
  func(1)
  ```

- Example of using Numpy array and external gsl library, assuming gsl installed at `/opt/gsl/`
  ```python
  code = r'''
  import numpy as np

  cdef extern from "gsl/gsl_math.h":
      double gsl_pow_int (double x, int n)

  def pow(double x, int n):
      y = gsl_pow_int(x, n)
      return y

  def pow_array(double[:] x, int n):
      cdef:
          int i, m=len(x)
          double[:] y=np.empty(m, dtype='f8')
      for i in range(m):
          y[i] = gsl_pow_int(x[i], n)
      return y.base
  '''
  pyx = cyper.inline(
      code,
      include_dirs=['/opt/gsl/include/'],
      library_dirs=['/opt/gsl/lib'],
      libraries=['gsl', 'gslcblas']
  )

  pyx.pow(2, 6)
  # 64.0

  import numpy as np
  pyx.pow_array(np.arange(5, dtype='f8'), 2)
  # array([ 0.,  1.,  4.,  9., 16.])
  ```

- Get better performance (at your own risk) with arrays
  ```python
  cyper.inline(code, fast_indexing=True)
  # or equivalently
  cyper.inline(code, directives=dict(boundscheck=False, wraparound=False))
  ```

### Advanced usage

- Set the compiler options, e.g., compiling OpenMP codes with gcc
  ```python
  cyper.inline(openmpcode,
               extra_compile_args=['-fopenmp'],
               extra_link_args=['-fopenmp'],
               )
  # use '-openmp' or '-qopenmp' (>=15.0) for Intel
  # use '/openmp' for Microsoft Visual C++ Compiler
  # use '-fopenmp=libomp' for Clang
  ```
  Or equivalently write this for short
  ```python
  cyper.inline(openmpcode, openmp='-fopenmp')
  ```

  The cython `directives` and distutils `extension_args` can also be set in a directive comment at the top of the code snippet, e.g.,
  ```python
  code = r'''
  # cython: boundscheck=False, wraparound=False, cdivision=True
  # distutils: extra_compile_args = -fopenmp
  # distutils: extra_link_args = -fopenmp
  ...<code>...
  '''
  cyper.inline(code)
  ```

- Set environment variables, e.g., using icc to compile
  ```python
  cyper.inline(code, environ={'CC':'icc', 'LDSHARED':'icc -shared'})
  ```
  See https://software.intel.com/en-us/articles/thread-parallelism-in-cython

- Set directory for searching cimport (.pxd file)
  ```python
  cyper.inline(code, cimport_dirs=[custom_path]})
  # or equivalently
  cyper.inline(code, cythonize_args={'include_path': [custom_path]})
  ```
  Try setting `cimport_dirs=sys.path` if Cython can not find the installed cimport modules.

## Installation

- Dependencies: Cython

- Installation:
  ```bash
  pip install cyper
  ```

## License

Cyper is licensed under the [MIT License](https://github.com/syrte/cyper/blob/master/LICENSE)