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

Local dev stubs #1

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
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
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -133,5 +133,4 @@ dmypy.json

.DS_Store
.idea
.vscode

43 changes: 43 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Python Debugger: Current File",
"type": "debugpy",
"request": "launch",
"program": "${file}",
"console": "integratedTerminal"
},
{
"name": "stage: register",
"type": "debugpy",
"request": "launch",
"program": "${workspaceFolder}/app/register.py",
"console": "integratedTerminal",
"cwd": "${workspaceFolder}",
"args": [
"--slug", "ebird", "--service-url", "https://tempuri.org"
],
"env":{
"PYTHONPATH":"${workspaceFolder}"
},
"envFile": "${workspaceFolder}/.env.stage"
},
{
"name": "Run handler",
"type": "debugpy",
"request": "launch",
"program": "${workspaceFolder}/handler_test_configuration.py",
"console": "integratedTerminal",
"cwd": "${workspaceFolder}",
"env":{
"PYTHONPATH":"${workspaceFolder}"
},
"envFile": "${workspaceFolder}/.env.stage"
},

]
}
16 changes: 16 additions & 0 deletions app/actions/configurations.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import pydantic
from .core import PullActionConfiguration, AuthActionConfiguration, ExecutableActionMixin

class AuthenticateConfig(AuthActionConfiguration, ExecutableActionMixin):
username: str
password: pydantic.SecretStr = pydantic.Field(...,
format="password",
title="Password",
description="Password for an eBird account.")

class PullEventsConfig(PullActionConfiguration):

some_important_value: float = pydantic.Field(0.0,
title="Some Important Value",
description="This is a value of great importance."
)
3 changes: 3 additions & 0 deletions app/actions/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ class PullActionConfiguration(ActionConfiguration):
pass


class ExecutableActionMixin:
pass

class PushActionConfiguration(ActionConfiguration):
pass

Expand Down
92 changes: 92 additions & 0 deletions app/actions/handlers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import asyncio
import httpx
import logging
import random
import app.settings

from datetime import timezone, timedelta, datetime

from app.actions.configurations import AuthenticateConfig, PullEventsConfig
from app.services.activity_logger import activity_logger
from app.services.gundi import send_events_to_gundi
from app.services.state import IntegrationStateManager
from app.services.errors import ConfigurationNotFound
from app.services.utils import find_config_for_action
from gundi_core.schemas.v2 import Integration


logger = logging.getLogger(__name__)
state_manager = IntegrationStateManager()


async def handle_transformed_data(transformed_data, integration_id, action_id):
try:
response = await send_events_to_gundi(
events=transformed_data,
integration_id=integration_id
)
except httpx.HTTPError as e:
msg = f'Sensors API returned error for integration_id: {integration_id}. Exception: {e}'
logger.exception(
msg,
extra={
'needs_attention': True,
'integration_id': integration_id,
'action_id': action_id
}
)
return [msg]
else:
return response



async def action_auth(integration, action_config: AuthenticateConfig):

logger.info(f"Executing auth action with integration {integration} and action_config {action_config}...")
return {"valid_credentials": action_config.username is not None and action_config.password is not None}


def get_auth_config(integration):
# Look for the login credentials, needed for any action
auth_config = find_config_for_action(
configurations=integration.configurations,
action_id="auth"
)
if not auth_config:
raise ConfigurationNotFound(
f"Authentication settings for integration {str(integration.id)} "
f"are missing. Please fix the integration setup in the portal."
)
return AuthenticateConfig.parse_obj(auth_config.data)


@activity_logger()
async def action_pull_events(integration:Integration, action_config: PullEventsConfig):

logger.info(f"Executing 'pull_events' action with integration {integration} and action_config {action_config}...")

auth_config = get_auth_config(integration)

logger.info(f'Fetching data for {auth_config.username}.')


sample_event = {
"title": "A dummy event",
"event_type": "sit_rep",
"recorded_at": datetime.now(tz=timezone.utc).isoformat(),
"location": {
"lat": -51.688645,
"lon": -72.704421
},
"event_details": {
"sitrep_currentactivity": "Creating an eBird integration."
}
}
transformed_data = [sample_event]

response = await send_events_to_gundi(
events=transformed_data,
integration_id=str(integration.id))

return {'result': {'events_extracted': 0}}
1 change: 1 addition & 0 deletions app/settings/integration.py
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
# Add your integration-specific settings here
INTEGRATION_TYPE_SLUG="ebird"
107 changes: 107 additions & 0 deletions handler_test_configuration.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import asyncio

# ---------- remove this ------------
from gundi_core.schemas.v2 import (
Integration,
IntegrationAction,
IntegrationType,
UUID,
IntegrationActionConfiguration,
IntegrationActionSummary,
ConnectionRoute,
Organization,
)
from app.actions.handlers import action_pull_events
from app.actions.configurations import PullEventsConfig

if __name__ == "__main__":
action_config = PullEventsConfig(some_important_value=42.0)

integration = Integration(
id=UUID("e9c1eef0-7c28-46bb-8155-fe9b31dedce7"),
name="Test eBird Connection",
type=IntegrationType(
id=UUID("cd401782-cf42-4c38-90c9-8248536139af"),
name="eBird",
value="ebird",
description="A type for eBird connections",
actions=[
IntegrationAction(
id=UUID("e0d2b2de-a277-4f67-89ef-13ef0e07623d"),
type="auth",
name="Auth",
value="auth",
description="",
action_schema={
"type": "object",
"title": "AuthenticateConfig",
"required": ["username", "password"],
"properties": {
"email": {"type": "string", "title": "Email"},
"password": {"type": "string", "title": "Password", "format": "password"},
},
},
),
IntegrationAction(
id=UUID("1306da74-7e87-45a0-a5de-c11974e4e63e"),
type="pull",
name="Pull Events",
value="pull_events",
description="eBird pull events action",
action_schema={
"type": "object",
"title": "PullEventsConfig",
"required": ["some_important_value"],
"properties": {
"some_important_value": {
"type": "number",
"title": "Some important value",
"default": 0.0,
"maximum": 50.0,
"minimum": 0.0,
"description": "Some value of great importance.",
},
},
},
),
],
webhook=None,
),
base_url="https://api.ebird.org",
enabled=True,
owner=Organization(
id=UUID("b56b585d-7f94-4a45-b8af-bb7dc6a9c731"),
name="EarthRanger Developers",
description="",
),
configurations=[
IntegrationActionConfiguration(
id=UUID("7c0cbf42-ad62-4725-8380-e4cf29acc406"),
integration=UUID("e9c1eef0-7c28-46bb-8155-fe9b31dedce7"),
action=IntegrationActionSummary(
id=UUID("1306da74-7e87-45a0-a5de-c11974e4e63e"),
type="pull",
name="Pull Events",
value="pull_events",
),
data={
"some_important_value": 7.0,
},
),
IntegrationActionConfiguration(
id=UUID("91930701-0cf3-4201-a4a5-02b458c460e1"),
integration=UUID("e9c1eef0-7c28-46bb-8155-fe9b31dedce7"),
action=IntegrationActionSummary(
id=UUID("e0d2b2de-a277-4f67-89ef-13ef0e07623d"),
type="auth",
name="Auth",
value="auth",
),
data={
"username": "[email protected]",
"password": "something-fancy"
},
),
],
)
asyncio.run(action_pull_events(integration=integration, action_config=action_config))