Metadata-Version: 2.1
Name: houston-client
Version: 1.2.dev0
Summary: Houston Python Client
Author-email: James Watkinson <info@datasparq.ai>, Matt Simmons <info@datasparq.ai>
License: MIT License
        
        Copyright (c) 2020, 2021, 2022 Datasparq
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
        
Project-URL: Homepage, https://github.com/datasparq-intelligent-products/houston-python
Keywords: houston
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Operating System :: OS Independent
Requires-Python: >=3.7
Description-Content-Type: text/markdown
Provides-Extra: gcp
Provides-Extra: azure
License-File: LICENSE

# Houston

![PyPI](https://img.shields.io/pypi/v/houston-client)

Houston Python Client Library (https://callhouston.io), links components to a simple workflow api.


## Installation

This client can be easily installed via pip:

```commandline
pip install houston-client
```

## Requirements

- Python >= 3.7


## Usage

Please read the documentation before getting started: https://callhouston.io/docs

Now ready, you'll need to initialise the Houston object with both an api_key and a mission 
(either the name if already saved or dict of new plan):

```python
from houston.client import Houston

houston = Houston(api_key="H...", plan="my-plan")
```

### Plan

A plan is the description of your workflow, to set a new plan please load the json to a dict. 
This can now be easily saved:


```python
from houston.client import Houston

houston = Houston(api_key="H...", plan=dict(name="my-plan", stages=[]))
houston.save_plan()
```

To return the plan in dictionary format, enter the plan name as a string:

```python
from houston.client import Houston

houston = Houston(api_key="H...", plan="my-plan")
houston.get_plan()
```

To remove the plan from Houston:
Note: Extra parameter [safe] available to ignore any invalid responses e.g. 400 - plan does not exist
      True, ignores any errors | False (default), raises any invalid responses 
      
```python
from houston.client import Houston

houston = Houston(api_key="H...", plan="my-plan")
houston.delete_plan(safe=True)
```

### Mission

A mission is an instance of a plan, a workflow. To start a mission, first use the methods create_mission to get a 
mission UUID.

```python
from houston.client import Houston

houston = Houston(api_key="H...", plan="my-plan")
mission_id = houston.create_mission()
```

### Stage

Once a mission has been created, the client can be used to modify a state's status and progress through the workflow. 
Start / end stage return the JSON response from the api as a dict for downstream use. 

Response keys include: 

- next: list, of downstream stages available to be started
- complete: boolean, True if mission is complete
- params: dict, contains key / value parameters if stage starting or stage names as keys and params as values if ending

Example of stage starting & ending:

```python
from houston.client import Houston

houston = Houston(api_key="H...", plan="test-plan")
mission_id = houston.create_mission()
houston.start_stage("test-stage", mission_id=mission_id)

# Note: only current task parameters returned as dict
stage_parameters = houston.get_params("test-stage")

# perform task, handle errors

houston_end_response = houston.end_stage("test-stage", mission_id=mission_id)

# Note: all available downstream task parameters returned as dict, keys are names of stages, values are dict of params 
next_task_parameters = houston_end_response["params"]["next-task"]

```

## Plugins

Plugins allow for Houston to easily integrate with external tools

### Google Cloud Pub/Sub

[Google Cloud Pub/Sub Documentation](https://cloud.google.com/pubsub/docs/overview)

Google Cloud Pub/Sub plugin publishes Houston responses to Topics, using Pub/Sub as a message bus between subscribing 
services.

To use this plugin, each stage must have a parameter named "topic" which defines the Pub/Sub Topic the stage service is 
listening to. 

Note: stage parameters must NOT include protected keys: "topic" & "data"

Before this plugin can be used, you must first create a Pub/Sub Topic and a Subscribing service which carries out your 
stage operations. When complete - the function `pubsub_trigger` can be used to easily trigger downstream 
stages via Pub/Sub. For example:

```python
# import GCP Houston plugin
from houston.plugin.gcp import GCPHouston

houston = GCPHouston(api_key="H...", plan="test-plan")
mission_id = houston.create_mission()
houston.start_stage("test-stage", mission_id=mission_id)

# get stage parameters
houston.get_params("test-stage")

# (perform task, handle errors)

response = houston.end_stage("test-stage", mission_id=mission_id)
for stage in response['next']:
    houston.pubsub_trigger({"stage": stage, "mission_id": mission_id})
```

#### Message Body

The message body (base64 encoded) contains a JSON object of the key stage information:

```json
{"stage":  "name of stage",
 "mission_id":  "id of current mission",
 "plan":  "name of plan"}
```

For convenience, a method "extract_stage_information" is provided in the plugin to decode the message body: 

```python
from houston.plugin.gcp import GCPHouston

def main(event, context):
    """Triggered from a message on a Cloud Pub/Sub topic. Calls Houston to start stage named in event payload, executes
    task function, calls Houston to finish stage.

    :param dict event: Event payload - expected to contain Houston 'stage' and 'mission_id'.
    :param google.cloud.functions.Context context: Metadata for the event.
    """
    houston = GCPHouston(api_key="H...", plan="test-plan")
    houston.extract_stage_information(event["data"])
```
