[py-dev] controlling assertions and difflib

holger krekel holger at merlinux.eu
Sat Oct 2 19:33:43 CEST 2010


Hey Floris,

On Fri, Oct 01, 2010 at 00:23 +0100, Floris Bruynooghe wrote:
> On 29 September 2010 14:28, holger krekel <holger at merlinux.eu> wrote:
> > On Wed, Sep 29, 2010 at 00:12 +0100, Floris Bruynooghe wrote:
> >> ______________________________ test_hang_in_diff _______________________________
> >> /tmp/sandbox/test_bugs.py:4: in test_hang_in_diff
> >> >       assert x == y
> >> E       assert '1\n1\n1\n1\n...n2\n2\n2\n2\n' == '1\n1\n1\n1\n...n2\n2\n2\n2\n'
> >> E         Skipping 1990 identical leading characters in diff
> >> E         Skipping 1991 identical trailing characters in diff
> >> E           1
> >> E           1
> >> E           1
> >> E           1
> >> E           1
> >> E         - abc2
> >> E         + def2
> >> E           2
> >> E           2
> >> E           2
> >> E           2
> >
> >
> > looks good to me!
> 
> I've committed a cleaned-up version of this now.

Great, thanks.  It's now merged to py-trunk!
 
> >> This whole issue made me wonder if it should be possible to disable
> >> the pytest_assert_binrepr hook.
> >
> > We could do a general "--assertmode=(choice)" with e.g.:
> >
> >    0: (no) don't do any assert reinterp (like --no-assert now)
> >    1: (basic) do basic reinterpreation
> >    2: (advanced) do basic reinterpretation + customizing hooks
> >
> > and default to 2.
> 
> Sounds like a good idea.  Do you think there's place for a
> advanced-no-builtin-plugin option in here, so that the builtin hook
> will not run any code?  Otherwise a bug in the builtin customisation
> hook would completely stop this from being useful.

I am not so afraid but we can do it.  
 
> > I think there is an elegant solution.  Instead of using "hook" in py/code/ we
> > use a generic "customize" function that is to be called.  In
> > pytest_assertion.py's pytest_configure we write that function
> > such that it calls
> >
> >    pytest_assert_binrepr(config, ...)
> >
> > hope that makes sense. If in doubt leave it to me and just use py.test.config.
> 
> Do you mean something like the attached diff does?  In that case I'm
> sort of tempted to remove the customise_assert() function I've added
> there and just expose the DebugInterpreter so that you can modify the
> attribute directly.  I also considered the
> customise_assert(binrepr_hook, config) signature for this, not sure
> which would be best.

I think i meant something different.  Please have a look into this 
changeset which i just added:

    http://bitbucket.org/hpk42/py-trunk/changeset/64962794201b

does this make sense to you? 

Also did a subsequent commit to rename to pytest_assertrepr_compare which
now can get a config object so we can now introduce variations controled 
by config values. 

best,
holger

> 
> 
> Regards
> Floris
> 
> 
> -- 
> Debian GNU/Linux -- The Power of Freedom
> www.debian.org | www.gnu.org | www.kernel.org

> diff --git a/py/__init__.py b/py/__init__.py
> --- a/py/__init__.py
> +++ b/py/__init__.py
> @@ -99,6 +99,7 @@ py.apipkg.initpkg(__name__, dict(
>          '_AssertionError'   : '._code.assertion:AssertionError',
>          '_reinterpret_old'  : '._code.assertion:reinterpret_old',
>          '_reinterpret'      : '._code.assertion:reinterpret',
> +        'customise_assert'  : '._code._assertionnew:customise_assert',
>      },
>  
>      # backports and additions of builtins
> diff --git a/py/_code/_assertionnew.py b/py/_code/_assertionnew.py
> --- a/py/_code/_assertionnew.py
> +++ b/py/_code/_assertionnew.py
> @@ -107,17 +107,21 @@ unary_map = {
>  }
>  
>  
> +def customise_assert(config):
> +    """Customise the DebugInterpreter with pytest config"""
> +    DebugInterpreter.pytest_config = config
> +
> +
>  class DebugInterpreter(ast.NodeVisitor):
>      """Interpret AST nodes to gleam useful debugging information.
>  
>      The _pytesthook attribute is used to detect if the py.test
>      pytest_assertion plugin is loaded and if so call it's hooks.
>      """
> +    pytest_config = None
>  
>      def __init__(self, frame):
>          self.frame = frame
> -        self._pytesthook = getattr(py.builtin.builtins.AssertionError,
> -                                   "_pytesthook")
>  
>      def generic_visit(self, node):
>          # Fallback when we don't have a special implementation.
> @@ -183,9 +191,10 @@ class DebugInterpreter(ast.NodeVisitor):
>              if not result:
>                  break
>              left_explanation, left_result = next_explanation, next_result
> -        if self._pytesthook:
> -            hook_result = self._pytesthook.pytest_assert_binrepr(
> -                op=op_symbol, left=left_result, right=next_result)
> +        if self.pytest_config:
> +            hook_result = self.pytest_config.hook.pytest_assert_binrepr(
> +                op=op_symbol, left=left_result, right=next_result,
> +                config=self.pytest_config)
>              if hook_result:
>                  for new_expl in hook_result:
>                      if new_expl:
> diff --git a/py/_plugin/hookspec.py b/py/_plugin/hookspec.py
> --- a/py/_plugin/hookspec.py
> +++ b/py/_plugin/hookspec.py
> @@ -127,7 +127,7 @@ def pytest_sessionfinish(session, exitst
>  # hooks for customising the assert methods
>  # -------------------------------------------------------------------------
>  
> -def pytest_assert_binrepr(op, left, right):
> +def pytest_assert_binrepr(op, left, right, config):
>      """Customise explanation for binary operators
>  
>      Return None or an empty list for no custom explanation, otherwise
> diff --git a/py/_plugin/pytest_assertion.py b/py/_plugin/pytest_assertion.py
> --- a/py/_plugin/pytest_assertion.py
> +++ b/py/_plugin/pytest_assertion.py
> @@ -16,7 +16,7 @@ def pytest_configure(config):
>          warn_about_missing_assertion()
>          config._oldassertion = py.builtin.builtins.AssertionError
>          py.builtin.builtins.AssertionError = py.code._AssertionError
> -        py.builtin.builtins.AssertionError._pytesthook = config.hook
> +        py.code.customise_assert(config)
>  
>  def pytest_unconfigure(config):
>      if hasattr(config, '_oldassertion'):

> _______________________________________________
> py-dev mailing list
> py-dev at codespeak.net
> http://codespeak.net/mailman/listinfo/py-dev


-- 



More information about the Pytest-dev mailing list