{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "Python for Everyone!
[Oregon Curriculum Network](http://4dsolutions.net/ocn/)\n", "\n", "## Spooky Castle\n", "### Context Managers in Python\n", "\n", "\"Spooky\n", "\n", "Halloween is nigh. Or lets pretend it is.\n", "\n", "Lets explore context manager syntax in the context of Halloween..." ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Welcome...\n", "Testing 1-2-3\n" ] } ], "source": [ "from random import choice\n", "\n", "class Trick(Exception):\n", " def __init__(self):\n", " self.value = \"Goblins & Ghosts!\"\n", " \n", "class Halloween:\n", " \n", " def __init__(self, arg=None):\n", " self.testing = arg\n", " \n", " def __enter__(self):\n", " self.where = \"Spooky Castle\"\n", " print(\"Welcome...\")\n", " self.trick_or_treat = [\"Trick\", \"Treat\"]\n", " self.candy = [ ]\n", " return self\n", " \n", " def __exit__(self, *uh_oh): # catch any exception info\n", " if uh_oh[0]: \n", " print(\"Trick!\")\n", " print(uh_oh[1].value) # lets look inside the exception\n", " return False\n", " return True\n", "\n", "try:\n", " with Halloween(\"Testing 1-2-3\") as obj:\n", " print(obj.testing)\n", " if choice(obj.trick_or_treat) == \"Trick\":\n", " raise Trick \n", "except Trick:\n", " print(\"Exception raised!\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Notice that test_trick below defines a function internally, and calls it, expecting an Exception to be raised. Defining functions internally to methods for testing purposes is a nice way to avoid creating any test functions globally. No need to clean up. No worries about persistence of \"hidden state\" across tests (tests should not depend on one another).\n", "\n", "One needs some fancy footwork to run the unittests in a Jupyter Notebook, but it's still very doable and fun!" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "collapsed": false }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ ".." ] }, { "name": "stdout", "output_type": "stream", "text": [ "Welcome...\n", "Welcome...\n", "Trick!\n", "Goblins & Ghosts!\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\n", "----------------------------------------------------------------------\n", "Ran 2 tests in 0.006s\n", "\n", "OK\n" ] }, { "data": { "text/plain": [ "" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import unittest\n", "\n", "class TestCastle(unittest.TestCase):\n", " \n", " def test_candy(self):\n", " outer = \"\"\n", " with Halloween() as context:\n", " outer = context.candy\n", " self.assertEqual(outer, [], \"Not OK!\")\n", " \n", " def test_trick(self):\n", " outer = \"\"\n", " def func():\n", " with Halloween() as context:\n", " raise Trick\n", " self.assertRaises(Trick, func)\n", " \n", "a = TestCastle() # the test suite\n", "suite = unittest.TestLoader().loadTestsFromModule(a) # fancy boilerplate\n", "unittest.TextTestRunner().run(suite) # run the test suite" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [] } ], "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.6.0" } }, "nbformat": 4, "nbformat_minor": 0 }