Skip to content
This repository

Adding -m option to %run, similar to -m for python interpreter. #819

Closed
wants to merge 5 commits into from

3 participants

Jörgen Stenarson Thomas Kluyver Fernando Perez
Jörgen Stenarson
Collaborator

I have long been missing an option to %run that is similar to -m for the regular python interpreter.

The -m option searches for a module on the python path and launches that module as a script.

This pull request is a first shot at this implementation. can you see anything that is missing?

I added some helper functions at top-level for locating modules, should they be somewhere else?

/Jörgen

IPython/core/magic.py
((17 lines not shown))
1559 1604
                                           mode='list',list_all=1)
  1605
+        if opts.has_key("m"):
  1606
+            modulename = opts.get("m")[0]
  1607
+            arg_lst = [find_mod(modulename)]
6
Thomas Kluyver Collaborator

This is currently going to replace all the arguments with the path to the module. Does Python itself allow you to do this sort of thing:

python -m somepkg.somemodule several args here

Fernando Perez Owner
fperez added a note October 07, 2011

@jstenar, one more thing for when you get a chance: let's use if "m" in opts instead of has_key, which is the more modern way to spell it out. We may have lingering uses of has_key but we shouldn't be using that for new code.

Fernando Perez Owner
fperez added a note October 07, 2011

And further, since you know that opts has m, then you can use modulename = opts['m'][0]. You only need to use get in dict access when you don't know for sure the key is available.

Jörgen Stenarson Collaborator
jstenar added a note October 08, 2011

Should I remove old has_key uses in magic_run as well?

Thomas Kluyver Collaborator

That's probably worth doing while you're working on it.

Jörgen Stenarson Collaborator
jstenar added a note October 08, 2011

I just pushed some changes that address these issues. I also did some pep-8 cleaning of magic_run.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
IPython/core/magic.py
((18 lines not shown))
  106
+    """Get __init__ file path for module with directory dirname
  107
+    """
  108
+    fbase =  os.path.join(dirname, "__init__")
  109
+    for ext in [".py", ".pyw", ".pyc", ".pyo"]:
  110
+        fname = fbase + ext
  111
+        if os.path.isfile(fname):
  112
+            return fname
  113
+
  114
+
  115
+def find_mod(name):
  116
+    """Find module *name* on sys.path
  117
+    """
  118
+    parts = name.split(".")
  119
+    if len(parts) == 1:
  120
+        basepath = find_module(parts[0])
  121
+    else:
2
Thomas Kluyver Collaborator

Doesn't look like you actually need this if/else test. Just doing the bit in else should be enough.

Jörgen Stenarson Collaborator
jstenar added a note October 08, 2011

Changed in c16a5a0a

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Thomas Kluyver
Collaborator

Another quick question - if the user for some reason does %run -m (with no module name) or %run -m misspelt.modname, how gracefully will this fail?

Jörgen Stenarson
Collaborator
Thomas Kluyver
Collaborator

That's fine, there's no rush. I was just checking through the list of pull requests. Hope you're well!

Jörgen Stenarson
Collaborator

Running %run -m without argument will fail with an error during parse_options:

In [1]: %run -m
UsageError: option -m requires argument ( allowed: "nidtN:b:pD:l:rs:T:em:" )
Fernando Perez
Owner

@jstenar, that error mode seems OK, as it gives the user enough information on what the issue is, so I'm OK with that. Did you see a problem with it?

On the other hand, due to other recent merges, this PR doesn't currently merge, so you'll need to give it a rebase and do a push --force. Let us know if you need a hand with any of that...

Jörgen Stena... added some commits September 07, 2011
Adding -m option to %run, similar to -m for python interpreter.
Added helper functions at top-level, should they be somewhere else?
55eff15
Improve error handling for %run -m 42da76c
Replace has_key with in in magic_run and some pep-8 fixes. 269e9c9
Jörgen Stenarson
Collaborator

I think I did the rebase correctly (my first one).

While I'm mucking about in magic_run I could take a stab at issue #710 as well or should I do that in a separate branch?

Thomas Kluyver
Collaborator

I think let's do that in a separate branch - magic_run is some of the more thorny code, so it's worth keeping a clear eye on what's going on with it.

Jörgen Stenarson
Collaborator
IPython/core/magic.py
@@ -91,6 +91,49 @@ def needs_local_scope(func):
91 91
     func.needs_local_scope = True
92 92
     return func
93 93
 
  94
+import imp, os
  95
+
  96
+def find_module(name, path=None):
  97
+    """imp.find_module variant that only return path of module.
  98
+    Return None if module is missing or does not have .py or .pyw extension
  99
+    """
1
Fernando Perez Owner
fperez added a note October 09, 2011

Let's try to follow the dev guidelines for docstrings; here it is for reference:

http://ipython.org/ipython-doc/dev/development/doc_guide.html#docstring-format

This ensures that we'll have consistency throughout, and that auto-generated API docs have the right signatures.

We just use the numpy standard, so it's nothing particularly complicated or special-case.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
IPython/core/magic.py
@@ -91,6 +91,49 @@ def needs_local_scope(func):
91 91
     func.needs_local_scope = True
92 92
     return func
93 93
 
  94
+import imp, os
1
Fernando Perez Owner
fperez added a note October 09, 2011

In general, we keep imports at the top of the file and in their own line, alphabetically sorted. Just see the top of the file.

That makes it easier to see at a glance what any given module needs. The only exception is for particularly expensive or potentially conflicting dependencies, that get imported inside the functions that use them (such as gui tools).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Fernando Perez
Owner

@jstenar, thanks for the updated work! I think we're almost there. But I see there are three new functions in the magic module now, so in addition to my in-line feedback, a couple of more general comments:

  • they are fairly generic utility functions related to module handling, so they should probably go elsewhere. I'd suggest a new module in IPython.utils, named something like modpaths.py. You can find a template with the necessary boilerplate at /docs/source/development/template.py.

  • Now that you have a nice new module with just three functions in it, the next thing is to ensure that you also add in utils/tests a file named test_modpaths.py that tests each one of these in isolation.

This way, the code will be easier to reuse elsewhere and will be validated. We want to move away from putting more and more tools into massive files like magic.py, that is already very unweildy.

So with a bit more iteration, we're close to having this solid for merge. Thanks for being patient, but that's how we ensure we build a more robust project moving forward!

Fernando Perez fperez closed this pull request from a commit October 13, 2011
Add -m option to %run to launch a module as a script.
The new -m option searches for a module on the python path and launches
that module as a script.  This is similar to Python's -m command-line
flag in behavior, but while staying inside IPython.

Conflicts:
	IPython/core/magic.py

Closes gh-819.
a4cfe5c
Fernando Perez fperez closed this in a4cfe5c October 13, 2011
Jörgen Stenarson
Collaborator
Fernando Perez
Owner

@jstenar: yes, I'd seen that, and the PR was merged 4 days ago :) Good work!

Jörgen Stenarson
Collaborator
Fernando Perez fperez referenced this pull request from a commit January 10, 2012
Commit has since been removed from the repository and is no longer available.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Showing 5 unique commits by 1 author.

Oct 09, 2011
Adding -m option to %run, similar to -m for python interpreter.
Added helper functions at top-level, should they be somewhere else?
55eff15
Improve error handling for %run -m 42da76c
Replace has_key with in in magic_run and some pep-8 fixes. 269e9c9
Fixing import statements and improving docstrings. 4811dd7
Oct 10, 2011
Moving helper functions to utils.module_paths, adding tests. ea3a0fc
This page is out of date. Refresh to see the latest.
88  IPython/core/magic.py
@@ -19,6 +19,7 @@
19 19
 import __future__
20 20
 import bdb
21 21
 import inspect
  22
+import imp
22 23
 import os
23 24
 import sys
24 25
 import shutil
@@ -54,6 +55,7 @@
54 55
 from IPython.testing.skipdoctest import skip_doctest
55 56
 from IPython.utils import py3compat
56 57
 from IPython.utils.io import file_read, nlprint
  58
+from IPython.utils.module_paths import find_mod
57 59
 from IPython.utils.path import get_py_filename, unquote_filename
58 60
 from IPython.utils.process import arg_split, abbrev_cwd
59 61
 from IPython.utils.terminal import set_term_title
@@ -91,6 +93,7 @@ def needs_local_scope(func):
91 93
     func.needs_local_scope = True
92 94
     return func
93 95
 
  96
+    
94 97
 # Used for exception handling in magic_edit
95 98
 class MacroToEdit(ValueError): pass
96 99
 
@@ -1448,7 +1451,7 @@ def magic_prun(self, parameter_s ='',user_mode=1,
1448 1451
             return None
1449 1452
 
1450 1453
     @skip_doctest
1451  
-    def magic_run(self, parameter_s ='',runner=None,
  1454
+    def magic_run(self, parameter_s ='', runner=None,
1452 1455
                   file_finder=get_py_filename):
1453 1456
         """Run the named file inside IPython as a program.
1454 1457
 
@@ -1557,17 +1560,34 @@ def magic_run(self, parameter_s ='',runner=None,
1557 1560
         There is one special usage for which the text above doesn't apply:
1558 1561
         if the filename ends with .ipy, the file is run as ipython script,
1559 1562
         just as if the commands were written on IPython prompt.
  1563
+
  1564
+        -m: specify module name to load instead of script path. Similar to
  1565
+        the -m option for the python interpreter. Use this option last if you
  1566
+        want to combine with other %run options. Unlike the python interpreter
  1567
+        only source modules are allowed no .pyc or .pyo files.
  1568
+        For example:
  1569
+
  1570
+            %run -m example
  1571
+
  1572
+        will run the example module.
  1573
+
1560 1574
         """
1561 1575
 
1562 1576
         # get arguments and set sys.argv for program to be run.
1563  
-        opts,arg_lst = self.parse_options(parameter_s,'nidtN:b:pD:l:rs:T:e',
1564  
-                                          mode='list',list_all=1)
1565  
-
  1577
+        opts, arg_lst = self.parse_options(parameter_s, 'nidtN:b:pD:l:rs:T:em:',
  1578
+                                           mode='list', list_all=1)
  1579
+        if "m" in opts:
  1580
+            modulename = opts["m"][0]
  1581
+            modpath = find_mod(modulename)
  1582
+            if modpath is None:
  1583
+                warn('%r is not a valid modulename on sys.path'%modulename)
  1584
+                return
  1585
+            arg_lst = [modpath] + arg_lst
1566 1586
         try:
1567 1587
             filename = file_finder(arg_lst[0])
1568 1588
         except IndexError:
1569 1589
             warn('you must provide at least a filename.')
1570  
-            print '\n%run:\n',oinspect.getdoc(self.magic_run)
  1590
+            print '\n%run:\n', oinspect.getdoc(self.magic_run)
1571 1591
             return
1572 1592
         except IOError as e:
1573 1593
             try:
@@ -1582,7 +1602,7 @@ def magic_run(self, parameter_s ='',runner=None,
1582 1602
             return
1583 1603
 
1584 1604
         # Control the response to exit() calls made by the script being run
1585  
-        exit_ignore = opts.has_key('e')
  1605
+        exit_ignore = 'e' in opts
1586 1606
 
1587 1607
         # Make sure that the running script gets a proper sys.argv as if it
1588 1608
         # were run from a system shell.
@@ -1591,9 +1611,9 @@ def magic_run(self, parameter_s ='',runner=None,
1591 1611
         # simulate shell expansion on arguments, at least tilde expansion
1592 1612
         args = [ os.path.expanduser(a) for a in arg_lst[1:] ]
1593 1613
 
1594  
-        sys.argv = [filename]+ args  # put in the proper filename
  1614
+        sys.argv = [filename] + args  # put in the proper filename
1595 1615
 
1596  
-        if opts.has_key('i'):
  1616
+        if 'i' in opts:
1597 1617
             # Run in user's interactive namespace
1598 1618
             prog_ns = self.shell.user_ns
1599 1619
             __name__save = self.shell.user_ns['__name__']
@@ -1601,7 +1621,7 @@ def magic_run(self, parameter_s ='',runner=None,
1601 1621
             main_mod = self.shell.new_main_mod(prog_ns)
1602 1622
         else:
1603 1623
             # Run in a fresh, empty namespace
1604  
-            if opts.has_key('n'):
  1624
+            if 'n' in opts:
1605 1625
                 name = os.path.splitext(os.path.basename(filename))[0]
1606 1626
             else:
1607 1627
                 name = '__main__'
@@ -1630,10 +1650,10 @@ def magic_run(self, parameter_s ='',runner=None,
1630 1650
         try:
1631 1651
             stats = None
1632 1652
             with self.readline_no_record:
1633  
-                if opts.has_key('p'):
1634  
-                    stats = self.magic_prun('',0,opts,arg_lst,prog_ns)
  1653
+                if 'p' in opts:
  1654
+                    stats = self.magic_prun('', 0, opts, arg_lst, prog_ns)
1635 1655
                 else:
1636  
-                    if opts.has_key('d'):
  1656
+                    if 'd' in opts:
1637 1657
                         deb = debugger.Pdb(self.shell.colors)
1638 1658
                         # reset Breakpoint state, which is moronically kept
1639 1659
                         # in a class
@@ -1642,11 +1662,11 @@ def magic_run(self, parameter_s ='',runner=None,
1642 1662
                         bdb.Breakpoint.bpbynumber = [None]
1643 1663
                         # Set an initial breakpoint to stop execution
1644 1664
                         maxtries = 10
1645  
-                        bp = int(opts.get('b',[1])[0])
1646  
-                        checkline = deb.checkline(filename,bp)
  1665
+                        bp = int(opts.get('b', [1])[0])
  1666
+                        checkline = deb.checkline(filename, bp)
1647 1667
                         if not checkline:
1648  
-                            for bp in range(bp+1,bp+maxtries+1):
1649  
-                                if deb.checkline(filename,bp):
  1668
+                            for bp in range(bp + 1, bp + maxtries + 1):
  1669
+                                if deb.checkline(filename, bp):
1650 1670
                                     break
1651 1671
                             else:
1652 1672
                                 msg = ("\nI failed to find a valid line to set "
@@ -1657,23 +1677,23 @@ def magic_run(self, parameter_s ='',runner=None,
1657 1677
                                 error(msg)
1658 1678
                                 return
1659 1679
                         # if we find a good linenumber, set the breakpoint
1660  
-                        deb.do_break('%s:%s' % (filename,bp))
  1680
+                        deb.do_break('%s:%s' % (filename, bp))
1661 1681
                         # Start file run
1662 1682
                         print "NOTE: Enter 'c' at the",
1663 1683
                         print "%s prompt to start your script." % deb.prompt
1664 1684
                         try:
1665  
-                            deb.run('execfile("%s")' % filename,prog_ns)
  1685
+                            deb.run('execfile("%s")' % filename, prog_ns)
1666 1686
 
1667 1687
                         except:
1668 1688
                             etype, value, tb = sys.exc_info()
1669 1689
                             # Skip three frames in the traceback: the %run one,
1670 1690
                             # one inside bdb.py, and the command-line typed by the
1671 1691
                             # user (run by exec in pdb itself).
1672  
-                            self.shell.InteractiveTB(etype,value,tb,tb_offset=3)
  1692
+                            self.shell.InteractiveTB(etype, value, tb, tb_offset=3)
1673 1693
                     else:
1674 1694
                         if runner is None:
1675 1695
                             runner = self.shell.safe_execfile
1676  
-                        if opts.has_key('t'):
  1696
+                        if 't' in opts:
1677 1697
                             # timed execution
1678 1698
                             try:
1679 1699
                                 nruns = int(opts['N'][0])
@@ -1685,11 +1705,11 @@ def magic_run(self, parameter_s ='',runner=None,
1685 1705
                             twall0 = time.time()
1686 1706
                             if nruns == 1:
1687 1707
                                 t0 = clock2()
1688  
-                                runner(filename,prog_ns,prog_ns,
  1708
+                                runner(filename, prog_ns, prog_ns,
1689 1709
                                        exit_ignore=exit_ignore)
1690 1710
                                 t1 = clock2()
1691  
-                                t_usr = t1[0]-t0[0]
1692  
-                                t_sys = t1[1]-t0[1]
  1711
+                                t_usr = t1[0] - t0[0]
  1712
+                                t_sys = t1[1] - t0[1]
1693 1713
                                 print "\nIPython CPU timings (estimated):"
1694 1714
                                 print "  User   : %10.2f s." % t_usr
1695 1715
                                 print "  System : %10.2f s." % t_sys
@@ -1697,30 +1717,30 @@ def magic_run(self, parameter_s ='',runner=None,
1697 1717
                                 runs = range(nruns)
1698 1718
                                 t0 = clock2()
1699 1719
                                 for nr in runs:
1700  
-                                    runner(filename,prog_ns,prog_ns,
  1720
+                                    runner(filename, prog_ns, prog_ns,
1701 1721
                                            exit_ignore=exit_ignore)
1702 1722
                                 t1 = clock2()
1703  
-                                t_usr = t1[0]-t0[0]
1704  
-                                t_sys = t1[1]-t0[1]
  1723
+                                t_usr = t1[0] - t0[0]
  1724
+                                t_sys = t1[1] - t0[1]
1705 1725
                                 print "\nIPython CPU timings (estimated):"
1706  
-                                print "Total runs performed:",nruns
1707  
-                                print "  Times  : %10.2f    %10.2f" % ('Total','Per run')
1708  
-                                print "  User   : %10.2f s, %10.2f s." % (t_usr,t_usr/nruns)
1709  
-                                print "  System : %10.2f s, %10.2f s." % (t_sys,t_sys/nruns)
  1726
+                                print "Total runs performed:", nruns
  1727
+                                print "  Times  : %10.2f    %10.2f" % ('Total', 'Per run')
  1728
+                                print "  User   : %10.2f s, %10.2f s." % (t_usr, t_usr / nruns)
  1729
+                                print "  System : %10.2f s, %10.2f s." % (t_sys, t_sys / nruns)
1710 1730
                             twall1 = time.time()
1711  
-                            print "Wall time: %10.2f s." % (twall1-twall0)
  1731
+                            print "Wall time: %10.2f s." % (twall1 - twall0)
1712 1732
 
1713 1733
                         else:
1714 1734
                             # regular execution
1715  
-                            runner(filename,prog_ns,prog_ns,exit_ignore=exit_ignore)
  1735
+                            runner(filename, prog_ns, prog_ns, exit_ignore=exit_ignore)
1716 1736
 
1717  
-                if opts.has_key('i'):
  1737
+                if 'i' in opts:
1718 1738
                     self.shell.user_ns['__name__'] = __name__save
1719 1739
                 else:
1720 1740
                     # The shell MUST hold a reference to prog_ns so after %run
1721 1741
                     # exits, the python deletion mechanism doesn't zero it out
1722 1742
                     # (leaving dangling references).
1723  
-                    self.shell.cache_main_mod(prog_ns,filename)
  1743
+                    self.shell.cache_main_mod(prog_ns, filename)
1724 1744
                     # update IPython interactive namespace
1725 1745
 
1726 1746
                     # Some forms of read errors on the file may mean the
125  IPython/utils/module_paths.py
... ...
@@ -0,0 +1,125 @@
  1
+"""Utility functions for finding modules
  2
+
  3
+Utility functions for finding modules on sys.path.
  4
+
  5
+`find_mod` finds named module on sys.path.
  6
+
  7
+`get_init` helper function that finds __init__ file in a directory.
  8
+
  9
+`find_module` variant of imp.find_module in std_lib that only returns
  10
+path to module and not an open file object as well.
  11
+
  12
+
  13
+
  14
+"""
  15
+#-----------------------------------------------------------------------------
  16
+# Copyright (c) 2011, the IPython Development Team.
  17
+#
  18
+# Distributed under the terms of the Modified BSD License.
  19
+#
  20
+# The full license is in the file COPYING.txt, distributed with this software.
  21
+#-----------------------------------------------------------------------------
  22
+
  23
+#-----------------------------------------------------------------------------
  24
+# Imports
  25
+#-----------------------------------------------------------------------------
  26
+from __future__ import print_function
  27
+
  28
+# Stdlib imports
  29
+import imp
  30
+import os
  31
+
  32
+# Third-party imports
  33
+
  34
+# Our own imports
  35
+
  36
+
  37
+#-----------------------------------------------------------------------------
  38
+# Globals and constants
  39
+#-----------------------------------------------------------------------------
  40
+
  41
+#-----------------------------------------------------------------------------
  42
+# Local utilities
  43
+#-----------------------------------------------------------------------------
  44
+
  45
+#-----------------------------------------------------------------------------
  46
+# Classes and functions
  47
+#-----------------------------------------------------------------------------
  48
+def find_module(name, path=None):
  49
+    """imp.find_module variant that only return path of module.
  50
+    
  51
+    The `imp.find_module` returns a filehandle that we are not interested in.
  52
+    Also we ignore any bytecode files that `imp.find_module` finds.
  53
+
  54
+    Parameters
  55
+    ----------
  56
+    name : str
  57
+        name of module to locate
  58
+    path : list of str
  59
+        list of paths to search for `name`. If path=None then search sys.path
  60
+
  61
+    Returns
  62
+    -------
  63
+    filename : str
  64
+        Return full path of module or None if module is missing or does not have
  65
+        .py or .pyw extension
  66
+    """
  67
+    if name is None:
  68
+        return None
  69
+    try:
  70
+        file, filename, _ = imp.find_module(name, path)
  71
+    except ImportError:
  72
+        return None
  73
+    if file is None:
  74
+        return filename
  75
+    else:
  76
+        file.close()
  77
+    if os.path.splitext(filename)[1] in [".py", "pyc"]:
  78
+        return filename
  79
+    else:
  80
+        return None
  81
+
  82
+def get_init(dirname):
  83
+    """Get __init__ file path for module directory
  84
+    
  85
+    Parameters
  86
+    ----------
  87
+    dirname : str
  88
+        Find the __init__ file in directory `dirname`
  89
+
  90
+    Returns
  91
+    -------
  92
+    init_path : str
  93
+        Path to __init__ file
  94
+    """
  95
+    fbase =  os.path.join(dirname, "__init__")
  96
+    for ext in [".py", ".pyw"]:
  97
+        fname = fbase + ext
  98
+        if os.path.isfile(fname):
  99
+            return fname
  100
+
  101
+
  102
+def find_mod(module_name):
  103
+    """Find module `module_name` on sys.path
  104
+    
  105
+    Return the path to module `module_name`. If `module_name` refers to
  106
+    a module directory then return path to __init__ file. Return full 
  107
+    path of module or None if module is missing or does not have .py or .pyw
  108
+    extension. We are not interested in running bytecode.
  109
+    
  110
+    Parameters
  111
+    ----------
  112
+    module_name : str
  113
+    
  114
+    Returns
  115
+    -------
  116
+    modulepath : str
  117
+        Path to module `module_name`.
  118
+    """
  119
+    parts = module_name.split(".")
  120
+    basepath = find_module(parts[0])
  121
+    for submodname in parts[1:]:
  122
+        basepath = find_module(submodname, [basepath])
  123
+    if basepath and os.path.isdir(basepath):
  124
+        basepath = get_init(basepath)
  125
+    return basepath
133  IPython/utils/tests/test_module_paths.py
... ...
@@ -0,0 +1,133 @@
  1
+# encoding: utf-8
  2
+"""Tests for IPython.utils.path.py"""
  3
+
  4
+#-----------------------------------------------------------------------------
  5
+#  Copyright (C) 2008  The IPython Development Team
  6
+#
  7
+#  Distributed under the terms of the BSD License.  The full license is in
  8
+#  the file COPYING, distributed as part of this software.
  9
+#-----------------------------------------------------------------------------
  10
+
  11
+#-----------------------------------------------------------------------------
  12
+# Imports
  13
+#-----------------------------------------------------------------------------
  14
+
  15
+from __future__ import with_statement
  16
+
  17
+import os
  18
+import shutil
  19
+import sys
  20
+import tempfile
  21
+import StringIO
  22
+
  23
+from os.path import join, abspath, split
  24
+
  25
+import nose.tools as nt
  26
+
  27
+from nose import with_setup
  28
+
  29
+import IPython
  30
+from IPython.testing import decorators as dec
  31
+from IPython.testing.decorators import skip_if_not_win32, skip_win32
  32
+from IPython.testing.tools import make_tempfile
  33
+from IPython.utils import path, io
  34
+from IPython.utils import py3compat
  35
+
  36
+import IPython.utils.module_paths as mp
  37
+
  38
+env = os.environ
  39
+TEST_FILE_PATH = split(abspath(__file__))[0]
  40
+TMP_TEST_DIR = tempfile.mkdtemp()
  41
+#
  42
+# Setup/teardown functions/decorators
  43
+#
  44
+
  45
+old_syspath = sys.path
  46
+sys.path = [TMP_TEST_DIR]
  47
+
  48
+def make_empty_file(fname):
  49
+    f = open(fname, 'w')
  50
+    f.close()
  51
+
  52
+
  53
+def setup():
  54
+    """Setup testenvironment for the module:
  55
+
  56
+    """
  57
+    # Do not mask exceptions here.  In particular, catching WindowsError is a
  58
+    # problem because that exception is only defined on Windows...
  59
+    os.makedirs(join(TMP_TEST_DIR, "xmod"))
  60
+    os.makedirs(join(TMP_TEST_DIR, "nomod"))
  61
+    make_empty_file(join(TMP_TEST_DIR, "xmod/__init__.py"))
  62
+    make_empty_file(join(TMP_TEST_DIR, "xmod/sub.py"))
  63
+    make_empty_file(join(TMP_TEST_DIR, "pack.py"))
  64
+    make_empty_file(join(TMP_TEST_DIR, "packpyc.pyc"))
  65
+
  66
+def teardown():
  67
+    """Teardown testenvironment for the module:
  68
+
  69
+            - Remove tempdir
  70
+    """
  71
+    # Note: we remove the parent test dir, which is the root of all test
  72
+    # subdirs we may have created.  Use shutil instead of os.removedirs, so
  73
+    # that non-empty directories are all recursively removed.
  74
+    shutil.rmtree(TMP_TEST_DIR)
  75
+
  76
+
  77
+def test_get_init_1():
  78
+    """See if get_init can find __init__.py in this testdir"""
  79
+    with make_tempfile(join(TMP_TEST_DIR, "__init__.py")):
  80
+        assert mp.get_init(TMP_TEST_DIR)
  81
+
  82
+def test_get_init_2():
  83
+    """See if get_init can find __init__.pyw in this testdir"""
  84
+    with make_tempfile(join(TMP_TEST_DIR, "__init__.pyw")):
  85
+        assert mp.get_init(TMP_TEST_DIR)
  86
+
  87
+def test_get_init_3():
  88
+    """get_init can't find __init__.pyc in this testdir"""
  89
+    with make_tempfile(join(TMP_TEST_DIR, "__init__.pyc")):
  90
+        assert mp.get_init(TMP_TEST_DIR) is None
  91
+
  92
+def test_get_init_3():
  93
+    """get_init can't find __init__ in empty testdir"""
  94
+    assert mp.get_init(TMP_TEST_DIR) is None
  95
+
  96
+
  97
+def test_find_mod_1():
  98
+    modpath = join(TMP_TEST_DIR, "xmod", "__init__.py")
  99
+    assert mp.find_mod("xmod") == modpath
  100
+
  101
+def test_find_mod_2():
  102
+    modpath = join(TMP_TEST_DIR, "xmod", "__init__.py")
  103
+    assert mp.find_mod("xmod") == modpath
  104
+
  105
+def test_find_mod_3():
  106
+    modpath = join(TMP_TEST_DIR, "xmod", "sub.py")
  107
+    assert mp.find_mod("xmod.sub") == modpath
  108
+
  109
+def test_find_mod_4():
  110
+    modpath = join(TMP_TEST_DIR, "pack.py")
  111
+    assert mp.find_mod("pack") == modpath
  112
+
  113
+def test_find_mod_5():
  114
+    assert mp.find_mod("packpyc") is None
  115
+
  116
+def test_find_module_1():
  117
+    modpath = join(TMP_TEST_DIR, "xmod")
  118
+    assert mp.find_module("xmod") == modpath
  119
+
  120
+def test_find_module_2():
  121
+    """Testing sys.path that is empty"""
  122
+    assert mp.find_module("xmod", []) is None
  123
+
  124
+def test_find_module_3():
  125
+    """Testing sys.path that is empty"""
  126
+    assert mp.find_module(None, None) is None
  127
+
  128
+def test_find_module_4():
  129
+    """Testing sys.path that is empty"""
  130
+    assert mp.find_module(None) is None
  131
+
  132
+def test_find_module_5():
  133
+    assert mp.find_module("xmod.nopack") is None
Commit_comment_tip

Tip: You can add notes to lines in a file. Hover to the left of a line to make a note

Something went wrong with that request. Please try again.