question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Wrong order of operation when using a context manager and python function

See original GitHub issue

Describe the bug

For some reason, having some operations run from a context manager and some other encapsulated in a python function raise a wrong order of operations. It is not clear yet if this is due to the context manager or not.

See non working and working example below, notice the only difference is the fact that the command is put in a python function.

To Reproduce

DOES NOT WORK:

import os
from pyinfra import host
from pyinfra.operations import files, server


class TmpDir:
    def __init__(self, name):
        self.tmp_dir_name = f"tmp_{name}"
        self.tmp_dir_path = os.path.join(os.sep, "home", host.data.ssh_user, "tmp", self.tmp_dir_name)
        self.create_tmp_dir = None

    def __enter__(self):
        self.create_tmp_dir = files.directory(name=f"Create temporary directory [{self.tmp_dir_name}]", path=self.tmp_dir_path, recursive=True)
        return self.tmp_dir_path

    def __exit__(self, type, value, traceback):
        files.directory(name=f"Destroy temporary directory [{self.tmp_dir_name}]", path=self.tmp_dir_path, present=False, assume_present=self.create_tmp_dir.changed)


def run_command(path):
    server.shell(name="Test ls", commands="ls .", _chdir=path)


with TmpDir("test") as tmp_dir_path:
    run_command(tmp_dir_path)
--> Loading config...
--> Loading inventory...

--> Connecting to hosts...
    No host key for *** found in known_hosts
    [***] Connected

--> Preparing operations...
    Loading: tasks/cm.py
    [***] Ready: tasks/cm.py

--> Proposed changes:
    Groups: ** / ***
    [***]   Operations: 3   Commands: 3

--> Beginning operation run...
--> Starting operation: Create temporary directory [tmp_test]
    [***] Success

--> Starting operation: Destroy temporary directory [tmp_test]
    [***] Success

--> Starting operation: Test ls
    [***] sh: line 0: cd: /home/***/tmp/tmp_test: No such file or directory
    [***] Error
No hosts remaining!
--> pyinfra error: 

WORKS:

import os
from pyinfra import host
from pyinfra.operations import files, server


class TmpDir:
    def __init__(self, name):
        self.tmp_dir_name = f"tmp_{name}"
        self.tmp_dir_path = os.path.join(os.sep, "home", host.data.ssh_user, "tmp", self.tmp_dir_name)
        self.create_tmp_dir = None

    def __enter__(self):
        self.create_tmp_dir = files.directory(name=f"Create temporary directory [{self.tmp_dir_name}]", path=self.tmp_dir_path, recursive=True)
        return self.tmp_dir_path

    def __exit__(self, type, value, traceback):
        files.directory(name=f"Destroy temporary directory [{self.tmp_dir_name}]", path=self.tmp_dir_path, present=False, assume_present=self.create_tmp_dir.changed)

with TmpDir("test") as tmp_dir_path:
    server.shell(name="Test ls", commands="ls .", _chdir=tmp_dir_path)
--> Loading config...
--> Loading inventory...

--> Connecting to hosts...
    No host key for *** found in known_hosts
    [***] Connected

--> Preparing operations...
    Loading: tasks/cm.py
    [***] Ready: tasks/cm.py

--> Proposed changes:
    Groups: ** / **
    [***]   Operations: 3   Commands: 3

--> Beginning operation run...
--> Starting operation: Create temporary directory [tmp_test]
    [***] Success

--> Starting operation: Test ls
    [***] Success

--> Starting operation: Destroy temporary directory [tmp_test]
    [***] Success

--> Results:
    Groups: ** / **
    [***]   Successful: 3   Errors: 0   Commands: 3/3

Steps to reproduce the behavior (include code & usage example):

Expected behavior

I would expect the order of operations remain unchanged whether I put them in python functions or not.

Meta

  • Include output of pyinfra --support.
--> Support information:

    If you are having issues with pyinfra or wish to make feature requests, please
    check out the GitHub issues at https://github.com/Fizzadar/pyinfra/issues .
    When adding an issue, be sure to include the following:

    System: Linux
      Platform: Linux-3.10.0-1160.59.1.el7.x86_64-x86_64-with-glibc2.17
      Release: 3.10.0-1160.59.1.el7.x86_64
      Machine: x86_64
    pyinfra: v2.0.1
    Executable: /home/**/.local/bin/pyinfra
    Python: 3.9.4 (CPython, GCC 4.8.5 20150623 (Red Hat 4.8.5-44))
  • How was pyinfra installed (source/pip)? pip

Issue Analytics

  • State:closed
  • Created a year ago
  • Comments:5 (2 by maintainers)

github_iconTop GitHub Comments

1reaction
Fizzadarcommented, Jun 4, 2022

This should now be fixed in v2.2!

0reactions
julienlavergnecommented, May 30, 2022

ok

Read more comments on GitHub >

github_iconTop Results From Across the Web

contextlib — Utilities for with-statement contexts ... - Python Docs
Source code: Lib/contextlib.py This module provides utilities for common tasks involving the with statement. For more information see also Context Manager ...
Read more >
Context Managers and Python's with Statement
In this step-by-step tutorial, you'll learn what the Python with statement is and how to use it with existing context managers.
Read more >
The Curious Case of Python's Context Manager
Notice the order they're closed. Context managers are treated as a stack, and should be exited in reverse order in which they're entered....
Read more >
Context Managers in Python: Using the "with" statement
A context manager, used in a with statement, defines a temporary context for the given set of operations. It does so by injecting...
Read more >
Using python's context manager to get the order of ...
I would like to create a context manager that is used as such: with my_context_manager(): add(1, 2) divide(3, 4) multiply(5, 6).
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found