{
 "metadata": {
  "name": "",
  "signature": "sha256:438767454582b96e9096bbcdb45197e77d89855bbed48f6811ba648244797485"
 },
 "nbformat": 3,
 "nbformat_minor": 0,
 "worksheets": [
  {
   "cells": [
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "%load_ext cython"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [],
     "prompt_number": 4
    },
    {
     "cell_type": "heading",
     "level": 1,
     "metadata": {},
     "source": [
      "Regular class vs extensions class"
     ]
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "%%cython\n",
      "\n",
      "cdef extern from \"Python.h\" nogil:\n",
      "     ctypedef class __builtin__.Exception [object PyBaseExceptionObject]:\n",
      "         pass\n",
      "\n",
      "cdef class FUSEErrorExt(Exception):\n",
      "    '''\n",
      "    This exception may be raised by request handlers to indicate that\n",
      "    the requested operation could not be carried out. The system call\n",
      "    that resulted in the request (if any) will then fail with error\n",
      "    code *errno_*.\n",
      "    '''\n",
      "\n",
      "    # If we call this variable \"errno\", we will get syntax errors\n",
      "    # during C compilation (maybe something else declares errno as\n",
      "    # a macro?)\n",
      "    cdef int errno_\n",
      "\n",
      "    property errno:\n",
      "        '''Error code to return to client process'''\n",
      "        def __get__(self):\n",
      "            return self.errno_\n",
      "        def __set__(self, val):\n",
      "            self.errno_ = val\n",
      "\n",
      "    def __init__(self, errno):\n",
      "        self.errno_ = errno"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [],
     "prompt_number": 5
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "class FUSEErrorInt(Exception):\n",
      "    def __init__(self, errno):\n",
      "        self.errno = errno"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [],
     "prompt_number": 6
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "def test_ext():\n",
      "    a = 0\n",
      "    for i in range(100):\n",
      "        try:\n",
      "            raise FUSEErrorExt(i)\n",
      "        except FUSEErrorExt as exc:\n",
      "            a += exc.errno\n",
      "        except:\n",
      "            print('This should not happen')\n",
      "    return a\n",
      "\n",
      "def test_int():\n",
      "    a = 0\n",
      "    for i in range(100):\n",
      "        try:\n",
      "            raise FUSEErrorInt(i)\n",
      "        except FUSEErrorInt as exc:\n",
      "            a += exc.errno\n",
      "        except:\n",
      "            print('This should not happen')\n",
      "    return a"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [],
     "prompt_number": 7
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "assert test_ext() == test_int()\n",
      "%timeit test_ext()\n",
      "%timeit test_int()"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "output_type": "stream",
       "stream": "stdout",
       "text": [
        "10000 loops, best of 3: 35.3 \u00b5s per loop\n",
        "10000 loops, best of 3: 55.6 \u00b5s per loop"
       ]
      },
      {
       "output_type": "stream",
       "stream": "stdout",
       "text": [
        "\n"
       ]
      }
     ],
     "prompt_number": 8
    },
    {
     "cell_type": "heading",
     "level": 1,
     "metadata": {},
     "source": [
      "Instantiation vs Factory Function with Cache"
     ]
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "(Unfortunately we cannot use @cython.freelist for derived classes)"
     ]
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "cache = dict()\n",
      "def getError(errno):\n",
      "    try:\n",
      "        return cache[errno]\n",
      "    except KeyError:\n",
      "        cache[errno] = FUSEErrorExt(errno)\n",
      "        return cache[errno]\n",
      "    \n",
      "def test_ext_cached():\n",
      "    a = 0\n",
      "    for i in range(100):\n",
      "        try:\n",
      "            raise getError(i)\n",
      "        except FUSEErrorExt as exc:\n",
      "            a += exc.errno\n",
      "        except:\n",
      "            print('This should not happen')\n",
      "    return a"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [],
     "prompt_number": 9
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "assert test_ext() == test_ext_cached()\n",
      "%timeit test_ext()\n",
      "%timeit test_ext_cached()"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "output_type": "stream",
       "stream": "stdout",
       "text": [
        "10000 loops, best of 3: 34.9 \u00b5s per loop\n",
        "10000 loops, best of 3: 38 \u00b5s per loop"
       ]
      },
      {
       "output_type": "stream",
       "stream": "stdout",
       "text": [
        "\n"
       ]
      }
     ],
     "prompt_number": 10
    },
    {
     "cell_type": "heading",
     "level": 2,
     "metadata": {},
     "source": [
      "Catching Exception vs Ordinary Return"
     ]
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "def handler(i):\n",
      "    return getError(i)\n",
      "\n",
      "def test_ext_direct():\n",
      "    a = 0\n",
      "    for i in range(100):\n",
      "        res = handler(i)\n",
      "        if isinstance(res, FUSEErrorExt):\n",
      "            a += res.errno\n",
      "    return a"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [],
     "prompt_number": 15
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "assert test_ext_cached() == test_ext_direct()\n",
      "%timeit test_ext_cached()\n",
      "%timeit test_ext_direct()"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "output_type": "stream",
       "stream": "stdout",
       "text": [
        "10000 loops, best of 3: 38 \u00b5s per loop\n",
        "10000 loops, best of 3: 29.1 \u00b5s per loop"
       ]
      },
      {
       "output_type": "stream",
       "stream": "stdout",
       "text": [
        "\n"
       ]
      }
     ],
     "prompt_number": 16
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [],
     "language": "python",
     "metadata": {},
     "outputs": []
    }
   ],
   "metadata": {}
  }
 ]
}