{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Start out by establishing a connection to a MongoDB instance."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "import pymongo\n",
    "conn = pymongo.MongoClient()\n",
    "db = conn.test\n",
    "coll = db.objects\n",
    "coll.drop()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Insert a couple of documents that represent themselves naturally in JSON."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<pymongo.results.InsertOneResult at 0x10489b708>"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import datetime\n",
    "coll.insert_one({'a': datetime.datetime.now(), 'b': 1.0})\n",
    "coll.insert_one({'items': [1, 2, 3, 'd']})"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "But what about more complex objects (classes and instances of those classes)?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "class MyObject:\n",
    "    def __init__(self, x, y):\n",
    "        self.x = x\n",
    "        self.y = y\n",
    "    \n",
    "    def __repr__(self):\n",
    "        return '{self.__class__.__name__}({self.x}, {self.y})'.format(**vars())\n",
    "\n",
    "ob1 = MyObject(1, 2)\n",
    "ob2 = MyObject(0, 5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "ename": "TypeError",
     "evalue": "document must be an instance of dict, bson.son.SON, bson.raw_bson.RawBSONDocument, or a type that inherits from collections.MutableMapping",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mTypeError\u001b[0m                                 Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-4-a5e91fbd96fd>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mcoll\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0minsert_one\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mob1\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[0;32m/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/pymongo-3.2-py3.5-macosx-10.6-intel.egg/pymongo/collection.py\u001b[0m in \u001b[0;36minsert_one\u001b[0;34m(self, document, bypass_document_validation)\u001b[0m\n\u001b[1;32m    617\u001b[0m         \u001b[0;34m.\u001b[0m\u001b[0;34m.\u001b[0m \u001b[0mversionadded\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0;36m3.0\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    618\u001b[0m         \"\"\"\n\u001b[0;32m--> 619\u001b[0;31m         \u001b[0mcommon\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mvalidate_is_document_type\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"document\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdocument\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m    620\u001b[0m         \u001b[0;32mif\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0misinstance\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdocument\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mRawBSONDocument\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mor\u001b[0m \u001b[0;34m\"_id\"\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mdocument\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    621\u001b[0m             \u001b[0mdocument\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m\"_id\"\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mObjectId\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/pymongo-3.2-py3.5-macosx-10.6-intel.egg/pymongo/common.py\u001b[0m in \u001b[0;36mvalidate_is_document_type\u001b[0;34m(option, value)\u001b[0m\n\u001b[1;32m    382\u001b[0m                         \u001b[0;34m\"bson.raw_bson.RawBSONDocument, or \"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    383\u001b[0m                         \u001b[0;34m\"a type that inherits from \"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 384\u001b[0;31m                         \"collections.MutableMapping\" % (option,))\n\u001b[0m\u001b[1;32m    385\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    386\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;31mTypeError\u001b[0m: document must be an instance of dict, bson.son.SON, bson.raw_bson.RawBSONDocument, or a type that inherits from collections.MutableMapping"
     ]
    }
   ],
   "source": [
    "coll.insert_one(ob1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'py/object': '__main__.MyObject', 'x': 1, 'y': 2}"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import jaraco.modb\n",
    "jaraco.modb.encode(ob1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Because a MyObject instance doesn't have a natural representation in JSON, it's serialized as a dictionary with a special key 'py/object', which signals to the decoder that this is a JSONPickled Python Object. As long as the system doing the decoding implements `__main__.MyObject` with a compatible interface, the object will decode nicely."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<pymongo.results.InsertOneResult at 0x10490c288>"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "coll.insert_one(jaraco.modb.encode(ob1))\n",
    "coll.insert_one(jaraco.modb.encode(ob2))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now the two objects should be persisted to the database. Query them to see how they appear."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[{'_id': ObjectId('56c9f5ff10334e93a39158b1'),\n",
       "  'a': datetime.datetime(2016, 2, 21, 13, 38, 7, 359000),\n",
       "  'b': 1.0},\n",
       " {'_id': ObjectId('56c9f5ff10334e93a39158b2'), 'items': [1, 2, 3, 'd']},\n",
       " {'_id': ObjectId('56c9f61410334e93a39158b3'),\n",
       "  'py/object': '__main__.MyObject',\n",
       "  'x': 1,\n",
       "  'y': 2},\n",
       " {'_id': ObjectId('56c9f61410334e93a39158b4'),\n",
       "  'py/object': '__main__.MyObject',\n",
       "  'x': 0,\n",
       "  'y': 5}]"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "list(coll.find())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "MyObject(0, 5)"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "next(map(jaraco.modb.decode, coll.find({'x': 0})))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "But what about more complex objects? Consider ob3 whose x attribute is another MyObject."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "MyObject(MyObject(0, 5), 2)"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ob3 = MyObject(ob2, 2)\n",
    "ob3"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<pymongo.results.InsertOneResult at 0x10489bf30>"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "coll.insert_one(jaraco.modb.encode(ob3))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Because MongoDB's document query engine allows reaching deep into the documents, one can even query based on child object's attributes."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "MyObject(MyObject(0, 5), 2)"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Find all objects whose x attribute has a y attribute with a value of 5\n",
    "query = {'x.y': 5}\n",
    "next(map(jaraco.modb.decode, coll.find(query)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Where are the limitations? What about integer keys?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "ename": "InvalidDocument",
     "evalue": "documents must have only string keys, key was 1",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mInvalidDocument\u001b[0m                           Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-12-5d51c33613b8>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mcoll\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0minsert_one\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m{\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0;36m3\u001b[0m\u001b[0;34m}\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[0;32m/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/pymongo-3.2-py3.5-macosx-10.6-intel.egg/pymongo/collection.py\u001b[0m in \u001b[0;36minsert_one\u001b[0;34m(self, document, bypass_document_validation)\u001b[0m\n\u001b[1;32m    623\u001b[0m             return InsertOneResult(\n\u001b[1;32m    624\u001b[0m                 self._insert(sock_info, document,\n\u001b[0;32m--> 625\u001b[0;31m                              bypass_doc_val=bypass_document_validation),\n\u001b[0m\u001b[1;32m    626\u001b[0m                 self.write_concern.acknowledged)\n\u001b[1;32m    627\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/pymongo-3.2-py3.5-macosx-10.6-intel.egg/pymongo/collection.py\u001b[0m in \u001b[0;36m_insert\u001b[0;34m(self, sock_info, docs, ordered, check_keys, manipulate, write_concern, op_id, bypass_doc_val)\u001b[0m\n\u001b[1;32m    528\u001b[0m             return self._insert_one(\n\u001b[1;32m    529\u001b[0m                 \u001b[0msock_info\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdocs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mordered\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 530\u001b[0;31m                 check_keys, manipulate, write_concern, op_id, bypass_doc_val)\n\u001b[0m\u001b[1;32m    531\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    532\u001b[0m         \u001b[0mids\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/pymongo-3.2-py3.5-macosx-10.6-intel.egg/pymongo/collection.py\u001b[0m in \u001b[0;36m_insert_one\u001b[0;34m(self, sock_info, doc, ordered, check_keys, manipulate, write_concern, op_id, bypass_doc_val)\u001b[0m\n\u001b[1;32m    510\u001b[0m                                        \u001b[0mcommand\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    511\u001b[0m                                        \u001b[0mcodec_options\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcodec_options\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 512\u001b[0;31m                                        check_keys=check_keys)\n\u001b[0m\u001b[1;32m    513\u001b[0m             \u001b[0m_check_write_command_response\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mresult\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    514\u001b[0m         \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/pymongo-3.2-py3.5-macosx-10.6-intel.egg/pymongo/pool.py\u001b[0m in \u001b[0;36mcommand\u001b[0;34m(self, dbname, spec, slave_ok, read_preference, codec_options, check, allowable_errors, check_keys, read_concern)\u001b[0m\n\u001b[1;32m    214\u001b[0m         \u001b[0;31m# Catch socket.error, KeyboardInterrupt, etc. and close ourselves.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    215\u001b[0m         \u001b[0;32mexcept\u001b[0m \u001b[0mBaseException\u001b[0m \u001b[0;32mas\u001b[0m \u001b[0merror\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 216\u001b[0;31m             \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_raise_connection_failure\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0merror\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m    217\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    218\u001b[0m     \u001b[0;32mdef\u001b[0m \u001b[0msend_message\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mmessage\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mmax_doc_size\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/pymongo-3.2-py3.5-macosx-10.6-intel.egg/pymongo/pool.py\u001b[0m in \u001b[0;36m_raise_connection_failure\u001b[0;34m(self, error)\u001b[0m\n\u001b[1;32m    341\u001b[0m             \u001b[0m_raise_connection_failure\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0maddress\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0merror\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    342\u001b[0m         \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 343\u001b[0;31m             \u001b[0;32mraise\u001b[0m \u001b[0merror\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m    344\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    345\u001b[0m     \u001b[0;32mdef\u001b[0m \u001b[0m__eq__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mother\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/pymongo-3.2-py3.5-macosx-10.6-intel.egg/pymongo/pool.py\u001b[0m in \u001b[0;36mcommand\u001b[0;34m(self, dbname, spec, slave_ok, read_preference, codec_options, check, allowable_errors, check_keys, read_concern)\u001b[0m\n\u001b[1;32m    209\u001b[0m                            \u001b[0mcheck\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mallowable_errors\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0maddress\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    210\u001b[0m                            \u001b[0mcheck_keys\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mlisteners\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmax_bson_size\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 211\u001b[0;31m                            read_concern)\n\u001b[0m\u001b[1;32m    212\u001b[0m         \u001b[0;32mexcept\u001b[0m \u001b[0mOperationFailure\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    213\u001b[0m             \u001b[0;32mraise\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/pymongo-3.2-py3.5-macosx-10.6-intel.egg/pymongo/network.py\u001b[0m in \u001b[0;36mcommand\u001b[0;34m(sock, dbname, spec, slave_ok, is_mongos, read_preference, codec_options, check, allowable_errors, address, check_keys, listeners, max_bson_size, read_concern)\u001b[0m\n\u001b[1;32m     76\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     77\u001b[0m     request_id, msg, size = message.query(flags, ns, 0, -1, spec,\n\u001b[0;32m---> 78\u001b[0;31m                                           None, codec_options, check_keys)\n\u001b[0m\u001b[1;32m     79\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     80\u001b[0m     if (max_bson_size is not None\n",
      "\u001b[0;31mInvalidDocument\u001b[0m: documents must have only string keys, key was 1"
     ]
    }
   ],
   "source": [
    "coll.insert_one({1: 3})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "res = coll.insert_one(jaraco.modb.encode({1: 3}))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'1': 3, '_id': ObjectId('56c9f63910334e93a39158b8')}"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "coll.find_one({'_id': res.inserted_id})"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You might note that the integer 1 is now represented as a string '1'. This limitation is an unfortunate side-effect of relying on JSON as a serialization layer."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.5.1"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
