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
539 changes: 539 additions & 0 deletions CONTRIBUTING.md

Large diffs are not rendered by default.

254 changes: 40 additions & 214 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,240 +2,66 @@

# Polywrap Python Client

[Polywrap](https://polywrap.io) is a developer tool that enables easy integration of Web3 protocols into any application. It makes it possible for applications on any platform, written in any language, to read and write data to Web3 protocols.
[Polywrap](https://polywrap.io) is a protocol for building and executing composable wrappers for any web3 protocol. Polywrap Python Client is a Python library that allows you to easily execute Polywrap Wrappers.

## Quickstart

# Working Features
### Import necessary packages

This MVP Python client enables the execution of **[WebAssembly](https://en.wikipedia.org/wiki/WebAssembly) Polywrappers** *(or just "wrappers")* on a python environment, regardless of what language this wrapper was built in.

The client is built following the functionality of the [JavaScript Polywrap Client](https://github.com/polywrap/toolchain), which is currently more robust and battle tested, as it has additional capabilities than this MVP. In the future, the Polywrap DAO will continue improving this Python capabilities to reach feature parity with the JS stack, while building in parallel clients for other languages like Go and Rust.

[Here](https://github.com/polywrap/client-test-harness) you can see which features have been implemented on each language, and make the decision of which one to use for your project.


# Getting Started:

Have questions or want to get involved? Join our community [Discord](https://discord.polywrap.io) or [open an issue](https://github.com/polywrap/toolchain/issues) on Github.

For detailed information about Polywrap and the WRAP standard, visit our [developer documentation](https://docs.polywrap.io/).

## Pre-requisites

### Clone the repo.
```
git clone https://github.com/polywrap/python-client
```

### `python ˆ3.10`
- Make sure you're running the correct version of python by running:
```
python3 --version
```
> If you are using a Linux system or WSL, which comes with Python3.8, then you will need to upgrade from Python3.8 to Python3.10 and also fix the `pip` and `distutil` as upgrading to Python3.10 will break them. You may follow [this guide](https://cloudbytes.dev/snippets/upgrade-python-to-latest-version-on-ubuntu-linux) to upgrade.

### `poetry ^1.1.14`
- To install poetry follow [this guide](https://python-poetry.org/docs/#installation).
- If you are on MacOS then you can install poetry simply with the following homebrew command
```
brew install poetry
```
> To make sure you're it's installed properly, run `poetry`. Learn more [here](https://python-poetry.org/docs/)



# Building and Testing

## Poetry

- We will be using [Poetry](https://python-poetry.org) for building and testing our packages.
Each of the package folders consists of the `pyproject.toml` file and the `poetry.lock` file. In `pyproject.toml` file, one can find out all the project dependencies and configs related to the package. These files will be utilized by Poetry to install correct dependencies, build, lint and test the package.

- For example, we can **install** deps, **build** and **test** the `polywrap-msgpack` package using Poetry.

- Install dependencies using Poetry.
```
poetry install
```
> Make sure your cwd is the appropriate module, for example `polywrap-msgpack`, `polywrap-wasm` or `polywrap-client`.

## Pytest

In order to assure the integrity of the modules Polywrap Python Client uses [pytest 7.1.3](https://docs.pytest.org/en/7.1.x/contents.html) as a testing framework.

- As we can see in the `pyproject.toml` files, we installed the [PyTest](https://docs.pytest.org) package. We will be using it as our testing framework.
- Now we are ready to **build** and **test** the core package using Poetry and PyTest.

To build the package run the following command
```
poetry build
```

You need to activate the venv with poetry using the `shell` command before running any other command
```
poetry shell
```

Finally, to test your module to execute the test suite:
```
poetry run pytest
```


This last command will run a series of scripts that verify that the specific module of the client is performing as expected in your local machine. The output on your console should look something like this:

```
$ poetry run pytest
>>
================================= test session starts =================================
platform darwin -- Python 3.10.0, pytest-7.1.3, pluggy-1.0.0
rootdir: /Users/polywrap/pycode/polywrap/toolchain/packages/py, configfile: pytest.ini
collected 26 items

tests/test_msgpack.py ........................ [100%]
```

### Debugging with Pytest:

You should expect to see the tests passing with a 100% accuracy. To better understand these outputs, read [this quick guide](https://docs.pytest.org/en/7.1.x/how-to/output.html). If any of the functionality fails (marked with an 'F'), or if there are any Warnings raised, you can debug them by running a verbose version of the test suite:
- `poetry run pytests -v` or `poetry run pytests -vv` for even more detail
- Reach out to the devs on the [Discord](https://discord.polywrap.io) explaining your situation, and what configuration you're using on your machine.


## TOX
We are using [`tox`](https://tox.wiki/en) to run lint and tests even more easily. Below are some basic commands to get you running.

### List all the testenv defined in the tox config
```
tox -a
```
### Run tests
```
tox
```
### Linting
```
tox -e lint
```
### Check types
```
tox -e typecheck
```

### Find security vulnerabilities, if any
```
tox -e secure
```

### Dev environment
Use this command to only apply lint fixes and style formatting.
```
tox -e dev
```

- After running these commands we should see all the tests passing and commands executing successfully, which means that we are ready to update and test the package.
- To create your own tox scripts, modify the `tox.ini` file in the respective module.

## VSCode users: Improved dev experience
If you use VSCode, we have prepared a pre-configured workspace that improves your dev experience. So when you open VScode, set up the workspace file `python-monorepo.code-workspace` by going to:

```
File -> Open Workspace from File...
```
![File -> Open Workspace from File](misc/VScode_OpenWorkspaceFromFile.png)

Each folder is now a project to VSCode. This action does not change the underlying code, but facilitates the development process. So our file directory should look like this now:

![all modules have their respective folder, along with a root folder](misc/VScode_workspace.png)

> Note: You might have to do this step again next time you close and open VS code!

### Picking up the virtual environments automatically
We will need to create a `.vscode/settings.json` file in each module's folder, pointing to the in-project virtual environment created by the poetry.

- You can easily find the path to the virtual env by running following command in the package for which you want to find it for:
```
poetry shell
```python
from polywrap_core import Uri, ClientConfig
from polywrap_client import PolywrapClient
from polywrap_client_config_builder import PolywrapClientConfigBuilder
from polywrap_sys_config_bundle import sys_bundle
from polywrap_web3_config_bundle import web3_bundle
```

- Once you get the path virtual env, you need to create the following `settings.json` file under the `.vscode/` folder of the given package. For example, in case of `polywrap-client` package, it would be under
`./polywrap-client/.vscode/settings.json`


Here's the structure `settings.json` file we are using for configuring the vscode. Make sure you update your virtual env path you got from poetry as the `python.defaultInterpreterPath` argument:
```json
{
"python.formatting.provider": "black",
"python.languageServer": "Pylance",
"python.analysis.typeCheckingMode": "strict",
"python.defaultInterpreterPath": "/Users/polywrap/Library/Caches/pypoetry/virtualenvs/polywrap-client-abcdef-py3.10"
}
### Configure and Instantiate the client
```python
builder = (
PolywrapClientConfigBuilder()
.add_bundle(sys_bundle)
.add_bundle(web3_bundle)
)
config = builder.build()
client = PolywrapClient(config)
```

Keep in mind that these venv paths will vary for each module you run `poetry shell` on. Once you configure these `setting.json` files correctly on each module you should be good to go!


# What WASM wrappers can you execute today?

Check these resources to browse a variety available wrappers, for DeFi, decentralised storage, and other development utilites:

- [Wrappers.io](https://wrappers.io/)
- [Polywrap Integrations Repository](https://github.com/polywrap/integrations)

# Example call

Calling a function of a wrapper from the python client is as simple as creating a file in the `TODO (?polywrap-client)` directory, importing the `PolywrapClient`, calling the `Uri` where the WASM wrapper is hosted, and specifying any required `arguments`.

Here is an example which takes in a message as a string and returns it.
### Invoke a wrapper

```python
# hello_world.py
from polywrap_client import PolywrapClient
from polywrap_core import Uri, InvokerOptions

async def echo_message(message: str):

# Instantiate the client
client = PolywrapClient()

# Load the WebAssembly wrapper through a URI that points to local file system
uri = Uri('wrap://ens/rinkeby/helloworld.dev.polywrap.eth')

args = {"arg": message }

# Configure the client
options = InvokerOptions(
uri=uri, method="simpleMethod", args=args, encode_result=False
)

# Invoke the wrapper
result = await client.invoke(options)

return result.result

if __name__ == "__main__":
return echo_message('hello polywrap!')
uri = Uri.from_str(
'wrapscan.io/polywrap/ipfs-http-client'
)
args = {
"cid": "QmZ4d7KWCtH3xfWFwcdRXEkjZJdYNwonrCwUckGF1gRAH9",
"ipfsProvider": "https://ipfs.io",
}
result = client.invoke(uri=uri, method="cat", args=args, encode_result=False)
assert result.startswith(b"<svg")
```

## Working Features

## Creating your own tests for the client
[Here](https://github.com/polywrap/client-test-harness) you can see which features have been implemented on each language client, and make the decision of which one to use for your project.

By creating tests you can quickly experiment with the Polywrap Client and its growing set of wrappers. Since Pytest is already set up on the repo, go to the `polywrap-client\tests\` directory, and take a look at how some of the functions are built. You can use similar patterns to mod your own apps and build new prototypes with more complex functionality.
## Feedback & Contributions
Bugs and feature requests can be made via [GitHub issues](https://github.com/polywrap/python-client/issues). Be aware that these issues are not private, so take care when providing output to make sure you are not disclosing any personal informations.

Here's a good guide to learn about [building tests with Pytest](https://realpython.com/pytest-python-testing/)
[Pull requests](https://github.com/polywrap/python-client/pulls) are also welcome via git.

# Contributing

The Polywrap project is completely open-source and we welcome contributors of all levels. Learn more about how you can contribute [here](https://github.com/polywrap/toolchain#contributing).
New contributors should read the [contributor guide](./CONTRIBUTING.md) to get started.
Folk who already have experience contributing to open source projects may not need the full guide but should still use the pull request checklist to make things easy for everyone.
Polywrap Python Client contributors are asked to adhere to the [Python Community Code of Conduct](https://www.python.org/psf/conduct/).

# Contact Us:

[Join our discord](https://discord.polywrap.io) and ask your questions right away!


# Resources

- [Polywrap Documentation](https://docs.polywrap.io)
- [Polywrap Integrations Repository](https://github.com/polywrap/integrations)
- [Running operations concurrently with python's asyncio](https://realpython.com/async-io-python/#the-10000-foot-view-of-async-io)
- [Intro Video](TODO)
- [Python Client Documentation](https://polywrap-client.rtfd.io)
- [Client Readiness](https://github.com/polywrap/client-readiness)
- [Discover Wrappers](https://wrapscan.io)
- [Polywrap Discord](https://discord.polywrap.io)
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.1.0b4
0.1.0b5
2 changes: 1 addition & 1 deletion packages/config-bundles/polywrap-sys-config-bundle/VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.1.0b4
0.1.0b5
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.1.0b4
0.1.0b5
2 changes: 1 addition & 1 deletion packages/plugins/polywrap-ethereum-provider/VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.1.0b4
0.1.0b5
2 changes: 1 addition & 1 deletion packages/plugins/polywrap-fs-plugin/VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.1.0b4
0.1.0b5
2 changes: 1 addition & 1 deletion packages/plugins/polywrap-http-plugin/VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.1.0b4
0.1.0b5
2 changes: 1 addition & 1 deletion packages/polywrap-client-config-builder/VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.1.0b4
0.1.0b5
2 changes: 1 addition & 1 deletion packages/polywrap-client/VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.1.0b4
0.1.0b5
2 changes: 1 addition & 1 deletion packages/polywrap-core/VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.1.0b4
0.1.0b5
2 changes: 1 addition & 1 deletion packages/polywrap-manifest/VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.1.0b4
0.1.0b5
2 changes: 1 addition & 1 deletion packages/polywrap-msgpack/VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.1.0b4
0.1.0b5
2 changes: 1 addition & 1 deletion packages/polywrap-plugin/VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.1.0b4
0.1.0b5
2 changes: 1 addition & 1 deletion packages/polywrap-test-cases/VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.1.0b4
0.1.0b5
2 changes: 1 addition & 1 deletion packages/polywrap-uri-resolvers/VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.1.0b4
0.1.0b5
2 changes: 1 addition & 1 deletion packages/polywrap-wasm/VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.1.0b4
0.1.0b5
2 changes: 1 addition & 1 deletion scripts/publish_packages.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ def publish_package(package: str, version: str) -> None:
subprocess.check_call(["yarn", "codegen"])

# Generate the README.rst file
subprocess.check_call(["poetry", "run", "python3", "scripts/generate_readme.py"])
subprocess.check_call(["poetry", "run", "python3", "scripts/extract_readme.py"])

try:
subprocess.check_call(["poetry", "publish", "--build", "--username", "__token__", "--password", os.environ["POLYWRAP_BUILD_BOT_PYPI_PAT"]])
Expand Down