Skip to content
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

2.12.1: pytest fails because missing files #258

Open
kloczek opened this issue Mar 13, 2024 · 1 comment · May be fixed by #261
Open

2.12.1: pytest fails because missing files #258

kloczek opened this issue Mar 13, 2024 · 1 comment · May be fixed by #261

Comments

@kloczek
Copy link

kloczek commented Mar 13, 2024

I'm packaging your module as an rpm package so I'm using the typical PEP517 based build, install and test cycle used on building packages from non-root account.

  • python3 -sBm build -w --no-isolation
  • because I'm calling build with --no-isolation I'm using during all processes only locally installed modules
  • install .whl file in </install/prefix> using installer module
  • run pytest with $PYTHONPATH pointing to sitearch and sitelib inside </install/prefix>
  • build is performed in env which is cut off from access to the public network (pytest is executed with -m "not network")

Looks like pytest fails because some files are missing in git repo.

Here is pytest output:
+ PYTHONPATH=/home/tkloczko/rpmbuild/BUILDROOT/python-anytree-2.12.1-2.fc36.x86_64/usr/lib64/python3.9/site-packages:/home/tkloczko/rpmbuild/BUILDROOT/python-anytree-2.12.1-2.fc36.x86_64/usr/lib/python3.9/site-packages
+ /usr/bin/pytest -ra -m 'not network'
==================================================================================== test session starts ====================================================================================
platform linux -- Python 3.9.18, pytest-8.1.1, pluggy-1.4.0
rootdir: /home/tkloczko/rpmbuild/BUILD/anytree-2.12.1
configfile: pyproject.toml
collected 163 items

tests/test_cachedsearch.py ....                                                                                                                                                       [  2%]
tests/test_dictexporter.py ....                                                                                                                                                       [  4%]
tests/test_dictimporter.py ..                                                                                                                                                         [  6%]
tests/test_dotexport.py FFF                                                                                                                                                           [  7%]
tests/test_dotexporter.py ......                                                                                                                                                      [ 11%]
tests/test_examples.py .                                                                                                                                                              [ 12%]
tests/test_iterators.py ......                                                                                                                                                        [ 15%]
tests/test_jsonexporter.py .                                                                                                                                                          [ 16%]
tests/test_jsonimporter.py .                                                                                                                                                          [ 17%]
tests/test_lightnode.py .....................                                                                                                                                         [ 30%]
tests/test_mermaidexporter.py .....                                                                                                                                                   [ 33%]
tests/test_node.py ................................                                                                                                                                   [ 52%]
tests/test_node_attach_detach.py ...                                                                                                                                                  [ 54%]
tests/test_node_integrity.py .                                                                                                                                                        [ 55%]
tests/test_node_sep.py ...                                                                                                                                                            [ 57%]
tests/test_node_symlink.py .                                                                                                                                                          [ 57%]
tests/test_pickle.py .                                                                                                                                                                [ 58%]
tests/test_render.py ..........                                                                                                                                                       [ 64%]
tests/test_resolver.py ..........                                                                                                                                                     [ 70%]
tests/test_search.py .....                                                                                                                                                            [ 73%]
tests/test_special_methods_access.py .................................                                                                                                                [ 93%]
tests/test_uniquedotexporter.py ......                                                                                                                                                [ 97%]
tests/test_util.py ...                                                                                                                                                                [ 99%]
tests/test_walker.py .                                                                                                                                                                [100%]

========================================================================================= FAILURES ==========================================================================================
________________________________________________________________________________________ test_tree1 _________________________________________________________________________________________

    @with_setup(setup, teardown)
    def test_tree1():
        """Tree1."""
        root = Node("root")
        s0 = Node("sub0", parent=root)
        Node("sub0B", parent=s0)
        Node("sub0A", parent=s0)
        s1 = Node("sub1", parent=root)
        Node("sub1A", parent=s1)
        Node("sub1B", parent=s1)
        s1c = Node("sub1C", parent=s1)
        Node(99, parent=s1c)

>       RenderTreeGraph(root).to_dotfile(join(GENPATH, "tree1.dot"))

tests/test_dotexport.py:39:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
anytree/exporter/dotexporter.py:284: in to_dotfile
    with codecs.open(filename, "w", "utf-8") as file:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

filename = '/home/tkloczko/rpmbuild/BUILD/anytree-2.12.1/tests/dotexport/tree1.dot', mode = 'wb', encoding = 'utf-8', errors = 'strict', buffering = -1

    def open(filename, mode='r', encoding=None, errors='strict', buffering=-1):

        """ Open an encoded file using the given mode and return
            a wrapped version providing transparent encoding/decoding.

            Note: The wrapped version will only accept the object format
            defined by the codecs, i.e. Unicode objects for most builtin
            codecs. Output is also codec dependent and will usually be
            Unicode as well.

            Underlying encoded files are always opened in binary mode.
            The default file mode is 'r', meaning to open the file in read mode.

            encoding specifies the encoding which is to be used for the
            file.

            errors may be given to define the error handling. It defaults
            to 'strict' which causes ValueErrors to be raised in case an
            encoding error occurs.

            buffering has the same meaning as for the builtin open() API.
            It defaults to -1 which means that the default buffer size will
            be used.

            The returned wrapped file object provides an extra attribute
            .encoding which allows querying the used encoding. This
            attribute is only available if an encoding was specified as
            parameter.

        """
        if encoding is not None and \
           'b' not in mode:
            # Force opening of the file in binary mode
            mode = mode + 'b'
>       file = builtins.open(filename, mode, buffering)
E       FileNotFoundError: [Errno 2] No such file or directory: '/home/tkloczko/rpmbuild/BUILD/anytree-2.12.1/tests/dotexport/tree1.dot'

/usr/lib64/python3.9/codecs.py:905: FileNotFoundError
________________________________________________________________________________________ test_tree2 _________________________________________________________________________________________

    @with_setup(setup, teardown)
    def test_tree2():
        """Tree2."""
        root = Node("root")
        s0 = Node("sub0", parent=root, edge=2)
        Node("sub0B", parent=s0, foo=4, edge=109)
        Node("sub0A", parent=s0, edge="")
        s1 = Node("sub1", parent=root, edge="")
        Node("sub1A", parent=s1, edge=7)
        Node("sub1B", parent=s1, edge=8)
        s1c = Node("sub1C", parent=s1, edge=22)
        Node("sub1Ca", parent=s1c, edge=42)

        def nodenamefunc(node):
            return "{}:{}".format(node.name, node.depth)

        def edgeattrfunc(node, child):
            return 'label="{}:{}"'.format(node.name, child.name)

        r = RenderTreeGraph(
            root,
            options=["rankdir=LR;"],
            nodenamefunc=nodenamefunc,
            nodeattrfunc=lambda node: "shape=box",
            edgeattrfunc=edgeattrfunc,
        )

>       r.to_dotfile(join(GENPATH, "tree2.dot"))

tests/test_dotexport.py:70:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
anytree/exporter/dotexporter.py:284: in to_dotfile
    with codecs.open(filename, "w", "utf-8") as file:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

filename = '/home/tkloczko/rpmbuild/BUILD/anytree-2.12.1/tests/dotexport/tree2.dot', mode = 'wb', encoding = 'utf-8', errors = 'strict', buffering = -1

    def open(filename, mode='r', encoding=None, errors='strict', buffering=-1):

        """ Open an encoded file using the given mode and return
            a wrapped version providing transparent encoding/decoding.

            Note: The wrapped version will only accept the object format
            defined by the codecs, i.e. Unicode objects for most builtin
            codecs. Output is also codec dependent and will usually be
            Unicode as well.

            Underlying encoded files are always opened in binary mode.
            The default file mode is 'r', meaning to open the file in read mode.

            encoding specifies the encoding which is to be used for the
            file.

            errors may be given to define the error handling. It defaults
            to 'strict' which causes ValueErrors to be raised in case an
            encoding error occurs.

            buffering has the same meaning as for the builtin open() API.
            It defaults to -1 which means that the default buffer size will
            be used.

            The returned wrapped file object provides an extra attribute
            .encoding which allows querying the used encoding. This
            attribute is only available if an encoding was specified as
            parameter.

        """
        if encoding is not None and \
           'b' not in mode:
            # Force opening of the file in binary mode
            mode = mode + 'b'
>       file = builtins.open(filename, mode, buffering)
E       FileNotFoundError: [Errno 2] No such file or directory: '/home/tkloczko/rpmbuild/BUILD/anytree-2.12.1/tests/dotexport/tree2.dot'

/usr/lib64/python3.9/codecs.py:905: FileNotFoundError
_______________________________________________________________________________________ test_tree_png _______________________________________________________________________________________

    @with_setup(setup, teardown)
    def test_tree_png():
        """Tree to png."""
        root = Node("root")
        s0 = Node("sub0", parent=root)
        Node("sub0B", parent=s0)
        Node("sub0A", parent=s0)
        s1 = Node("sub1", parent=root)
        Node("sub1A", parent=s1)
        Node("sub1B", parent=s1)
        s1c = Node("sub1C", parent=s1)
        Node("sub1Ca", parent=s1c)

>       RenderTreeGraph(root).to_picture(join(GENPATH, "tree1.png"))

tests/test_dotexport.py:87:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
anytree/exporter/dotexporter.py:303: in to_picture
    check_call(cmd)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

popenargs = (['dot', '/tmp/tmpmr32tg5n', '-T', 'png', '-o', '/home/tkloczko/rpmbuild/BUILD/anytree-2.12.1/tests/dotexport/tree1.png'],), kwargs = {}, retcode = 1
cmd = ['dot', '/tmp/tmpmr32tg5n', '-T', 'png', '-o', '/home/tkloczko/rpmbuild/BUILD/anytree-2.12.1/tests/dotexport/tree1.png']

    def check_call(*popenargs, **kwargs):
        """Run command with arguments.  Wait for command to complete.  If
        the exit code was zero then return, otherwise raise
        CalledProcessError.  The CalledProcessError object will have the
        return code in the returncode attribute.

        The arguments are the same as for the call function.  Example:

        check_call(["ls", "-l"])
        """
        retcode = call(*popenargs, **kwargs)
        if retcode:
            cmd = kwargs.get("args")
            if cmd is None:
                cmd = popenargs[0]
>           raise CalledProcessError(retcode, cmd)
E           subprocess.CalledProcessError: Command '['dot', '/tmp/tmpmr32tg5n', '-T', 'png', '-o', '/home/tkloczko/rpmbuild/BUILD/anytree-2.12.1/tests/dotexport/tree1.png']' returned non-zero exit status 1.

/usr/lib64/python3.9/subprocess.py:373: CalledProcessError
----------------------------------------------------------------------------------- Captured stderr call ------------------------------------------------------------------------------------
Error: Could not open "/home/tkloczko/rpmbuild/BUILD/anytree-2.12.1/tests/dotexport/tree1.png" for writing : No such file or directory
===================================================================================== warnings summary ======================================================================================
tests/test_dotexport.py::test_tree1
tests/test_dotexport.py::test_tree2
tests/test_dotexport.py::test_tree_png
  /home/tkloczko/rpmbuild/BUILD/anytree-2.12.1/anytree/dotexport.py:9: DeprecationWarning: anytree.RenderTreeGraph has moved. Use anytree.exporter.DotExporter instead
    warnings.warn(

tests/test_node.py::test_ancestors
  /home/tkloczko/rpmbuild/BUILD/anytree-2.12.1/anytree/node/nodemixin.py:359: DeprecationWarning: .anchestors was a typo and will be removed in version 3.0.0
    warnings.warn(".anchestors was a typo and will be removed in version 3.0.0", DeprecationWarning)

-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
================================================================================== short test summary info ==================================================================================
FAILED tests/test_dotexport.py::test_tree1 - FileNotFoundError: [Errno 2] No such file or directory: '/home/tkloczko/rpmbuild/BUILD/anytree-2.12.1/tests/dotexport/tree1.dot'
FAILED tests/test_dotexport.py::test_tree2 - FileNotFoundError: [Errno 2] No such file or directory: '/home/tkloczko/rpmbuild/BUILD/anytree-2.12.1/tests/dotexport/tree2.dot'
FAILED tests/test_dotexport.py::test_tree_png - subprocess.CalledProcessError: Command '['dot', '/tmp/tmpmr32tg5n', '-T', 'png', '-o', '/home/tkloczko/rpmbuild/BUILD/anytree-2.12.1/tests/dotexport/tree1.png']' returned non-zero exit...
========================================================================= 3 failed, 160 passed, 4 warnings in 0.99s =========================================================================
List of installed modules in build env:
Package                       Version
----------------------------- -----------
alabaster                     0.7.16
Babel                         2.14.0
build                         1.1.1
charset-normalizer            3.3.2
distro                        1.9.0
docutils                      0.20.1
exceptiongroup                1.1.3
idna                          3.6
imagesize                     1.4.1
importlib_metadata            7.0.1
iniconfig                     2.0.0
installer                     0.7.0
Jinja2                        3.1.3
MarkupSafe                    2.1.3
packaging                     24.0
pluggy                        1.4.0
poetry-core                   1.9.0
Pygments                      2.17.2
pyproject_hooks               1.0.0
pytest                        8.1.1
python-dateutil               2.9.0.post0
requests                      2.31.0
snowballstemmer               2.2.0
Sphinx                        7.2.6
sphinxcontrib-applehelp       1.0.8
sphinxcontrib-devhelp         1.0.5
sphinxcontrib-htmlhelp        2.0.5
sphinxcontrib-jsmath          1.0.1
sphinxcontrib-qthelp          1.0.7
sphinxcontrib-serializinghtml 1.1.10
tokenize_rt                   5.2.0
tomli                         2.0.1
urllib3                       1.26.18
wheel                         0.43.0
zipp                          3.17.0

Please let me know if you need more details or want me to perform some diagnostics.

@ncopa
Copy link

ncopa commented Apr 2, 2024

I think this happens due to a race condition. The GENPATH directory is created an destroyed for each test, and I suspect that recent pytest tries to run the tests in parallel, meaning one test deletes the GENPATH while second tests tries to write to it.

Its better to use the tmpdir fixture.

ncopa added a commit to ncopa/anytree that referenced this issue Apr 2, 2024
@ncopa ncopa linked a pull request Apr 2, 2024 that will close this issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants