<commit_before>"""Nose Plugin that supports IPython doctests.

Limitations:

- When generating examples for use as doctests, make sure that you have
  pretty-printing OFF.  This can be done either by starting ipython with the
  flag '--nopprint', by setting pprint to 0 in your ipythonrc file, or by
  interactively disabling it with %Pprint.  This is required so that IPython
  output matches that of normal Python, which is used by doctest for internal
  execution.

- Do not rely on specific prompt numbers for results (such as using
  '_34==True', for example).  For IPython tests run via an external process the
  prompt numbers may be different, and IPython tests run as normal python code
  won't even have these special _NN variables set at all.
"""

#-----------------------------------------------------------------------------
# Module imports

# From the standard library
import __builtin__
import commands
import doctest
import inspect
import logging
import os
import re
import sys
import traceback
import unittest

from inspect import getmodule
from StringIO import StringIO

# We are overriding the default doctest runner, so we need to import a few
# things from doctest directly
from doctest import (REPORTING_FLAGS, REPORT_ONLY_FIRST_FAILURE,
                     _unittest_reportflags, DocTestRunner,
                     _extract_future_flags, pdb, _OutputRedirectingPdb,
                     _exception_traceback,
                     linecache)

# Third-party modules
import nose.core

from nose.plugins import doctests, Plugin
from nose.util import anyp, getpackage, test_address, resolve_name, tolist

#-----------------------------------------------------------------------------
# Module globals and other constants

log = logging.getLogger(__name__)

###########################################################################
# *** HACK ***
# We must start our own ipython object and heavily muck with it so that all the
# modifications IPython makes to system behavior don't send the doctest
# machinery into a fit.  This code should be considered a gross hack, but it
# gets the job done.


# Hack to modify the %run command so we can sync the user's namespace with the
# test globals.  Once we move over to a clean magic system, this will be done
# with much less ugliness.

class py_file_finder(object):
    def __init__(self,test_filename):
        self.test_filename = test_filename
        
    def __call__(self,name):
        from IPython.genutils import get_py_filename
        try:
            return get_py_filename(name)
        except IOError:
            test_dir = os.path.dirname(self.test_filename)
            new_path = os.path.join(test_dir,name)
            return get_py_filename(new_path)
    

def _run_ns_sync(self,arg_s,runner=None):
    """Modified version of %run that syncs testing namespaces.

    This is strictly needed for running doctests that call %run.
    """

    finder = py_file_finder(_run_ns_sync.test_filename)
    out = _ip.IP.magic_run_ori(arg_s,runner,finder)
    _run_ns_sync.test_globs.update(_ip.user_ns)
    return out


class ipnsdict(dict):
    """A special subclass of dict for use as an IPython namespace in doctests.

    This subclass adds a simple checkpointing capability so that when testing
    machinery clears it (we use it as the test execution context), it doesn't
    get completely destroyed.
    """
    
    def __init__(self,*a):
        dict.__init__(self,*a)
        self._savedict = {}
        
    def clear(self):
        dict.clear(self)
        self.update(self._savedict)

    def _checkpoint(self):
        self._savedict.clear()
        self._savedict.update(self)

    def update(self,other):
        self._checkpoint()
        dict.update(self,other)
        # If '_' is in the namespace, python won't set it when executing code,
        # and we have examples that test it.  So we ensure that the namespace
        # is always 'clean' of it before it's used for test code execution.
        self.pop('_',None)
        

def start_ipython():
    """Start a global IPython shell, which we need for IPython-specific syntax.
    """

    # This function should only ever run once!
    if hasattr(start_ipython,'already_called'):
        return
    start_ipython.already_called = True

    # Ok,  first time we're called, go ahead
    import new

    import IPython

    def xsys(cmd):
        """Execute a command and print its output.

        This is just a convenience function to replace the IPython system call
        with one that is more doctest-friendly.
        """
        cmd = _ip.IP.var_expand(cmd,depth=1)
        sys.stdout.write(commands.getoutput(cmd))
        sys.stdout.flush()

    # Store certain global objects that IPython modifies
    _displayhook = sys.displayhook
    _excepthook = sys.excepthook
    _main = sys.modules.get('__main__')

    # Start IPython instance.  We customize it to start with minimal frills.
    user_ns,global_ns = IPython.ipapi.make_user_namespaces(ipnsdict(),dict())
    IPython.Shell.IPShell(['--colors=NoColor','--noterm_title'],
                          user_ns,global_ns)

    # Deactivate the various python system hooks added by ipython for
    # interactive convenience so we don't confuse the doctest system
    sys.modules['__main__'] = _main
    sys.displayhook = _displayhook
    sys.excepthook = _excepthook

    # So that ipython magics and aliases can be doctested (they work by making
    # a call into a global _ip object)
    _ip = IPython.ipapi.get()
    __builtin__._ip = _ip

    # Modify the IPython system call with one that uses getoutput, so that we
    # can capture subcommands and print them to Python's stdout, otherwise the
    # doctest machinery would miss them.
    _ip.system = xsys

    # Also patch our %run function in.
    im = new.instancemethod(_run_ns_sync,_ip.IP, _ip.IP.__class__)<commit_msg>Make default argv for testing instances.<commit_after>"""Nose Plugin that supports IPython doctests.

Limitations:

- When generating examples for use as doctests, make sure that you have
  pretty-printing OFF.  This can be done either by starting ipython with the
  flag '--nopprint', by setting pprint to 0 in your ipythonrc file, or by
  interactively disabling it with %Pprint.  This is required so that IPython
  output matches that of normal Python, which is used by doctest for internal
  execution.

- Do not rely on specific prompt numbers for results (such as using
  '_34==True', for example).  For IPython tests run via an external process the
  prompt numbers may be different, and IPython tests run as normal python code
  won't even have these special _NN variables set at all.
"""

#-----------------------------------------------------------------------------
# Module imports

# From the standard library
import __builtin__
import commands
import doctest
import inspect
import logging
import os
import re
import sys
import traceback
import unittest

from inspect import getmodule
from StringIO import StringIO

# We are overriding the default doctest runner, so we need to import a few
# things from doctest directly
from doctest import (REPORTING_FLAGS, REPORT_ONLY_FIRST_FAILURE,
                     _unittest_reportflags, DocTestRunner,
                     _extract_future_flags, pdb, _OutputRedirectingPdb,
                     _exception_traceback,
                     linecache)

# Third-party modules
import nose.core

from nose.plugins import doctests, Plugin
from nose.util import anyp, getpackage, test_address, resolve_name, tolist

#-----------------------------------------------------------------------------
# Module globals and other constants

log = logging.getLogger(__name__)

###########################################################################
# *** HACK ***
# We must start our own ipython object and heavily muck with it so that all the
# modifications IPython makes to system behavior don't send the doctest
# machinery into a fit.  This code should be considered a gross hack, but it
# gets the job done.

def default_argv():
    """Return a valid default argv for creating testing instances of ipython"""

    # Get the install directory for the user configuration and tell ipython to
    # use the default profile from there.
    from IPython import UserConfig
    ipcdir = os.path.dirname(UserConfig.__file__)
    #ipconf = os.path.join(ipcdir,'ipy_user_conf.py')
    ipconf = os.path.join(ipcdir,'ipythonrc')
    #print 'conf:',ipconf # dbg
    
    return ['--colors=NoColor','--noterm_title','-rcfile=%s' % ipconf]


# Hack to modify the %run command so we can sync the user's namespace with the
# test globals.  Once we move over to a clean magic system, this will be done
# with much less ugliness.

class py_file_finder(object):
    def __init__(self,test_filename):
        self.test_filename = test_filename
        
    def __call__(self,name):
        from IPython.genutils import get_py_filename
        try:
            return get_py_filename(name)
        except IOError:
            test_dir = os.path.dirname(self.test_filename)
            new_path = os.path.join(test_dir,name)
            return get_py_filename(new_path)
    

def _run_ns_sync(self,arg_s,runner=None):
    """Modified version of %run that syncs testing namespaces.

    This is strictly needed for running doctests that call %run.
    """

    finder = py_file_finder(_run_ns_sync.test_filename)
    out = _ip.IP.magic_run_ori(arg_s,runner,finder)
    _run_ns_sync.test_globs.update(_ip.user_ns)
    return out


class ipnsdict(dict):
    """A special subclass of dict for use as an IPython namespace in doctests.

    This subclass adds a simple checkpointing capability so that when testing
    machinery clears it (we use it as the test execution context), it doesn't
    get completely destroyed.
    """
    
    def __init__(self,*a):
        dict.__init__(self,*a)
        self._savedict = {}
        
    def clear(self):
        dict.clear(self)
        self.update(self._savedict)

    def _checkpoint(self):
        self._savedict.clear()
        self._savedict.update(self)

    def update(self,other):
        self._checkpoint()
        dict.update(self,other)
        # If '_' is in the namespace, python won't set it when executing code,
        # and we have examples that test it.  So we ensure that the namespace
        # is always 'clean' of it before it's used for test code execution.
        self.pop('_',None)
        

def start_ipython():
    """Start a global IPython shell, which we need for IPython-specific syntax.
    """

    # This function should only ever run once!
    if hasattr(start_ipython,'already_called'):
        return
    start_ipython.already_called = True

    # Ok,  first time we're called, go ahead
    import new

    import IPython

    def xsys(cmd):
        """Execute a command and print its output.

        This is just a convenience function to replace the IPython system call
        with one that is more doctest-friendly.
        """
        cmd = _ip.IP.var_expand(cmd,depth=1)
        sys.stdout.write(commands.getoutput(cmd))
        sys.stdout.flush()

    # Store certain global objects that IPython modifies
    _displayhook = sys.displayhook
    _excepthook = sys.excepthook
    _main = sys.modules.get('__main__')

    argv = default_argv()
    
    # Start IPython instance.  We customize it to start with minimal frills.
    user_ns,global_ns = IPython.ipapi.make_user_namespaces(ipnsdict(),dict())
    IPython.Shell.IPShell(argv,user_ns,global_ns)

    # Deactivate the various python system hooks added by ipython for
    # interactive convenience so we don't confuse the doctest system
    sys.modules['__main__'] = _main
    sys.displayhook = _displayhook
    sys.excepthook = _excepthook

    # So that ipython magics and aliases can be doctested (they work by making
    # a call into a global _ip object)
    _ip = IPython.ipapi.get()
    __builtin__._ip = _ip

    # Modify the IPython system call with one that uses getoutput, so that we
    # can capture subcommands and print them to Python's stdout, otherwise the
    # doctest machinery would miss them.
    _ip.system = xsys

    # Also patch our %run function in.
    im = new.instancemethod(_run_ns_sync,_ip.IP, _ip.IP.__class__)
{'fraction_non_alphanumeric': 0.10346228868660598, 'fraction_numerical': 0.0006501950585175553, 'mean_word_length': 2.8178715482469747, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1346982', 'n_tokens_mistral': 3517, 'n_tokens_neox': 3391, 'n_words': 1278}