Skip to content

Commit

Permalink
feat(config): set environment by parameter and envar (#87)
Browse files Browse the repository at this point in the history
* feat(config): set environment by parameter and envar

* fix(static-analysis): solve mypy warnings
  • Loading branch information
acostapazo authored Sep 6, 2023
1 parent 216e976 commit 3a53674
Show file tree
Hide file tree
Showing 20 changed files with 113 additions and 38 deletions.
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

0 comments on commit 3a53674

Please sign in to comment.