diff --git a/IPython/genutils.py b/IPython/genutils.py index a9590d2..85f8d2d 100644 --- a/IPython/genutils.py +++ b/IPython/genutils.py @@ -922,12 +922,15 @@ def get_home_dir(): # first, check py2exe distribution root directory for _ipython. # This overrides all. Normally does not exist. - if '\\library.zip\\' in IPython.__file__.lower(): - root, rest = IPython.__file__.lower().split('library.zip') - if isdir(root + '_ipython'): - os.environ["IPYKITROOT"] = root.rstrip('\\') - return root - + if hasattr(sys, "frozen"): #Is frozen by py2exe + if '\\library.zip\\' in IPython.__file__.lower():#libraries compressed to zip-file + root, rest = IPython.__file__.lower().split('library.zip') + else: + root=os.path.join(os.path.split(IPython.__file__)[0],"../../") + root=os.path.abspath(root).rstrip('\\') + if isdir(os.path.join(root, '_ipython')): + os.environ["IPYKITROOT"] = root + return root try: homedir = env['HOME'] if not isdir(homedir): @@ -947,7 +950,7 @@ def get_home_dir(): if not isdir(homedir): raise HomeDirError return homedir - except: + except KeyError: try: # Use the registry to get the 'My Documents' folder. import _winreg as wreg @@ -986,8 +989,8 @@ def get_ipython_dir(): ipdir_def = '_ipython' home_dir = get_home_dir() ipdir = os.path.abspath(os.environ.get('IPYTHONDIR', - os.path.join(home_dir,ipdir_def))) - return ipdir + os.path.join(home_dir, ipdir_def))) + return ipdir.decode(sys.getfilesystemencoding()) def get_security_dir(): """Get the IPython security directory. diff --git a/IPython/iplib.py b/IPython/iplib.py index 394f0d5..612fa2e 100644 --- a/IPython/iplib.py +++ b/IPython/iplib.py @@ -1414,6 +1414,7 @@ want to merge them back into the new files.""" % locals() # not run as the syntax for libedit is different. if not readline.uses_libedit: for rlcommand in self.rc.readline_parse_and_bind: + #print "loading rl:",rlcommand # dbg readline.parse_and_bind(rlcommand) # remove some chars from the delimiters list diff --git a/IPython/ipmaker.py b/IPython/ipmaker.py index a1c1be8..d3e88a8 100644 --- a/IPython/ipmaker.py +++ b/IPython/ipmaker.py @@ -128,20 +128,15 @@ object? -> Details about 'object'. ?object also works, ?? prints more. IP.usage = interactive_usage - # Platform-dependent suffix and directory names. We use _ipython instead - # of .ipython under win32 b/c there's software that breaks with .named - # directories on that platform. + # Platform-dependent suffix. if os.name == 'posix': rc_suffix = '' - ipdir_def = '.ipython' else: rc_suffix = '.ini' - ipdir_def = '_ipython' # default directory for configuration - ipythondir_def = os.path.abspath(os.environ.get('IPYTHONDIR', - os.path.join(IP.home_dir,ipdir_def))) - + ipythondir_def = get_ipython_dir() + sys.path.insert(0, '') # add . to sys.path. Fix from Prabhu Ramachandran # we need the directory where IPython itself is installed diff --git a/IPython/testing/decorators.py b/IPython/testing/decorators.py index 99e5066..5d588a0 100644 --- a/IPython/testing/decorators.py +++ b/IPython/testing/decorators.py @@ -233,12 +233,22 @@ skip_doctest = make_label_dec('skip_doctest', etc.""") # Decorators to skip certain tests on specific platforms. -skip_win32 = skipif(sys.platform=='win32', +skip_win32 = skipif(sys.platform == 'win32', "This test does not run under Windows") -skip_linux = skipif(sys.platform=='linux2',"This test does not run under Linux") -skip_osx = skipif(sys.platform=='darwin',"This test does not run under OS X") +skip_linux = skipif(sys.platform == 'linux2', + "This test does not run under Linux") +skip_osx = skipif(sys.platform == 'darwin',"This test does not run under OS X") +# Decorators to skip tests if not on specific platforms. +skip_if_not_win32 = skipif(sys.platform != 'win32', + "This test only runs under Windows") +skip_if_not_linux = skipif(sys.platform != 'linux2', + "This test only runs under Linux") +skip_if_not_osx = skipif(sys.platform != 'darwin', + "This test only runs under OSX") + +# Other skip decorators skipif_not_numpy = skipif(numpy_not_available,"This test requires numpy") skipknownfailure = skip('This test is known to fail') diff --git a/IPython/tests/test_genutils.py b/IPython/tests/test_genutils.py index 9072ec1..ec79815 100644 --- a/IPython/tests/test_genutils.py +++ b/IPython/tests/test_genutils.py @@ -15,18 +15,277 @@ __docformat__ = "restructuredtext en" # Imports #----------------------------------------------------------------------------- +# stdlib +import os +import shutil +import sys +import tempfile + +from os.path import join, abspath, split + +# third-party +import nose.tools as nt + +from nose import with_setup +from nose.tools import raises + +# Our own +import IPython from IPython import genutils +from IPython.testing.decorators import skipif, skip_if_not_win32 + +# Platform-dependent imports +try: + import _winreg as wreg +except ImportError: + #Fake _winreg module on none windows platforms + import new + sys.modules["_winreg"] = new.module("_winreg") + import _winreg as wreg + #Add entries that needs to be stubbed by the testing code + (wreg.OpenKey, wreg.QueryValueEx,) = (None, None) + +#----------------------------------------------------------------------------- +# Globals +#----------------------------------------------------------------------------- +env = os.environ +TEST_FILE_PATH = split(abspath(__file__))[0] +TMP_TEST_DIR = tempfile.mkdtemp() +HOME_TEST_DIR = join(TMP_TEST_DIR, "home_test_dir") +IP_TEST_DIR = join(HOME_TEST_DIR,'_ipython') +# +# Setup/teardown functions/decorators +# + +def setup(): + """Setup testenvironment for the module: + + - Adds dummy home dir tree + """ + # Do not mask exceptions here. In particular, catching WindowsError is a + # problem because that exception is only defined on Windows... + os.makedirs(IP_TEST_DIR) + +def teardown(): + """Teardown testenvironment for the module: + + - Remove dummy home dir tree + """ + # Note: we remove the parent test dir, which is the root of all test + # subdirs we may have created. Use shutil instead of os.removedirs, so + # that non-empty directories are all recursively removed. + shutil.rmtree(TMP_TEST_DIR) + + +def setup_environment(): + """Setup testenvironment for some functions that are tested + in this module. In particular this functions stores attributes + and other things that we need to stub in some test functions. + This needs to be done on a function level and not module level because + each testfunction needs a pristine environment. + """ + global oldstuff, platformstuff + oldstuff = (env.copy(), os.name, genutils.get_home_dir, IPython.__file__,) + + if os.name == 'nt': + platformstuff = (wreg.OpenKey, wreg.QueryValueEx,) + + if 'IPYTHONDIR' in env: + del env['IPYTHONDIR'] + +def teardown_environment(): + """Restore things that were remebered by the setup_environment function + """ + (oldenv, os.name, genutils.get_home_dir, IPython.__file__,) = oldstuff + for key in env.keys(): + if key not in oldenv: + del env[key] + env.update(oldenv) + if hasattr(sys, 'frozen'): + del sys.frozen + if os.name == 'nt': + (wreg.OpenKey, wreg.QueryValueEx,) = platformstuff + +# Build decorator that uses the setup_environment/setup_environment +with_enivronment = with_setup(setup_environment, teardown_environment) + + +# +# Tests for get_home_dir +# + +@skip_if_not_win32 +@with_enivronment +def test_get_home_dir_1(): + """Testcase for py2exe logic, un-compressed lib + """ + sys.frozen = True + + #fake filename for IPython.__init__ + IPython.__file__ = abspath(join(HOME_TEST_DIR, "Lib/IPython/__init__.py")) + + home_dir = genutils.get_home_dir() + nt.assert_equal(home_dir, abspath(HOME_TEST_DIR)) + +@skip_if_not_win32 +@with_enivronment +def test_get_home_dir_2(): + """Testcase for py2exe logic, compressed lib + """ + sys.frozen = True + #fake filename for IPython.__init__ + IPython.__file__ = abspath(join(HOME_TEST_DIR, "Library.zip/IPython/__init__.py")).lower() + + home_dir = genutils.get_home_dir() + nt.assert_equal(home_dir, abspath(HOME_TEST_DIR).lower()) + +@with_enivronment +def test_get_home_dir_3(): + """Testcase $HOME is set, then use its value as home directory.""" + env["HOME"] = HOME_TEST_DIR + home_dir = genutils.get_home_dir() + nt.assert_equal(home_dir, env["HOME"]) + +@with_enivronment +def test_get_home_dir_4(): + """Testcase $HOME is not set, os=='poix'. + This should fail with HomeDirError""" + + os.name = 'posix' + if 'HOME' in env: del env['HOME'] + nt.assert_raises(genutils.HomeDirError, genutils.get_home_dir) + +@skip_if_not_win32 +@with_enivronment +def test_get_home_dir_5(): + """Testcase $HOME is not set, os=='nt' + env['HOMEDRIVE'],env['HOMEPATH'] points to path.""" + + os.name = 'nt' + if 'HOME' in env: del env['HOME'] + env['HOMEDRIVE'], env['HOMEPATH'] = os.path.splitdrive(HOME_TEST_DIR) + home_dir = genutils.get_home_dir() + nt.assert_equal(home_dir, abspath(HOME_TEST_DIR)) + +@skip_if_not_win32 +@with_enivronment +def test_get_home_dir_6(): + """Testcase $HOME is not set, os=='nt' + env['HOMEDRIVE'],env['HOMEPATH'] do not point to path. + env['USERPROFILE'] points to path + """ + + os.name = 'nt' + if 'HOME' in env: del env['HOME'] + env['HOMEDRIVE'], env['HOMEPATH'] = os.path.abspath(TEST_FILE_PATH), "DOES NOT EXIST" + env["USERPROFILE"] = abspath(HOME_TEST_DIR) + + home_dir = genutils.get_home_dir() + nt.assert_equal(home_dir, abspath(HOME_TEST_DIR)) + +# Should we stub wreg fully so we can run the test on all platforms? +@skip_if_not_win32 +@with_enivronment +def test_get_home_dir_7(): + """Testcase $HOME is not set, os=='nt' + env['HOMEDRIVE'],env['HOMEPATH'], env['USERPROFILE'] missing + """ + os.name = 'nt' + if 'HOME' in env: del env['HOME'] + if 'HOMEDRIVE' in env: del env['HOMEDRIVE'] + + #Stub windows registry functions + def OpenKey(x, y): + class key: + def Close(self): + pass + return key() + def QueryValueEx(x, y): + return [abspath(HOME_TEST_DIR)] + + wreg.OpenKey = OpenKey + wreg.QueryValueEx = QueryValueEx -def test_get_home_dir(): - """Make sure we can get the home directory.""" home_dir = genutils.get_home_dir() + nt.assert_equal(home_dir, abspath(HOME_TEST_DIR)) + + +# +# Tests for get_ipython_dir +# + +@with_enivronment +def test_get_ipython_dir_1(): + """test_get_ipython_dir_1, Testcase to see if we can call get_ipython_dir without Exceptions.""" + env['IPYTHONDIR'] = "someplace/.ipython" + ipdir = genutils.get_ipython_dir() + nt.assert_equal(ipdir, os.path.abspath("someplace/.ipython")) -def test_get_ipython_dir(): - """Make sure we can get the ipython directory.""" + +@with_enivronment +def test_get_ipython_dir_2(): + """test_get_ipython_dir_2, Testcase to see if we can call get_ipython_dir without Exceptions.""" + genutils.get_home_dir = lambda : "someplace" + os.name = "posix" + ipdir = genutils.get_ipython_dir() + nt.assert_equal(ipdir, os.path.abspath(os.path.join("someplace", ".ipython"))) + +@with_enivronment +def test_get_ipython_dir_3(): + """test_get_ipython_dir_3, Testcase to see if we can call get_ipython_dir without Exceptions.""" + genutils.get_home_dir = lambda : "someplace" + os.name = "nt" ipdir = genutils.get_ipython_dir() + nt.assert_equal(ipdir, os.path.abspath(os.path.join("someplace", "_ipython"))) + + +# +# Tests for get_security_dir +# +@with_enivronment def test_get_security_dir(): - """Make sure we can get the ipython/security directory.""" + """Testcase to see if we can call get_security_dir without Exceptions.""" sdir = genutils.get_security_dir() - \ No newline at end of file + + +# +# Tests for popkey +# + +def test_popkey_1(): + """test_popkey_1, Basic usage test of popkey + """ + dct = dict(a=1, b=2, c=3) + nt.assert_equal(genutils.popkey(dct, "a"), 1) + nt.assert_equal(dct, dict(b=2, c=3)) + nt.assert_equal(genutils.popkey(dct, "b"), 2) + nt.assert_equal(dct, dict(c=3)) + nt.assert_equal(genutils.popkey(dct, "c"), 3) + nt.assert_equal(dct, dict()) + +def test_popkey_2(): + """test_popkey_2, Test to see that popkey of non occuring keys + generates a KeyError exception + """ + dct = dict(a=1, b=2, c=3) + nt.assert_raises(KeyError, genutils.popkey, dct, "d") + +def test_popkey_3(): + """test_popkey_3, Tests to see that popkey calls returns the correct value + and that the key/value was removed from the dict. + """ + dct = dict(a=1, b=2, c=3) + nt.assert_equal(genutils.popkey(dct, "A", 13), 13) + nt.assert_equal(dct, dict(a=1, b=2, c=3)) + nt.assert_equal(genutils.popkey(dct, "B", 14), 14) + nt.assert_equal(dct, dict(a=1, b=2, c=3)) + nt.assert_equal(genutils.popkey(dct, "C", 15), 15) + nt.assert_equal(dct, dict(a=1, b=2, c=3)) + nt.assert_equal(genutils.popkey(dct, "a"), 1) + nt.assert_equal(dct, dict(b=2, c=3)) + nt.assert_equal(genutils.popkey(dct, "b"), 2) + nt.assert_equal(dct, dict(c=3)) + nt.assert_equal(genutils.popkey(dct, "c"), 3) + nt.assert_equal(dct, dict()) diff --git a/docs/source/development/overview.txt b/docs/source/development/overview.txt index a0dcd9b..c9cdda6 100644 --- a/docs/source/development/overview.txt +++ b/docs/source/development/overview.txt @@ -338,6 +338,19 @@ Most of the release process is automated by the :file:`release` script in the #. Celebrate! +Porting to 3.0 +============== +There are no definite plans for porting of IPython to python 3. The major +issue is the dependency on twisted framework for the networking/threading +stuff. It is possible that it the traditional IPython interactive console +could be ported more easily since it has no such dependency. Here are a few +things that will need to be considered when doing such a port especially +if we want to have a codebase that works directly on both 2.x and 3.x. + + 1. The syntax for exceptions changed (PEP 3110). The old + `except exc, var` changed to `except exc as var`. At last + count there was 78 occurences of this usage in the codebase + .. [Bazaar] Bazaar. http://bazaar-vcs.org/ .. [Launchpad] Launchpad. http://www.launchpad.net/ipython .. [reStructuredText] reStructuredText. http://docutils.sourceforge.net/rst.html