3 new commits in pytest:

https://bitbucket.org/hpk42/pytest/commits/8c92bc4c65aa/
Changeset:   8c92bc4c65aa
Branch:      argcomplete
User:        Anthon van der Neut
Date:        2013-07-30 11:26:15
Summary:     Fixes for argcomplete

- separate out most argcomplete related stuff in new file _argcomplete.py
  (could probably be in the py library)
- allow positional arguments to be interspaced with optional arguments
  ( + test in test_parseopt.py )
- removed double argument in tox.ini
- add documentation on installing argcomplete (>=0.5.7 as needed for
  Python 3), might need improving/incorporation in index.

This does not work on 2.5 yet. I have patches for argcomplete
(with/print()/"".format) but I am not sure they will be accepted.
Agreed with hpk not to push for that.

Removing argcomplete and leaving completion code active now works by early
exit, so <TAB> no longer re-runs the programs without parameters
(which took long for py.test)

test calls bash with a script that redirects filedescriptor 8 (as used by
argcomplete), so the result can be tested.
Affected #:  5 files

diff -r 1530d0e3abf3e60a37cfc91aac47a5545a11628c -r 
8c92bc4c65aa426cf9e795dbf4a2654cef71b46c _pytest/_argcomplete.py
--- /dev/null
+++ b/_pytest/_argcomplete.py
@@ -0,0 +1,68 @@
+
+"""allow bash-completion for argparse with argcomplete if installed
+needs argcomplete>=0.5.6 for python 3.2/3.3 (older versions fail
+to find the magic string, so _ARGCOMPLETE env. var is never set, and
+this does not need special code.
+
+argcomplete does not support python 2.5 (although the changes for that
+are minor).
+
+Function try_argcomplete(parser) should be called directly before
+the call to ArgumentParser.parse_args().
+
+The filescompleter is what you normally would use on the positional
+arguments specification, in order to get "dirname/" after "dirn<TAB>"
+instead of the default "dirname ":
+
+   optparser.add_argument(Config._file_or_dir, nargs='*'
+                               ).completer=filescompleter
+
+Other, application specific, completers should go in the file
+doing the add_argument calls as they need to be specified as .completer
+attributes as well. (If argcomplete is not installed, the function the
+attribute points to will not be used).
+
+---
+To include this support in another application that has setup.py generated
+scripts:
+- add the line:
+    # PYTHON_ARGCOMPLETE_OK
+  near the top of the main python entry point
+- include in the file calling parse_args():
+    from _argcomplete import try_argcomplete, filescompleter
+   , call try_argcomplete just before parse_args(), and optionally add
+   filescompleter to the positional arguments' add_argument()
+If things do not work right away:
+- switch on argcomplete debugging with (also helpful when doing custom
+  completers):
+    export _ARC_DEBUG=1
+- run:
+    python-argcomplete-check-easy-install-script $(which appname)
+    echo $?
+  will echo 0 if the magic line has been found, 1 if not
+- sometimes it helps to find early on errors using:
+    _ARGCOMPLETE=1 _ARC_DEBUG=1 appname
+  which should throw a KeyError: 'COMPLINE' (which is properly set by the
+  global argcomplete script).
+   
+"""
+
+import sys
+import os
+
+if os.environ.get('_ARGCOMPLETE'):
+    # argcomplete 0.5.6 is not compatible with python 2.5.6: print/with/format
+    if sys.version_info[:2] < (2, 6):
+        sys.exit(1)
+    try:
+        import argcomplete
+        import argcomplete.completers
+    except ImportError:
+        sys.exit(-1)
+    filescompleter = argcomplete.completers.FilesCompleter()
+
+    def try_argcomplete(parser):
+        argcomplete.autocomplete(parser)
+else:
+    def try_argcomplete(parser): pass
+    filescompleter = None

diff -r 1530d0e3abf3e60a37cfc91aac47a5545a11628c -r 
8c92bc4c65aa426cf9e795dbf4a2654cef71b46c _pytest/config.py
--- a/_pytest/config.py
+++ b/_pytest/config.py
@@ -4,6 +4,7 @@
 import sys, os
 from _pytest.core import PluginManager
 import pytest
+from _argcomplete import try_argcomplete, filescompleter
 
 # enable after some grace period for plugin writers
 TYPE_WARN = False
@@ -91,7 +92,9 @@
                     n = option.names()
                     a = option.attrs()
                     arggroup.add_argument(*n, **a)
-        optparser.add_argument(Config._file_or_dir, nargs='*')
+        # bash like autocompletion for dirs (appending '/')
+        optparser.add_argument(Config._file_or_dir, nargs='*'
+                               ).completer=filescompleter
         try_argcomplete(self.optparser)
         return self.optparser.parse_args([str(x) for x in args])
 
@@ -115,13 +118,6 @@
         self._inidict[name] = (help, type, default)
         self._ininames.append(name)
 
-def try_argcomplete(parser):
-    try:
-        import argcomplete
-    except ImportError:
-        pass
-    else:
-        argcomplete.autocomplete(parser)
 
 class ArgumentError(Exception):
     """
@@ -304,6 +300,7 @@
         self._parser = parser
         py.std.argparse.ArgumentParser.__init__(self, usage=parser._usage,
             add_help=False)
+
     def format_epilog(self, formatter):
         hints = self._parser.hints
         if hints:
@@ -312,6 +309,18 @@
             return s
         return ""
 
+    def parse_args(self, args=None, namespace=None):
+        """allow splitting of positional arguments"""
+        args, argv = self.parse_known_args(args, namespace)
+        if argv:
+            for arg in argv:
+                if arg and arg[0] == '-':
+                    msg = py.std.argparse._('unrecognized arguments: %s')
+                    self.error(msg % ' '.join(argv))
+            getattr(args, Config._file_or_dir).extend(argv)
+        return args
+
+    
 class Conftest(object):
     """ the single place for accessing values and interacting
         towards conftest modules from py.test objects.

diff -r 1530d0e3abf3e60a37cfc91aac47a5545a11628c -r 
8c92bc4c65aa426cf9e795dbf4a2654cef71b46c doc/en/bash-completion.txt
--- /dev/null
+++ b/doc/en/bash-completion.txt
@@ -0,0 +1,28 @@
+
+.. _bash_completion:
+
+Setting up bash completion
+==========================
+
+When using bash as your shell, ``py.test`` can use argcomplete 
+(https://argcomplete.readthedocs.org/) for auto-completion.
+For this ``argcomplete`` needs to be installed **and** enabled.
+
+Install argcomplete using::
+
+        sudo pip install 'argcomplete>=0.5.7'
+
+For global activation of all argcomplete enabled python applications run::
+
+       sudo activate-global-python-argcomplete
+
+For permanent (but not global) ``py.test`` activation, use::
+
+        register-python-argcomplete py.test >> ~/.bashrc
+
+For one-time activation of argcomplete for ``py.test`` only, use::
+
+        eval "$(register-python-argcomplete py.test)"
+
+
+

diff -r 1530d0e3abf3e60a37cfc91aac47a5545a11628c -r 
8c92bc4c65aa426cf9e795dbf4a2654cef71b46c testing/test_parseopt.py
--- a/testing/test_parseopt.py
+++ b/testing/test_parseopt.py
@@ -130,6 +130,21 @@
         args = parser.parse(['--ultimate-answer', '42'])
         assert args.ultimate_answer == 42
 
+    def test_parse_split_positional_arguments(self):
+        parser = parseopt.Parser()
+        parser.addoption("-R", action='store_true')
+        parser.addoption("-S", action='store_false')
+        args = parser.parse(['-R', '4', '2', '-S'])
+        assert getattr(args, parseopt.Config._file_or_dir) == ['4', '2']
+        args = parser.parse(['-R', '-S', '4', '2', '-R'])
+        assert getattr(args, parseopt.Config._file_or_dir) == ['4', '2']
+        assert args.R == True
+        assert args.S == False
+        args = parser.parse(['-R', '4', '-S', '2'])
+        assert getattr(args, parseopt.Config._file_or_dir) == ['4', '2']
+        assert args.R == True
+        assert args.S == False
+
     def test_parse_defaultgetter(self):
         def defaultget(option):
             if not hasattr(option, 'type'):
@@ -158,3 +173,28 @@
     #assert result.ret != 0
     result.stdout.fnmatch_lines(["hint: hello world", "hint: from me too"])
 
+@pytest.mark.skipif("sys.version_info < (2,5)")
+def test_argcomplete(testdir):
+    import os
+    p = py.path.local.make_numbered_dir(prefix="test_argcomplete-",
+                keep=None, rootdir=testdir.tmpdir)
+    script = p._fastjoin('test_argcomplete')
+    with open(str(script), 'w') as fp:
+        # redirect output from argcomplete to stdin and stderr is not trivial
+        # http://stackoverflow.com/q/12589419/1307905
+        # so we use bash
+        fp.write('COMP_WORDBREAKS="$COMP_WORDBREAKS" $(which py.test) '
+                 '8>&1 9>&2')
+    os.environ['_ARGCOMPLETE'] = "1"
+    os.environ['_ARGCOMPLETE_IFS'] =  "\x0b"
+    os.environ['COMP_LINE'] = "py.test --fu"
+    os.environ['COMP_POINT'] = "12"
+    os.environ['COMP_WORDBREAKS'] = ' \\t\\n"\\\'><=;|&(:'
+
+    result = testdir.run('bash', str(script), '--fu')
+    print dir(result), result.ret
+    if result.ret == 255:
+        # argcomplete not found
+        assert True
+    else:
+        result.stdout.fnmatch_lines(["--funcargs", "--fulltrace"])

diff -r 1530d0e3abf3e60a37cfc91aac47a5545a11628c -r 
8c92bc4c65aa426cf9e795dbf4a2654cef71b46c tox.ini
--- a/tox.ini
+++ b/tox.ini
@@ -43,7 +43,7 @@
 deps=twisted
      pexpect
 commands=
-  py.test -rsxf testing/test_unittest.py \
+  py.test -rsxf \
         --junitxml={envlogdir}/junit-{envname}.xml 
{posargs:testing/test_unittest.py}
 [testenv:doctest]
 changedir=.


https://bitbucket.org/hpk42/pytest/commits/f44d44a4142b/
Changeset:   f44d44a4142b
Branch:      argcomplete
User:        Anthon van der Neut
Date:        2013-07-30 12:33:38
Summary:     minor adjustment, added test for positional argument completion
Affected #:  2 files

diff -r 8c92bc4c65aa426cf9e795dbf4a2654cef71b46c -r 
f44d44a4142b72a260007e413e6419549b3c1dc1 _pytest/_argcomplete.py
--- a/_pytest/_argcomplete.py
+++ b/_pytest/_argcomplete.py
@@ -55,7 +55,6 @@
     if sys.version_info[:2] < (2, 6):
         sys.exit(1)
     try:
-        import argcomplete
         import argcomplete.completers
     except ImportError:
         sys.exit(-1)

diff -r 8c92bc4c65aa426cf9e795dbf4a2654cef71b46c -r 
f44d44a4142b72a260007e413e6419549b3c1dc1 testing/test_parseopt.py
--- a/testing/test_parseopt.py
+++ b/testing/test_parseopt.py
@@ -175,10 +175,10 @@
 
 @pytest.mark.skipif("sys.version_info < (2,5)")
 def test_argcomplete(testdir):
+    if not py.path.local.sysfind('bash'):
+        pytest.skip("bash not available")    
     import os
-    p = py.path.local.make_numbered_dir(prefix="test_argcomplete-",
-                keep=None, rootdir=testdir.tmpdir)
-    script = p._fastjoin('test_argcomplete')
+    script = os.path.join(os.getcwd(), 'test_argcomplete')
     with open(str(script), 'w') as fp:
         # redirect output from argcomplete to stdin and stderr is not trivial
         # http://stackoverflow.com/q/12589419/1307905
@@ -187,14 +187,22 @@
                  '8>&1 9>&2')
     os.environ['_ARGCOMPLETE'] = "1"
     os.environ['_ARGCOMPLETE_IFS'] =  "\x0b"
-    os.environ['COMP_LINE'] = "py.test --fu"
-    os.environ['COMP_POINT'] = "12"
     os.environ['COMP_WORDBREAKS'] = ' \\t\\n"\\\'><=;|&(:'
 
-    result = testdir.run('bash', str(script), '--fu')
+    arg = '--fu'
+    os.environ['COMP_LINE'] = "py.test " + arg
+    os.environ['COMP_POINT'] = str(len(os.environ['COMP_LINE']))
+    result = testdir.run('bash', str(script), arg)
     print dir(result), result.ret
     if result.ret == 255:
         # argcomplete not found
-        assert True
+        pytest.skip("argcomplete not available")
     else:
         result.stdout.fnmatch_lines(["--funcargs", "--fulltrace"])
+
+    os.mkdir('test_argcomplete.d')
+    arg = 'test_argc'
+    os.environ['COMP_LINE'] = "py.test " + arg
+    os.environ['COMP_POINT'] = str(len(os.environ['COMP_LINE']))
+    result = testdir.run('bash', str(script), arg)
+    result.stdout.fnmatch_lines(["test_argcomplete", "test_argcomplete.d/"])


https://bitbucket.org/hpk42/pytest/commits/73015defd88f/
Changeset:   73015defd88f
User:        hpk42
Date:        2013-07-31 07:51:07
Summary:     Merged in anthon_van_der_neut/pytest/argcomplete (pull request #50)

Fixes for argcomplete
Affected #:  5 files

diff -r 1530d0e3abf3e60a37cfc91aac47a5545a11628c -r 
73015defd88f6a45ba44fd6e109b03bc8b3e82e9 _pytest/_argcomplete.py
--- /dev/null
+++ b/_pytest/_argcomplete.py
@@ -0,0 +1,67 @@
+
+"""allow bash-completion for argparse with argcomplete if installed
+needs argcomplete>=0.5.6 for python 3.2/3.3 (older versions fail
+to find the magic string, so _ARGCOMPLETE env. var is never set, and
+this does not need special code.
+
+argcomplete does not support python 2.5 (although the changes for that
+are minor).
+
+Function try_argcomplete(parser) should be called directly before
+the call to ArgumentParser.parse_args().
+
+The filescompleter is what you normally would use on the positional
+arguments specification, in order to get "dirname/" after "dirn<TAB>"
+instead of the default "dirname ":
+
+   optparser.add_argument(Config._file_or_dir, nargs='*'
+                               ).completer=filescompleter
+
+Other, application specific, completers should go in the file
+doing the add_argument calls as they need to be specified as .completer
+attributes as well. (If argcomplete is not installed, the function the
+attribute points to will not be used).
+
+---
+To include this support in another application that has setup.py generated
+scripts:
+- add the line:
+    # PYTHON_ARGCOMPLETE_OK
+  near the top of the main python entry point
+- include in the file calling parse_args():
+    from _argcomplete import try_argcomplete, filescompleter
+   , call try_argcomplete just before parse_args(), and optionally add
+   filescompleter to the positional arguments' add_argument()
+If things do not work right away:
+- switch on argcomplete debugging with (also helpful when doing custom
+  completers):
+    export _ARC_DEBUG=1
+- run:
+    python-argcomplete-check-easy-install-script $(which appname)
+    echo $?
+  will echo 0 if the magic line has been found, 1 if not
+- sometimes it helps to find early on errors using:
+    _ARGCOMPLETE=1 _ARC_DEBUG=1 appname
+  which should throw a KeyError: 'COMPLINE' (which is properly set by the
+  global argcomplete script).
+   
+"""
+
+import sys
+import os
+
+if os.environ.get('_ARGCOMPLETE'):
+    # argcomplete 0.5.6 is not compatible with python 2.5.6: print/with/format
+    if sys.version_info[:2] < (2, 6):
+        sys.exit(1)
+    try:
+        import argcomplete.completers
+    except ImportError:
+        sys.exit(-1)
+    filescompleter = argcomplete.completers.FilesCompleter()
+
+    def try_argcomplete(parser):
+        argcomplete.autocomplete(parser)
+else:
+    def try_argcomplete(parser): pass
+    filescompleter = None

diff -r 1530d0e3abf3e60a37cfc91aac47a5545a11628c -r 
73015defd88f6a45ba44fd6e109b03bc8b3e82e9 _pytest/config.py
--- a/_pytest/config.py
+++ b/_pytest/config.py
@@ -4,6 +4,7 @@
 import sys, os
 from _pytest.core import PluginManager
 import pytest
+from _argcomplete import try_argcomplete, filescompleter
 
 # enable after some grace period for plugin writers
 TYPE_WARN = False
@@ -91,7 +92,9 @@
                     n = option.names()
                     a = option.attrs()
                     arggroup.add_argument(*n, **a)
-        optparser.add_argument(Config._file_or_dir, nargs='*')
+        # bash like autocompletion for dirs (appending '/')
+        optparser.add_argument(Config._file_or_dir, nargs='*'
+                               ).completer=filescompleter
         try_argcomplete(self.optparser)
         return self.optparser.parse_args([str(x) for x in args])
 
@@ -115,13 +118,6 @@
         self._inidict[name] = (help, type, default)
         self._ininames.append(name)
 
-def try_argcomplete(parser):
-    try:
-        import argcomplete
-    except ImportError:
-        pass
-    else:
-        argcomplete.autocomplete(parser)
 
 class ArgumentError(Exception):
     """
@@ -304,6 +300,7 @@
         self._parser = parser
         py.std.argparse.ArgumentParser.__init__(self, usage=parser._usage,
             add_help=False)
+
     def format_epilog(self, formatter):
         hints = self._parser.hints
         if hints:
@@ -312,6 +309,18 @@
             return s
         return ""
 
+    def parse_args(self, args=None, namespace=None):
+        """allow splitting of positional arguments"""
+        args, argv = self.parse_known_args(args, namespace)
+        if argv:
+            for arg in argv:
+                if arg and arg[0] == '-':
+                    msg = py.std.argparse._('unrecognized arguments: %s')
+                    self.error(msg % ' '.join(argv))
+            getattr(args, Config._file_or_dir).extend(argv)
+        return args
+
+    
 class Conftest(object):
     """ the single place for accessing values and interacting
         towards conftest modules from py.test objects.

diff -r 1530d0e3abf3e60a37cfc91aac47a5545a11628c -r 
73015defd88f6a45ba44fd6e109b03bc8b3e82e9 doc/en/bash-completion.txt
--- /dev/null
+++ b/doc/en/bash-completion.txt
@@ -0,0 +1,28 @@
+
+.. _bash_completion:
+
+Setting up bash completion
+==========================
+
+When using bash as your shell, ``py.test`` can use argcomplete 
+(https://argcomplete.readthedocs.org/) for auto-completion.
+For this ``argcomplete`` needs to be installed **and** enabled.
+
+Install argcomplete using::
+
+        sudo pip install 'argcomplete>=0.5.7'
+
+For global activation of all argcomplete enabled python applications run::
+
+       sudo activate-global-python-argcomplete
+
+For permanent (but not global) ``py.test`` activation, use::
+
+        register-python-argcomplete py.test >> ~/.bashrc
+
+For one-time activation of argcomplete for ``py.test`` only, use::
+
+        eval "$(register-python-argcomplete py.test)"
+
+
+

diff -r 1530d0e3abf3e60a37cfc91aac47a5545a11628c -r 
73015defd88f6a45ba44fd6e109b03bc8b3e82e9 testing/test_parseopt.py
--- a/testing/test_parseopt.py
+++ b/testing/test_parseopt.py
@@ -130,6 +130,21 @@
         args = parser.parse(['--ultimate-answer', '42'])
         assert args.ultimate_answer == 42
 
+    def test_parse_split_positional_arguments(self):
+        parser = parseopt.Parser()
+        parser.addoption("-R", action='store_true')
+        parser.addoption("-S", action='store_false')
+        args = parser.parse(['-R', '4', '2', '-S'])
+        assert getattr(args, parseopt.Config._file_or_dir) == ['4', '2']
+        args = parser.parse(['-R', '-S', '4', '2', '-R'])
+        assert getattr(args, parseopt.Config._file_or_dir) == ['4', '2']
+        assert args.R == True
+        assert args.S == False
+        args = parser.parse(['-R', '4', '-S', '2'])
+        assert getattr(args, parseopt.Config._file_or_dir) == ['4', '2']
+        assert args.R == True
+        assert args.S == False
+
     def test_parse_defaultgetter(self):
         def defaultget(option):
             if not hasattr(option, 'type'):
@@ -158,3 +173,36 @@
     #assert result.ret != 0
     result.stdout.fnmatch_lines(["hint: hello world", "hint: from me too"])
 
+@pytest.mark.skipif("sys.version_info < (2,5)")
+def test_argcomplete(testdir):
+    if not py.path.local.sysfind('bash'):
+        pytest.skip("bash not available")    
+    import os
+    script = os.path.join(os.getcwd(), 'test_argcomplete')
+    with open(str(script), 'w') as fp:
+        # redirect output from argcomplete to stdin and stderr is not trivial
+        # http://stackoverflow.com/q/12589419/1307905
+        # so we use bash
+        fp.write('COMP_WORDBREAKS="$COMP_WORDBREAKS" $(which py.test) '
+                 '8>&1 9>&2')
+    os.environ['_ARGCOMPLETE'] = "1"
+    os.environ['_ARGCOMPLETE_IFS'] =  "\x0b"
+    os.environ['COMP_WORDBREAKS'] = ' \\t\\n"\\\'><=;|&(:'
+
+    arg = '--fu'
+    os.environ['COMP_LINE'] = "py.test " + arg
+    os.environ['COMP_POINT'] = str(len(os.environ['COMP_LINE']))
+    result = testdir.run('bash', str(script), arg)
+    print dir(result), result.ret
+    if result.ret == 255:
+        # argcomplete not found
+        pytest.skip("argcomplete not available")
+    else:
+        result.stdout.fnmatch_lines(["--funcargs", "--fulltrace"])
+
+    os.mkdir('test_argcomplete.d')
+    arg = 'test_argc'
+    os.environ['COMP_LINE'] = "py.test " + arg
+    os.environ['COMP_POINT'] = str(len(os.environ['COMP_LINE']))
+    result = testdir.run('bash', str(script), arg)
+    result.stdout.fnmatch_lines(["test_argcomplete", "test_argcomplete.d/"])

diff -r 1530d0e3abf3e60a37cfc91aac47a5545a11628c -r 
73015defd88f6a45ba44fd6e109b03bc8b3e82e9 tox.ini
--- a/tox.ini
+++ b/tox.ini
@@ -43,7 +43,7 @@
 deps=twisted
      pexpect
 commands=
-  py.test -rsxf testing/test_unittest.py \
+  py.test -rsxf \
         --junitxml={envlogdir}/junit-{envname}.xml 
{posargs:testing/test_unittest.py}
 [testenv:doctest]
 changedir=.

Repository URL: https://bitbucket.org/hpk42/pytest/

--

This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
_______________________________________________
pytest-commit mailing list
pytest-commit@python.org
http://mail.python.org/mailman/listinfo/pytest-commit

Reply via email to