Repository: microsoft/playwright-python

Issue:
Running playwright raises PermissionError on Linux
### Reproducing the error

- Created a virtual environment 
- Installed playwright with `python -m pip install playwright`

Tried to run some code

```python
from playwright import sync_playwright

with sync_playwright() as p:
    for browser_type in [p.chromium, p.firefox, p.webkit]:
        browser = browser_type.launch()
        page = browser.newPage()
        page.goto('http://whatsmyuseragent.org/')
        page.screenshot(path=f'example-{browser_type.name}.png')
        browser.close()
```

Then it raised this error

```python
PermissionError: [Errno 13] Permission denied: '/home/leno/Desktop/open-source/pwright/env/lib/python3.8/site-packages/playwright/drivers/driver-linux
```

I think this is not a normal behavior since running Python under sudo is a terrible idea.

**OS**: Ubuntu 20.04
**Python Version**: 3.8.2
**Playwright Version**:  0.142.3




Discussion:
Hi, could you try

```
chmod +x /home/leno/Desktop/open-source/pwright/env/lib/python3.8/site-packages/playwright/drivers/driver-linux
```

and run your script afterwards. If that works, we would implement that in our codebase.

Resolving patch:
diff --git a/playwright/main.py b/playwright/main.py
--- a/playwright/main.py
+++ b/playwright/main.py
@@ -14,8 +14,6 @@
 
 import asyncio
 import io
-import os
-import stat
 import subprocess
 import sys
 from pathlib import Path
@@ -27,7 +25,7 @@
 from playwright.connection import Connection
 from playwright.helper import Error
 from playwright.object_factory import create_remote_object
-from playwright.path_utils import get_file_dirname
+from playwright.path_utils import get_file_dirname, make_file_executable
 from playwright.playwright import Playwright
 from playwright.sync_api import Playwright as SyncPlaywright
 from playwright.sync_base import dispatcher_fiber, set_dispatcher_fiber
@@ -37,15 +35,19 @@ def compute_driver_executable() -> Path:
     package_path = get_file_dirname()
     platform = sys.platform
     if platform == "darwin":
-        return package_path / "drivers" / "driver-darwin"
+        path = package_path / "drivers" / "driver-darwin"
+        return make_file_executable(path)
     elif platform == "linux":
-        return package_path / "drivers" / "driver-linux"
+        path = package_path / "drivers" / "driver-linux"
+        return make_file_executable(path)
     elif platform == "win32":
         result = package_path / "drivers" / "driver-win32-amd64.exe"
         if result.exists():
             return result
         return package_path / "drivers" / "driver-win32.exe"
-    return package_path / "drivers" / "driver-linux"
+
+    path = package_path / "drivers" / "driver-linux"
+    return make_file_executable(path)
 
 
 async def run_driver_async() -> Connection:
@@ -140,11 +142,7 @@ def main() -> None:
         print('Run "python -m playwright install" to complete installation')
         return
     driver_executable = compute_driver_executable()
-    # Fix the executable bit during the installation.
-    if not sys.platform == "win32":
-        st = os.stat(driver_executable)
-        if st.st_mode & stat.S_IEXEC == 0:
-            os.chmod(driver_executable, st.st_mode | stat.S_IEXEC)
+
     print("Installing the browsers...")
     subprocess.check_call([str(driver_executable), "install"])
 
diff --git a/playwright/path_utils.py b/playwright/path_utils.py
--- a/playwright/path_utils.py
+++ b/playwright/path_utils.py
@@ -1,4 +1,5 @@
 import inspect
+import stat
 from pathlib import Path
 
 
@@ -8,3 +9,9 @@ def get_file_dirname() -> Path:
     module = inspect.getmodule(frame[0])
     assert module
     return Path(module.__file__).parent.absolute()
+
+
+def make_file_executable(file_path: Path) -> Path:
+    """Makes a file executable."""
+    file_path.chmod(file_path.stat().st_mode | stat.S_IEXEC)
+    return file_path


Test patch: