earthscope-sdk 0.2.0__tar.gz → 1.0.0b0__tar.gz

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. {earthscope-sdk-0.2.0 → earthscope_sdk-1.0.0b0}/PKG-INFO +144 -115
  2. earthscope_sdk-1.0.0b0/README.md +141 -0
  3. {earthscope-sdk-0.2.0 → earthscope_sdk-1.0.0b0}/pyproject.toml +22 -16
  4. earthscope_sdk-1.0.0b0/src/earthscope_sdk/__init__.py +5 -0
  5. earthscope_sdk-1.0.0b0/src/earthscope_sdk/auth/auth_flow.py +318 -0
  6. earthscope_sdk-1.0.0b0/src/earthscope_sdk/auth/client_credentials_flow.py +80 -0
  7. earthscope_sdk-1.0.0b0/src/earthscope_sdk/auth/device_code_flow.py +241 -0
  8. earthscope_sdk-1.0.0b0/src/earthscope_sdk/auth/error.py +46 -0
  9. earthscope_sdk-1.0.0b0/src/earthscope_sdk/client/__init__.py +3 -0
  10. earthscope_sdk-1.0.0b0/src/earthscope_sdk/client/_client.py +35 -0
  11. earthscope_sdk-1.0.0b0/src/earthscope_sdk/client/user/_base.py +39 -0
  12. earthscope_sdk-1.0.0b0/src/earthscope_sdk/client/user/_service.py +94 -0
  13. earthscope_sdk-1.0.0b0/src/earthscope_sdk/client/user/models.py +53 -0
  14. earthscope_sdk-1.0.0b0/src/earthscope_sdk/common/__init__.py +0 -0
  15. earthscope_sdk-1.0.0b0/src/earthscope_sdk/common/_sync_runner.py +141 -0
  16. earthscope_sdk-1.0.0b0/src/earthscope_sdk/common/client.py +99 -0
  17. earthscope_sdk-1.0.0b0/src/earthscope_sdk/common/context.py +174 -0
  18. earthscope_sdk-1.0.0b0/src/earthscope_sdk/common/service.py +54 -0
  19. earthscope_sdk-1.0.0b0/src/earthscope_sdk/config/__init__.py +0 -0
  20. earthscope_sdk-1.0.0b0/src/earthscope_sdk/config/_compat.py +148 -0
  21. earthscope_sdk-1.0.0b0/src/earthscope_sdk/config/_util.py +48 -0
  22. earthscope_sdk-1.0.0b0/src/earthscope_sdk/config/error.py +4 -0
  23. earthscope_sdk-1.0.0b0/src/earthscope_sdk/config/models.py +208 -0
  24. earthscope_sdk-1.0.0b0/src/earthscope_sdk/config/settings.py +284 -0
  25. {earthscope-sdk-0.2.0 → earthscope_sdk-1.0.0b0}/src/earthscope_sdk.egg-info/PKG-INFO +144 -115
  26. earthscope_sdk-1.0.0b0/src/earthscope_sdk.egg-info/SOURCES.txt +36 -0
  27. earthscope_sdk-1.0.0b0/src/earthscope_sdk.egg-info/requires.txt +12 -0
  28. earthscope_sdk-1.0.0b0/tests/test_auth.py +204 -0
  29. earthscope_sdk-1.0.0b0/tests/test_client.py +130 -0
  30. earthscope_sdk-1.0.0b0/tests/test_context.py +116 -0
  31. earthscope_sdk-1.0.0b0/tests/test_settings.py +427 -0
  32. earthscope-sdk-0.2.0/README.md +0 -122
  33. earthscope-sdk-0.2.0/src/earthscope_sdk/__init__.py +0 -1
  34. earthscope-sdk-0.2.0/src/earthscope_sdk/auth/auth_flow.py +0 -441
  35. earthscope-sdk-0.2.0/src/earthscope_sdk/auth/client_credentials_flow.py +0 -190
  36. earthscope-sdk-0.2.0/src/earthscope_sdk/auth/device_code_flow.py +0 -294
  37. earthscope-sdk-0.2.0/src/earthscope_sdk/user/user.py +0 -32
  38. earthscope-sdk-0.2.0/src/earthscope_sdk.egg-info/SOURCES.txt +0 -16
  39. earthscope-sdk-0.2.0/src/earthscope_sdk.egg-info/requires.txt +0 -10
  40. {earthscope-sdk-0.2.0 → earthscope_sdk-1.0.0b0}/LICENSE +0 -0
  41. {earthscope-sdk-0.2.0 → earthscope_sdk-1.0.0b0}/setup.cfg +0 -0
  42. {earthscope-sdk-0.2.0 → earthscope_sdk-1.0.0b0}/setup.py +0 -0
  43. {earthscope-sdk-0.2.0 → earthscope_sdk-1.0.0b0}/src/earthscope_sdk/auth/__init__.py +0 -0
  44. {earthscope-sdk-0.2.0/src/earthscope_sdk → earthscope_sdk-1.0.0b0/src/earthscope_sdk/client}/user/__init__.py +0 -0
  45. {earthscope-sdk-0.2.0 → earthscope_sdk-1.0.0b0}/src/earthscope_sdk.egg-info/dependency_links.txt +0 -0
  46. {earthscope-sdk-0.2.0 → earthscope_sdk-1.0.0b0}/src/earthscope_sdk.egg-info/top_level.txt +0 -0
@@ -1,8 +1,8 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: earthscope-sdk
3
- Version: 0.2.0
3
+ Version: 1.0.0b0
4
4
  Summary: An SDK for EarthScope API
5
- Author-email: EarthScope <software@unavco.org>
5
+ Author-email: EarthScope <data-help@earthscope.org>
6
6
  License: Apache License
7
7
  Version 2.0, January 2004
8
8
  http://www.apache.org/licenses/
@@ -210,130 +210,159 @@ Classifier: License :: OSI Approved :: Apache Software License
210
210
  Classifier: Programming Language :: Python
211
211
  Classifier: Programming Language :: Python :: 3
212
212
  Classifier: Operating System :: OS Independent
213
- Requires-Python: >=3.7
213
+ Requires-Python: >=3.9
214
214
  Description-Content-Type: text/markdown
215
- Provides-Extra: dev
216
215
  License-File: LICENSE
216
+ Requires-Dist: httpx>=0.27.0
217
+ Requires-Dist: pydantic-settings[toml]>=2.7.0
218
+ Provides-Extra: dev
219
+ Requires-Dist: bumpver; extra == "dev"
220
+ Requires-Dist: build; extra == "dev"
221
+ Requires-Dist: pytest; extra == "dev"
222
+ Requires-Dist: twine; extra == "dev"
223
+ Requires-Dist: pip-tools; extra == "dev"
224
+ Requires-Dist: pytest-httpx; extra == "dev"
225
+ Requires-Dist: pytest-asyncio; extra == "dev"
226
+ Requires-Dist: ruff; extra == "dev"
217
227
 
218
228
  # EarthScope SDK
219
229
 
220
- An SDK for authenticating with the EarthScope API
230
+ An SDK for interacting with EarthScope's APIs
221
231
 
222
232
  ## Getting Started
223
233
 
224
- ### USAGE
234
+ ### Installation
225
235
 
226
- 1. **(Optional) Suggest setting up and activating a python virtual environment so as not to clutter your system python**
236
+ Install from PyPI
227
237
 
228
- ```shell
229
- python3 -m venv venv
230
- . venv/bin/activate
238
+ ```shell
239
+ pip install earthscope-sdk
240
+ ```
241
+
242
+ ### Usage
243
+
244
+ For detailed usage options and examples, visit [our usage docs](docs/usage.md).
245
+
246
+ ```py
247
+ # Import and create a client
248
+ from earthscope_sdk import EarthScopeClient
249
+
250
+ client = EarthScopeClient()
251
+
252
+ # Example client method usage; retrieve your user profile
253
+ profile = client.user.get_profile()
254
+ print(profile)
255
+
256
+ # Client cleanup
257
+ client.close()
258
+ ```
259
+
260
+ #### Async Usage
261
+
262
+ There is also an `async` client available
263
+
264
+ ```py
265
+ import asyncio
266
+ from earthscope_sdk import AsyncEarthScopeClient
267
+
268
+ async def main():
269
+ client = AsyncEarthScopeClient()
270
+
271
+ profile = await client.user.get_profile()
272
+ print(profile)
273
+
274
+ await client.close()
275
+
276
+ asyncio.run(main())
277
+ ```
278
+
279
+ #### Context Managers
280
+
281
+ Client classes can also be used as context managers to ensure resource cleanup occurs.
282
+
283
+ ```py
284
+ # sync
285
+ with EarthScopeClient() as client:
286
+ client.user.get_profile()
287
+
288
+ # async
289
+ async with AsyncEarthScopeClient() as client:
290
+ await client.user.get_profile()
291
+ ```
292
+
293
+ ## Bootstrapping Authentication
294
+
295
+ There are a few methods of bootstrapping authentication for the SDK.
296
+
297
+ Once refreshable credentials are available to the SDK, it will transparently handle access token refresh on your behalf.
298
+
299
+ ### Same host
300
+
301
+ If you have the [EarthScope CLI](TODO) installed on the same host that is running your application which uses `earthscope-sdk`, you can simply log in using the CLI. The CLI shares credentials and configuration with this SDK (when running on the same host).
302
+
303
+ Running `es login` will open your browser and prompt you to log in to your EarthScope account.
304
+
305
+ ```console
306
+ $ es login
307
+ Attempting to automatically open the SSO authorization page in your default browser.
308
+ If the browser does not open or you wish to use a different device to authorize this request, open the following URL:
309
+
310
+ https://login.earthscope.org/activate?user_code=ABCD-EFGH
311
+
312
+ Successful login! Access token expires at 2024-12-27 18:50:37+00:00
313
+ ```
314
+
315
+ Now when you run your application, `earthscope-sdk` will find your credentials.
316
+
317
+ ### Different hosts
318
+
319
+ Sometimes your workload runs on different hosts than your main workstation and you cannot feasibly "log in" on all of them. For example, maybe you're running many containers in your workload.
320
+
321
+ You can still use the [EarthScope CLI](TODO) to facilitate auth for applications on other machines.
322
+
323
+ 1. Use the CLI on your primary workstation [as described above](#same-host) to log in.
324
+
325
+ 1. Use the CLI to retrieve your refresh token.
326
+
327
+ ```console
328
+ $ es user get-refresh-token
329
+ <your-refresh-token>
231
330
  ```
232
331
 
233
- 2. **Install earthscope-sdk**
332
+ > **Note: your refresh token should be treated as a secret credential. Anyone with a valid refresh token can use it to continually retrieve new access tokens on your behalf**.
333
+
334
+ 1. Pass this refresh token to all the hosts needing auth for the `earthscope-sdk`. For example, inject the `ES_OAUTH2__REFRESH_TOKEN` environment variable on these hosts.
234
335
 
235
336
  ```shell
236
- pip install earthscope-sdk
237
- ```
238
- For developers:
239
- ```bash
240
- pip -e install earthscope-sdk[dev]
337
+ export ES_OAUTH2__REFRESH_TOKEN="<your-refresh-token>"
241
338
  ```
242
-
243
- 3. **Create/Use required subclasses**
244
- \
245
- To use the **Device Authorization Flow** you will need to create a subclass of the DeviceCodeFlow class. Similarly, to use
246
- the **Machine-to-Machine Client Credentials Flow** you will need to create a subclass of the ClientCredientialFlow class.
247
-
248
- Simple subclasses exist for your use that you can import and use which will allow for locally loading and saving access tokens:
249
- *DeviceCodeFlowSimple* and *ClientCredentialsFlowSimple* (see below for examples on useage)
250
- <br/><br/>
251
- Creating your own subclass:
252
- \
253
- Implementing the following methods in the subclass is required:
254
- * `load_tokens` should implement the ability to load saved tokens
255
- * `save_tokens` should implement the ability to save tokens locally
256
-
257
- additionally for DeviceCodeFlow only:
258
- * `prompt_user` should provide the user with the SSO authorization uri
259
-
260
- You will need to instantiate your subclass with the following instance attributes:
261
-
262
- For DeviceCodeFlow:
263
- * `audience`, `domain`, `client_id`, and `scope`.
264
-
265
- For ClientCredentialsFlow:
266
- * `audience`, `client_credentials`, and `domain`.
267
-
268
- where client_credentials contains the machine-to-machine `client_id` and `client_secret`.
269
-
270
- These values are all obtained from [Auth0](https://manage.auth0.com/).
271
- <br/><br/>
272
- 4. **Use the SDK**
273
- \
274
- You can now use the subclasses to define actions such as logging in/out, retrieving or refreshing access tokens, etc...
275
- \
276
- **NOTE: Never share your access token or refresh tokens**
277
-
278
- Additionally, once the subclasses have been instantiated, you can pass your access token as a parameter to retrieve
279
- your user/anonymous user information using the earthscope_sdk.user.user *get_user* and *lookup_anon* functions.
280
-
281
-
282
- 5. **Example useages:**
283
- \
284
- Note: To see an example of an application using this SDK (and creating custom subclass), check out the [EarthScope CLI Repository](https://gitlab.com/earthscope/public/earthscope-cli).
285
- <br/><br/>
286
- How to use the existing simple subclass for device code flow:
287
- \
288
- *simple example python code*:
289
- ```
290
- import requests
291
- from pathlib import Path
292
-
293
- from earthscope_sdk.auth.device_code_flow import DeviceCodeFlowSimple
294
- from earthscope_sdk.auth.auth_flow import NoTokensError
295
-
296
- # choose where you want the token saved - the default file name is sso_tokens.json
297
- # if you want to keep the default name, set the path to a directory. Include a file name to rename.
298
- token_path = "/Users/my_user/token_dir"
299
-
300
- url = "https://data-idm.unavco.org/path/to/data_file"
301
- # example: "https://data-idm.unavco.org/archive/gnss/rinex/obs/2022/298/ar272980.22d.Z"
302
-
303
- # instantiate the device code flow subclass
304
- device_flow = DeviceCodeFlowSimple(Path(token_path))
305
- try:
306
- # get access token from local path
307
- device_flow.get_access_token_refresh_if_necessary()
308
- except NoTokensError:
309
- # if no token was found locally, do the device code flow
310
- device_flow.do_flow()
311
- token = device_flow.access_token
312
-
313
- # request a file and provide the token in the Authorization header
314
- file_name = Path(url).name
315
- directory_to_save_file = Path.cwd() # where you want to save the downloaded file
316
-
317
- r = requests.get(url, headers={"authorization": f"Bearer {token}"})
318
- if r.status_code == requests.codes.ok:
319
- # save the file
320
- with open(Path(directory_to_save_file / file_name), 'wb') as f:
321
- for data in r:
322
- f.write(data)
323
- else:
324
- #problem occured
325
- print(f"failure: {r.status_code}, {r.reason}")
326
- ```
327
-
328
- Instantiate the subclass and set the token_path where you want to load/save the token.
329
- If you provide only a directory, the file will be saved as sso_tokens.json.
330
- We hard-code this variable in this simple example, but we recommend setting this path as an environment variable and
331
- reading the environment varibale in your code.
332
-
333
-
334
- the **get_access_token_refresh_if_necessary** method will retrieve the token and refresh the token if it is expired.
335
- If there is no token, then the **do_flow** method will begin the device code flow and once you complete the flow,
336
- the token will be saved at the token_path. You can use the **requests** library to download the file you want
337
- (or files in a loop) and pass in the access token in the Authorization header.
338
-
339
- Learn more about [data access methods](https://www.unavco.org/data/gps-gnss/data-access-methods/data-access-methods.html).
339
+
340
+ ## SDK Settings
341
+
342
+ SDK Settings are provided via the following methods (in order of precedence):
343
+
344
+ 1. initialization arguments (e.g. via class constructors)
345
+ 1. environment variables
346
+ 1. dotenv file (.env) variables
347
+ 1. user's home directory settings files
348
+ 1. `~/.earthscope/config.toml` (for configuration)
349
+ 1. `~/.earthscope/<profile-name>/tokens.json` (for tokens)
350
+ 1. legacy EarthScope CLI v0 credentials
351
+ 1. default settings
352
+
353
+ SDK configuration is managed by the `SdkSettings` class, and calling the constructor performs this settings loading chain.
354
+
355
+ ```py
356
+ from earthscope_sdk.config.settings import SdkSettings
357
+
358
+ settings = SdkSettings() # loads settings via loading chain
359
+ ```
360
+
361
+ For more details on SDK configuration, including what options are available, see [our settings docs](docs/settings.md).
362
+
363
+ ## Contributing
364
+
365
+ For details on contributing to the EarthScope SDK, please see:
366
+
367
+ - [design docs](docs/design.md)
368
+ - [development docs](docs/development.md)
@@ -0,0 +1,141 @@
1
+ # EarthScope SDK
2
+
3
+ An SDK for interacting with EarthScope's APIs
4
+
5
+ ## Getting Started
6
+
7
+ ### Installation
8
+
9
+ Install from PyPI
10
+
11
+ ```shell
12
+ pip install earthscope-sdk
13
+ ```
14
+
15
+ ### Usage
16
+
17
+ For detailed usage options and examples, visit [our usage docs](docs/usage.md).
18
+
19
+ ```py
20
+ # Import and create a client
21
+ from earthscope_sdk import EarthScopeClient
22
+
23
+ client = EarthScopeClient()
24
+
25
+ # Example client method usage; retrieve your user profile
26
+ profile = client.user.get_profile()
27
+ print(profile)
28
+
29
+ # Client cleanup
30
+ client.close()
31
+ ```
32
+
33
+ #### Async Usage
34
+
35
+ There is also an `async` client available
36
+
37
+ ```py
38
+ import asyncio
39
+ from earthscope_sdk import AsyncEarthScopeClient
40
+
41
+ async def main():
42
+ client = AsyncEarthScopeClient()
43
+
44
+ profile = await client.user.get_profile()
45
+ print(profile)
46
+
47
+ await client.close()
48
+
49
+ asyncio.run(main())
50
+ ```
51
+
52
+ #### Context Managers
53
+
54
+ Client classes can also be used as context managers to ensure resource cleanup occurs.
55
+
56
+ ```py
57
+ # sync
58
+ with EarthScopeClient() as client:
59
+ client.user.get_profile()
60
+
61
+ # async
62
+ async with AsyncEarthScopeClient() as client:
63
+ await client.user.get_profile()
64
+ ```
65
+
66
+ ## Bootstrapping Authentication
67
+
68
+ There are a few methods of bootstrapping authentication for the SDK.
69
+
70
+ Once refreshable credentials are available to the SDK, it will transparently handle access token refresh on your behalf.
71
+
72
+ ### Same host
73
+
74
+ If you have the [EarthScope CLI](TODO) installed on the same host that is running your application which uses `earthscope-sdk`, you can simply log in using the CLI. The CLI shares credentials and configuration with this SDK (when running on the same host).
75
+
76
+ Running `es login` will open your browser and prompt you to log in to your EarthScope account.
77
+
78
+ ```console
79
+ $ es login
80
+ Attempting to automatically open the SSO authorization page in your default browser.
81
+ If the browser does not open or you wish to use a different device to authorize this request, open the following URL:
82
+
83
+ https://login.earthscope.org/activate?user_code=ABCD-EFGH
84
+
85
+ Successful login! Access token expires at 2024-12-27 18:50:37+00:00
86
+ ```
87
+
88
+ Now when you run your application, `earthscope-sdk` will find your credentials.
89
+
90
+ ### Different hosts
91
+
92
+ Sometimes your workload runs on different hosts than your main workstation and you cannot feasibly "log in" on all of them. For example, maybe you're running many containers in your workload.
93
+
94
+ You can still use the [EarthScope CLI](TODO) to facilitate auth for applications on other machines.
95
+
96
+ 1. Use the CLI on your primary workstation [as described above](#same-host) to log in.
97
+
98
+ 1. Use the CLI to retrieve your refresh token.
99
+
100
+ ```console
101
+ $ es user get-refresh-token
102
+ <your-refresh-token>
103
+ ```
104
+
105
+ > **Note: your refresh token should be treated as a secret credential. Anyone with a valid refresh token can use it to continually retrieve new access tokens on your behalf**.
106
+
107
+ 1. Pass this refresh token to all the hosts needing auth for the `earthscope-sdk`. For example, inject the `ES_OAUTH2__REFRESH_TOKEN` environment variable on these hosts.
108
+
109
+ ```shell
110
+ export ES_OAUTH2__REFRESH_TOKEN="<your-refresh-token>"
111
+ ```
112
+
113
+ ## SDK Settings
114
+
115
+ SDK Settings are provided via the following methods (in order of precedence):
116
+
117
+ 1. initialization arguments (e.g. via class constructors)
118
+ 1. environment variables
119
+ 1. dotenv file (.env) variables
120
+ 1. user's home directory settings files
121
+ 1. `~/.earthscope/config.toml` (for configuration)
122
+ 1. `~/.earthscope/<profile-name>/tokens.json` (for tokens)
123
+ 1. legacy EarthScope CLI v0 credentials
124
+ 1. default settings
125
+
126
+ SDK configuration is managed by the `SdkSettings` class, and calling the constructor performs this settings loading chain.
127
+
128
+ ```py
129
+ from earthscope_sdk.config.settings import SdkSettings
130
+
131
+ settings = SdkSettings() # loads settings via loading chain
132
+ ```
133
+
134
+ For more details on SDK configuration, including what options are available, see [our settings docs](docs/settings.md).
135
+
136
+ ## Contributing
137
+
138
+ For details on contributing to the EarthScope SDK, please see:
139
+
140
+ - [design docs](docs/design.md)
141
+ - [development docs](docs/development.md)
@@ -4,11 +4,11 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "earthscope-sdk"
7
- version = "0.2.0"
7
+ version = "1.0.0b0"
8
8
  description = "An SDK for EarthScope API"
9
9
  readme = "README.md"
10
- authors = [{ name = "EarthScope", email = "software@unavco.org"}]
11
- license = { file = "LICENSE"}
10
+ authors = [{ name = "EarthScope", email = "data-help@earthscope.org" }]
11
+ license = { file = "LICENSE" }
12
12
  classifiers = [
13
13
  "License :: OSI Approved :: Apache Software License",
14
14
  "Programming Language :: Python",
@@ -17,29 +17,35 @@ classifiers = [
17
17
  ]
18
18
 
19
19
  #Suggestion not to pin dependencies since the package should work in many different python environments
20
- dependencies = [
21
- "pyjwt >= 2.4.0",
22
- "requests >= 2.27.1"
23
- ]
24
- requires-python = ">=3.7"
20
+ dependencies = ["httpx>=0.27.0", "pydantic-settings[toml]>=2.7.0"]
21
+ requires-python = ">=3.9"
25
22
 
26
23
  [project.optional-dependencies]
27
- dev = ["black", "bumpver", "build", "pytest", "twine", "pip-tools"]
24
+ dev = [
25
+ "bumpver",
26
+ "build",
27
+ "pytest",
28
+ "twine",
29
+ "pip-tools",
30
+ "pytest-httpx",
31
+ "pytest-asyncio",
32
+ "ruff",
33
+ ]
28
34
 
29
35
  [project.urls]
30
36
  Homepage = "https://gitlab.com/earthscope/public/earthscope-sdk"
31
37
 
32
38
  [tool.bumpver]
33
- current_version = "0.2.0"
34
- version_pattern = "MAJOR.MINOR.PATCH"
35
- commit_message = "bump version {old_version} -> {new_version}"
39
+ current_version = "1.0.0b0"
40
+ version_pattern = "MAJOR.MINOR.PATCH[PYTAGNUM]"
41
+ commit_message = "chore: bump version {old_version} -> {new_version}"
36
42
  commit = true
37
43
  tag = true
38
44
  push = false
39
45
 
40
46
  [tool.bumpver.file_patterns]
41
- "pyproject.toml" = [
42
- 'current_version = "{version}"',
43
- 'version = "{version}"',
44
- ]
47
+ "pyproject.toml" = ['current_version = "{version}"', 'version = "{version}"']
45
48
  "src/earthscope_sdk/__init__.py" = ["{version}"]
49
+
50
+ [tool.pytest.ini_options]
51
+ asyncio_default_fixture_loop_scope = "function"
@@ -0,0 +1,5 @@
1
+ __version__ = "1.0.0b0"
2
+
3
+ from earthscope_sdk.client import AsyncEarthScopeClient, EarthScopeClient
4
+
5
+ __all__ = ["AsyncEarthScopeClient", "EarthScopeClient"]