Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(config): set environment by parameter and envar #87

Merged
merged 3 commits into from
Sep 6, 2023
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
25 changes: 25 additions & 0 deletions .mypy.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
[mypy]
disable_error_code = type-abstract
plugins = pydantic.mypy

# --strict
disallow_any_generics = true
disallow_subclassing_any = true
disallow_untyped_calls = true
disallow_untyped_defs = true
disallow_incomplete_defs = true
check_untyped_defs = true
disallow_untyped_decorators = true
no_implicit_optional = true
warn_redundant_casts = true
warn_unused_ignores = true
warn_return_any = true
implicit_reexport = false
strict_equality = true

# --strict end

[pydantic-mypy]
init_forbid_extra = True
init_typed = True
warn_required_dynamic_aliases = True
17 changes: 15 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,25 @@ pip install alice-onboarding

Configure your credentials with *Config* class

```
```python
from alice import Config

config = Config(api_key=given_valid_api_key)
config = Config(api_key="<YOUR-API-KEY>")
```

By default, this configure the `production` environment, if you
want to use the `sandbox` environment, you have two options:

* Add `environment` parameter on `Config`
```python
from alice import Config, Environment

config = Config(api_key="<YOUR-API-KEY>", environment=Environment.SANDBOX)
```
* Or, just export the `ALICE_ENVIRONMENT` environment variable
```console
export ALICE_ENVIRONMENT=sandbox
```

#### Onboarding

Expand Down
2 changes: 1 addition & 1 deletion alice/auth/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ def from_config(config: Config) -> "Auth":
return Auth(
api_key=config.api_key, # type: ignore
session=session,
url=config.onboarding_url,
url=config.onboarding_url, # type: ignore
timeout=config.timeout,
verbose=config.verbose,
)
Expand Down
1 change: 0 additions & 1 deletion alice/auth/auth_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ def __init__(
def create_user_token(
self, user_id: str, verbose: Optional[bool] = False
) -> Response:

print_intro("create_user_token", verbose=verbose)

token = self._cached_user_token_stack.get(user_id)
Expand Down
2 changes: 0 additions & 2 deletions alice/auth/cached_token_stack.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,9 @@ def show(self) -> None:

@timeit
def _clear_expired_tokens(self) -> None:

num_data = len(self._data)

if num_data > 0:

latest_expired_token = None
for i, token in enumerate(reversed(list(self._data.values()))):
if not is_valid_token(token):
Expand Down
60 changes: 49 additions & 11 deletions alice/config.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,60 @@
from typing import Union

from pydantic import BaseModel, Field
from pydantic import Field, model_validator
from pydantic_settings import BaseSettings, SettingsConfigDict
from requests import Session

from alice.onboarding.enums.environment import Environment

class Config(BaseModel):
class Config:
arbitrary_types_allowed = True

onboarding_url: str = Field(default="https://apis.alicebiometrics.com/onboarding")
sandbox_url: str = Field(
default="https://apis.alicebiometrics.com/onboarding/sandbox"
)
class Config(BaseSettings):
model_config = SettingsConfigDict(arbitrary_types_allowed=True)

api_key: Union[str, None] = Field(default=None)
sandbox_token: Union[str, None] = Field(default=None)
environment: Union[Environment, None] = Field(
default=Environment.PRODUCTION, alias="ALICE_ENVIRONMENT"
)
verbose: bool = Field(default=False)
session: Union[Session, None] = Field(default=None)
timeout: Union[float, None] = Field(
default=None, description="Timeout for every request in seconds", ge=0, le=100
)
send_agent: bool = Field(default=True)
verbose: bool = Field(default=False)
session: Union[Session, None] = Field(default=None)
onboarding_url: Union[str, None] = Field(
default="https://apis.alicebiometrics.com/onboarding"
)
sandbox_url: Union[str, None] = Field(
default="https://apis.alicebiometrics.com/onboarding/sandbox",
description="This path is only used for trials",
)
sandbox_token: Union[str, None] = Field(
default=None, description="This token is only used for trials"
)

@model_validator(mode="after")
def validate_urls(self) -> "Config":
if self.environment is None:
if isinstance(self.onboarding_url, str):
if "sandbox" in self.onboarding_url:
self.environment = Environment.SANDBOX
elif "staging" in self.onboarding_url:
self.environment = Environment.STAGING
else:
if self.environment == Environment.PRODUCTION:
self.onboarding_url = "https://apis.alicebiometrics.com/onboarding"
self.sandbox_url = "https://apis.alicebiometrics.com/onboarding/sandbox"
elif self.environment == Environment.SANDBOX:
self.onboarding_url = (
"https://apis.sandbox.alicebiometrics.com/onboarding"
)
self.sandbox_url = (
"https://apis.sandbox.alicebiometrics.com/onboarding/sandbox"
)
elif self.environment == Environment.STAGING:
self.onboarding_url = (
"https://apis.staging.alicebiometrics.com/onboarding"
)
self.sandbox_url = (
"https://apis.staging.alicebiometrics.com/onboarding/sandbox"
)
return self
7 changes: 7 additions & 0 deletions alice/onboarding/enums/environment.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from enum import Enum


class Environment(Enum):
SANDBOX = "sandbox"
PRODUCTION = "production"
STAGING = "staging"
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from typing import Union

from pydantic import BaseModel, Field


Expand All @@ -6,9 +8,9 @@ class DocumentSideReportMeta(BaseModel):
It collects document side metadata
"""

template: str = Field(
template: Union[str, None] = Field(
default=None, description="Document version used to extract the info"
)
manual: bool = Field(
manual: Union[bool, None] = Field(
default=None, description="True if the capture was taken in manual mode"
)
3 changes: 1 addition & 2 deletions alice/onboarding/onboarding.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ def from_config(config: Config) -> "Onboarding":
session = Session()
return Onboarding(
auth=Auth.from_config(config),
url=config.onboarding_url,
url=config.onboarding_url, # type: ignore
timeout=config.timeout,
send_agent=config.send_agent,
verbose=config.verbose,
Expand Down Expand Up @@ -2027,7 +2027,6 @@ def request(
user_id: Union[str, None] = None,
verbose: bool = False,
) -> Result[bool, OnboardingError]:

response = self.onboarding_client.request(
func=func,
user_id=user_id,
Expand Down
1 change: 0 additions & 1 deletion alice/onboarding/onboarding_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -2342,7 +2342,6 @@ def request(
user_id: Union[str, None] = None,
verbose: bool = False,
) -> Result[Response, Error]:

print_intro("request", verbose=verbose)

token = self.auth.create_backend_token(user_id).unwrap_or_return()
Expand Down
3 changes: 3 additions & 0 deletions alice/public_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
"""Public API of Alice Onboarding Python SDK"""
from typing import List

from alice.onboarding.enums.environment import Environment

# Modules
from alice.webhooks.webhook import Webhook
from alice.webhooks.webhooks import Webhooks
Expand Down Expand Up @@ -61,6 +63,7 @@
"DocumentReport",
"SelfieReport",
"OtherTrustedDocumentReport",
"Environment",
]


Expand Down
2 changes: 1 addition & 1 deletion alice/sandbox/sandbox.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class Sandbox:
def from_config(config: Config) -> "Sandbox":
return Sandbox(
sandbox_token=config.sandbox_token, # type: ignore
url=config.sandbox_url,
url=config.sandbox_url, # type: ignore
verbose=config.verbose,
)

Expand Down
2 changes: 1 addition & 1 deletion alice/webhooks/webhooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def from_config(config: Config) -> "Webhooks":
session = Session()
return Webhooks(
auth=Auth.from_config(config),
url=config.onboarding_url,
url=config.onboarding_url, # type: ignore
send_agent=config.send_agent,
verbose=config.verbose,
session=session,
Expand Down
10 changes: 5 additions & 5 deletions requirements/dev-requirements.txt
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
black==22.10.0
flake8==5.0.4
isort[colors]==5.10.1
pre-commit==2.20.0
mypy==0.982
black==23.7.0
flake8==6.1.0
isort[colors]==5.12.0
pre-commit==3.3.3
mypy==1.4.1
pytest==7.2.0
pytest-cov==4.0.0
pytest-mock==3.10.0
Expand Down
1 change: 1 addition & 0 deletions requirements/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
pyjwt>=2.3.0,<3
pydantic>=1.8.2,<3
pydantic-settings<3
requests>=2.26.0,<3
meiga>=1.9.1,<2
4 changes: 0 additions & 4 deletions tests/test_integration_auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,31 +24,27 @@ def should_return_an_error_when_the_api_key_is_not_configured(self):
result.assert_failure(value_is_instance_of=AuthError)

def should_create_a_valid_backend_token(self, given_valid_api_key):

config = Config(api_key=given_valid_api_key)
auth = Auth.from_config(config)

result = auth.create_backend_token()
result.assert_success(value_is_instance_of=str)

def should_create_a_valid_backend_token_with_timeout(self, given_valid_api_key):

config = Config(api_key=given_valid_api_key, timeout=5)
auth = Auth.from_config(config)

result = auth.create_backend_token()
result.assert_success(value_is_instance_of=str)

def should_create_a_valid_backend_token_with_user(self, given_valid_api_key):

config = Config(api_key=given_valid_api_key)
auth = Auth.from_config(config)

result = auth.create_backend_token(user_id=self._get_user_id(config))
result.assert_success(value_is_instance_of=str)

def should_create_a_valid_user_token(self, given_valid_api_key):

config = Config(api_key=given_valid_api_key)
auth = Auth.from_config(config)

Expand Down
1 change: 0 additions & 1 deletion tests/test_integration_flows.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@

@pytest.mark.unit
def test_should_return_an_error_when_the_api_key_is_not_configured():

config = Config()
onboarding = Onboarding.from_config(config)

Expand Down
1 change: 0 additions & 1 deletion tests/test_integration_onboarding.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@

@pytest.mark.unit
def test_should_return_an_error_when_the_api_key_is_not_configured():

config = Config()
onboarding = Onboarding.from_config(config)

Expand Down
2 changes: 0 additions & 2 deletions tests/test_integration_sandbox.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

@pytest.mark.unit
def test_should_return_an_error_when_the_sandbox_token_is_not_configured():

config = Config()
sandbox = Sandbox.from_config(config)

Expand All @@ -19,7 +18,6 @@ def test_should_return_an_error_when_the_sandbox_token_is_not_configured():
def test_should_create_a_user_and_get_user_token_and_delete_it(
given_valid_sandbox_token, given_any_valid_mail
):

config = Config(sandbox_token=given_valid_sandbox_token)
sandbox = Sandbox.from_config(config)

Expand Down
1 change: 0 additions & 1 deletion tests/test_integration_webhooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@

@pytest.mark.unit
def test_should_return_an_error_when_the_api_key_is_not_configured():

config = Config()
webhooks_client = Webhooks.from_config(config)

Expand Down