Repository: microsoft/playwright-python

Issue:
[Bug] Page.setDefaultTimeout does not work in sync mode
Will return a coroutine was expected. Can also take care, just created it so we can track this bug.


Discussion:

Resolving patch:
diff --git a/playwright/sync_api.py b/playwright/sync_api.py
--- a/playwright/sync_api.py
+++ b/playwright/sync_api.py
@@ -191,7 +191,7 @@ def isNavigationRequest(self) -> bool:
         -------
         bool
         """
-        return mapping.from_maybe_impl(self._sync(self._impl_obj.isNavigationRequest()))
+        return mapping.from_maybe_impl(self._impl_obj.isNavigationRequest())
 
 
 mapping.register(RequestImpl, Request)
@@ -756,7 +756,7 @@ def asElement(self) -> typing.Union["ElementHandle", NoneType]:
         -------
         typing.Union[ElementHandle, NoneType]
         """
-        return mapping.from_impl_nullable(self._sync(self._impl_obj.asElement()))
+        return mapping.from_impl_nullable(self._impl_obj.asElement())
 
     def dispose(self) -> NoneType:
         """JSHandle.dispose
@@ -797,7 +797,7 @@ def asElement(self) -> typing.Union["ElementHandle", NoneType]:
         -------
         typing.Union[ElementHandle, NoneType]
         """
-        return mapping.from_impl_nullable(self._sync(self._impl_obj.asElement()))
+        return mapping.from_impl_nullable(self._impl_obj.asElement())
 
     def ownerFrame(self) -> typing.Union["Frame", NoneType]:
         """ElementHandle.ownerFrame
@@ -2062,7 +2062,7 @@ def isDetached(self) -> bool:
         -------
         bool
         """
-        return mapping.from_maybe_impl(self._sync(self._impl_obj.isDetached()))
+        return mapping.from_maybe_impl(self._impl_obj.isDetached())
 
     def addScriptTag(
         self, url: str = None, path: str = None, content: str = None, type: str = None
@@ -3155,7 +3155,7 @@ def frame(
             frame matching the criteria. Returns `null` if no frame matches.
         """
         return mapping.from_impl_nullable(
-            self._sync(self._impl_obj.frame(name=name, url=self._wrap_handler(url)))
+            self._impl_obj.frame(name=name, url=self._wrap_handler(url))
         )
 
     def setDefaultNavigationTimeout(self, timeout: int) -> NoneType:
@@ -3178,7 +3178,7 @@ def setDefaultNavigationTimeout(self, timeout: int) -> NoneType:
             Maximum navigation time in milliseconds
         """
         return mapping.from_maybe_impl(
-            self._sync(self._impl_obj.setDefaultNavigationTimeout(timeout=timeout))
+            self._impl_obj.setDefaultNavigationTimeout(timeout=timeout)
         )
 
     def setDefaultTimeout(self, timeout: int) -> NoneType:
@@ -3194,7 +3194,7 @@ def setDefaultTimeout(self, timeout: int) -> NoneType:
             Maximum time in milliseconds
         """
         return mapping.from_maybe_impl(
-            self._sync(self._impl_obj.setDefaultTimeout(timeout=timeout))
+            self._impl_obj.setDefaultTimeout(timeout=timeout)
         )
 
     def querySelector(self, selector: str) -> typing.Union["ElementHandle", NoneType]:
@@ -3974,7 +3974,7 @@ def viewportSize(self) -> typing.Union[Viewport, NoneType]:
         -------
         typing.Union[Viewport, NoneType]
         """
-        return mapping.from_maybe_impl(self._sync(self._impl_obj.viewportSize()))
+        return mapping.from_maybe_impl(self._impl_obj.viewportSize())
 
     def bringToFront(self) -> NoneType:
         """Page.bringToFront
@@ -4149,7 +4149,7 @@ def isClosed(self) -> bool:
         -------
         bool
         """
-        return mapping.from_maybe_impl(self._sync(self._impl_obj.isClosed()))
+        return mapping.from_maybe_impl(self._impl_obj.isClosed())
 
     def click(
         self,
@@ -5003,7 +5003,7 @@ def setDefaultNavigationTimeout(self, timeout: int) -> NoneType:
             Maximum navigation time in milliseconds
         """
         return mapping.from_maybe_impl(
-            self._sync(self._impl_obj.setDefaultNavigationTimeout(timeout=timeout))
+            self._impl_obj.setDefaultNavigationTimeout(timeout=timeout)
         )
 
     def setDefaultTimeout(self, timeout: int) -> NoneType:
@@ -5019,7 +5019,7 @@ def setDefaultTimeout(self, timeout: int) -> NoneType:
             Maximum time in milliseconds
         """
         return mapping.from_maybe_impl(
-            self._sync(self._impl_obj.setDefaultTimeout(timeout=timeout))
+            self._impl_obj.setDefaultTimeout(timeout=timeout)
         )
 
     def newPage(self) -> "Page":
@@ -5374,7 +5374,7 @@ def isConnected(self) -> bool:
         -------
         bool
         """
-        return mapping.from_maybe_impl(self._sync(self._impl_obj.isConnected()))
+        return mapping.from_maybe_impl(self._impl_obj.isConnected())
 
     def newContext(
         self,
diff --git a/scripts/generate_sync_api.py b/scripts/generate_sync_api.py
--- a/scripts/generate_sync_api.py
+++ b/scripts/generate_sync_api.py
@@ -12,6 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+import inspect
 import re
 from types import FunctionType
 from typing import Any, get_type_hints  # type: ignore
@@ -87,8 +88,14 @@ def generate(t: Any) -> None:
             [prefix, suffix] = return_value(
                 get_type_hints(value, api_globals)["return"]
             )
-            prefix = "        return " + prefix + f"self._sync(self._impl_obj.{name}("
-            suffix = "))" + suffix
+            if inspect.iscoroutinefunction(value):
+                prefix = (
+                    "        return " + prefix + f"self._sync(self._impl_obj.{name}("
+                )
+                suffix = "))" + suffix
+            else:
+                prefix = "        return " + prefix + f"self._impl_obj.{name}("
+                suffix = ")" + suffix
             print(f"{prefix}{arguments(value, len(prefix))}{suffix}")
         if "expect_" in name:
             print("")


Test patch:
diff --git a/tests/test_sync.py b/tests/test_sync.py
--- a/tests/test_sync.py
+++ b/tests/test_sync.py
@@ -16,7 +16,7 @@
 
 import pytest
 
-from playwright import Error, sync_playwright
+from playwright import Error, TimeoutError, sync_playwright
 from playwright.sync_api import Browser, Page
 
 
@@ -214,3 +214,10 @@ def test_sync_playwright_multiple_times():
             with sync_playwright() as pw2:
                 assert pw1.chromium == pw2.chromium
         assert "Can only run one Playwright at a time." in exc.value.message
+
+
+def test_sync_set_default_timeout(page):
+    page.setDefaultTimeout(1)
+    with pytest.raises(TimeoutError) as exc:
+        page.waitForFunction("false")
+    assert "Timeout 1ms exceeded." in exc.value.message