Skip to content

Commit

Permalink
initial release
Browse files Browse the repository at this point in the history
  • Loading branch information
gasse committed Mar 11, 2024
0 parents commit 57d7879
Show file tree
Hide file tree
Showing 91 changed files with 8,512 additions and 0 deletions.
121 changes: 121 additions & 0 deletions .github/workflows/pypi.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
name: Publish Python 🐍 distribution 📦 to PyPI and TestPyPI

on: [push, workflow_dispatch]

jobs:
build:
name: Build
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: "3.x"

- name: Install pypa/build
run: python3 -m pip install build --user

- name: Build a binary wheel and a source tarball
run: python3 -m build core

- name: Store the distribution packages
uses: actions/upload-artifact@v3
with:
name: python-package-distributions
path: core/dist/

publish-to-pypi:
name: Publish to PyPI
if: startsWith(github.ref, 'refs/tags/') # only publish to PyPI on tag pushes
needs:
- build
runs-on: ubuntu-latest
environment:
name: pypi
url: https://pypi.org/p/browsergym-core

permissions:
id-token: write # IMPORTANT: mandatory for trusted publishing

steps:
- name: Download all the dists
uses: actions/download-artifact@v3
with:
name: python-package-distributions
path: core/dist/

- name: Publish distribution 📦 to PyPI
uses: pypa/gh-action-pypi-publish@release/v1

github-release:
name: >-
Sign with Sigstore
and upload them to GitHub Release
needs:
- publish-to-pypi
runs-on: ubuntu-latest

permissions:
contents: write # IMPORTANT: mandatory for making GitHub Releases
id-token: write # IMPORTANT: mandatory for sigstore

steps:
- name: Download all the dists
uses: actions/download-artifact@v3
with:
name: python-package-distributions
path: dist/

- name: Sign the dists with Sigstore
uses: sigstore/gh-action-sigstore-python@v1.2.3
with:
inputs: >-
./dist/*.tar.gz
./dist/*.whl
- name: Create GitHub Release
env:
GITHUB_TOKEN: ${{ github.token }}
run: >-
gh release create
'${{ github.ref_name }}'
--repo '${{ github.repository }}'
--notes ""
- name: Upload artifact signatures to GitHub Release
env:
GITHUB_TOKEN: ${{ github.token }}
# Upload to GitHub Release using the `gh` CLI.
# `dist/` contains the built packages, and the
# sigstore-produced signatures and certificates.
run: >-
gh release upload
'${{ github.ref_name }}' dist/**
--repo '${{ github.repository }}'
publish-to-testpypi:
name: Publish to TestPyPI
needs:
- build
runs-on: ubuntu-latest

environment:
name: testpypi
url: https://test.pypi.org/p/browsergym-core

permissions:
id-token: write # IMPORTANT: mandatory for trusted publishing

steps:
- name: Download all the dists
uses: actions/download-artifact@v3
with:
name: python-package-distributions
path: dist/
- name: Publish distribution 📦 to TestPyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
repository-url: https://test.pypi.org/legacy/
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.DS_store
13 changes: 13 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
Copyright 2024 ServiceNow

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
24 changes: 24 additions & 0 deletions core/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# BrowserGym

This package provides `browsergym.core`, which provides the core functionalities of [BrowserGym](https://github.com/ServiceNow/BrowserGym).

## Setup

1. Install the package
```sh
pip install browsergym-core
```

2. Install playwright browsers
```sh
playwright install
```

## Usage

```python
import gymnasium as gym
import browsergym.core # register gym environments

env = gym.make("browsergym/openended")
```
40 changes: 40 additions & 0 deletions core/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
[build-system]
requires = ["hatchling", "hatch-requirements-txt"]
build-backend = "hatchling.build"

[project]
name = "browsergym-core"
description = "BrowserGym: a gym environment for web task automation on the Chrome browser"
authors = [
{name = "Rim Assouel"},
{name = "Léo Boisvert"},
{name = "Massimo Caccia"},
{name = "Alex Drouin"},
{name = "Maxime Gasse"},
{name = "Alex Lacoste"},
{name = "Tom Marty"},
]
readme = "README.md"
requires-python = ">3.7"
license = {text = "Apache-2.0"}
classifiers = [
"Development Status :: 2 - Pre-Alpha",
"Programming Language :: Python :: 3",
"Operating System :: OS Independent",
"Intended Audience :: Science/Research",
"Topic :: Scientific/Engineering :: Artificial Intelligence",
"License :: OSI Approved :: Apache Software License",
]
dynamic = ["dependencies", "version"]

[project.urls]
homepage = "https://github.com/ServiceNow/BrowserGym"

[tool.hatch.version]
path = "src/browsergym/core/__init__.py"

[tool.hatch.metadata.hooks.requirements_txt]
files = ["requirements.txt"]

[tool.hatch.build.targets.wheel]
packages = ["src/browsergym"]
7 changes: 7 additions & 0 deletions core/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
playwright>=1.32,<1.40
gymnasium>=0.27
numpy>=1.14
pyparsing>=3
Pillow>=10.1
beautifulsoup4>=4.12
lxml>=4.9
27 changes: 27 additions & 0 deletions core/src/browsergym/core/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
__version__ = "0.0.1a0"

import playwright.sync_api

# we use a global playwright instance
_PLAYWRIGHT = None


def _set_global_playwright(pw: playwright.sync_api.Playwright):
global _PLAYWRIGHT
_PLAYWRIGHT = pw


def _get_global_playwright():
global _PLAYWRIGHT
if not _PLAYWRIGHT:
pw = playwright.sync_api.sync_playwright().start()
_set_global_playwright(pw)

return _PLAYWRIGHT


# register the open-ended task
from .registration import register_task
from .task import OpenEndedTask

register_task(OpenEndedTask.get_task_id(), OpenEndedTask)
56 changes: 56 additions & 0 deletions core/src/browsergym/core/action/base.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import playwright.sync_api
from abc import ABC, abstractmethod


class AbstractActionSet(ABC):
def __init__(self, strict: bool = False):
self.strict = strict

@abstractmethod
def describe(self, with_long_description: bool = True, with_examples: bool = True) -> str:
"""
Returns a textual description of this action space.
"""

@abstractmethod
def example_action(self, abstract: bool) -> str:
"""
Returns an example action as a string.
"""

@abstractmethod
def to_python_code(self, action) -> str:
"""
Converts the given action to browsergym-compatible python code.
Args:
action: the action to convert.
Returns:
Executable python code that performs the action in a browsergym environment.
"""


def execute_python_code(
code: str,
page: playwright.sync_api.Page,
send_message_to_user: callable,
):
"""
Executes Python code in a new context, except for a playwright `page` object and a `send_message_to_user` function.
WARNING: this is not safe!
https://stackoverflow.com/questions/77655440/can-you-protect-a-python-variable-with-exec
Args:
code: the Python code to execute, as a string.
page: the playwright page that will be made accessible to the code.
send_message_to_user: utility function that will be made accessible to the code. It should take one text argument.
"""

globals = {
"page": page,
"send_message_to_user": send_message_to_user,
}

exec(code, globals)
Loading

0 comments on commit 57d7879

Please sign in to comment.