Skip to content

Commit af13a51

Browse files
chestm007charlta
andauthored
[DEV-7574] Generate GraphQL client (#58)
Signed-off-by: Max Chesterfield <max.chesterfield@zepben.com> Signed-off-by: Anthony Charlton <anthony.charlton@zepben.com> Co-authored-by: Anthony Charlton <anthony.charlton@zepben.com>
1 parent 07d5dbe commit af13a51

38 files changed

+7275
-3479
lines changed

README.md

Lines changed: 139 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,59 @@
11
# Evolve App Server Python Client #
22

3-
This library provides a wrapper to the Evolve App Server's API, allowing users of the evolve SDK to authenticate with
3+
This library provides a wrapper to the Evolve App Server's API, allowing users of the Evolve SDK to authenticate with
44
the Evolve App Server and upload studies.
55

66
# Usage #
77

88
```python
99
from geojson import FeatureCollection
10-
from zepben.eas import EasClient, Study, Result, Section, GeoJsonOverlay
10+
from zepben.eas import EasClient, StudyInput, StudyResultInput, GeoJsonOverlayInput, ResultSectionInput, SectionType, Mutation
1111

1212
eas_client = EasClient(
1313
host="<host>",
1414
port=1234,
1515
access_token="<access_token>",
16-
client_id="<client_id>",
17-
username="<username>",
18-
password="<password>",
19-
client_secret="<client_secret>"
16+
asynchronous=False,
2017
)
2118

22-
eas_client.upload_study(
23-
Study(
24-
name="<study name>",
25-
description="<study description>",
26-
tags=["<tag>", "<tag2>"],
27-
results=[
28-
Result(
29-
name="<result_name>",
30-
geo_json_overlay=GeoJsonOverlay(
31-
data=FeatureCollection( ... ),
32-
styles=["style1"]
33-
),
34-
sections=Section(
35-
type="TABLE",
36-
name="<table name>",
37-
description = "<table description>",
38-
columns=[
39-
{ "key": "<column 1 key>", "name": "<column 1 name>" },
40-
{ "key": "<column 2 key>", "name": "<column 2 name>" },
41-
],
42-
data=[
43-
{ "<column 1 key>": "<column 1 row 1 value>", "<column 2 key>": "<column 2 row 1 value>" },
44-
{ "<column 1 key>": "<column 1 row 2 value>", "<column 2 key>": "<column 2 row 2 value>" }
45-
]
46-
)
19+
eas_client.mutation(
20+
Mutation.add_studies(
21+
[
22+
StudyInput(
23+
name="<study name>",
24+
description="<study description>",
25+
tags=["<tag>", "<tag2>"],
26+
results=[
27+
StudyResultInput(
28+
name="<result_name>",
29+
geoJsonOverlay=GeoJsonOverlayInput(
30+
data=FeatureCollection(...),
31+
styles=["style1"]
32+
),
33+
sections=[
34+
ResultSectionInput(
35+
type=SectionType.TABLE,
36+
name="<table name>",
37+
description="<table description>",
38+
columns=[
39+
{"key": "<column 1 key>", "name": "<column 1 name>"},
40+
{"key": "<column 2 key>", "name": "<column 2 name>"},
41+
],
42+
data=[
43+
{"<column 1 key>": "<column 1 row 1 value>", "<column 2 key>": "<column 2 row 1 value>"},
44+
{"<column 1 key>": "<column 1 row 2 value>", "<column 2 key>": "<column 2 row 2 value>"}
45+
]
46+
)
47+
]
48+
)
49+
],
50+
styles=[
51+
{
52+
"id": "style1",
53+
# other Mapbox GL JS style properties
54+
}
55+
]
4756
)
48-
],
49-
styles=[
50-
{
51-
"id": "style1",
52-
# other Mapbox GL JS style properties
53-
}
5457
]
5558
)
5659
)
@@ -59,62 +62,119 @@ eas_client.close()
5962
```
6063

6164
## AsyncIO ##
62-
Asyncio is also supported using aiohttp. A session will be created for you when you create an EasClient if not provided via the `session` parameter to EasClient.
63-
64-
To use the asyncio API use `async_upload_study` like so:
65+
The EasClient can operate in async mode if specified, like so:
6566

6667
```python
6768
from aiohttp import ClientSession
6869
from geojson import FeatureCollection
69-
from zepben.eas import EasClient, Study, Result, Section, GeoJsonOverlay
70+
from zepben.eas import EasClient, StudyInput, StudyResultInput, GeoJsonOverlayInput, ResultSectionInput, SectionType, Mutation
71+
7072

7173
async def upload():
7274
eas_client = EasClient(
7375
host="<host>",
7476
port=1234,
7577
access_token="<access_token>",
76-
client_id="<client_id>",
77-
username="<username>",
78-
password="<password>",
79-
client_secret="<client_secret>",
80-
session=ClientSession(...)
78+
asynchronous=True, # returns all methods as plain async methods
8179
)
8280

83-
await eas_client.async_upload_study(
84-
Study(
85-
name="<study name>",
86-
description="<study description>",
87-
tags=["<tag>", "<tag2>"],
88-
results=[
89-
Result(
90-
name="<result_name>",
91-
geo_json_overlay=GeoJsonOverlay(
92-
data=FeatureCollection( ... ),
93-
styles=["style1"]
94-
),
95-
sections=Section(
96-
type="TABLE",
97-
name="<table name>",
98-
description = "<table description>",
99-
columns=[
100-
{ "key": "<column 1 key>", "name": "<column 1 name>" },
101-
{ "key": "<column 2 key>", "name": "<column 2 name>" },
102-
],
103-
data=[
104-
{ "<column 1 key>": "<column 1 row 1 value>", "<column 2 key>": "<column 2 row 1 value>" },
105-
{ "<column 1 key>": "<column 1 row 2 value>", "<column 2 key>": "<column 2 row 2 value>" }
106-
]
107-
)
81+
await eas_client.mutation(
82+
Mutation.add_studies(
83+
[
84+
StudyInput(
85+
name="<study name>",
86+
description="<study description>",
87+
tags=["<tag>", "<tag2>"],
88+
results=[
89+
StudyResultInput(
90+
name="<result_name>",
91+
geoJsonOverlay=GeoJsonOverlayInput(
92+
data=FeatureCollection(...),
93+
styles=["style1"]
94+
),
95+
sections=[
96+
ResultSectionInput(
97+
type=SectionType.TABLE,
98+
name="<table name>",
99+
description="<table description>",
100+
columns=[
101+
{"key": "<column 1 key>", "name": "<column 1 name>"},
102+
{"key": "<column 2 key>", "name": "<column 2 name>"},
103+
],
104+
data=[
105+
{"<column 1 key>": "<column 1 row 1 value>", "<column 2 key>": "<column 2 row 1 value>"},
106+
{"<column 1 key>": "<column 1 row 2 value>", "<column 2 key>": "<column 2 row 2 value>"}
107+
]
108+
)
109+
]
110+
)
111+
],
112+
styles=[
113+
{
114+
"id": "style1",
115+
# other Mapbox GL JS style properties
116+
}
117+
]
118+
)
119+
]
120+
)
121+
)
122+
123+
await eas_client.close()
124+
```
125+
126+
# I'm used to the old client, what do i do? #
127+
128+
## Migrating existing code ##
129+
130+
Most of the objects passed into requests are similar.
131+
The new EasClient is fully type hinted and self documenting.
132+
133+
For example.
134+
135+
```python
136+
from zepben.eas import EasClient, WorkPackageInput, HcExecutorConfigInput, FeederConfigsInput, FeederConfigInput
137+
138+
client = EasClient(host='host', port=1234)
139+
client.get_work_package_cost_estimation(
140+
WorkPackageInput(
141+
feederConfigs=FeederConfigsInput(
142+
configs=[
143+
FeederConfigInput(
144+
feeder='myFeeder',
145+
years=[2024, 2025],
146+
scenarios=['scenario1']
108147
)
109-
],
110-
styles=[
111-
{
112-
"id": "style1",
113-
# other Mapbox GL JS style properties
114-
}
115148
]
116149
)
117150
)
151+
)
152+
```
153+
154+
Hovering over any kwarg or looking at any class definition will show all possible parameters, and their expected types.
155+
156+
## Enabling legacy convenience methods ##
157+
158+
Legacy convenience methods can be enabled by passing `enable_legacy_methods` to `__init__` of `EasClient`. eg:
159+
160+
```python
161+
from zepben.eas import EasClient
162+
163+
client = EasClient(enable_legacy_methods=True)
164+
```
165+
166+
This will enable all `deprecated` and `opt_in` methods on the class, they are disabled by default.
167+
168+
# Development #
118169

119-
await eas_client.aclose()
120-
```
170+
To regenerate the graphql client you will need to install `zepben.eas` with `eas-codegen` optional dependencies:
171+
172+
```shell
173+
pip install -e ".[eas-codegen]"
174+
```
175+
176+
With these installed and EAS running locally on port 7654, you can then generate the client:
177+
178+
```shell
179+
ariadne-codegen
180+
```

changelog.md

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,33 @@
11
# EAS Python client
22
## [0.30.0] - UNRELEASED
33
### Breaking Changes
4-
* None.
4+
* Deprecated methods in EasClient:
5+
* aclose
6+
* get_work_package_cost_estimation
7+
* run_hosting_capacity_work_package
8+
* cancel_hosting_capacity_work_package
9+
* get_hosting_capacity_work_packages_progress
10+
* run_feeder_load_analysis_report
11+
* get_feeder_load_analysis_report_status
12+
* upload_study
13+
* run_ingestor
14+
* get_ingestor_run
15+
* get_ingestor_run_list
16+
* run_hosting_capacity_calibration
17+
* get_hosting_capacity_calibration_run
18+
* get_hosting_capacity_calibration_sets
19+
* get_transformer_tap_settings
20+
* run_opendss_export
21+
* get_paged_opendss_models
22+
* get_opendss_model
23+
* Most Input object will need to be migrated over to the new data model
524

625
### New Features
726
* None.
827

928
### Enhancements
10-
* None.
29+
* EasClient has new `query` and `mutation` methods that will accept `Query` and `Mutation` objects respectively.
30+
* Available queries and mutations can be found as `@classmethods` on `Queries` and `Mutations`.
1131

1232
### Fixes
1333
* None.

pyproject.toml

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright 2025 Zeppelin Bend Pty Ltd
1+
# Copyright 2026 Zeppelin Bend Pty Ltd
22
#
33
# This Source Code Form is subject to the terms of the Mozilla Public
44
# License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -7,14 +7,13 @@
77
[build-system]
88
requires = [
99
"setuptools",
10-
"wheel",
1110
"build>=1.2.0"
1211
]
1312
build-backend = "setuptools.build_meta"
1413

1514
[project]
1615
name = "zepben.eas"
17-
version = "0.30.0b1"
16+
version = "1.0.0b1"
1817
description = "Python SDK for interacting with the Evolve App Server"
1918
readme = {file = "README.md", content-type = "text/markdown"}
2019
license = "MPL-2.0"
@@ -25,10 +24,10 @@ authors = [
2524
]
2625
dependencies = [
2726
"geojson==2.5.0",
28-
"requests<3.0.0,>=2.26.0",
29-
"urllib3==2.5.0",
30-
"zepben.ewb==1.1.0",
31-
"aiohttp[speedups]==3.9.0",
27+
"httpx",
28+
"graphql-core==3.2.8",
29+
"pydantic",
30+
"pydantic_core",
3231
]
3332
classifiers = [
3433
"Programming Language :: Python :: 3",
@@ -50,6 +49,23 @@ test = [
5049
"pytest-httpserver==1.0.8",
5150
"trustme==0.9.0"
5251
]
52+
codegen = [
53+
"ariadne-codegen @ git+https://github.com/chestm007/ariadne-codegen" # This could break a pypi upload. Waiting on https://github.com/mirumee/ariadne-codegen/pull/413 to be merged.
54+
]
5355

5456
[tool.setuptools.packages.find]
5557
where = ["src/"]
58+
59+
[tool.ariadne-codegen]
60+
remote_schema_url = "http://127.0.0.1:7654/api/graphql" # Set to address of Evolve App Server
61+
enable_custom_operations=true
62+
include_comments=false
63+
target_package_path='src/zepben/eas/lib'
64+
target_package_name='generated_graphql_client'
65+
introspection_descriptions=true
66+
introspection_input_value_deprecations=true
67+
plugins=[
68+
"zepben.eas.lib.ariadne_plugins.custom_query_type_hinter.CustomQueryTypeHinterPlugin",
69+
"zepben.eas.lib.ariadne_plugins.missed_import_checker.MissedImportCheckerPlugin",
70+
"zepben.eas.lib.ariadne_plugins.gql_all_fields.GqlAllFieldsPlugin"
71+
]

src/zepben/eas/__init__.py

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,19 @@
1-
# Copyright 2020 Zeppelin Bend Pty Ltd
1+
# Copyright 2026 Zeppelin Bend Pty Ltd
22
#
33
# This Source Code Form is subject to the terms of the Mozilla Public
44
# License, v. 2.0. If a copy of the MPL was not distributed with this
55
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
66
#
7+
import warnings
78

89
from zepben.eas.client.eas_client import *
9-
from zepben.eas.client.feeder_load_analysis_input import *
10-
from zepben.eas.client.fla_forecast_config import *
11-
from zepben.eas.client.opendss import *
12-
from zepben.eas.client.study import *
13-
from zepben.eas.client.work_package import *
10+
11+
try:
12+
from zepben.eas.lib.generated_graphql_client import *
13+
from zepben.eas.lib.generated_graphql_client.custom_mutations import *
14+
from zepben.eas.lib.generated_graphql_client.custom_queries import *
15+
from zepben.eas.lib.generated_graphql_client.custom_fields import *
16+
except ImportError:
17+
warnings.warn(
18+
"Could not import `zepben.eas.lib.generated_graphql_client`. "
19+
)

src/zepben/eas/client/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright 2020 Zeppelin Bend Pty Ltd
1+
# Copyright 2026 Zeppelin Bend Pty Ltd
22
#
33
# This Source Code Form is subject to the terms of the Mozilla Public
44
# License, v. 2.0. If a copy of the MPL was not distributed with this

0 commit comments

Comments
 (0)