From 5aa32fcf30c1163600beddb0b6ee3256e81bff6e Mon Sep 17 00:00:00 2001 From: Aaron Meurer Date: Sat, 8 Jun 2013 20:43:57 -0500 Subject: [PATCH 1/3] Code cleanup --- ipython_doctester.py | 47 ++++++++++++++++++++++---------------------- 1 file changed, 23 insertions(+), 24 deletions(-) diff --git a/ipython_doctester.py b/ipython_doctester.py index eb3f24c..df67906 100644 --- a/ipython_doctester.py +++ b/ipython_doctester.py @@ -9,12 +9,12 @@ Note: It's easy to cheat by simply deleting or changing the doctest. That's OK, cheating is learning, too. -If you want to track students' progress through a notebook in a -classroom setting, you can; see +If you want to track students' progress through a notebook in a +classroom setting, you can; see http://ipython-docent.appspot.com/ for instructions. - -Developed for the Dayton Python Workshop: + +Developed for the Dayton Python Workshop: https://openhatch.org/wiki/Dayton_Python_Workshop catherine.devlin@gmail.com @@ -28,7 +28,6 @@ import IPython.zmq.displayhook __version__ = '0.2.2' -finder = doctest.DocTestFinder() docent_url = 'http://ipython-docent.appspot.com' """Set these per session, as desired.""" @@ -37,7 +36,7 @@ # even for successes """Set these if desired to track student progress -at http://ipython-docent.appspot.com/. +at http://ipython-docent.appspot.com/. See that page for more instructions.""" student_name = None workshop_name = None @@ -58,7 +57,7 @@ def __init__(self): """ success_template = """

Success!

- """ + """ def trap_txt(self, txt): self.txt += txt def publish(self): @@ -69,8 +68,8 @@ def publish(self): def _repr_html_(self): result = self.fail_template if self.failed else self.success_template if verbose or self.failed: - examples = '\n '.join(self.example_template % - (cgi.escape(e.source), cgi.escape(e.want), + examples = '\n '.join(self.example_template % + (cgi.escape(e.source), cgi.escape(e.want), e.color, cgi.escape(e.got) )for e in self.examples) result += """ @@ -80,7 +79,7 @@ def _repr_html_(self): """ return result - + reporter = Reporter() @@ -103,7 +102,7 @@ def report_success(self, out, test, example, got): example.want = self._or_nothing(example.want) example.color = 'green' reporter.examples.append(example) - return doctest.DocTestRunner.report_success(self, out, test, example, got) + return doctest.DocTestRunner.report_success(self, out, test, example, got) def report_unexpected_exception(self, out, test, example, exc_info): reporter.failed = True trim = len(reporter.txt) @@ -114,38 +113,38 @@ def report_unexpected_exception(self, out, test, example, exc_info): example.color = 'red' reporter.examples.append(example) return result - - + + runner = Runner() finder = doctest.DocTestFinder() -class IPythonDoctesterException(StandardError): +class IPythonDoctesterException(StandardError): def _repr_html_(self): return '
\n%s\n
' % self.txt - + class NoTestsException(IPythonDoctesterException): txt = """ - OOPS! We expected to find a doctest - + OOPS! We expected to find a doctest - a string immediately after the function definition, looking something like def do_something(): ''' >>> do_something() 'did something' - ''' + ''' ... but it wasn't there. Did you insert code between the function definition - and the doctest? + and the doctest? """ - + class NoStudentNameException(IPythonDoctesterException): txt = """ - OOPS! We need you to set the ipython_doctester.student_name variable; + OOPS! We need you to set the ipython_doctester.student_name variable; please look for it (probably in the first cell in this worksheet) and enter your name, like ipython_doctester.student_name = 'Catherine' ... then hit Shift+Enter to execute that cell, then come back here to execute this one. """ - + def testobj(func): tests = finder.find(func) if not tests: @@ -161,13 +160,13 @@ def testobj(func): runner.run(t, out=reporter.trap_txt) reporter.publish() if workshop_name: - payload = dict(function_name = func.__name__, - failure=reporter.failed, + payload = dict(function_name = func.__name__, + failure=reporter.failed, source=inspect.getsource(func), workshop_name = workshop_name, student_name = student_name) requests.post(docent_url+'/record', data=payload) - + return reporter def report_error(e): From 566c65896332ae01922acf9002fdb1c7b3ea28ae Mon Sep 17 00:00:00 2001 From: Aaron Meurer Date: Sat, 8 Jun 2013 20:46:47 -0500 Subject: [PATCH 2/3] Don't require requests unless you actually plan to upload stuff --- ipython_doctester.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/ipython_doctester.py b/ipython_doctester.py index df67906..0541526 100644 --- a/ipython_doctester.py +++ b/ipython_doctester.py @@ -24,7 +24,12 @@ import cgi import inspect import sys -import requests + +try: + import requests +except ImportError: + requests = None + import IPython.zmq.displayhook __version__ = '0.2.2' @@ -160,6 +165,8 @@ def testobj(func): runner.run(t, out=reporter.trap_txt) reporter.publish() if workshop_name: + if not requests: + raise ImportError("The requests module is required to upload results.") payload = dict(function_name = func.__name__, failure=reporter.failed, source=inspect.getsource(func), From 489d7f7d283290e33abb3a34098cab20a7c67bfc Mon Sep 17 00:00:00 2001 From: Aaron Meurer Date: Sat, 8 Jun 2013 20:55:36 -0500 Subject: [PATCH 3/3] Use the function's globals in the doctest runner --- ipython_doctester.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ipython_doctester.py b/ipython_doctester.py index 0541526..092dc33 100644 --- a/ipython_doctester.py +++ b/ipython_doctester.py @@ -156,7 +156,7 @@ def testobj(func): raise NoTestsException if workshop_name and not student_name: raise NoStudentNameException() - globs = {} # TODO: get the ipython globals? + globs = func.__globals__ reporter.__init__() globs[func.__name__] = func globs['reporter'] = reporter