Repository: microsoft/playwright-python
Pull request #2714 (2025-01-13 17:22:04)

build(deps): bump pyopenssl from 24.3.0 to 25.0.0
Bumps [pyopenssl](https://github.com/pyca/pyopenssl) from 24.3.0 to 25.0.0.
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a href="https://github.com/pyca/pyopenssl/blob/main/CHANGELOG.rst">pyopenssl's changelog</a>.</em></p>
<blockquote>
<h2>25.0.0 (2025-01-12)</h2>
<p>Backward-incompatible changes:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^</p>
<p>Deprecations:
^^^^^^^^^^^^^</p>
<p>Changes:
^^^^^^^^</p>
<ul>
<li>Corrected type annotations on <code>Context.set_alpn_select_callback</code>, <code>Context.set_session_cache_mode</code>, <code>Context.set_options</code>, <code>Context.set_mode</code>, <code>X509.subject_name_hash</code>, and <code>X509Store.load_locations</code>.</li>
<li>Deprecated APIs are now marked using <code>warnings.deprecated</code>. <code>mypy</code> will emit deprecation notices for them when used with <code>--enable-error-code deprecated</code>.</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a href="https://github.com/pyca/pyopenssl/commit/787f176092b52c513eda8ebaeeef8bd8b8ff849d"><code>787f176</code></a> Prepare for 25.0.0 release (<a href="https://redirect.github.com/pyca/pyopenssl/issues/1411">#1411</a>)</li>
<li><a href="https://github.com/pyca/pyopenssl/commit/2d6299b6423edbed954cee5d1eb6a7a69ba3a332"><code>2d6299b</code></a> Bump actions/upload-artifact in /.github/actions/upload-coverage (<a href="https://redirect.github.com/pyca/pyopenssl/issues/1410">#1410</a>)</li>
<li><a href="https://github.com/pyca/pyopenssl/commit/96a44592b1a64860ba47417f9dcd313302b2c096"><code>96a4459</code></a> Bump actions/upload-artifact from 4.5.0 to 4.6.0 (<a href="https://redirect.github.com/pyca/pyopenssl/issues/1409">#1409</a>)</li>
<li><a href="https://github.com/pyca/pyopenssl/commit/1b2b0ed21986e283a996d0c4357a4bc361daf815"><code>1b2b0ed</code></a> Use type-level deprecations (<a href="https://redirect.github.com/pyca/pyopenssl/issues/1389">#1389</a>)</li>
<li><a href="https://github.com/pyca/pyopenssl/commit/70e2835232ce76d07e696601d21746abcde752f2"><code>70e2835</code></a> Bring full tests directory to typing correctly (<a href="https://redirect.github.com/pyca/pyopenssl/issues/1407">#1407</a>)</li>
<li><a href="https://github.com/pyca/pyopenssl/commit/9422c3688eec75f825949e367ea7cfb26b1c49c5"><code>9422c36</code></a> Bring us under 30 test_ssl type-check issues (<a href="https://redirect.github.com/pyca/pyopenssl/issues/1406">#1406</a>)</li>
<li><a href="https://github.com/pyca/pyopenssl/commit/a3972a02d573f8d1ffee6835107824a9dd64fb63"><code>a3972a0</code></a> A bit more test_ssl.py type check cleanup (<a href="https://redirect.github.com/pyca/pyopenssl/issues/1405">#1405</a>)</li>
<li><a href="https://github.com/pyca/pyopenssl/commit/9baefbaade98c6b76650fbfe07bf19b926578779"><code>9baefba</code></a> Bring us under 100 test_ssl type-check issues (<a href="https://redirect.github.com/pyca/pyopenssl/issues/1404">#1404</a>)</li>
<li><a href="https://github.com/pyca/pyopenssl/commit/317c7fa65b5dc0473f038452f4df334b910812b9"><code>317c7fa</code></a> Burn down another 100 mypy errors in test_ssl.py (<a href="https://redirect.github.com/pyca/pyopenssl/issues/1403">#1403</a>)</li>
<li><a href="https://github.com/pyca/pyopenssl/commit/7c771de5829b4290d4445621d4651039c9ea1d11"><code>7c771de</code></a> Type check all tests except test_ssl.py (<a href="https://redirect.github.com/pyca/pyopenssl/issues/1402">#1402</a>)</li>
<li>Additional commits viewable in <a href="https://github.com/pyca/pyopenssl/compare/24.3.0...25.0.0">compare view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=pyopenssl&package-manager=pip&previous-version=24.3.0&new-version=25.0.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)


</details>


Patch:
diff --git a/.azure-pipelines/publish.yml b/.azure-pipelines/publish.yml
index 0076089..1b2a518 100644
--- a/.azure-pipelines/publish.yml
+++ b/.azure-pipelines/publish.yml
@@ -29,7 +29,12 @@ extends:
     stages:
     - stage: Stage
       jobs:
-      - job: HostJob
+      - job: Build
+        templateContext:
+          outputs:
+          - output: pipelineArtifact
+            path: $(Build.ArtifactStagingDirectory)/esrp-build
+            artifact: esrp-build
         steps:
         - task: UsePythonVersion@0
           inputs:
@@ -41,9 +46,20 @@ extends:
             pip install -r requirements.txt
             pip install -e .
             for wheel in $(python setup.py --list-wheels); do
-              PLAYWRIGHT_TARGET_WHEEL=$wheel python -m build --wheel
+              PLAYWRIGHT_TARGET_WHEEL=$wheel python -m build --wheel --outdir $(Build.ArtifactStagingDirectory)/esrp-build
             done
           displayName: 'Install & Build'
+    - job: Publish
+      dependsOn: Build
+      templateContext:
+        type: releaseJob
+        isProduction: true
+        inputs:
+        - input: pipelineArtifact
+          artifactName: esrp-build
+          targetPath: $(Build.ArtifactStagingDirectory)/esrp-build
+      steps:
+        - checkout: none
         - task: EsrpRelease@7
           inputs:
             connectedservicename: 'Playwright-ESRP-Azure'
@@ -56,7 +72,7 @@ extends:
             # Keeping it commented out as a workaround for:
             # https://portal.microsofticm.com/imp/v3/incidents/incident/499972482/summary
             # contentsource: 'folder'
-            folderlocation: './dist/'
+            folderlocation: '$(Build.ArtifactStagingDirectory)/esrp-build'
             waitforreleasecompletion: true
             owners: 'maxschmitt@microsoft.com'
             approvers: 'maxschmitt@microsoft.com'
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 929b05b..80dd922 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -169,8 +169,9 @@ jobs:
       - name: Get conda
         uses: conda-incubator/setup-miniconda@v3
         with:
-          python-version: 3.9
+          python-version: 3.12
           channels: conda-forge
+          miniconda-version: latest
       - name: Prepare
         run: conda install conda-build conda-verify
       - name: Build
diff --git a/local-requirements.txt b/local-requirements.txt
index a81932b..e927f38 100644
--- a/local-requirements.txt
+++ b/local-requirements.txt
@@ -3,12 +3,12 @@ black==25.1.0
 build==1.2.2.post1
 flake8==7.1.1
 flaky==3.8.1
-mypy==1.14.1
+mypy==1.15.0
 objgraph==3.6.2
 Pillow==11.1.0
 pixelmatch==0.3.0
 pre-commit==3.5.0
-pyOpenSSL==24.3.0
+pyOpenSSL==25.0.0
 pytest==8.3.4
 pytest-asyncio==0.25.3
 pytest-cov==6.0.0
diff --git a/meta.yaml b/meta.yaml
index f78f0e9..803565a 100644
--- a/meta.yaml
+++ b/meta.yaml
@@ -6,6 +6,7 @@ source:
   path: .
 
 build:
+  noarch: python
   number: 0
   script: "{{ PYTHON }} -m pip install . --no-deps -vv"
   binary_relocation: False
diff --git a/playwright/_impl/_locator.py b/playwright/_impl/_locator.py
index 91ea790..1ad18f9 100644
--- a/playwright/_impl/_locator.py
+++ b/playwright/_impl/_locator.py
@@ -481,7 +481,7 @@ class Locator:
 
     async def is_enabled(self, timeout: float = None) -> bool:
         params = locals_to_params(locals())
-        return await self._frame.is_editable(
+        return await self._frame.is_enabled(
             self._selector,
             strict=True,
             **params,


Test patch:
diff --git a/tests/async/test_fill.py b/tests/async/test_fill.py
index 4dd6db3..c5f0a55 100644
--- a/tests/async/test_fill.py
+++ b/tests/async/test_fill.py
@@ -22,7 +22,14 @@ async def test_fill_textarea(page: Page, server: Server) -> None:
     assert await page.evaluate("result") == "some value"
 
 
-#
+async def test_is_enabled_for_non_editable_button(page: Page) -> None:
+    await page.set_content(
+        """
+        <button>button</button>
+    """
+    )
+    button = page.locator("button")
+    assert await button.is_enabled() is True
 
 
 async def test_fill_input(page: Page, server: Server) -> None:
diff --git a/tests/async/test_locators.py b/tests/async/test_locators.py
index 3855384..aceb399 100644
--- a/tests/async/test_locators.py
+++ b/tests/async/test_locators.py
@@ -128,27 +128,15 @@ async def test_locators_is_enabled_and_is_disabled_should_work(page: Page) -> No
     )
 
     div = page.locator("div")
-    with pytest.raises(
-        Error,
-        match=r"Element is not an <input>, <textarea>, <select> or \[contenteditable\] and does not have a role allowing \[aria-readonly\]",
-    ):
-        assert await div.is_enabled()
+    assert await div.is_enabled()
     assert await div.is_disabled() is False
 
     button1 = page.locator(':text("button1")')
-    with pytest.raises(
-        Error,
-        match=r"Element is not an <input>, <textarea>, <select> or \[contenteditable\] and does not have a role allowing \[aria-readonly\]",
-    ):
-        assert await button1.is_enabled()
+    assert await button1.is_enabled() is False
     assert await button1.is_disabled() is True
 
     button1 = page.locator(':text("button2")')
-    with pytest.raises(
-        Error,
-        match=r"Element is not an <input>, <textarea>, <select> or \[contenteditable\] and does not have a role allowing \[aria-readonly\]",
-    ):
-        assert await button1.is_enabled()
+    assert await button1.is_enabled()
     assert await button1.is_disabled() is False
 
 
diff --git a/tests/sync/test_locators.py b/tests/sync/test_locators.py
index f3a1e74..f373abd 100644
--- a/tests/sync/test_locators.py
+++ b/tests/sync/test_locators.py
@@ -126,27 +126,15 @@ def test_locators_is_enabled_and_is_disabled_should_work(page: Page) -> None:
     )
 
     div = page.locator("div")
-    with pytest.raises(
-        Error,
-        match=r"Element is not an <input>, <textarea>, <select> or \[contenteditable\] and does not have a role allowing \[aria-readonly\]",
-    ):
-        div.is_enabled()
+    assert div.is_enabled()
     assert div.is_disabled() is False
 
     button1 = page.locator(':text("button1")')
-    with pytest.raises(
-        Error,
-        match=r"Element is not an <input>, <textarea>, <select> or \[contenteditable\] and does not have a role allowing \[aria-readonly\]",
-    ):
-        assert button1.is_enabled()
+    assert button1.is_enabled() is False
     assert button1.is_disabled() is True
 
     button1 = page.locator(':text("button2")')
-    with pytest.raises(
-        Error,
-        match=r"Element is not an <input>, <textarea>, <select> or \[contenteditable\] and does not have a role allowing \[aria-readonly\]",
-    ):
-        assert button1.is_enabled()
+    assert button1.is_enabled()
     assert button1.is_disabled() is False