solcast-pv 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- solcast_pv-0.1.0/LICENSE +21 -0
- solcast_pv-0.1.0/PKG-INFO +246 -0
- solcast_pv-0.1.0/README.md +217 -0
- solcast_pv-0.1.0/pyproject.toml +149 -0
- solcast_pv-0.1.0/src/solcast_pv/__init__.py +20 -0
- solcast_pv-0.1.0/src/solcast_pv/exceptions.py +17 -0
- solcast_pv-0.1.0/src/solcast_pv/models.py +54 -0
- solcast_pv-0.1.0/src/solcast_pv/py.typed +0 -0
- solcast_pv-0.1.0/src/solcast_pv/solcast_pv.py +171 -0
solcast_pv-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Klaas Schoute
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: solcast-pv
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Asynchronous Python client for getting forecast data from Solcast
|
|
5
|
+
Home-page: https://github.com/klaasnicolaas/python-solcast-pv
|
|
6
|
+
License: MIT
|
|
7
|
+
Keywords: api,async,client,solcast,forecast,energy,solar
|
|
8
|
+
Author: Klaas Schoute
|
|
9
|
+
Author-email: hello@student-techlife.com
|
|
10
|
+
Maintainer: Klaas Schoute
|
|
11
|
+
Maintainer-email: hello@student-techlife.com
|
|
12
|
+
Requires-Python: >=3.11,<4.0
|
|
13
|
+
Classifier: Framework :: AsyncIO
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Natural Language :: English
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
21
|
+
Requires-Dist: aiohttp (>=3.0.0)
|
|
22
|
+
Requires-Dist: yarl (>=1.6.0)
|
|
23
|
+
Project-URL: Bug Tracker, https://github.com/klaasnicolaas/python-solcast-pv/issues
|
|
24
|
+
Project-URL: Changelog, https://github.com/klaasnicolaas/python-solcast-pv/releases
|
|
25
|
+
Project-URL: Documentation, https://github.com/klaasnicolaas/python-solcast-pv
|
|
26
|
+
Project-URL: Repository, https://github.com/klaasnicolaas/python-solcast-pv
|
|
27
|
+
Description-Content-Type: text/markdown
|
|
28
|
+
|
|
29
|
+
<!-- Banner -->
|
|
30
|
+

|
|
31
|
+
|
|
32
|
+
<!-- PROJECT SHIELDS -->
|
|
33
|
+
[![GitHub Release][releases-shield]][releases]
|
|
34
|
+
[![Python Versions][python-versions-shield]][pypi]
|
|
35
|
+
![Project Stage][project-stage-shield]
|
|
36
|
+
![Project Maintenance][maintenance-shield]
|
|
37
|
+
[![License][license-shield]](LICENSE)
|
|
38
|
+
|
|
39
|
+
[![GitHub Activity][commits-shield]][commits-url]
|
|
40
|
+
[![PyPi Downloads][downloads-shield]][downloads-url]
|
|
41
|
+
[![GitHub Last Commit][last-commit-shield]][commits-url]
|
|
42
|
+
[![Open in Dev Containers][devcontainer-shield]][devcontainer]
|
|
43
|
+
|
|
44
|
+
[![Build Status][build-shield]][build-url]
|
|
45
|
+
[![Typing Status][typing-shield]][typing-url]
|
|
46
|
+
[![Maintainability][maintainability-shield]][maintainability-url]
|
|
47
|
+
[![Code Coverage][codecov-shield]][codecov-url]
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
Asynchronous Python client for [Solcast][solcast].
|
|
51
|
+
|
|
52
|
+
## About
|
|
53
|
+
|
|
54
|
+
[Solcast][solcast] provides solar radiation and solar power forecasts, estimated and
|
|
55
|
+
historical data. This package allows you to get the data from the [API][solcast-api]
|
|
56
|
+
and use it in your own application.
|
|
57
|
+
|
|
58
|
+
> [!NOTE]
|
|
59
|
+
> This package is still in development and rooftop forecast is not yet implemented.
|
|
60
|
+
|
|
61
|
+
## Installation
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
pip install solcast-pv
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Datasets
|
|
68
|
+
|
|
69
|
+
- List of all your created rooftop sites linked to your account.
|
|
70
|
+
- Get rate limits for your account.
|
|
71
|
+
|
|
72
|
+
<details>
|
|
73
|
+
<summary>CLICK HERE! to see all datasets</summary>
|
|
74
|
+
|
|
75
|
+
### Rooftop Site
|
|
76
|
+
|
|
77
|
+
**Note**: _requesting the list of all your created rooftop sites linked to your account, will not affect your daily rate limit._
|
|
78
|
+
|
|
79
|
+
| Name | Type | Description |
|
|
80
|
+
| :--- | :--- | :---------- |
|
|
81
|
+
| `name` | `str` | The name of the rooftop site. |
|
|
82
|
+
| `resource_id` | `str` | The unique identifier of the rooftop site. |
|
|
83
|
+
| `install_date` | `datetime` | The installation date of your solar panels. |
|
|
84
|
+
| `capacity` | `float` | The capacity of the solar panels. |
|
|
85
|
+
| `capacity_dc` | `float` | The capacity of the solar panels in DC. |
|
|
86
|
+
| `azimuth` | `int` | The azimuth of the solar panels. |
|
|
87
|
+
| `tilt` | `int` | The tilt of the solar panels. |
|
|
88
|
+
| `loss_factor` | `float` | The loss factor of the solar panels. |
|
|
89
|
+
|
|
90
|
+
### Rate Limits
|
|
91
|
+
|
|
92
|
+
**Note**: _requesting the rate limits for your account will not affect your daily rate limit._
|
|
93
|
+
|
|
94
|
+
| Name | Type | Description |
|
|
95
|
+
| :--- | :--- | :---------- |
|
|
96
|
+
| `daily_limit` | `int` | The daily limit of API calls. |
|
|
97
|
+
| `remaining_daily` | `int` | The remaining daily limit of API calls. |
|
|
98
|
+
| `consumed_daily` | `int` | How many API calls you have consumed today. |
|
|
99
|
+
</details>
|
|
100
|
+
|
|
101
|
+
### Example
|
|
102
|
+
|
|
103
|
+
```python
|
|
104
|
+
import asyncio
|
|
105
|
+
|
|
106
|
+
from solcast_pv import Solcast, RooftopSite
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
async def main() -> None:
|
|
110
|
+
"""Show example on using this package."""
|
|
111
|
+
async with Solcast(token="API_KEY") as client:
|
|
112
|
+
rooftops: list[RooftopSite] = await client.get_rooftop_sites()
|
|
113
|
+
print(rooftops)
|
|
114
|
+
|
|
115
|
+
if __name__ == "__main__":
|
|
116
|
+
asyncio.run(main())
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
More examples can be found in the [examples folder](./examples/).
|
|
120
|
+
|
|
121
|
+
## Contributing
|
|
122
|
+
|
|
123
|
+
This is an active open-source project. We are always open to people who want to
|
|
124
|
+
use the code or contribute to it.
|
|
125
|
+
|
|
126
|
+
We've set up a separate document for our
|
|
127
|
+
[contribution guidelines](CONTRIBUTING.md).
|
|
128
|
+
|
|
129
|
+
Thank you for being involved! :heart_eyes:
|
|
130
|
+
|
|
131
|
+
## Setting up development environment
|
|
132
|
+
|
|
133
|
+
The simplest way to begin is by utilizing the [Dev Container][devcontainer]
|
|
134
|
+
feature of Visual Studio Code or by opening a CodeSpace directly on GitHub.
|
|
135
|
+
By clicking the button below you immediately start a Dev Container in Visual Studio Code.
|
|
136
|
+
|
|
137
|
+
[![Open in Dev Containers][devcontainer-shield]][devcontainer]
|
|
138
|
+
|
|
139
|
+
This Python project relies on [Poetry][poetry] as its dependency manager,
|
|
140
|
+
providing comprehensive management and control over project dependencies.
|
|
141
|
+
|
|
142
|
+
You need at least:
|
|
143
|
+
|
|
144
|
+
- Python 3.11+
|
|
145
|
+
- [Poetry][poetry-install]
|
|
146
|
+
|
|
147
|
+
Install all packages, including all development requirements:
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
poetry install
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
Poetry creates by default an virtual environment where it installs all
|
|
154
|
+
necessary pip packages, to enter or exit the venv run the following commands:
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
poetry shell
|
|
158
|
+
exit
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Setup the pre-commit check, you must run this inside the virtual environment:
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
pre-commit install
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
*Now you're all set to get started!*
|
|
168
|
+
|
|
169
|
+
As this repository uses the [pre-commit][pre-commit] framework, all changes
|
|
170
|
+
are linted and tested with each commit. You can run all checks and tests
|
|
171
|
+
manually, using the following command:
|
|
172
|
+
|
|
173
|
+
```bash
|
|
174
|
+
poetry run pre-commit run --all-files
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
To run just the Python tests:
|
|
178
|
+
|
|
179
|
+
```bash
|
|
180
|
+
poetry run pytest
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
To update the [syrupy](https://github.com/tophat/syrupy) snapshot tests:
|
|
184
|
+
|
|
185
|
+
```bash
|
|
186
|
+
poetry run pytest --snapshot-update
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
## License
|
|
190
|
+
|
|
191
|
+
MIT License
|
|
192
|
+
|
|
193
|
+
Copyright (c) 2024 Klaas Schoute
|
|
194
|
+
|
|
195
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
196
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
197
|
+
in the Software without restriction, including without limitation the rights
|
|
198
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
199
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
200
|
+
furnished to do so, subject to the following conditions:
|
|
201
|
+
|
|
202
|
+
The above copyright notice and this permission notice shall be included in all
|
|
203
|
+
copies or substantial portions of the Software.
|
|
204
|
+
|
|
205
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
206
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
207
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
208
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
209
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
210
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
211
|
+
SOFTWARE.
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
<!-- LINKS FROM PLATFORM -->
|
|
215
|
+
[solcast]: https://solcast.com/
|
|
216
|
+
[solcast-api]: https://docs.solcast.com.au/
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
<!-- MARKDOWN LINKS & IMAGES -->
|
|
220
|
+
[build-shield]: https://github.com/klaasnicolaas/python-solcast-pv/actions/workflows/tests.yaml/badge.svg
|
|
221
|
+
[build-url]: https://github.com/klaasnicolaas/python-solcast-pv/actions/workflows/tests.yaml
|
|
222
|
+
[codecov-shield]: https://codecov.io/gh/klaasnicolaas/python-solcast-pv/branch/main/graph/badge.svg?token=X4799ZA1V2
|
|
223
|
+
[codecov-url]: https://codecov.io/gh/klaasnicolaas/python-solcast-pv
|
|
224
|
+
[commits-shield]: https://img.shields.io/github/commit-activity/y/klaasnicolaas/python-solcast-pv.svg
|
|
225
|
+
[commits-url]: https://github.com/klaasnicolaas/python-solcast-pv/commits/main
|
|
226
|
+
[devcontainer-shield]: https://img.shields.io/static/v1?label=Dev%20Containers&message=Open&color=blue&logo=visualstudiocode
|
|
227
|
+
[devcontainer]: https://vscode.dev/redirect?url=vscode://ms-vscode-remote.remote-containers/cloneInVolume?url=https://github.com/klaasnicolaas/python-solcast-pv
|
|
228
|
+
[downloads-shield]: https://img.shields.io/pypi/dm/solcast-pv
|
|
229
|
+
[downloads-url]: https://pypistats.org/packages/solcast-pv
|
|
230
|
+
[last-commit-shield]: https://img.shields.io/github/last-commit/klaasnicolaas/python-solcast-pv.svg
|
|
231
|
+
[license-shield]: https://img.shields.io/github/license/klaasnicolaas/python-solcast-pv.svg
|
|
232
|
+
[maintainability-shield]: https://api.codeclimate.com/v1/badges/37e0267f0b2ab438f848/maintainability
|
|
233
|
+
[maintainability-url]: https://codeclimate.com/github/klaasnicolaas/python-solcast-pv/maintainability
|
|
234
|
+
[maintenance-shield]: https://img.shields.io/maintenance/yes/2024.svg
|
|
235
|
+
[project-stage-shield]: https://img.shields.io/badge/project%20stage-experimental-yellow.svg
|
|
236
|
+
[pypi]: https://pypi.org/project/solcast-pv/
|
|
237
|
+
[python-versions-shield]: https://img.shields.io/pypi/pyversions/solcast-pv
|
|
238
|
+
[releases-shield]: https://img.shields.io/github/release/klaasnicolaas/python-solcast-pv.svg
|
|
239
|
+
[releases]: https://github.com/klaasnicolaas/python-solcast-pv/releases
|
|
240
|
+
[typing-shield]: https://github.com/klaasnicolaas/python-solcast-pv/actions/workflows/typing.yaml/badge.svg
|
|
241
|
+
[typing-url]: https://github.com/klaasnicolaas/python-solcast-pv/actions/workflows/typing.yaml
|
|
242
|
+
|
|
243
|
+
[poetry-install]: https://python-poetry.org/docs/#installation
|
|
244
|
+
[poetry]: https://python-poetry.org
|
|
245
|
+
[pre-commit]: https://pre-commit.com
|
|
246
|
+
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
<!-- Banner -->
|
|
2
|
+

|
|
3
|
+
|
|
4
|
+
<!-- PROJECT SHIELDS -->
|
|
5
|
+
[![GitHub Release][releases-shield]][releases]
|
|
6
|
+
[![Python Versions][python-versions-shield]][pypi]
|
|
7
|
+
![Project Stage][project-stage-shield]
|
|
8
|
+
![Project Maintenance][maintenance-shield]
|
|
9
|
+
[![License][license-shield]](LICENSE)
|
|
10
|
+
|
|
11
|
+
[![GitHub Activity][commits-shield]][commits-url]
|
|
12
|
+
[![PyPi Downloads][downloads-shield]][downloads-url]
|
|
13
|
+
[![GitHub Last Commit][last-commit-shield]][commits-url]
|
|
14
|
+
[![Open in Dev Containers][devcontainer-shield]][devcontainer]
|
|
15
|
+
|
|
16
|
+
[![Build Status][build-shield]][build-url]
|
|
17
|
+
[![Typing Status][typing-shield]][typing-url]
|
|
18
|
+
[![Maintainability][maintainability-shield]][maintainability-url]
|
|
19
|
+
[![Code Coverage][codecov-shield]][codecov-url]
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
Asynchronous Python client for [Solcast][solcast].
|
|
23
|
+
|
|
24
|
+
## About
|
|
25
|
+
|
|
26
|
+
[Solcast][solcast] provides solar radiation and solar power forecasts, estimated and
|
|
27
|
+
historical data. This package allows you to get the data from the [API][solcast-api]
|
|
28
|
+
and use it in your own application.
|
|
29
|
+
|
|
30
|
+
> [!NOTE]
|
|
31
|
+
> This package is still in development and rooftop forecast is not yet implemented.
|
|
32
|
+
|
|
33
|
+
## Installation
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
pip install solcast-pv
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Datasets
|
|
40
|
+
|
|
41
|
+
- List of all your created rooftop sites linked to your account.
|
|
42
|
+
- Get rate limits for your account.
|
|
43
|
+
|
|
44
|
+
<details>
|
|
45
|
+
<summary>CLICK HERE! to see all datasets</summary>
|
|
46
|
+
|
|
47
|
+
### Rooftop Site
|
|
48
|
+
|
|
49
|
+
**Note**: _requesting the list of all your created rooftop sites linked to your account, will not affect your daily rate limit._
|
|
50
|
+
|
|
51
|
+
| Name | Type | Description |
|
|
52
|
+
| :--- | :--- | :---------- |
|
|
53
|
+
| `name` | `str` | The name of the rooftop site. |
|
|
54
|
+
| `resource_id` | `str` | The unique identifier of the rooftop site. |
|
|
55
|
+
| `install_date` | `datetime` | The installation date of your solar panels. |
|
|
56
|
+
| `capacity` | `float` | The capacity of the solar panels. |
|
|
57
|
+
| `capacity_dc` | `float` | The capacity of the solar panels in DC. |
|
|
58
|
+
| `azimuth` | `int` | The azimuth of the solar panels. |
|
|
59
|
+
| `tilt` | `int` | The tilt of the solar panels. |
|
|
60
|
+
| `loss_factor` | `float` | The loss factor of the solar panels. |
|
|
61
|
+
|
|
62
|
+
### Rate Limits
|
|
63
|
+
|
|
64
|
+
**Note**: _requesting the rate limits for your account will not affect your daily rate limit._
|
|
65
|
+
|
|
66
|
+
| Name | Type | Description |
|
|
67
|
+
| :--- | :--- | :---------- |
|
|
68
|
+
| `daily_limit` | `int` | The daily limit of API calls. |
|
|
69
|
+
| `remaining_daily` | `int` | The remaining daily limit of API calls. |
|
|
70
|
+
| `consumed_daily` | `int` | How many API calls you have consumed today. |
|
|
71
|
+
</details>
|
|
72
|
+
|
|
73
|
+
### Example
|
|
74
|
+
|
|
75
|
+
```python
|
|
76
|
+
import asyncio
|
|
77
|
+
|
|
78
|
+
from solcast_pv import Solcast, RooftopSite
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
async def main() -> None:
|
|
82
|
+
"""Show example on using this package."""
|
|
83
|
+
async with Solcast(token="API_KEY") as client:
|
|
84
|
+
rooftops: list[RooftopSite] = await client.get_rooftop_sites()
|
|
85
|
+
print(rooftops)
|
|
86
|
+
|
|
87
|
+
if __name__ == "__main__":
|
|
88
|
+
asyncio.run(main())
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
More examples can be found in the [examples folder](./examples/).
|
|
92
|
+
|
|
93
|
+
## Contributing
|
|
94
|
+
|
|
95
|
+
This is an active open-source project. We are always open to people who want to
|
|
96
|
+
use the code or contribute to it.
|
|
97
|
+
|
|
98
|
+
We've set up a separate document for our
|
|
99
|
+
[contribution guidelines](CONTRIBUTING.md).
|
|
100
|
+
|
|
101
|
+
Thank you for being involved! :heart_eyes:
|
|
102
|
+
|
|
103
|
+
## Setting up development environment
|
|
104
|
+
|
|
105
|
+
The simplest way to begin is by utilizing the [Dev Container][devcontainer]
|
|
106
|
+
feature of Visual Studio Code or by opening a CodeSpace directly on GitHub.
|
|
107
|
+
By clicking the button below you immediately start a Dev Container in Visual Studio Code.
|
|
108
|
+
|
|
109
|
+
[![Open in Dev Containers][devcontainer-shield]][devcontainer]
|
|
110
|
+
|
|
111
|
+
This Python project relies on [Poetry][poetry] as its dependency manager,
|
|
112
|
+
providing comprehensive management and control over project dependencies.
|
|
113
|
+
|
|
114
|
+
You need at least:
|
|
115
|
+
|
|
116
|
+
- Python 3.11+
|
|
117
|
+
- [Poetry][poetry-install]
|
|
118
|
+
|
|
119
|
+
Install all packages, including all development requirements:
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
poetry install
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Poetry creates by default an virtual environment where it installs all
|
|
126
|
+
necessary pip packages, to enter or exit the venv run the following commands:
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
poetry shell
|
|
130
|
+
exit
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Setup the pre-commit check, you must run this inside the virtual environment:
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
pre-commit install
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
*Now you're all set to get started!*
|
|
140
|
+
|
|
141
|
+
As this repository uses the [pre-commit][pre-commit] framework, all changes
|
|
142
|
+
are linted and tested with each commit. You can run all checks and tests
|
|
143
|
+
manually, using the following command:
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
poetry run pre-commit run --all-files
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
To run just the Python tests:
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
poetry run pytest
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
To update the [syrupy](https://github.com/tophat/syrupy) snapshot tests:
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
poetry run pytest --snapshot-update
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
## License
|
|
162
|
+
|
|
163
|
+
MIT License
|
|
164
|
+
|
|
165
|
+
Copyright (c) 2024 Klaas Schoute
|
|
166
|
+
|
|
167
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
168
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
169
|
+
in the Software without restriction, including without limitation the rights
|
|
170
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
171
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
172
|
+
furnished to do so, subject to the following conditions:
|
|
173
|
+
|
|
174
|
+
The above copyright notice and this permission notice shall be included in all
|
|
175
|
+
copies or substantial portions of the Software.
|
|
176
|
+
|
|
177
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
178
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
179
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
180
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
181
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
182
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
183
|
+
SOFTWARE.
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
<!-- LINKS FROM PLATFORM -->
|
|
187
|
+
[solcast]: https://solcast.com/
|
|
188
|
+
[solcast-api]: https://docs.solcast.com.au/
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
<!-- MARKDOWN LINKS & IMAGES -->
|
|
192
|
+
[build-shield]: https://github.com/klaasnicolaas/python-solcast-pv/actions/workflows/tests.yaml/badge.svg
|
|
193
|
+
[build-url]: https://github.com/klaasnicolaas/python-solcast-pv/actions/workflows/tests.yaml
|
|
194
|
+
[codecov-shield]: https://codecov.io/gh/klaasnicolaas/python-solcast-pv/branch/main/graph/badge.svg?token=X4799ZA1V2
|
|
195
|
+
[codecov-url]: https://codecov.io/gh/klaasnicolaas/python-solcast-pv
|
|
196
|
+
[commits-shield]: https://img.shields.io/github/commit-activity/y/klaasnicolaas/python-solcast-pv.svg
|
|
197
|
+
[commits-url]: https://github.com/klaasnicolaas/python-solcast-pv/commits/main
|
|
198
|
+
[devcontainer-shield]: https://img.shields.io/static/v1?label=Dev%20Containers&message=Open&color=blue&logo=visualstudiocode
|
|
199
|
+
[devcontainer]: https://vscode.dev/redirect?url=vscode://ms-vscode-remote.remote-containers/cloneInVolume?url=https://github.com/klaasnicolaas/python-solcast-pv
|
|
200
|
+
[downloads-shield]: https://img.shields.io/pypi/dm/solcast-pv
|
|
201
|
+
[downloads-url]: https://pypistats.org/packages/solcast-pv
|
|
202
|
+
[last-commit-shield]: https://img.shields.io/github/last-commit/klaasnicolaas/python-solcast-pv.svg
|
|
203
|
+
[license-shield]: https://img.shields.io/github/license/klaasnicolaas/python-solcast-pv.svg
|
|
204
|
+
[maintainability-shield]: https://api.codeclimate.com/v1/badges/37e0267f0b2ab438f848/maintainability
|
|
205
|
+
[maintainability-url]: https://codeclimate.com/github/klaasnicolaas/python-solcast-pv/maintainability
|
|
206
|
+
[maintenance-shield]: https://img.shields.io/maintenance/yes/2024.svg
|
|
207
|
+
[project-stage-shield]: https://img.shields.io/badge/project%20stage-experimental-yellow.svg
|
|
208
|
+
[pypi]: https://pypi.org/project/solcast-pv/
|
|
209
|
+
[python-versions-shield]: https://img.shields.io/pypi/pyversions/solcast-pv
|
|
210
|
+
[releases-shield]: https://img.shields.io/github/release/klaasnicolaas/python-solcast-pv.svg
|
|
211
|
+
[releases]: https://github.com/klaasnicolaas/python-solcast-pv/releases
|
|
212
|
+
[typing-shield]: https://github.com/klaasnicolaas/python-solcast-pv/actions/workflows/typing.yaml/badge.svg
|
|
213
|
+
[typing-url]: https://github.com/klaasnicolaas/python-solcast-pv/actions/workflows/typing.yaml
|
|
214
|
+
|
|
215
|
+
[poetry-install]: https://python-poetry.org/docs/#installation
|
|
216
|
+
[poetry]: https://python-poetry.org
|
|
217
|
+
[pre-commit]: https://pre-commit.com
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
[tool.poetry]
|
|
2
|
+
name = "solcast-pv"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "Asynchronous Python client for getting forecast data from Solcast"
|
|
5
|
+
authors = ["Klaas Schoute <hello@student-techlife.com>"]
|
|
6
|
+
maintainers = ["Klaas Schoute <hello@student-techlife.com>"]
|
|
7
|
+
license = "MIT"
|
|
8
|
+
readme = "README.md"
|
|
9
|
+
homepage = "https://github.com/klaasnicolaas/python-solcast-pv"
|
|
10
|
+
repository = "https://github.com/klaasnicolaas/python-solcast-pv"
|
|
11
|
+
documentation = "https://github.com/klaasnicolaas/python-solcast-pv"
|
|
12
|
+
keywords = ["api", "async", "client", "solcast", "forecast", "energy", "solar"]
|
|
13
|
+
classifiers = [
|
|
14
|
+
"Framework :: AsyncIO",
|
|
15
|
+
"Intended Audience :: Developers",
|
|
16
|
+
"License :: OSI Approved :: MIT License",
|
|
17
|
+
"Natural Language :: English",
|
|
18
|
+
"Programming Language :: Python :: 3.11",
|
|
19
|
+
"Programming Language :: Python :: 3.12",
|
|
20
|
+
"Programming Language :: Python :: 3",
|
|
21
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
22
|
+
]
|
|
23
|
+
packages = [
|
|
24
|
+
{ include = "solcast_pv", from = "src"},
|
|
25
|
+
]
|
|
26
|
+
|
|
27
|
+
[tool.poetry.dependencies]
|
|
28
|
+
aiohttp = ">=3.0.0"
|
|
29
|
+
python = "^3.11"
|
|
30
|
+
yarl = ">=1.6.0"
|
|
31
|
+
|
|
32
|
+
[tool.poetry.urls]
|
|
33
|
+
"Bug Tracker" = "https://github.com/klaasnicolaas/python-solcast-pv/issues"
|
|
34
|
+
Changelog = "https://github.com/klaasnicolaas/python-solcast-pv/releases"
|
|
35
|
+
|
|
36
|
+
[tool.poetry.group.dev.dependencies]
|
|
37
|
+
aresponses = "3.0.0"
|
|
38
|
+
codespell = "2.3.0"
|
|
39
|
+
covdefaults = "2.3.0"
|
|
40
|
+
coverage = {version = "7.5.3", extras = ["toml"]}
|
|
41
|
+
mypy = "1.10.0"
|
|
42
|
+
pre-commit = "3.7.1"
|
|
43
|
+
pre-commit-hooks = "4.6.0"
|
|
44
|
+
pylint = "3.2.3"
|
|
45
|
+
pytest = "8.2.2"
|
|
46
|
+
pytest-asyncio = "0.23.7"
|
|
47
|
+
pytest-cov = "5.0.0"
|
|
48
|
+
ruff = "0.4.8"
|
|
49
|
+
syrupy = "4.6.1"
|
|
50
|
+
yamllint = "1.35.1"
|
|
51
|
+
|
|
52
|
+
[tool.coverage.run]
|
|
53
|
+
plugins = ["covdefaults"]
|
|
54
|
+
source = ["solcast_pv"]
|
|
55
|
+
|
|
56
|
+
[tool.coverage.report]
|
|
57
|
+
fail_under = 90
|
|
58
|
+
show_missing = true
|
|
59
|
+
|
|
60
|
+
[tool.mypy]
|
|
61
|
+
# Specify the target platform details in config, so your developers are
|
|
62
|
+
# free to run mypy on Windows, Linux, or macOS and get consistent
|
|
63
|
+
# results.
|
|
64
|
+
platform = "linux"
|
|
65
|
+
python_version = "3.11"
|
|
66
|
+
|
|
67
|
+
# flake8-mypy expects the two following for sensible formatting
|
|
68
|
+
show_column_numbers = true
|
|
69
|
+
|
|
70
|
+
# show error messages from unrelated files
|
|
71
|
+
follow_imports = "normal"
|
|
72
|
+
|
|
73
|
+
# suppress errors about unsatisfied imports
|
|
74
|
+
ignore_missing_imports = true
|
|
75
|
+
|
|
76
|
+
# be strict
|
|
77
|
+
check_untyped_defs = true
|
|
78
|
+
disallow_any_generics = true
|
|
79
|
+
disallow_incomplete_defs = true
|
|
80
|
+
disallow_subclassing_any = true
|
|
81
|
+
disallow_untyped_calls = true
|
|
82
|
+
disallow_untyped_decorators = true
|
|
83
|
+
disallow_untyped_defs = true
|
|
84
|
+
no_implicit_optional = true
|
|
85
|
+
no_implicit_reexport = true
|
|
86
|
+
strict_optional = true
|
|
87
|
+
warn_incomplete_stub = true
|
|
88
|
+
warn_no_return = true
|
|
89
|
+
warn_redundant_casts = true
|
|
90
|
+
warn_return_any = true
|
|
91
|
+
warn_unused_configs = true
|
|
92
|
+
warn_unused_ignores = true
|
|
93
|
+
|
|
94
|
+
[tool.pylint.MASTER]
|
|
95
|
+
ignore = ["tests"]
|
|
96
|
+
|
|
97
|
+
[tool.pylint.BASIC]
|
|
98
|
+
good-names = ["_", "ex", "fp", "i", "id", "j", "k", "on", "Run", "T"]
|
|
99
|
+
|
|
100
|
+
[tool.pylint."MESSAGES CONTROL"]
|
|
101
|
+
disable= [
|
|
102
|
+
"duplicate-code",
|
|
103
|
+
"format",
|
|
104
|
+
"unsubscriptable-object",
|
|
105
|
+
]
|
|
106
|
+
|
|
107
|
+
[tool.pylint.SIMILARITIES]
|
|
108
|
+
ignore-imports = true
|
|
109
|
+
|
|
110
|
+
[tool.pylint.FORMAT]
|
|
111
|
+
max-line-length = 88
|
|
112
|
+
|
|
113
|
+
[tool.pylint.DESIGN]
|
|
114
|
+
max-attributes = 20
|
|
115
|
+
|
|
116
|
+
[tool.pytest.ini_options]
|
|
117
|
+
addopts = "--cov"
|
|
118
|
+
asyncio_mode = "auto"
|
|
119
|
+
|
|
120
|
+
[tool.ruff]
|
|
121
|
+
lint.select = ["ALL"]
|
|
122
|
+
lint.ignore = [
|
|
123
|
+
"ANN101", # Self... explanatory
|
|
124
|
+
"ANN102", # cls... just as useless
|
|
125
|
+
"ANN401", # Opinioated warning on disallowing dynamically typed expressions
|
|
126
|
+
"D203", # Conflicts with other rules
|
|
127
|
+
"D213", # Conflicts with other rules
|
|
128
|
+
"D417", # False positives in some occasions
|
|
129
|
+
"PLR2004", # Just annoying, not really useful
|
|
130
|
+
"SLOT000", # Has a bug with enums: https://github.com/astral-sh/ruff/issues/5748
|
|
131
|
+
|
|
132
|
+
# Conflicts with the Ruff formatter
|
|
133
|
+
"COM812",
|
|
134
|
+
"ISC001",
|
|
135
|
+
]
|
|
136
|
+
|
|
137
|
+
[tool.ruff.lint.flake8-pytest-style]
|
|
138
|
+
mark-parentheses = false
|
|
139
|
+
fixture-parentheses = false
|
|
140
|
+
|
|
141
|
+
[tool.ruff.lint.isort]
|
|
142
|
+
known-first-party = ["solcast_pv"]
|
|
143
|
+
|
|
144
|
+
[tool.ruff.lint.mccabe]
|
|
145
|
+
max-complexity = 25
|
|
146
|
+
|
|
147
|
+
[build-system]
|
|
148
|
+
build-backend = "poetry.core.masonry.api"
|
|
149
|
+
requires = ["poetry-core>=1.0.0"]
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"""Asynchronous Python client for Solcast."""
|
|
2
|
+
|
|
3
|
+
from .exceptions import (
|
|
4
|
+
SolcastAuthenticationError,
|
|
5
|
+
SolcastConnectionError,
|
|
6
|
+
SolcastError,
|
|
7
|
+
SolcastResultsError,
|
|
8
|
+
)
|
|
9
|
+
from .models import RateLimit, RooftopSite
|
|
10
|
+
from .solcast_pv import Solcast
|
|
11
|
+
|
|
12
|
+
__all__ = [
|
|
13
|
+
"RateLimit",
|
|
14
|
+
"RooftopSite",
|
|
15
|
+
"Solcast",
|
|
16
|
+
"SolcastAuthenticationError",
|
|
17
|
+
"SolcastConnectionError",
|
|
18
|
+
"SolcastError",
|
|
19
|
+
"SolcastResultsError",
|
|
20
|
+
]
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"""Asynchronous Python client for Solcast."""
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class SolcastError(Exception):
|
|
5
|
+
"""Generic Solcast exception."""
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class SolcastConnectionError(SolcastError):
|
|
9
|
+
"""Solcast connection exception."""
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class SolcastAuthenticationError(SolcastError):
|
|
13
|
+
"""Solcast authentication exception."""
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class SolcastResultsError(SolcastError):
|
|
17
|
+
"""Solcast results exception."""
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"""Asynchronous Python client for Solcast."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
from datetime import datetime
|
|
7
|
+
from typing import Any
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@dataclass
|
|
11
|
+
class RooftopSite:
|
|
12
|
+
"""Object representing the rooftop site for the Solcast API."""
|
|
13
|
+
|
|
14
|
+
name: str
|
|
15
|
+
resource_id: str
|
|
16
|
+
install_date: datetime
|
|
17
|
+
|
|
18
|
+
capacity: float
|
|
19
|
+
capacity_dc: float
|
|
20
|
+
azimuth: int
|
|
21
|
+
tilt: int
|
|
22
|
+
loss_factor: float
|
|
23
|
+
|
|
24
|
+
@classmethod
|
|
25
|
+
def from_dict(cls: type[RooftopSite], data: dict[str, Any]) -> RooftopSite:
|
|
26
|
+
"""Create a new instance of the RooftopSites class from a dictionary."""
|
|
27
|
+
return cls(
|
|
28
|
+
name=data["name"],
|
|
29
|
+
resource_id=data["resource_id"],
|
|
30
|
+
install_date=datetime.fromisoformat(data["install_date"]),
|
|
31
|
+
capacity=data["capacity"],
|
|
32
|
+
capacity_dc=data["capacity_dc"],
|
|
33
|
+
azimuth=data["azimuth"],
|
|
34
|
+
tilt=data["tilt"],
|
|
35
|
+
loss_factor=data["loss_factor"],
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
@dataclass
|
|
40
|
+
class RateLimit:
|
|
41
|
+
"""Object representing the rate limit status for the Solcast API."""
|
|
42
|
+
|
|
43
|
+
daily_limit: int
|
|
44
|
+
remaining_daily: int
|
|
45
|
+
consumed_daily: int
|
|
46
|
+
|
|
47
|
+
@classmethod
|
|
48
|
+
def from_dict(cls: type[RateLimit], data: dict[str, Any]) -> RateLimit:
|
|
49
|
+
"""Create a new instance of the RateLimit class from a dictionary."""
|
|
50
|
+
return cls(
|
|
51
|
+
daily_limit=data["daily_limit"],
|
|
52
|
+
remaining_daily=int(data["daily_limit"] - data["daily_limit_consumed"]),
|
|
53
|
+
consumed_daily=data["daily_limit_consumed"],
|
|
54
|
+
)
|
|
File without changes
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
"""Asynchronous Python client for Solcast."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import asyncio
|
|
6
|
+
import socket
|
|
7
|
+
from dataclasses import dataclass
|
|
8
|
+
from importlib import metadata
|
|
9
|
+
from typing import Any, Self
|
|
10
|
+
|
|
11
|
+
from aiohttp import ClientError, ClientResponseError, ClientSession
|
|
12
|
+
from aiohttp.hdrs import METH_GET
|
|
13
|
+
from yarl import URL
|
|
14
|
+
|
|
15
|
+
from .exceptions import (
|
|
16
|
+
SolcastAuthenticationError,
|
|
17
|
+
SolcastConnectionError,
|
|
18
|
+
SolcastError,
|
|
19
|
+
SolcastResultsError,
|
|
20
|
+
)
|
|
21
|
+
from .models import RateLimit, RooftopSite
|
|
22
|
+
|
|
23
|
+
VERSION = metadata.version(__package__)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@dataclass
|
|
27
|
+
class Solcast:
|
|
28
|
+
"""Main class for handling connections with the Solcast API."""
|
|
29
|
+
|
|
30
|
+
token: str
|
|
31
|
+
|
|
32
|
+
request_timeout: float = 10.0
|
|
33
|
+
session: ClientSession | None = None
|
|
34
|
+
|
|
35
|
+
_close_session: bool = False
|
|
36
|
+
|
|
37
|
+
async def _request(
|
|
38
|
+
self,
|
|
39
|
+
uri: str,
|
|
40
|
+
*,
|
|
41
|
+
method: str = METH_GET,
|
|
42
|
+
params: dict[str, Any] | None = None,
|
|
43
|
+
) -> Any:
|
|
44
|
+
"""Handle a request to the Solcast API.
|
|
45
|
+
|
|
46
|
+
Args:
|
|
47
|
+
----
|
|
48
|
+
uri: Request URI, without '/api/', for example, 'status'.
|
|
49
|
+
method: HTTP method to use.
|
|
50
|
+
params: Extra options to improve or limit the response.
|
|
51
|
+
|
|
52
|
+
Returns:
|
|
53
|
+
-------
|
|
54
|
+
A Python dictionary (JSON decoded) with the response from
|
|
55
|
+
the Solcast API.
|
|
56
|
+
|
|
57
|
+
Raises:
|
|
58
|
+
------
|
|
59
|
+
SolcastConnectionError: Error occurred while connecting to Solcast API.
|
|
60
|
+
SolcastError: Unexpected content type response from Solcast API.
|
|
61
|
+
|
|
62
|
+
"""
|
|
63
|
+
url = URL.build(
|
|
64
|
+
scheme="https",
|
|
65
|
+
host="api.solcast.com.au",
|
|
66
|
+
path="/",
|
|
67
|
+
).join(URL(uri))
|
|
68
|
+
|
|
69
|
+
headers = {
|
|
70
|
+
"Authorization": f"Bearer {self.token}",
|
|
71
|
+
"Accept": "application/json",
|
|
72
|
+
"User-Agent": f"PythonSolcastPV/{VERSION}",
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if self.session is None:
|
|
76
|
+
self.session = ClientSession()
|
|
77
|
+
self._close_session = True
|
|
78
|
+
|
|
79
|
+
try:
|
|
80
|
+
async with asyncio.timeout(self.request_timeout):
|
|
81
|
+
response = await self.session.request(
|
|
82
|
+
method,
|
|
83
|
+
url,
|
|
84
|
+
headers=headers,
|
|
85
|
+
params=params,
|
|
86
|
+
ssl=True,
|
|
87
|
+
)
|
|
88
|
+
response.raise_for_status()
|
|
89
|
+
except TimeoutError as exception:
|
|
90
|
+
msg = "Timeout occurred while connecting to Solcast API."
|
|
91
|
+
raise SolcastConnectionError(msg) from exception
|
|
92
|
+
except ClientResponseError as exception:
|
|
93
|
+
if exception.status == 401:
|
|
94
|
+
msg = "Invalid API key provided to Solcast API."
|
|
95
|
+
raise SolcastAuthenticationError(msg) from exception
|
|
96
|
+
if exception.status == 403:
|
|
97
|
+
msg = "API key does not have access to the requested resource."
|
|
98
|
+
raise SolcastAuthenticationError(msg) from exception
|
|
99
|
+
if exception.status == 404:
|
|
100
|
+
msg = "Requested resource was not found on Solcast API."
|
|
101
|
+
raise SolcastError(msg) from exception
|
|
102
|
+
msg = "Error occurred while connecting to Solcast API."
|
|
103
|
+
raise SolcastConnectionError(msg) from exception
|
|
104
|
+
except (ClientError, socket.gaierror) as exception:
|
|
105
|
+
msg = "Error occurred while connecting to Solcast API."
|
|
106
|
+
raise SolcastConnectionError(msg) from exception
|
|
107
|
+
|
|
108
|
+
content_type = response.headers.get("Content-Type", "")
|
|
109
|
+
if "application/json" not in content_type:
|
|
110
|
+
text = await response.text()
|
|
111
|
+
msg = "Unexpected content type response from Solcast API."
|
|
112
|
+
raise SolcastError(
|
|
113
|
+
msg,
|
|
114
|
+
{"content_type": content_type, "text": text},
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
return await response.json()
|
|
118
|
+
|
|
119
|
+
async def get_rooftop_sites(self) -> list[RooftopSite]:
|
|
120
|
+
"""Get the rooftop sites for the Solcast API.
|
|
121
|
+
|
|
122
|
+
Returns
|
|
123
|
+
-------
|
|
124
|
+
RooftopSite: The rooftop site.
|
|
125
|
+
|
|
126
|
+
"""
|
|
127
|
+
response = await self._request("rooftop_sites")
|
|
128
|
+
try:
|
|
129
|
+
results: list[RooftopSite] = [
|
|
130
|
+
RooftopSite.from_dict(site) for site in response["sites"]
|
|
131
|
+
]
|
|
132
|
+
except KeyError as exception:
|
|
133
|
+
msg = "No rooftop sites found on your Solcast account."
|
|
134
|
+
raise SolcastResultsError(msg) from exception
|
|
135
|
+
return results
|
|
136
|
+
|
|
137
|
+
async def get_ratelimit(self) -> RateLimit:
|
|
138
|
+
"""Get the rate limit status for the Solcast API.
|
|
139
|
+
|
|
140
|
+
Returns
|
|
141
|
+
-------
|
|
142
|
+
RateLimit: The rate limit status.
|
|
143
|
+
|
|
144
|
+
"""
|
|
145
|
+
response = await self._request("json/reply/GetUserUsageAllowance")
|
|
146
|
+
return RateLimit.from_dict(response)
|
|
147
|
+
|
|
148
|
+
async def close(self) -> None:
|
|
149
|
+
"""Close open client session."""
|
|
150
|
+
if self.session and self._close_session:
|
|
151
|
+
await self.session.close()
|
|
152
|
+
|
|
153
|
+
async def __aenter__(self) -> Self:
|
|
154
|
+
"""Async enter.
|
|
155
|
+
|
|
156
|
+
Returns
|
|
157
|
+
-------
|
|
158
|
+
The Solcast object.
|
|
159
|
+
|
|
160
|
+
"""
|
|
161
|
+
return self
|
|
162
|
+
|
|
163
|
+
async def __aexit__(self, *_exc_info: object) -> None:
|
|
164
|
+
"""Async exit.
|
|
165
|
+
|
|
166
|
+
Args:
|
|
167
|
+
----
|
|
168
|
+
_exc_info: Exec type.
|
|
169
|
+
|
|
170
|
+
"""
|
|
171
|
+
await self.close()
|