Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
5e03597
chore: vs code workspace config, include plugins and ccb, and reworki…
rihp Nov 16, 2022
f3df141
set up config and fix tests
rihp Nov 16, 2022
4bb2d6c
wip:workspase_renaming
rihp Nov 18, 2022
fae0f54
ClientConfigBuilder functionality and tests *(add envs, interfaces, r…
rihp Nov 18, 2022
76bf954
feat:implemented_add_envs, added tests for add_envs and set_envs toge…
rihp Nov 22, 2022
c27ff74
chore: refactoring abstract base classes to remove IClientConfigBuilder
rihp Nov 24, 2022
958caf9
readme
rihp Nov 24, 2022
002eecc
readme
rihp Nov 24, 2022
3957124
feat:packages property on CCB
rihp Nov 25, 2022
7a861be
feat: ccb generic add function and tests outline for configuring pack…
rihp Nov 25, 2022
2c2c61e
feat: packages refactor, added generic add function, plus a tests sui…
rihp Nov 24, 2022
7dd6a59
feat: set packages tests and functionality
rihp Nov 29, 2022
e833157
git rebase squashing commits
rihp Nov 29, 2022
e14a2ef
chore:creating fixtures for tests
rihp Nov 29, 2022
54ce58c
chore:creating fixtures for tests, cleanup
rihp Nov 29, 2022
572901c
feat:implement uri_redirects
rihp Nov 29, 2022
a339f54
feat: set_redirects, remove_redirects, add many redirects, plus their…
rihp Nov 29, 2022
921eb64
conftest
rihp Nov 29, 2022
a3601a8
chore: small test refactors, all linting fixes
rihp Nov 29, 2022
df0976d
Merge branch 'main' into feat/ccb_refactor
Niraj-Kamdar Nov 30, 2022
efe30ac
Merge branch 'main' into feat/ccb_refactor
Niraj-Kamdar Nov 30, 2022
4b725f3
chore: isort and cleanup
rihp Nov 30, 2022
32f17e8
Merge branch 'feat/ccb_refactor' of https://github.com/polywrap/pytho…
rihp Nov 30, 2022
5e5b011
Merge branch 'dev' into feat/ccb_refactor
Niraj-Kamdar Apr 1, 2023
07b0031
wip: client config builder
Niraj-Kamdar Apr 3, 2023
2274633
wip: client config builder
Niraj-Kamdar Apr 3, 2023
b20c6f1
feat: initial version of client-config-builder
Niraj-Kamdar Apr 3, 2023
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
14 changes: 14 additions & 0 deletions packages/polywrap-client-config-builder/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@

# Polywrap Python Client
## This object allows you to build proper Polywrapt ClientConfig objects

These objects are needed to configure your python client's wrappers, pluggins, env variables, resolvers and interfaces.

Look at [this file](./polywrap_client_config_builder/client_config_builder.py) to detail all of its functionality
And at [tests](./tests/test_client_config_builder.py)

---

The current implementation uses the `ClientConfig` as a dataclass to later create an Abstract Base Class of a `BaseClientConfigBuilder` which defines more clearly the functions of the module, like add_envs, set_resolvers, remove_wrappers, and so on.

This `BaseClientConfigBuilder` is later used in the class `ClientConfigBuilder` which only implements the build method, for now, and inherits all the abstract methods of the `BaseClientConfigBuilder`.
1,431 changes: 1,431 additions & 0 deletions packages/polywrap-client-config-builder/poetry.lock

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
"""This package contains modules related to client config builder."""

from .client_config_builder import *
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
"""This module provides a simple builder for building a ClientConfig object."""

from typing import Any, Dict, List, Optional, cast

from polywrap_core import (
ClientConfig,
Env,
Uri,
UriPackage,
UriPackageOrWrapper,
UriResolver,
UriWrapper,
WrapPackage,
Wrapper,
)
from polywrap_uri_resolvers import (
ExtendableUriResolver,
InMemoryWrapperCache,
PackageToWrapperResolver,
RecursiveResolver,
RequestSynchronizerResolver,
StaticResolver,
UriResolverAggregator,
WrapperCacheResolver,
)

from .types import BuilderConfig, BuildOptions


class ClientConfigBuilder:
"""Defines a simple builder for building a ClientConfig object.

The ClientConfigBuilder is used to create a ClientConfig object,\
which is used to configure the Polywrap Client and its sub-components.\
ClientConfigBuilder provides a simple interface for setting\
the redirects, wrappers, packages, and other configuration options\
for the Polywrap Client.
"""

def __init__(self):
"""Initialize the builder's config attributes with empty values."""
self.config = BuilderConfig(
envs={}, interfaces={}, resolvers=[], wrappers={}, packages={}, redirects={}
)

def build(self, options: Optional[BuildOptions] = None) -> ClientConfig:
"""Build the ClientConfig object from the builder's config."""
resolver = (
options.resolver
if options and options.resolver
else RecursiveResolver(
RequestSynchronizerResolver(
WrapperCacheResolver(
PackageToWrapperResolver(
UriResolverAggregator(
[
StaticResolver(self.config.redirects),
StaticResolver(self.config.wrappers),
StaticResolver(self.config.packages),
*self.config.resolvers,
ExtendableUriResolver(),
]
)
),
options.wrapper_cache
if options and options.wrapper_cache
else InMemoryWrapperCache(),
)
)
)
)

return ClientConfig(
envs=self.config.envs,
interfaces=self.config.interfaces,
resolver=resolver,
)

def add(self, config: BuilderConfig):
"""Add the values from the given config to the builder's config."""
if config.envs:
self.config.envs.update(config.envs)
if config.interfaces:
self.config.interfaces.update(config.interfaces)
if config.redirects:
self.config.redirects.update(config.redirects)
if config.resolvers:
self.config.resolvers.extend(config.resolvers)
if config.wrappers:
self.config.wrappers.update(config.wrappers)
if config.packages:
self.config.packages.update(config.packages)
return self

def get_envs(self) -> Dict[Uri, Dict[str, Any]]:
"""Return the envs from the builder's config."""
return self.config.envs

def set_env(self, uri: Uri, env: Env):
"""Set the env by uri in the builder's config, overiding any existing values."""
self.config.envs[uri] = env
return self

def set_envs(self, uri_envs: Dict[Uri, Env]):
"""Set the envs in the builder's config, overiding any existing values."""
self.config.envs.update(uri_envs)
return self

def add_env(self, uri: Uri, env: Env):
"""Add an env for the given uri.

If an Env is already associated with the uri, it is modified.
"""
if self.config.envs.get(uri):
for key in self.config.envs[uri]:
self.config.envs[uri][key] = env[key]
else:
self.config.envs[uri] = env
return self

def add_envs(self, uri_envs: Dict[Uri, Env]):
"""Add a list of envs to the builder's config."""
for uri, env in uri_envs.items():
self.add_env(uri, env)
return self

def add_interface_implementations(
self, interface_uri: Uri, implementations_uris: List[Uri]
):
"""Add a list of implementation URIs for the given interface URI to the builder's config."""
if interface_uri in self.config.interfaces.keys():
self.config.interfaces[interface_uri].extend(implementations_uris)
else:
self.config.interfaces[interface_uri] = implementations_uris
return self

def add_wrapper(self, uri: Uri, wrapper: Wrapper[UriPackageOrWrapper]):
"""Add a wrapper by its URI to the builder's config."""
self.config.wrappers[uri] = wrapper
return self

def add_wrappers(self, uri_wrappers: List[UriWrapper[UriPackageOrWrapper]]):
"""Add a list of URI-wrapper pairs to the builder's config."""
for uri_wrapper in uri_wrappers:
self.add_wrapper(cast(Uri, uri_wrapper), uri_wrapper.wrapper)
return self

def remove_wrapper(self, uri: Uri):
"""Remove a wrapper by its URI from the builder's config."""
del self.config.wrappers[uri]
return self

def remove_wrappers(self, uris: List[Uri]):
"""Remove a list of wrappers by its URIs."""
for uri in uris:
self.remove_wrapper(uri)
return self

def add_package(self, uri: Uri, package: WrapPackage[UriPackageOrWrapper]):
"""Add a package by its URI to the builder's config."""
self.config.packages[uri] = package
return self

def add_packages(self, uri_packages: List[UriPackage[UriPackageOrWrapper]]):
"""Add a list of URI-package pairs to the builder's config."""
for uri_package in uri_packages:
self.add_package(cast(Uri, uri_package), uri_package.package)
return self

def remove_package(self, uri: Uri):
"""Remove a package by its URI from the builder's config."""
del self.config.packages[uri]
return self

def remove_packages(self, uris: List[Uri]):
"""Remove a list of packages by its URIs from the builder's config."""
for uri in uris:
self.remove_package(uri)
return self

def add_resolver(self, resolver: UriResolver):
"""Add a resolver to the builder's config."""
self.config.resolvers.append(resolver)
return self

def add_resolvers(self, resolvers_list: List[UriResolver]):
"""Add a list of resolvers to the builder's config."""
for resolver in resolvers_list:
self.add_resolver(resolver)
return self

def add_redirect(self, from_uri: Uri, to_uri: Uri):
"""Add a URI redirect from `from_uri` to `to_uri`."""
self.config.redirects[from_uri] = to_uri
return self

def remove_redirect(self, from_uri: Uri):
"""Remove a URI redirect by `from_uri`."""
del self.config.redirects[from_uri]
return self

def add_redirects(self, redirects: Dict[Uri, Uri]):
"""Add a list of URI redirects to the builder's config."""
self.config.redirects.update(redirects)
return self
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
"""This package contains types related to client config builder."""
from .build_options import *
from .builder_config import *
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
"""This module contains the BuildOptions class."""
from dataclasses import dataclass
from typing import Optional

from polywrap_core import UriResolver
from polywrap_uri_resolvers import WrapperCache


@dataclass(slots=True, kw_only=True)
class BuildOptions:
"""
Abstract class used to configure the polywrap client before it executes a call.

The ClientConfig class is created and modified with the ClientConfigBuilder module.
"""

wrapper_cache: Optional[WrapperCache] = None
resolver: Optional[UriResolver] = None
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
"""This module contains the BuilderConfig class."""
from dataclasses import dataclass
from typing import Any, Dict, List

from polywrap_core import Uri, UriPackageOrWrapper, UriResolver, WrapPackage, Wrapper


@dataclass(slots=True, kw_only=True)
class BuilderConfig:
"""
Abstract class used to configure the polywrap client before it executes a call.

The ClientConfig class is created and modified with the ClientConfigBuilder module.
"""

envs: Dict[Uri, Dict[str, Any]]
interfaces: Dict[Uri, List[Uri]]
wrappers: Dict[Uri, Wrapper[UriPackageOrWrapper]]
packages: Dict[Uri, WrapPackage[UriPackageOrWrapper]]
resolvers: List[UriResolver]
redirects: Dict[Uri, Uri]
58 changes: 58 additions & 0 deletions packages/polywrap-client-config-builder/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"

[tool.poetry]
name = "polywrap-client-config-builder"
version = "0.1.0"
description = ""
authors = ["Media <media@polywrap.io>", "Cesar <cesar@polywrap.io>", "Niraj <niraj@polywrap.io>"]
readme = "README.md"

[tool.poetry.dependencies]
python = "^3.10"
polywrap-core = { path = "../polywrap-core", develop = true }

[tool.poetry.dev-dependencies]
polywrap-client = { path = "../polywrap-client", develop = true }
pytest = "^7.1.2"
pytest-asyncio = "^0.19.0"
pylint = "^2.15.4"
black = "^22.10.0"
bandit = { version = "^1.7.4", extras = ["toml"]}
tox = "^3.26.0"
tox-poetry = "^0.4.1"
isort = "^5.10.1"
pyright = "^1.1.275"
pydocstyle = "^6.1.1"

[tool.bandit]
exclude_dirs = ["tests"]

[tool.black]
target-version = ["py310"]

[tool.pyright]
# default

[tool.pytest.ini_options]
asyncio_mode = "auto"
testpaths = [
"tests"
]

[tool.pylint]
disable = [
"too-many-return-statements",
"too-many-public-methods",
]
ignore = [
"tests/"
]

[tool.isort]
profile = "black"
multi_line_output = 3

[tool.pydocstyle]
# default
38 changes: 38 additions & 0 deletions packages/polywrap-client-config-builder/tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
from polywrap_core import Uri
from pytest import fixture

# Variables

@fixture
def env_varA():
return { 'color': "yellow", 'size': "large" }

@fixture
def env_varB():
return { 'color': "red", 'size': "small" }

@fixture
def env_varN():
return { 'dog': "poodle", 'season': "summer" }

@fixture
def env_varM():
return { 'dog': "corgi", 'season': "autumn" }

@fixture
def env_varS():
return { 'vehicle': "scooter"}

# Uris

@fixture
def env_uriX():
return Uri.from_str("wrap://ens/eth.plugin.one/X")

@fixture
def env_uriY():
return Uri.from_str("wrap://ipfs/filecoin.wrapper.two/Y")

@fixture
def env_uriZ():
return Uri.from_str("wrap://pinlist/dev.wrappers.io/Z")
Loading