Skip to content

Conversation

tumregels
Copy link
Contributor

@tumregels tumregels commented Dec 4, 2020

fix get_file_dirname so that playwright can function when freezed with pyinstaller (fix #342).

@mxschmitt
Copy link
Member

Do you know the reason why it is not working in this specific case? The workaround looks quite weird, but I'm also not very experienced in Python.

@tumregels
Copy link
Contributor Author

Not sure, but this issue somewhat explains the problem

@pavelfeldman
Copy link
Member

@tumregels this looks good to me, but do you think we could replace the usage of this method with something more straightforward in main.py instead? That's the only call site that works at runtime, the rest is for testing...

@tumregels
Copy link
Contributor Author

@pavelfeldman there seems to be no solid solution to this problem, at least can't suggest any. This answer tries to cover the available options. And the recommended pkgutil is not an option for this case.

@mxschmitt
Copy link
Member

@pavelfeldman there seems to be no solid solution to this problem, at least can't suggest any. This answer tries to cover the available options. And the recommended pkgutil is not an option for this case.

What about removing the single occurrence in the source and moving it inline into the callee and moving the get_file_dirname function into the tests directory?

@tumregels
Copy link
Contributor Author

tumregels commented Dec 8, 2020

@mxschmitt - based on the table here can suggest to change compute_driver_executable with this code

import importlib.resources as pkg_resources

def compute_driver_executable() -> Path:
    _pkg = '.'.join(__name__.split(".")[:-1])
    with pkg_resources.path(_pkg, "") as package_path:
        assert package_path
        platform = sys.platform
        if platform == "win32":
            return package_path / "driver" / "playwright-cli.exe"
        return package_path / "driver" / "playwright-cli"

where _pkg is a workaround for this issue.

And this solution works with pyinstaller.

@pavelfeldman
Copy link
Member

pavelfeldman commented Dec 9, 2020

@tumregels

Something as simple as below works for me:

from importlib import resources

with resources.path("playwright", "driver") as driver_folder:

Can we just use it in main.py? Will that keep installer working?

Another variation to try:

import playwright
from importlib import resources

with resources.path(playwright, "driver") as driver_folder:

@tumregels
Copy link
Contributor Author

@pavelfeldman

just checked this one with pyinstaller - it works

import playwright
from importlib import resources

def compute_driver_executable() -> Path:
    with resources.path(playwright, "driver") as driver_folder:
        assert driver_folder
        platform = sys.platform
        if platform == "win32":
            return driver_folder / "playwright-cli.exe"
        return driver_folder / "playwright-cli"

we can also change playwright with playwright.__name__ because pycharm wrongly complains with Expected type 'Union[str, ModuleType]', got '__init__.py' instead

@pavelfeldman
Copy link
Member

@pavelfeldman: nice! do you want to update your PR with it?

@tumregels
Copy link
Contributor Author

@pavelfeldman will update the PR today.

@mxschmitt
Copy link
Member

Can we also move the get_file_dirname function to the tests utils.py file?

@tumregels
Copy link
Contributor Author

tumregels commented Dec 10, 2020

@mxschmitt @pavelfeldman the proposed solution is wrong.
"driver" is not a resource - cannot be a directory.
probably the package was fixed in python3.9, therefore it fails only there.

@pavelfeldman
Copy link
Member

So we should either add init.py into the folder or move the driver executable into the root folder? Either way should do...

@tumregels
Copy link
Contributor Author

tumregels commented Dec 11, 2020

@pavelfeldman current implementation should work.

import inspect
import playwright

def compute_driver_executable() -> Path:
    package_path = Path(inspect.getfile(playwright)).parent
    platform = sys.platform
    if platform == "win32":
        return package_path / "driver" / "playwright-cli.exe"
    return package_path / "driver" / "playwright-cli"

it's failing because setup.py is using curl - which is a fragile solution.

regarding previous solution with importlib.resources - even adding __init__.py will not help - I already tried.
moving to the root is not recommended - as far as know.

@pavelfeldman pavelfeldman merged commit 8ce0314 into microsoft:master Dec 11, 2020
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.

Inspect fails to retrieve module inside frozen app
3 participants