Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -128,11 +128,11 @@ jobs:
# ── Linux x86_64 ──
- os: ubuntu-latest
target: x86_64-unknown-linux-gnu
manylinux: auto
manylinux: "2_28"
# ── Linux aarch64 ──
- os: ubuntu-latest
target: aarch64-unknown-linux-gnu
manylinux: auto
manylinux: "2_28"
# ── macOS x86_64 (Intel, cross-compiled on ARM) ──
- os: macos-14
target: x86_64-apple-darwin
Expand Down Expand Up @@ -203,8 +203,10 @@ jobs:

- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
verbose: true
# Uses Trusted Publisher (OIDC) — no API token needed.
# Register at: https://pypi.org/manage/project/playleft/settings/publishing/
# Register at: https://pypi.org/manage/project/playwleft/settings/publishing/

# ── 6. Create GitHub Release ──────────────────────────────
release:
Expand Down Expand Up @@ -238,10 +240,10 @@ jobs:

**Rust-powered release** — native compiled extensions for maximum performance.

Published to [PyPI](https://pypi.org/project/playleft/${{ needs.check-version.outputs.new_version }}/).
Published to [PyPI](https://pypi.org/project/playwleft/${{ needs.check-version.outputs.new_version }}/).

```bash
pip install playleft==${{ needs.check-version.outputs.new_version }}
pip install playwleft==${{ needs.check-version.outputs.new_version }}
```

### Platforms
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ of visual tooling.

```python
import asyncio
from playleft import PlaywLeft
from playwleft import PlaywLeft

async def main():
async with PlaywLeft() as pw:
Expand Down Expand Up @@ -76,7 +76,7 @@ asyncio.run(main())
## Installation

```bash
pip install playleft
pip install playwleft
```

## Class Hierarchy
Expand Down
4 changes: 2 additions & 2 deletions crates/core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ tracing-subscriber = { workspace = true }
futures-util = { workspace = true }
url = { workspace = true }

# WebSocket client for CDP (rustls for cross-platform builds)
# WebSocket client for CDP (rustls = pure Rust, no system dependencies)
tokio-tungstenite = { version = "0.26", features = ["rustls-tls-webpki-roots"] }

# HTTP client for browser discovery
reqwest = { version = "0.12", default-features = false, features = ["json", "rustls-tls"] }
reqwest = { version = "0.12", default-features = false, features = ["json", "rustls-tls-webpki-roots"] }

# Process management
which = "7"
Expand Down
2 changes: 1 addition & 1 deletion examples/agent_workflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import asyncio
import json
from playleft import PlaywLeft
from playwleft import PlaywLeft


async def search_and_extract(query: str) -> dict:
Expand Down
2 changes: 1 addition & 1 deletion examples/basic_navigation.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""Basic navigation example for playwLeft."""

import asyncio
from playleft import PlaywLeft
from playwleft import PlaywLeft


async def main():
Expand Down
2 changes: 1 addition & 1 deletion examples/web_scraping.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import asyncio
import json
from playleft import PlaywLeft
from playwleft import PlaywLeft


async def main():
Expand Down
4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ requires = ["maturin>=1.7,<2.0"]
build-backend = "maturin"

[project]
name = "playleft"
name = "playwleft"
version = "0.1.0"
description = "Agent-first browser automation toolkit — Playwright alternative built in Rust"
readme = "README.md"
Expand Down Expand Up @@ -46,7 +46,7 @@ Issues = "https://github.com/CocoRoF/playwLeft/issues"

[tool.maturin]
manifest-path = "crates/python/Cargo.toml"
module-name = "playleft._core"
module-name = "playwleft._core"
python-source = "python"
features = ["pyo3/extension-module"]

Expand Down
4 changes: 2 additions & 2 deletions python/playleft/__init__.py → python/playwleft/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

Usage:
import asyncio
from playleft import PlaywLeft
from playwleft import PlaywLeft

async def main():
pw = PlaywLeft()
Expand All @@ -20,7 +20,7 @@ async def main():
asyncio.run(main())
"""

from playleft._core import (
from playwleft._core import (
PlaywLeft,
BrowserType,
Browser,
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
Empty file added tests/__init__.py
Empty file.
39 changes: 39 additions & 0 deletions tests/test_smoke.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
"""Smoke tests — verify the package installs and imports correctly.

These tests don't require a browser and should pass in any CI environment.
"""

import playwleft


def test_version_exists():
"""__version__ should be a non-empty string."""
assert isinstance(playwleft.__version__, str)
assert len(playwleft.__version__) > 0


def test_version_format():
"""__version__ should look like semver (x.y.z)."""
parts = playwleft.__version__.split(".")
assert len(parts) == 3
for part in parts:
assert part.isdigit()


def test_all_public_classes_importable():
"""Every name in __all__ should be importable."""
for name in playwleft.__all__:
assert hasattr(playwleft, name), f"{name} listed in __all__ but not found"


def test_playwleft_instantiation():
"""PlaywLeft() should create an instance without errors."""
pw = playwleft.PlaywLeft()
assert pw is not None


def test_chromium_browser_type():
"""PlaywLeft().chromium() should return a BrowserType."""
pw = playwleft.PlaywLeft()
bt = pw.chromium()
assert isinstance(bt, playwleft.BrowserType)
Loading