canopy


Namecanopy JSON
Version 8.42 PyPI version JSON
download
home_pagehttps://github.com/canopysimulations/canopy-python/
SummaryPython Client for the Canopy Simulation API
upload_time2023-11-09 14:10:37
maintainer
docs_urlNone
authorJames Thurley
requires_python
licenseMIT
keywords canopy api canopy simulations canopy client
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # Installation

### Versioning

This library uses [SimVer](http://simver.org/) versioning, where a change in the major version number indicates a
breaking change and a change in the minor version number indicates a non-breaking change (such as an additional
feature or bug fix).

### Changelog

The changelog is available [here](CHANGELOG.md).

### Requirements.

This library has been tested on Python 3.6 and higher.

### pip install

```sh
pip install canopy
```

You may need to run `pip` with root permission: `sudo pip install canopy`.

From a Jupyter Notebook you can run `!pip install canopy`.

### Setuptools

Install via [Setuptools](http://pypi.python.org/pypi/setuptools).

```sh
python setup.py install --user
```
(or `sudo python setup.py install` to install the package for all users)

### Running Tests

Unit tests can be run with:
```
pytest canopy
```

Integration tests can be run with:
```
pytest integration_tests
```

To run the integration tests you'll need to ensure you have an environment variable called `CANOPY_PYTHON_INTEGRATION_TEST_CREDENTIALS`
containing the string `<client_id>|<client_secret>|<username>|<tenant_name>|<password>`.

# Getting Started

## Example Usage
See the [Canopy Python Examples](https://github.com/CanopySimulations/canopy-python-examples) repository for example usage.

## Introduction

This package is designed for customers of [Canopy Simulations](https://www.canopysimulations.com/) who would like
to access the Canopy API from Python, for example using Jupyter Notebooks.

Currently the library is split into two parts:

 - The client generated using the OpenAPI toolset is located in the "canopy/openapi" folder.
   We don't have a great deal of control over how this code looks, but it should give a fairly complete interface to the main API.

 - One folder up from that in the "canopy" folder we are adding helper functions which wrap common use cases in simple functions.
   You can also use these functions as a reference to using the OpenAPI generated code.

When using the library you generally start by creating a `canopy.Session` object. 
The session object manages authentication, and the caching of user settings.
Calling `session.authentication.authenticate()` before calling OpenAPI generated client functions ensures that you are
authenticated and that any expired access tokens are refreshed.
Our helper functions will handle calling `authenticate` before making any calls, so if you are only using our
helper functions you won't need to call it yourself.

The `session` should generally be created once per application. It will automatically dispose itself when the application
shuts down. Alternatively you can enclose it in an `async with` or a `with` block if you need to create multiple sessions,
as shown in the examples below. 

If you are using the OpenAPI generated code then you can pass the `session.async_client` or `session.sync_client` into the OpenAPI 
generated API client instance as the `api_client` parameter as shown below. Passing in `async_client` will cause it to use
`asyncio`, and you will need to `await` the calls. Passing in `sync_client` will cause the calls to complete synchronously.

Our helper functions all use `asyncio` for efficient parallelisation of downloads, and must therefore be awaited.

The following example shows how to create a session and request some output channels from a study using our helper function:

```python
import canopy
import asyncio

async with canopy.Session(client_id='<your_client_id>', username='<your_username>') as session:
    study_data = await canopy.load_study(session, '<study_id>', 'DynamicLap', ['sRun', 'vCar'])

    # Using the OpenAPI generated client directly:
    study_api = canopy.openapi.StudyApi(session.async_client)
    job_result = await study_api.study_get_study_job_metadata(
        session.authentication.tenant_id,
        '<study_id>',
        0)

    # Using asyncio.ensure_future() to enable us to perform multiple calls in parallel
    job_result_task = asyncio.ensure_future(study_api.study_get_study_job_metadata(
        session.authentication.tenant_id,
        '<study_id>',
        0))

    job_result_2 = await job_result_task

```

When running this code you will be prompted for your client secret and your password if 
it is the first time `session.authentication.authenticate()` has been called for this session instance. Alternatively
you can pass the client secret and password into the Session class (after fetching them from a secure location) to
avoid being prompted.

If you can't use `asyncio` and `async/await` you can instead instantiate the session object synchronously 
and use the `canopy.run` method when calling our async helper methods. 
You can pass `session.sync_client` into the OpenAPI client classes instead of `session.async_client` to make them 
return results synchronously.

```python
import canopy

with canopy.Session(client_id='<your_client_id>', username='<your_username>') as session:
    # Note we are using canopy.run(..) to force the async method to run synchronously.
    # This is a wrapper for asyncio.get_event_loop().run_until_complete(..).
    study_data = canopy.run(canopy.load_study(session, '<study_id>', 'DynamicLap', ['sRun', 'vCar']))

    # Using the OpenAPI generated client synchronously by passing in sync_client:
    study_api = canopy.openapi.StudyApi(session.sync_client)
    job_result = study_api.study_get_study_job_metadata(
        session.authentication.tenant_id,
        '<study_id>',
        0)

    # You can still run synchronous OpenAPI client methods asynchronously using threads if you need to:
    job_result_thread = study_api.study_get_study_job_metadata(
        session.authentication.tenant_id,
        '<study_id>',
        0,
        async_req=True)

    job_result_2 = job_result_thread.get()
```

## Proxy Servers

You can configure your proxy server by passing in a `proxy` argument to the `canopy.Session` object:
```python
async with canopy.Session(authentication_data, proxy=canopy.ProxyConfiguration('http://some.proxy.com', 'user', 'pass')) as session:
``` 

# Updating the OpenAPI Client

This needs to be tidied up, improved, and automated.

Additional options can be found here: https://openapi-generator.tech/docs/generators/openapi/
 - e.g. enumUnknownDefaultCase could be useful if the remaining exposed enums change in future. 

You can use the Dockerfile in this repository to create a docker image to generate the new API stubs:

```sh
docker image build -t canopy-python-gen:1 .
docker container run -i -t --mount type=bind,src='<path>/<to>/canopy/canopy-python',dst=/canopy/repo canopy-python-gen:1 /bin/bash
```

```sh
java -jar openapi-generator-cli.jar generate -g python-legacy -i https://api.canopysimulations.com/swagger/v1/swagger.json -o ./gen --package-name "canopy.openapi"
rm -r repo/canopy/openapi
rm -r repo/docs
cp -r gen/canopy/openapi repo/canopy
cp -r gen/docs repo
cp -r gen/README.md repo/OPENAPI_README.md
```

To regenerate the `asyncio` files execute:
```sh
rm -r gen
java -jar openapi-generator-cli.jar generate -g python-legacy -i https://api.canopysimulations.com/swagger/v1/swagger.json -o ./gen --package-name "canopy.openapi" --library asyncio
mv gen/canopy/openapi gen/canopy/openapi_asyncio
rm -r gen/canopy/openapi_asyncio/api
rm -r gen/canopy/openapi_asyncio/models
rm gen/canopy/openapi_asyncio/configuration.py
rm gen/canopy/openapi_asyncio/exceptions.py
sed -i 's/from canopy\.openapi import rest/from canopy.openapi_asyncio import rest/g' gen/canopy/openapi_asyncio/api_client.py
sed -i '/from canopy.*/d' gen/canopy/openapi_asyncio/__init__.py
sed -i '/# import /d' gen/canopy/openapi_asyncio/__init__.py
echo 'from canopy.openapi_asyncio.api_client import ApiClient' >> gen/canopy/openapi_asyncio/__init__.py
cp -r gen/canopy/openapi_asyncio repo/canopy
```

Note: The `openapi/configuration.py` file will need to be manually modified to add the default API host URL.
Note: The `openapi_asyncio/rest.py` file will need to be manually modified to support proxy servers after generation. 
Note: The `openapi_asyncio/client_api.py` and `openapi/client_api.py` files will need to be manually modified to 
support numpy array serialization after generation. 

## Documentation for OpenAPI Generated Client

OpenAPI generated documentation can be found [here](OPENAPI_README.md).
            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/canopysimulations/canopy-python/",
    "name": "canopy",
    "maintainer": "",
    "docs_url": null,
    "requires_python": "",
    "maintainer_email": "",
    "keywords": "Canopy API,Canopy Simulations,Canopy Client",
    "author": "James Thurley",
    "author_email": "james.thurley@canopysimulations.com",
    "download_url": "https://files.pythonhosted.org/packages/22/85/e456926a09d60252872ad1c318fd558d4b85d727ae8db6eec00087dfab97/canopy-8.42.tar.gz",
    "platform": null,
    "description": "# Installation\n\n### Versioning\n\nThis library uses [SimVer](http://simver.org/) versioning, where a change in the major version number indicates a\nbreaking change and a change in the minor version number indicates a non-breaking change (such as an additional\nfeature or bug fix).\n\n### Changelog\n\nThe changelog is available [here](CHANGELOG.md).\n\n### Requirements.\n\nThis library has been tested on Python 3.6 and higher.\n\n### pip install\n\n```sh\npip install canopy\n```\n\nYou may need to run `pip` with root permission: `sudo pip install canopy`.\n\nFrom a Jupyter Notebook you can run `!pip install canopy`.\n\n### Setuptools\n\nInstall via [Setuptools](http://pypi.python.org/pypi/setuptools).\n\n```sh\npython setup.py install --user\n```\n(or `sudo python setup.py install` to install the package for all users)\n\n### Running Tests\n\nUnit tests can be run with:\n```\npytest canopy\n```\n\nIntegration tests can be run with:\n```\npytest integration_tests\n```\n\nTo run the integration tests you'll need to ensure you have an environment variable called `CANOPY_PYTHON_INTEGRATION_TEST_CREDENTIALS`\ncontaining the string `<client_id>|<client_secret>|<username>|<tenant_name>|<password>`.\n\n# Getting Started\n\n## Example Usage\nSee the [Canopy Python Examples](https://github.com/CanopySimulations/canopy-python-examples) repository for example usage.\n\n## Introduction\n\nThis package is designed for customers of [Canopy Simulations](https://www.canopysimulations.com/) who would like\nto access the Canopy API from Python, for example using Jupyter Notebooks.\n\nCurrently the library is split into two parts:\n\n - The client generated using the OpenAPI toolset is located in the \"canopy/openapi\" folder.\n   We don't have a great deal of control over how this code looks, but it should give a fairly complete interface to the main API.\n\n - One folder up from that in the \"canopy\" folder we are adding helper functions which wrap common use cases in simple functions.\n   You can also use these functions as a reference to using the OpenAPI generated code.\n\nWhen using the library you generally start by creating a `canopy.Session` object. \nThe session object manages authentication, and the caching of user settings.\nCalling `session.authentication.authenticate()` before calling OpenAPI generated client functions ensures that you are\nauthenticated and that any expired access tokens are refreshed.\nOur helper functions will handle calling `authenticate` before making any calls, so if you are only using our\nhelper functions you won't need to call it yourself.\n\nThe `session` should generally be created once per application. It will automatically dispose itself when the application\nshuts down. Alternatively you can enclose it in an `async with` or a `with` block if you need to create multiple sessions,\nas shown in the examples below. \n\nIf you are using the OpenAPI generated code then you can pass the `session.async_client` or `session.sync_client` into the OpenAPI \ngenerated API client instance as the `api_client` parameter as shown below. Passing in `async_client` will cause it to use\n`asyncio`, and you will need to `await` the calls. Passing in `sync_client` will cause the calls to complete synchronously.\n\nOur helper functions all use `asyncio` for efficient parallelisation of downloads, and must therefore be awaited.\n\nThe following example shows how to create a session and request some output channels from a study using our helper function:\n\n```python\nimport canopy\nimport asyncio\n\nasync with canopy.Session(client_id='<your_client_id>', username='<your_username>') as session:\n    study_data = await canopy.load_study(session, '<study_id>', 'DynamicLap', ['sRun', 'vCar'])\n\n    # Using the OpenAPI generated client directly:\n    study_api = canopy.openapi.StudyApi(session.async_client)\n    job_result = await study_api.study_get_study_job_metadata(\n        session.authentication.tenant_id,\n        '<study_id>',\n        0)\n\n    # Using asyncio.ensure_future() to enable us to perform multiple calls in parallel\n    job_result_task = asyncio.ensure_future(study_api.study_get_study_job_metadata(\n        session.authentication.tenant_id,\n        '<study_id>',\n        0))\n\n    job_result_2 = await job_result_task\n\n```\n\nWhen running this code you will be prompted for your client secret and your password if \nit is the first time `session.authentication.authenticate()` has been called for this session instance. Alternatively\nyou can pass the client secret and password into the Session class (after fetching them from a secure location) to\navoid being prompted.\n\nIf you can't use `asyncio` and `async/await` you can instead instantiate the session object synchronously \nand use the `canopy.run` method when calling our async helper methods. \nYou can pass `session.sync_client` into the OpenAPI client classes instead of `session.async_client` to make them \nreturn results synchronously.\n\n```python\nimport canopy\n\nwith canopy.Session(client_id='<your_client_id>', username='<your_username>') as session:\n    # Note we are using canopy.run(..) to force the async method to run synchronously.\n    # This is a wrapper for asyncio.get_event_loop().run_until_complete(..).\n    study_data = canopy.run(canopy.load_study(session, '<study_id>', 'DynamicLap', ['sRun', 'vCar']))\n\n    # Using the OpenAPI generated client synchronously by passing in sync_client:\n    study_api = canopy.openapi.StudyApi(session.sync_client)\n    job_result = study_api.study_get_study_job_metadata(\n        session.authentication.tenant_id,\n        '<study_id>',\n        0)\n\n    # You can still run synchronous OpenAPI client methods asynchronously using threads if you need to:\n    job_result_thread = study_api.study_get_study_job_metadata(\n        session.authentication.tenant_id,\n        '<study_id>',\n        0,\n        async_req=True)\n\n    job_result_2 = job_result_thread.get()\n```\n\n## Proxy Servers\n\nYou can configure your proxy server by passing in a `proxy` argument to the `canopy.Session` object:\n```python\nasync with canopy.Session(authentication_data, proxy=canopy.ProxyConfiguration('http://some.proxy.com', 'user', 'pass')) as session:\n``` \n\n# Updating the OpenAPI Client\n\nThis needs to be tidied up, improved, and automated.\n\nAdditional options can be found here: https://openapi-generator.tech/docs/generators/openapi/\n - e.g. enumUnknownDefaultCase could be useful if the remaining exposed enums change in future. \n\nYou can use the Dockerfile in this repository to create a docker image to generate the new API stubs:\n\n```sh\ndocker image build -t canopy-python-gen:1 .\ndocker container run -i -t --mount type=bind,src='<path>/<to>/canopy/canopy-python',dst=/canopy/repo canopy-python-gen:1 /bin/bash\n```\n\n```sh\njava -jar openapi-generator-cli.jar generate -g python-legacy -i https://api.canopysimulations.com/swagger/v1/swagger.json -o ./gen --package-name \"canopy.openapi\"\nrm -r repo/canopy/openapi\nrm -r repo/docs\ncp -r gen/canopy/openapi repo/canopy\ncp -r gen/docs repo\ncp -r gen/README.md repo/OPENAPI_README.md\n```\n\nTo regenerate the `asyncio` files execute:\n```sh\nrm -r gen\njava -jar openapi-generator-cli.jar generate -g python-legacy -i https://api.canopysimulations.com/swagger/v1/swagger.json -o ./gen --package-name \"canopy.openapi\" --library asyncio\nmv gen/canopy/openapi gen/canopy/openapi_asyncio\nrm -r gen/canopy/openapi_asyncio/api\nrm -r gen/canopy/openapi_asyncio/models\nrm gen/canopy/openapi_asyncio/configuration.py\nrm gen/canopy/openapi_asyncio/exceptions.py\nsed -i 's/from canopy\\.openapi import rest/from canopy.openapi_asyncio import rest/g' gen/canopy/openapi_asyncio/api_client.py\nsed -i '/from canopy.*/d' gen/canopy/openapi_asyncio/__init__.py\nsed -i '/# import /d' gen/canopy/openapi_asyncio/__init__.py\necho 'from canopy.openapi_asyncio.api_client import ApiClient' >> gen/canopy/openapi_asyncio/__init__.py\ncp -r gen/canopy/openapi_asyncio repo/canopy\n```\n\nNote: The `openapi/configuration.py` file will need to be manually modified to add the default API host URL.\nNote: The `openapi_asyncio/rest.py` file will need to be manually modified to support proxy servers after generation. \nNote: The `openapi_asyncio/client_api.py` and `openapi/client_api.py` files will need to be manually modified to \nsupport numpy array serialization after generation. \n\n## Documentation for OpenAPI Generated Client\n\nOpenAPI generated documentation can be found [here](OPENAPI_README.md).",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "Python Client for the Canopy Simulation API",
    "version": "8.42",
    "project_urls": {
        "Homepage": "https://github.com/canopysimulations/canopy-python/"
    },
    "split_keywords": [
        "canopy api",
        "canopy simulations",
        "canopy client"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "2285e456926a09d60252872ad1c318fd558d4b85d727ae8db6eec00087dfab97",
                "md5": "35b9413f98d0189eba915af06fd57f84",
                "sha256": "0be1de23a243c7877a582e65cf7e07311771147f8b8fb806ccada09d4c70642b"
            },
            "downloads": -1,
            "filename": "canopy-8.42.tar.gz",
            "has_sig": false,
            "md5_digest": "35b9413f98d0189eba915af06fd57f84",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": null,
            "size": 166937,
            "upload_time": "2023-11-09T14:10:37",
            "upload_time_iso_8601": "2023-11-09T14:10:37.168032Z",
            "url": "https://files.pythonhosted.org/packages/22/85/e456926a09d60252872ad1c318fd558d4b85d727ae8db6eec00087dfab97/canopy-8.42.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2023-11-09 14:10:37",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "canopysimulations",
    "github_project": "canopy-python",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "requirements": [],
    "lcname": "canopy"
}
        
Elapsed time: 1.63222s