Commits

Jonathan Eunice committed 337fafe

Seeing test errors implicating show.introspect.CallArgs. Added test_introspect, discovered that is probably not the source of the errors.

Comments (0)

Files changed (4)

 system = str(sys.platform).lower()
 impl = platform.python_implementation()
 
-install_requires = ['six', 'options', 'say>=0.969', 'stuf>=0.9.12',
+install_requires = ['six', 'options==0.5', 'say>=0.969', 'stuf>=0.9.12',
                     'mementos>=0.506', 'codegen' ]
 
 if 'darwin' in system:
 
     def get_arg_tuples(self, caller, values):
         """
-        Return a list of argument name, value tuples with the given values.
+        Return a list of argument (name, value) tuples.
+        :caller: The calling frame.
+        :values: The with the given values.
         """
         filename, lineno = frame_to_source_info(caller)
         try:
             argnames = CallArgs(filename, lineno).args
         except ArgsUnavailable:
-            argnames = '?' * len(values)
-        argtuples = list(zip(list(argnames), list(values)))
-        return argtuples
+            argnames = None
+        if argnames is None:
+            argnames = ['?'] * len(values)
+        return list(zip(argnames, list(values)))
 
     def settings(self, **kwargs):
         """
         assert not args  # for now
         locdict = caller.f_locals
 
-        to_omit = ' '.join((opts.omit or []) + '@py_assert*')
+        to_omit = ' '.join((opts.omit or []) + ['@py_assert*'])
         names = omitnames(locdict.keys(), to_omit)
 
         # Construct the result string
-        valstr = opts.sep.join([ self.arg_format(name, locdict[name], caller) for name in names ])
+        valstr = opts.sep.join([ self.arg_format(name, locdict[name], caller, opts) for name in names ])
         locval = [ self.call_location(caller) + ":  ", valstr ] if opts.where else [ valstr ]
 
         # Emit the result string, and optionally return it
 
         # Construct the result string
         if names:
-            valstr = opts.sep.join([ self.arg_format(name, to_show[name], caller) for name in names ])
+            valstr = opts.sep.join([ self.arg_format(name, to_show[name], caller, opts) for name in names ])
         else:
             valstr = six.u('\u2205')
         locval = [ self.call_location(caller) + ":  ", valstr ] if opts.where else [ valstr ]
 
 show = Show()
 
+if __name__ == '__main__':
+    x = 1
+    show(x)
+
 # Add show to sys.modules so that "import show" is all you need.
 # sys.modules['show'] = show
 

show/introspect.py

 
     @classmethod
     def add_target_func(cls, name):
-        suffixes = [ '', '.items', '.props', '.changed', '.dir', '.chars' ]
+        """
+        When inspecting ASTs, must know the name of the "show" functions
+        to consider. E.g. 'show', 'show.items', 'show.dir' and so on.
+        This function adds those names for a given base name.
+        """
+        suffixes = '.items .props .changed .dir .chars .local .watched'.split()
+        suffixes.insert(0, '')
         names = [ name + s for s in suffixes ]
         cls.TARGET_FUNCS.update(names)
 
     def __init__(self, filepath, lineno):
+        """
+        Start a new CallArgs instance for a given filepath and lineno
+        """
         ast.NodeVisitor.__init__(self)
         self.filepath = filepath
         self.lineno   = lineno

test/test_introspect.py

+
+import os, random, string
+
+# --- TEST FIXTURES ---
+
+def lines(text, noblanks=True, dedent=True, lstrip=False, rstrip=True, join=False):
+    """
+    Grab lines from a string. First and last lines are assumed to be uninteresting if blank.
+    :param text:     text to be processed
+    :param dedent:   a common prefix should be stripped from each line (default `True`)
+    :param noblanks: allow no blank lines at all (default `True`)
+    :param lstrip:   all left space be stripped from each line (default `False`);
+                     dedent and lstrip are mutualy exclusive
+    :param rstrip:   all right space be stripped from each line (default `True`)
+    :param join:     if False, no effect; otherwise a string used to join the lines
+    """
+
+    textlines = text.expandtabs().splitlines()
+
+    # remove blank lines if noblanks
+    if noblanks:
+        textlines = [ line for line in textlines if line.strip() != '' ]
+    else:
+        # even if intermediate blank lines ok, first and last are due to Python formatting
+        if textlines and textlines[0].strip() == "":
+            textlines.pop(0)
+        if textlines and textlines[-1].strip() == "":
+            textlines.pop()
+
+    if dedent and not lstrip:
+        nonblanklines = [ line for line in textlines if line.strip() != "" ]
+        prefix = os.path.commonprefix(nonblanklines)
+        prelen, maxprelen = 0, len(prefix)
+        while prelen < maxprelen and prefix[prelen] == ' ':
+            prelen += 1
+        if prelen:
+            textlines = [ line[prelen:] for line in textlines ]
+
+    # perform requested left and right space stripping (must be done
+    # late so as to not interfere with dedent's common prefix detection)
+    if lstrip and rstrip:
+        textlines = [ line.strip() for line in textlines ]
+    elif lstrip:
+        textlines = [ line.lstrip() for line in textlines ]
+    elif rstrip:
+        textlines = [ line.rstrip() for line in textlines ]
+
+    if join is False:
+        return textlines
+    else:
+        if join is True:
+            join = ''
+        return join.join(textlines)
+
+
+def textlines(text, **kwargs):
+    """
+    Like ``lines()``, but returns result as unified text. Useful primarily because
+    of the nice cleanups ``lines()`` does.
+    """
+    sep = kwargs.get('join', None)
+    if sep is None or sep is False:
+        kwargs['join'] = '\n'
+    return lines(text, **kwargs)
+
+ALPHABET = string.ascii_lowercase + string.digits
+
+def tempfile(text, tmpdir):
+    """
+    Make a temporary file.
+    :text: Text contents to add to the file.
+    :name: File name. If None, chosen randomly.
+    """
+    name = ''.join(random.choice(ALPHABET) for i in range(12)) + '.py'
+    p = tmpdir.join(name)
+    p.write(textlines(text))
+    return p
+
+
+
+# --- END TEST FIXTURES ---
+
+from show.introspect import *
+
+CallArgs.add_target_func('show')
+
+def test_callargs_one(tmpdir):
+    p = tempfile("""
+        def func():
+            x = 12
+            show(x)
+    """, tmpdir=tmpdir)
+
+    assert CallArgs(p.strpath, 3).args == ['x']
+
+def test_callargs_two(tmpdir):
+    p = tempfile("""
+        def func():
+            x = 12
+            y = 99
+            show(x, y)
+    """, tmpdir=tmpdir)
+
+    assert CallArgs(p.strpath, 4).args == ['x', 'y']
+
+def test_callargs_three(tmpdir):
+    p = tempfile("""
+        def func():
+            x = 12
+            y = 99
+            show(x, y, x)
+    """, tmpdir=tmpdir)
+
+    assert CallArgs(p.strpath, 4).args == ['x', 'y', 'x']
+
+def test_callargs_four(tmpdir):
+    p = tempfile("""
+        def func(x, z):
+            def nested(y):
+                show.dir(x, y, z)
+            y = 99
+            show(y, x)
+    """, tmpdir=tmpdir)
+
+    assert CallArgs(p.strpath, 3).args == ['x', 'y', 'z']
+    assert CallArgs(p.strpath, 5).args == ['y', 'x']
+
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.