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

Unix Viewers - 2nd attempt #6021

Closed
wants to merge 5 commits into from

Conversation

alv2017
Copy link

@alv2017 alv2017 commented Feb 4, 2022

Fixes #5945, #5976

Changes proposed in this pull request:

  • Viewer class properties format and options have been moved to the parent Viewer class, those properties were removed from the Viewer child classed. format is set to "PNG" and options are set to {"compress_level": 1} The exception is IPythonViewer class, for this class format was set to None and options are set to {}.
  • Python threads were used to control opening/closing of images by external Linux/Unix viewers.
  • Within current setup, when working with Linux viewers the Python program remains opened till the user closes the image in the viewer.
  • Implementation description: there are viewer thread and monitoring thread. Viewer thread is responsible for opening an image in a viewer; the monitoring thread is responsible for removal of temporary images after user closed the image in the viewer.
  • Corresponding documentation is updated.
  • Affected tests are updated: Tests/test_imageshow.py, Tests/helper.py

…y files changed:

- Viewer class format property changed to 'PNG', format property removed from child classes.
- Viewer class options property changed to {"compress_level": 1}, format property removed from child classes.
- IPythonViewer format option set to None, IPythonViewer options set to {}.
- Corresponding test Tests/test_imageshow.py::test_viewer changed to meet the changes mentioned above.
- In the current implementation of UnixViewers threads were used in order to control opening/closing of images by external Linux/Unix viewers.
- The Python program remains opened till the user closes the image in the viewer.
- I used viewer thread and monitoring thread, the monitoring thread is responsible for removal of the temporary images after user closed the image in the viewer.
- Corresponding documentation is updated.
- Tests are updated: Tests/test_imageshow.py, Tests/helper.py
@alv2017 alv2017 changed the title Alv2017/unix viewers Unix Viewers - 2nd attempt Feb 4, 2022
@alv2017

This comment was marked as resolved.

@hugovk

This comment was marked as resolved.

@alv2017

This comment was marked as resolved.

@radarhere

This comment was marked as resolved.

@alv2017
Copy link
Author

alv2017 commented Feb 5, 2022

@hugovk, @radarhere

Please let me know if this PR has a chance of being accepted. Thanks!

Tests/test_imageshow.py Outdated Show resolved Hide resolved
@radarhere radarhere mentioned this pull request Feb 7, 2022
Test skip reason have been corrected.
@alv2017
Copy link
Author

alv2017 commented Feb 7, 2022

@radarhere I corrected the test skip message.

}

th = threading.Thread(
target=subprocess.run, args=(command.split(),), kwargs=kwargs, name=path
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We've recently had to address the possibility of the file path having a space in it. This would split() incorrectly in such a situation, yes?

Copy link
Author

@alv2017 alv2017 Feb 8, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1) I do not think that there is a a split problem, because the file(path) is quoted, and the path always be represented as a single entity.
2) I wouldn't be concerned about users having a temporary path "foo bar baz", I think that they will be able to sort this out.
3) If you know how to break this, then I would be curious to see an example :)

@radarhere
Now I see what you mean.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The solution was to run the viewer command as a shell command. User input has been sanitized in get_command_ex stage. As a result (a) path problem solved; (b) possible security problem solved;

        kwargs = {"shell": True, "stdout": subprocess.PIPE, "stderr": subprocess.PIPE}

        th = threading.Thread(
            target=subprocess.run, args=(command,), kwargs=kwargs, name=path
        )



class GmDisplayViewer(UnixViewer):
"""The GraphicsMagick ``gm display`` command."""

def get_command_ex(self, file, **options):
executable = "gm"
command = "gm display"
command = f"gm display {quote(file)}"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As I've said before, I consider this to be a backwards incompatible change.

Copy link
Author

@alv2017 alv2017 Feb 8, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that it is more convenient to keep a viewer opening shell command at one place. The user input is sanitized and the command is ready for execution, with no further manipulations needed. The commands are readable and easy to understand .

As excuse I will add, that get_command_ex() is a helper function, and the interface of the function was preserved.

@@ -27,8 +27,7 @@
class test_image_results:
@staticmethod
def upload(a, b):
a.show()
b.show()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the reason for this change?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it is hit, the tests will hang infinitely. I do not see any good reason for a.show(), b.show(): we are interested in return value of the upload function, and return value here is None.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Huh? This is only used if there is an environment variale SHOW_ERRORS set, which means the user is asking to be shown failed image comparisons. Removing this breaks that functionality. Also, the result of the upload function is irrelevant as there is a check in place to see if it is defined. If it isn't defined, it is never called anyway, so if this were to be removed, you would remove the whole if block.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. As I mentioned above, I implemented the viewers as a UI part, and it was not an option to use them in tests.

  2. To be honest, I find this part of code quite confusing:

Tests/helper.py

if os.environ.get("SHOW_ERRORS", None):
    # local img.show for errors.
    HAS_UPLOADER = True

    class test_image_results:
        @staticmethod
        def upload(a, b):
            return None

elif "GITHUB_ACTIONS" in os.environ:
    HAS_UPLOADER = True

    class test_image_results:
        @staticmethod
        def upload(a, b):
            dir_errors = os.path.join(os.path.dirname(__file__), "errors")
            os.makedirs(dir_errors, exist_ok=True)
            tmpdir = tempfile.mkdtemp(dir=dir_errors)
            a.save(os.path.join(tmpdir, "a.png"))
            b.save(os.path.join(tmpdir, "b.png"))
            return tmpdir

else:
    try:
        import test_image_results

        HAS_UPLOADER = True
    except ImportError:
        pass

@radarhere
Copy link
Member

I've created #6039 as an alternate version of this. The primary difference is that it doesn't cause Python to hang while waiting for the image viewer to close. See what you think.

@hugovk
Copy link
Member

hugovk commented Feb 19, 2022

#6045 has been merged instead. Thank you for a way for the suggestion!

@hugovk hugovk closed this Feb 19, 2022
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 this pull request may close these issues.

Image.open on Ubuntu 20.04 gives the error "No images found" in the viewer
4 participants