Skip to content

"AttributeError: object has no attribute 'add_mark'" when marks clash with existing attributes #3631

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
DRMacIver opened this issue Jun 28, 2018 · 8 comments
Labels
type: bug problem that needs to be addressed

Comments

@DRMacIver
Copy link

When running the following code with python -m pytest foo.py:

import pytest


def assign_foo(f):
    f.foo = "Hi"
    return f


@pytest.mark.foo
@assign_foo
def test():
    pass

I get the following error:

foo.py:10: in <module>
    @assign_foo
v/lib/python3.6/site-packages/_pytest/mark/structures.py:213: in __call__
    store_legacy_markinfo(func, self.mark)
v/lib/python3.6/site-packages/_pytest/mark/structures.py:250: in store_legacy_markinfo
    holder.add_mark(mark)
E   AttributeError: 'str' object has no attribute 'add_mark'

This is on 3.6.0 with the following packages in the virtualenv (i.e. a clean install of pytest 3.6.2):

Package        Version
-------------- -------
atomicwrites   1.1.5
attrs          18.1.0
more-itertools 4.2.0
pip            10.0.1
pluggy         0.6.0
py             1.5.4
pytest         3.6.2
setuptools     39.2.0
six            1.11.0
wheel          0.31.1

We encountered this because someone was applying @pytest.mark.hypothesis to a @given decorated test (see HypothesisWorks/hypothesis#1362), which broke when we added a hypothesis attribute on the decorated function.

I believe this is only a problem with the legacy support and is not required for marks to work: we already apply a hypothesis mark to all @given decorated tests, and it is still working fine, so it seems likely that a fix that checked if the attribute was already present and did nothing if it was not a MarkInfo would be backwards compatible and fix this problem.

@pytestbot
Copy link
Contributor

GitMate.io thinks possibly related issues are #49 (AttributeError: 'Session' object has no attribute '_setupstate'), #362 (AttributeError: 'MyOptionParser' object has no attribute 'parse_known_args'), #2162 (AttributeError: 'SubRequest' object has no attribute 'param'), #1310 (AttributeError: '_HookCaller' object has no attribute 'spec_opts'), and #1447 (AttributeError: 'OutputWriter' object has no attribute 'isatty').

@pytestbot pytestbot added the type: bug problem that needs to be addressed label Jun 28, 2018
@RonnyPfannschmidt
Copy link
Member

good find and thanks for the minimal case, i believe introducing a warning there and doing nothing is indeed a good way forward there

@nicoddemus i'd appreciate your opinion

@DRMacIver
Copy link
Author

introducing a warning there

What would the warning be? What should the user be doing differently in this case?

Given that the more modern mark storage mechanism means that (as far as I can tell) it's perfectly fine to have an attribute and a mark of the same name, it seems a shame to let the legacy support turn reasonable behaviour into a warning unless there's something the user can do that will avoid that.

(In the case of Hypothesis this doesn't matter because the fix for this problem was just to tell the use "Don't do that then" as we're already applying the mark, I'm just not a fan of non-actionable warnings)

@RonnyPfannschmidt
Copy link
Member

@DRMacIver the warning is necessary since we dont act on the actual instruction of applying a mark anymore - aka we no longer add something the code says we do

@DRMacIver
Copy link
Author

we dont act on the actual instruction of applying a mark anymore - aka we no longer add something the code says we do

I don't think that's true though, unless I'm misunderstanding the code.

The problem is occurring only in the part of the code that applies the legacy mark info, which adds an attribute to the function. The part that adds it to the pytestmark attribute should continue to work unchanged AFAICT and so the mark would continue to work properly, it just wouldn't be available via an attribute on the function.

@RonnyPfannschmidt
Copy link
Member

@DRMacIver the legacy storage is the only storage pre pytest 3.6 and the api of it is expected to work - just because its deprecated, it should just start to work worse than it already is without telling users

@RonnyPfannschmidt
Copy link
Member

i started to review history, the issue got introduced by me earlier, im now tracking back to the version that introduces it

@RonnyPfannschmidt
Copy link
Member

i finished the evaluation, the call was always broken, on the feature branch we should opt to do nothing in the case, thanks for calling me out on the warning

RonnyPfannschmidt added a commit to RonnyPfannschmidt/pytest that referenced this issue Jun 29, 2018
RonnyPfannschmidt added a commit to RonnyPfannschmidt/pytest that referenced this issue Jun 29, 2018
RonnyPfannschmidt added a commit to RonnyPfannschmidt/pytest that referenced this issue Jun 29, 2018
nicoddemus added a commit that referenced this issue Jun 30, 2018
fix #3631 - don't store legacy markinfo when its impossible
jezdez referenced this issue in mozilla/telemetry-analysis-service Aug 14, 2018
This PR updates [pytest](https://pypi.org/project/pytest) from **3.6.2** to **3.7.1**.



<details>
  <summary>Changelog</summary>
  
  
   ### 3.7.1
   ```
   =========================

Bug Fixes
---------

- `3473 &lt;https://github.com/pytest-dev/pytest/issues/3473&gt;`_: Raise immediately if ``approx()`` is given an expected value of a type it doesn&#39;t understand (e.g. strings, nested dicts, etc.).


- `3712 &lt;https://github.com/pytest-dev/pytest/issues/3712&gt;`_: Correctly represent the dimensions of an numpy array when calling ``repr()`` on ``approx()``.

- `3742 &lt;https://github.com/pytest-dev/pytest/issues/3742&gt;`_: Fix incompatibility with third party plugins during collection, which produced the error ``object has no attribute &#39;_collectfile&#39;``.

- `3745 &lt;https://github.com/pytest-dev/pytest/issues/3745&gt;`_: Display the absolute path if ``cache_dir`` is not relative to the ``rootdir`` instead of failing.


- `3747 &lt;https://github.com/pytest-dev/pytest/issues/3747&gt;`_: Fix compatibility problem with plugins and the warning code issued by fixture functions when they are called directly.


- `3748 &lt;https://github.com/pytest-dev/pytest/issues/3748&gt;`_: Fix infinite recursion in ``pytest.approx`` with arrays in ``numpy&lt;1.13``.


- `3757 &lt;https://github.com/pytest-dev/pytest/issues/3757&gt;`_: Pin pathlib2 to ``&gt;=2.2.0`` as we require ``__fspath__`` support.


- `3763 &lt;https://github.com/pytest-dev/pytest/issues/3763&gt;`_: Fix ``TypeError`` when the assertion message is ``bytes`` in python 3.
   ```
   
  
  
   ### 3.7.0
   ```
   =========================

Deprecations and Removals
-------------------------

- `2639 &lt;https://github.com/pytest-dev/pytest/issues/2639&gt;`_: ``pytest_namespace`` has been deprecated.

  See the documentation for ``pytest_namespace`` hook for suggestions on how to deal
  with this in plugins which use this functionality.


- `3661 &lt;https://github.com/pytest-dev/pytest/issues/3661&gt;`_: Calling a fixture function directly, as opposed to request them in a test function, now issues a ``RemovedInPytest4Warning``. It will be changed into an error in pytest ``4.0``.

  This is a great source of confusion to new users, which will often call the fixture functions and request them from test functions interchangeably, which breaks the fixture resolution model.



Features
--------

- `2283 &lt;https://github.com/pytest-dev/pytest/issues/2283&gt;`_: New ``package`` fixture scope: fixtures are finalized when the last test of a *package* finishes. This feature is considered **experimental**, so use it sparingly.


- `3576 &lt;https://github.com/pytest-dev/pytest/issues/3576&gt;`_: ``Node.add_marker`` now supports an ``append=True/False`` parameter to determine whether the mark comes last (default) or first.


- `3579 &lt;https://github.com/pytest-dev/pytest/issues/3579&gt;`_: Fixture ``caplog`` now has a ``messages`` property, providing convenient access to the format-interpolated log messages without the extra data provided by the formatter/handler.


- `3610 &lt;https://github.com/pytest-dev/pytest/issues/3610&gt;`_: New ``--trace`` option to enter the debugger at the start of a test.


- `3623 &lt;https://github.com/pytest-dev/pytest/issues/3623&gt;`_: Introduce ``pytester.copy_example`` as helper to do acceptance tests against examples from the project.



Bug Fixes
---------

- `2220 &lt;https://github.com/pytest-dev/pytest/issues/2220&gt;`_: Fix a bug where fixtures overridden by direct parameters (for example parametrization) were being instantiated even if they were not being used by a test.


- `3695 &lt;https://github.com/pytest-dev/pytest/issues/3695&gt;`_: Fix ``ApproxNumpy`` initialisation argument mixup, ``abs`` and ``rel`` tolerances were flipped causing strange comparsion results.
  Add tests to check ``abs`` and ``rel`` tolerances for ``np.array`` and test for expecting ``nan`` with ``np.array()``


- `980 &lt;https://github.com/pytest-dev/pytest/issues/980&gt;`_: Fix truncated locals output in verbose mode.



Improved Documentation
----------------------

- `3295 &lt;https://github.com/pytest-dev/pytest/issues/3295&gt;`_: Correct the usage documentation of ``--last-failed-no-failures`` by adding the missing ``--last-failed`` argument in the presented examples, because they are misleading and lead to think that the missing argument is not needed.



Trivial/Internal Changes
------------------------

- `3519 &lt;https://github.com/pytest-dev/pytest/issues/3519&gt;`_: Now a ``README.md`` file is created in ``.pytest_cache`` to make it clear why the directory exists.
   ```
   
  
  
   ### 3.6.4
   ```
   =========================

Bug Fixes
---------

- Invoke pytest using ``-mpytest`` so ``sys.path`` does not get polluted by packages installed in ``site-packages``. (`742 &lt;https://github.com/pytest-dev/pytest/issues/742&gt;`_)


Improved Documentation
----------------------

- Use ``smtp_connection`` instead of ``smtp`` in fixtures documentation to avoid possible confusion. (`3592 &lt;https://github.com/pytest-dev/pytest/issues/3592&gt;`_)


Trivial/Internal Changes
------------------------

- Remove obsolete ``__future__`` imports. (`2319 &lt;https://github.com/pytest-dev/pytest/issues/2319&gt;`_)

- Add CITATION to provide information on how to formally cite pytest. (`3402 &lt;https://github.com/pytest-dev/pytest/issues/3402&gt;`_)

- Replace broken type annotations with type comments. (`3635 &lt;https://github.com/pytest-dev/pytest/issues/3635&gt;`_)

- Pin ``pluggy`` to ``&lt;0.8``. (`3727 &lt;https://github.com/pytest-dev/pytest/issues/3727&gt;`_)
   ```
   
  
  
   ### 3.6.3
   ```
   =========================

Bug Fixes
---------

- Fix ``ImportWarning`` triggered by explicit relative imports in
  assertion-rewritten package modules. (`3061
  &lt;https://github.com/pytest-dev/pytest/issues/3061&gt;`_)

- Fix error in ``pytest.approx`` when dealing with 0-dimension numpy
  arrays. (`3593 &lt;https://github.com/pytest-dev/pytest/issues/3593&gt;`_)

- No longer raise ``ValueError`` when using the ``get_marker`` API. (`3605
  &lt;https://github.com/pytest-dev/pytest/issues/3605&gt;`_)

- Fix problem where log messages with non-ascii characters would not
  appear in the output log file.
  (`3630 &lt;https://github.com/pytest-dev/pytest/issues/3630&gt;`_)

- No longer raise ``AttributeError`` when legacy marks can&#39;t be stored in
  functions. (`3631 &lt;https://github.com/pytest-dev/pytest/issues/3631&gt;`_)


Improved Documentation
----------------------

- The description above the example for ``pytest.mark.skipif`` now better
  matches the code. (`3611
  &lt;https://github.com/pytest-dev/pytest/issues/3611&gt;`_)


Trivial/Internal Changes
------------------------

- Internal refactoring: removed unused ``CallSpec2tox ._globalid_args``
  attribute and ``metafunc`` parameter from ``CallSpec2.copy()``. (`3598
  &lt;https://github.com/pytest-dev/pytest/issues/3598&gt;`_)

- Silence usage of ``reduce`` warning in Python 2 (`3609
  &lt;https://github.com/pytest-dev/pytest/issues/3609&gt;`_)

- Fix usage of ``attr.ib`` deprecated ``convert`` parameter. (`3653
  &lt;https://github.com/pytest-dev/pytest/issues/3653&gt;`_)
   ```
   
  
</details>


 

<details>
  <summary>Links</summary>
  
  - PyPI: https://pypi.org/project/pytest
  - Changelog: https://pyup.io/changelogs/pytest/
  - Repo: https://github.com/pytest-dev/pytest/issues
  - Homepage: http://pytest.org
</details>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: bug problem that needs to be addressed
Projects
None yet
Development

No branches or pull requests

3 participants