Skip to content
Merged
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
e0bcaa1
3.0 branch
carl-adams-planet Apr 9, 2025
575dcf8
Merge branch 'main' into main-3.0-dev
carl-adams-planet Apr 10, 2025
c04fb72
Merge branch 'main' into main-3.0-dev
carl-adams-planet Apr 11, 2025
99fc41c
remove dead release workflow
carl-adams-planet Apr 12, 2025
06fbcd7
add step to releas to check doc status.
carl-adams-planet Apr 12, 2025
d0c7c21
Merge branch 'main' into main-3.0-dev
carl-adams-planet Apr 18, 2025
edf05dc
Merge branch 'main' into main-3.0-dev
carl-adams-planet Apr 24, 2025
4cd5f01
Merge branch 'main' into main-3.0-dev
carl-adams-planet Apr 25, 2025
62e53c2
Merge branch 'main' into main-3.0-dev
carl-adams-planet Apr 29, 2025
c721967
cicd for 3.x dev branches (#1127)
carl-adams-planet May 7, 2025
b29af00
Merge pull request #1128 from planetlabs/main
carl-adams-planet May 7, 2025
356b05e
oauth via plauth lib for main 3.0 dev branch (#1121)
carl-adams-planet May 15, 2025
db667ae
Merge pull request #1133 from planetlabs/main
carl-adams-planet May 15, 2025
154f418
Merge pull request #1145 from planetlabs/main
carl-adams-planet May 20, 2025
bedbf62
DRAFT: Update docs prior to pushing alpha out (#1140)
carl-adams-planet May 20, 2025
5e8c2d2
Merge pull request #1150 from planetlabs/main
carl-adams-planet May 28, 2025
6475f28
Merge pull request #1154 from planetlabs/main
carl-adams-planet Jun 6, 2025
94de3d4
Merge pull request #1157 from planetlabs/main
carl-adams-planet Jun 11, 2025
35ca9ef
Merge pull request #1158 from planetlabs/main
ischneider Jun 12, 2025
bc109b3
Merge pull request #1160 from planetlabs/main
carl-adams-planet Jun 25, 2025
7c2a57f
updates from beta feedback (#1148)
carl-adams-planet Jun 25, 2025
a527c05
bump dependencies (#1163)
carl-adams-planet Jul 9, 2025
1e58f02
Merge pull request #1166 from planetlabs/main
carl-adams-planet Jul 9, 2025
473bbce
update doc links
carl-adams-planet Jul 15, 2025
41fcf0d
Merge pull request #1167 from planetlabs/carl/3.0--release-update
carl-adams-planet Jul 15, 2025
19d39b0
Sync CLAUDE.md with main-3.0-dev (#1172)
asonnenschein Jul 24, 2025
4d3beef
Simplify subscription clip rules in the Subscriptions API SDK (#1169)
asonnenschein Jul 24, 2025
36a554b
Merge pull request #1174 from planetlabs/main
carl-adams-planet Jul 24, 2025
94e3b8d
initial mosaics cli + async client
ischneider May 12, 2025
d11d905
address feedback and typos
ischneider May 19, 2025
2530afb
add sync client and tests, minor fixups
ischneider May 21, 2025
e22b178
some tweaks
ischneider Jun 17, 2025
94b1fd2
Merge pull request #1131 from planetlabs/mosaics-api
ischneider Jul 24, 2025
4dbe92b
Refactor planetary_variable_source() signature (#1170)
asonnenschein Jul 25, 2025
1adae09
Sync client base_url option (#1171)
asonnenschein Jul 28, 2025
4fa0002
Add 'Additional Breaking Changes' section to v3.0 migration guide (#1…
asonnenschein Jul 28, 2025
c62bc30
Merge branch 'main' into carl/update-3.0-from-main
carl-adams-planet Jul 31, 2025
3ea85e6
fixing linting.
carl-adams-planet Jul 31, 2025
87fa4a1
Merging in post v2-to-v3 merge fixes for destinations manager (#1180)
charcey Aug 1, 2025
746a8bc
Merge pull request #1179 from planetlabs/carl/update-3.0-from-main
carl-adams-planet Aug 1, 2025
375f248
Merge branch 'main' into carl/update-3.0-from-main
carl-adams-planet Aug 1, 2025
f0f7176
Merge pull request #1182 from planetlabs/carl/update-3.0-from-main
carl-adams-planet Aug 1, 2025
fc6ceeb
Update documents for release (#1177)
carl-adams-planet Aug 1, 2025
1c70886
fix recursive call to download_quad in sync client
ischneider Aug 6, 2025
b0a8f71
Update active branches for 3.0 release
tbarsballe Aug 6, 2025
43b13f5
Carl/release merge cleanup (#1184)
carl-adams-planet Aug 6, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/publish-pypi.yml
Original file line number Diff line number Diff line change
@@ -24,7 +24,7 @@ jobs:
restore-keys: |
${{ runner.os }}-pip
- name: Build, verify, and upload to TestPyPI
- name: Build, verify, and upload to PyPI
run: |
pip install --upgrade nox
nox -s build publish_pypi
51 changes: 0 additions & 51 deletions .github/workflows/release.yml

This file was deleted.

2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -23,7 +23,9 @@ coverage.xml
*.pyc

# Editors
.idea/
.vscode/
# Docs build
site
.venv
venv
16 changes: 9 additions & 7 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -19,13 +19,15 @@ insofar as is practical within the scope of changes targeted to the next major r
versioning, major releases do not guarantee backwards compatibility. Stability is not guaranteed
during the development cycle.

During the development cycle of a new major release, `RELEASE-PLANNING-X.0.md` should be maintained
with a brief summary of the major and breaking changes underpinning the reason for the upcoming
major release version. Upon release, this content is expected to be folded into package documentation
as appropriate, and this file should be removed.

When a new major release is ready, the development mainline branch will be renamed to `main`, and the
old mainline branch will be renamed to `maint-X.0` and will be used as the base for maintenance releases.
During the development cycle of a new major release, a GitHub Project and Milestone should be
created to track changes targeted the release. A file such as `RELEASE-PLANNING-X.0.md` in the
root of the source tree may be used for early development prior to the creation of a GitHub
project, but should be retired when a new release becomes more formalized. Upon release,
all content is expected to be folded into package documentation as appropriate (announcements,
company blog posts, changelogs, migration guides, etc.).

When a new major release is ready, the old mainline branch will be copied to `maint-X.x` (e.g. `maint-2.x`),
to be used as the base for maintenance releases, and the development mainline branch will be merged into to `main`

#### Development Branches

23 changes: 11 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
@@ -7,15 +7,15 @@ The [Planet](https://planet.com) Software Development Kit (SDK) for Python
provides both a Python API and a command-line interface (CLI)
to make use of [the Planet APIs](https://docs.planet.com/develop/apis/).
Everything you need to get started is found in our
[online documentation](https://planet-sdk-for-python-v2.readthedocs.io/en/latest/).
[online documentation](https://planet-sdk-for-python.readthedocs.io/en/latest/).

Version 2.0 includes support for the core workflows of the following APIs:

* [Data](https://docs.planet.com/develop/apis/data/) - Search for imagery from Planet's data catalog.
* [Orders](https://docs.planet.com/develop/apis/orders/) - Process and download or deliver imagery.
* [Subscriptions](https://docs.planet.com/develop/apis/subscriptions/) - Set up a search to auto-process and deliver imagery.
* [Features](https://docs.planet.com/develop/apis/features/) - Upload areas of interest to the Planet platform.
* [Destinations] (https://docs.planet.com/develop/apis/destinations/) - Create destinations to securely store cloud credentials.
* [Destinations](https://docs.planet.com/develop/apis/destinations/) - Create destinations to securely store cloud credentials.

After the initial 2.0 release there will be additional work to support the
remaining Planet APIs: [basemaps](https://docs.planet.com/develop/apis/basemaps/),
@@ -34,7 +34,7 @@ with semantic version identifiers that comply with [PEP 440](https://peps.python
The Semantic Versioning stability scheme only applies to APIs that
are considered part of the public API. This includes library APIs exported
from the `planet` package and documented in our
[SDK developer documentation](https://planet-sdk-for-python-v2.readthedocs.io/en/latest/),
[SDK developer documentation](https://planet-sdk-for-python.readthedocs.io/en/latest/),
and the `planet` CLI interface used for scripts. It does not include
library interfaces below the top level `planet` Python package which are
considered internal and subject to change without notice.
@@ -82,11 +82,11 @@ See [CONTRIBUTING.md](CONTRIBUTING.md#branches) for more information on branches

##### Current Mainline Versions and Branches

| Version | Status | Branch | Documentation | Initial Release | End of Active Development | End of Maintenance | Notes |
|---------|---------------|----------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------|-----------------|---------------------------|--------------------|------------------------------------------------------------------------------------------------------------------------------|
| 3.x | `development` | [`main-3.0-dev`](https://github.com/planetlabs/planet-client-python/tree/main-3.0-dev) | TBD | TBD | TBD | TBD | See [RELEASE-PLANNING-X.0.md](https://github.com/planetlabs/planet-client-python/tree/main-3.0-dev/RELEASE-PLANNING-3.0.md). |
| 2.x | `active` | [`main`](https://github.com/planetlabs/planet-client-python/tree/main) | [Planet Labs Python Client v2 on Readthedocs.io](https://planet-sdk-for-python-v2.readthedocs.io/en/latest/) | April 2023 | TBD | TBD | |
| 1.x | `end-of-life` | [`v1`](https://github.com/planetlabs/planet-client-python/tree/v1) | [Planet Labs Python Client v1 on Github.io](https://planetlabs.github.io/planet-client-python/) | April 2017 | April 2023 | TBD | |
| Version | Status | Branch | Documentation | Initial Release | End of Active Development | End of Maintenance | Notes |
|---------|---------------|----------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------|-----------------|---------------------------|--------------------|------------------------------------------------------------------------------------------------------------------------------|
| 3.x | `active` | [`main`](https://github.com/planetlabs/planet-client-python/tree/main) | TBD | TBD | TBD | TBD | See [RELEASE-PLANNING-X.0.md](https://github.com/planetlabs/planet-client-python/tree/main-3.0-dev/RELEASE-PLANNING-3.0.md). |
| 2.x | `maintenance` | [`maint-2.x`](https://github.com/planetlabs/planet-client-python/tree/maint-2.x) | [Planet Labs Python Client v2 on Readthedocs.io](https://planet-sdk-for-python-v2.readthedocs.io/en/latest/) | April 2023 | TBD | TBD | |
| 1.x | `end-of-life` | [`v1`](https://github.com/planetlabs/planet-client-python/tree/v1) | [Planet Labs Python Client v1 on Github.io](https://planetlabs.github.io/planet-client-python/) | April 2017 | April 2023 | TBD | |

## Installation and Quick Start

@@ -104,20 +104,19 @@ pip install .

Note that the above commands will install the Planet SDK into the global system Python unless a virtual environment is enabled. For more information on configuring a virtual environment from system Python, see the official Python [venv](https://docs.python.org/3/library/venv.html) documentation. For users who are running multiple versions of Python via [pyenv](https://github.com/pyenv/pyenv), see the [pyenv-virtualenv](https://github.com/pyenv/pyenv-virtualenv) extension documentation.

Detailed installation instructions for the Planet SDK can be found in the [Quick Start Guide](https://planet-sdk-for-python-v2.readthedocs.io/en/latest/get-started/quick-start-guide/) of the documentation.
Detailed installation instructions for the Planet SDK can be found in the [Quick Start Guide](https://planet-sdk-for-python.readthedocs.io/en/latest/get-started/quick-start-guide/) of the documentation.

## Contributing and Development

To contribute or develop with this library, see [CONTRIBUTING.md](CONTRIBUTING.md).

## Documentation

Documentation is currently [hosted online](https://planet-sdk-for-python-v2.readthedocs.io/en/latest/)
Documentation is currently [hosted online](https://planet-sdk-for-python.readthedocs.io/en/latest/)
It should be considered 'in progress', with many updates to come. It can also
be built and hosted locally (see [CONTRIBUTING.md](CONTRIBUTING.md)) or can be
read from source in the [docs](/docs) directory.

## Authentication

Planet's APIs require an account for use. To get started you need to
[Get a Planet Account](https://planet-sdk-for-python-v2.readthedocs.io/en/latest/get-started/get-your-planet-account/).
Planet's APIs require an account for use. To learn how to authenticate, see the [client authentication overview](https://planet-sdk-for-python.readthedocs.io/en/latest/auth/auth-overview/)
1 change: 0 additions & 1 deletion RELEASE.md
Original file line number Diff line number Diff line change
@@ -54,7 +54,6 @@ The SDK follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html) and t
* _`version`_: [https://planet-sdk-for-python-v2.readthedocs.io/en/X.YY.ZZ/](https://planet-sdk-for-python-v2.readthedocs.io/en/X.YY.ZZ/) - Should point to version `X.YY.ZZ`.
* Pre-release versions should _not_ impact the default version of the documentation. Pre-release version may be published as the `latest` version.


## Local publishing

Publishing to testpypi and pypi can also be performed locally with:
39 changes: 39 additions & 0 deletions docs/auth/auth-dev-app-managed-apikey.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Application Managed Sessions - Planet API Key

## Planet API Key Sessions
Legacy applications that need to continue to support Planet API keys may do so
until API keys are deprecated. This method should not be adopted for new
development if possible.

### Examples - Planet API Keys

#### In Memory Session State
Once provided with an API key, an application may operate with the API key
in memory indefinitely without the need to prompt the user for re-authentication.
```python linenums="1" title="Access APIs using Planet API keys in memory"
{% include 'auth-session-management/app_managed_auth_state__in_memory__api_key.py' %}
```

#### Version 2 Compatibility
The SDK continues to support files written by version 2 of the SDK to save
auth state.
```python linenums="1" title="Access APIs using Planet API keys using the on disk file format used by older versions of the SDK"
{% include 'auth-session-management/app_managed_auth_state__on_disk_legacy__api_key.py' %}
```

```json linenums="1" title="Legacy API Key file example"
{% include 'auth-session-management/legacy_api_key_file.json' %}
```

#### Session State Shared with CLI
```python linenums="1" title="Access APIs using Planet API keys with CLI managed shared state on disk"
{% include 'auth-session-management/app_managed_auth_state__on_disk_cli_shared__api_key.py' %}
```

#### Session State Saved to Application Storage

```python linenums="1" title="Access APIs using Planet API keys with sessions persisted to application provided storage"
{% include 'auth-session-management/app_managed_auth_state__app_custom_storage__api_key.py' %}
```

----
174 changes: 174 additions & 0 deletions docs/auth/auth-dev-app-managed-oauth.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
# Application Managed Sessions - OAuth2

If an application cannot or should not use a login session initiated by the
[`planet auth`](../../cli/cli-reference/#auth) CLI command, the application will be
responsible for managing the process on its own, persisting session state as
needed.

Application managed sessions may be used with all authentication protocols.
Application developers may control whether sessions are visible to the CLI.
This is managed with the `save_state_to_storage` parameter on the `planet.Auth`
constructor methods illustrated below.

The process varies depending on the authentication protocol used.
Depending on the use case, applications may need to support multiple authentication
methods, just as the [`planet`](../../cli/cli-reference) CLI command supports interacting with Planet APIs
using either a user or a service user account.

## OAuth2 Session for Users
User session initialization inherently involves using a web browser to
complete user authentication. This architecture allows for greater security
by keeping the user's password from being directly exposed to the application
code. This also allows for flexibility in user federation and multifactor
authentication procedures without the complexity of these needing to
be exposed to the application developer who is focused on geospatial
operations using the Planet platform, and not the nuances of user
authentication and authorization.

### OAuth2 User Client Registration
Developers of applications must register client applications with Planet, and
will be issued a Client ID as part of that process. Developers should register
a client for each distinct application so that end-users may discretely manage
applications permitted to access Planet APIs on their behalf.

See [OAuth2 Client Registration](http://docs.planet.com/develop/authentication/#interactive-client-registration)
for more information.

### With a Local Web Browser
In environments where a local browser is available, the Planet SDK library can manage
the process of launching the browser locally, transferring control to the Planet
authorization services for session initialization, and accepting a network
callback from the local browser to regain control once the authorization
process is complete. At a network protocol level, this establishes the user
login session using the OAuth2 authorization code flow.

To use this method using the SDK, the following requirements must be met:

* The application must be able to launch a local web browser.
* The web browser must be able to connect to Planet services.
* The application must be able to listen on a network port that is accessible
to the browser.

#### Examples - OAuth2 Authorization Code Flow

##### In Memory Session State
When an application cannot safely store user session state, it may operate purely in memory. When this
method is used, the user will be prompted to complete the login process each time the application is run.

```python linenums="1" title="Login as a user using a local browser with in memory only state persistance"
{% include 'auth-session-management/app_managed_auth_state__in_memory__oauth_user_authcode__with_browser.py' %}
```

##### Session State Shared with CLI
Applications may save their session state in a way that is shared with the CLI. With saved state,
the user will only be prompted to complete the login process once.
```python linenums="1" title="Login as a user using a local browser with sessions persisted on disk and shared with the CLI"
{% include 'auth-session-management/app_managed_auth_state__on_disk_cli_shared__oauth_user_authcode__with_browser.py' %}
```

##### Session State Saved to Application Storage
Applications may save their session state to application provided storage. With saved state,
the user should only be prompted to complete the login process once. Using application provided storage
will result in the session state not being shared with the CLI.

Applications needing to use their own storage will do so by providing
the `Auth` layer in the SDK with a custom implementation of the
[`planet_auth.ObjectStorageProvider`](https://planet-auth.readthedocs.io/en/latest/api-planet-auth/#planet_auth.ObjectStorageProvider)
abstract base class. See examples below for more details.

```python linenums="1" title="Login as a user using a local browser with sessions persisted to application provided storage"
{% include 'auth-session-management/app_managed_auth_state__app_custom_storage__oauth_user_authcode__with_browser.py' %}
```

### Without a Local Web Browser
In environments where a local web browser is not available, additional steps must
be taken by the application author to initialize the user session.
For example, a remote shell to a cloud environment is not likely
to be able to open a browser on the user's desktop or receive network callbacks
from the user's desktop browser. In these cases, a browser is
still required. To complete login in such a case, the SDK will generate a URL and a
verification code that must be presented to the user. The user must visit the
URL out of band to complete the login process while the application polls for
the completion of the login process using the SDK. At a network protocol
level, this establishes the user login session using the OAuth2 device
code flow.

To use this method using the SDK, the following requirements must be met:

* The application must be able to connect to Planet services.
* The application must be able to display instructions to the user, directing
them to a web location to complete login.

As above, this may be done with state only persisted in memory, with state
shared with the CLI, or with state saved to application provided storage.

#### Examples - OAuth2 Device Code Flow

##### In Memory Session State
```python linenums="1" title="Login as a user using an external browser with in memory only state persistance"
{% include 'auth-session-management/app_managed_auth_state__in_memory__oauth_user_devicecode__external_browser.py' %}
```

##### Session State Shared with CLI
```python linenums="1" title="Login as a user using an external browser with sessions persisted on disk and shared with the CLI"
{% include 'auth-session-management/app_managed_auth_state__on_disk_cli_shared__oauth_user_devicecode__external_browser.py' %}
```

##### Session State Saved to Application Storage
```python linenums="1" title="Login as a user using an external browser with sessions persisted to application provided storage"
{% include 'auth-session-management/app_managed_auth_state__app_custom_storage__oauth_user_devicecode__external_browser.py' %}
```

## OAuth2 Session for Service Accounts
Service account session initialization is simpler than user session
initialization, and does not require a web browser.

While preserving session state for user sessions was a concern driven
in part by a concern for the user experience of using a web browser for
initialization, for service accounts it remains a concern to avoid
throttling by the authorization service.

If applications are expected to run longer than the life of an access token
(a few hours), then in memory operations are acceptable (for example: a long-running
data processing job). If application lifespan is short and frequent,
then the application should take steps to persist the session state (for
example: a command line utility run repeatedly from a shell with a short lifespan).

Like the session state itself, service account initialization parameters are
sensitive, and it is the responsibility of the application to store them
securely.

At a network protocol level, OAuth2 service account sessions are implemented
using the OAuth2 authorization code flow. This carries with it some additional
security concerns, discussed in
[RFC 6819 §4.4.4](https://datatracker.ietf.org/doc/html/rfc6819#section-4.4.4).
Because of these considerations, service accounts should only be used for
workflows that are independent of a controlling user.

As above, this may be done with state only persisted in memory, with state
shared with the CLI, or with state saved to application provided storage.

### OAuth2 M2M Client Registration
Service accounts are managed under the
**OAuth Clients** panel on the [Planet Insights Account](https://insights.planet.com/account/#/) page.

See [Sentinel Hub Authentication](https://docs.sentinel-hub.com/api/latest/api/overview/authentication/) for further information.

### Examples - OAuth2 Client Credentials Flow

#### In Memory Session State
```python linenums="1" title="Access APIs using a service account with in memory only state persistance"
{% include 'auth-session-management/app_managed_auth_state__in_memory__oauth_m2m.py' %}
```

#### Session State Shared with CLI
```python linenums="1" title="Access APIs using a service account with sessions persisted on disk and shared with the CLI"
{% include 'auth-session-management/app_managed_auth_state__on_disk_cli_shared__oauth_m2m.py' %}
```

#### Session State Saved to Application Storage
```python linenums="1" title="Access APIs using a service account with sessions persisted to application provided storage"
{% include 'auth-session-management/app_managed_auth_state__app_custom_storage__oauth_m2m.py' %}
```

----
110 changes: 110 additions & 0 deletions docs/auth/auth-dev-cli-managed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
# CLI Managed Sessions
For simple programs and scripts, it is easiest for the program to defer
session management to the [`planet auth`](../../cli/cli-reference/#auth)
CLI. This method will store session information in the user's home directory
in the `~/.planet.json` file and `~/.planet/` directory. The Python SDK will
use the information saved in these locations to make API calls.

When this approach is taken, the authentication session will be shared between
actions taken by the `planet` utility and those taken by programs built
using the SDK. Changes made by one will impact the behavior of the other.

CLI managed sessions can be used for all authentication protocols supported
by the SDK library.

**Requirements and Limitations:**

* The program must have read and write access to the user's home directory.
* This method requires that the end-user has access to and understands
the [`planet`](../../cli/cli-reference) CLI command needed to manage
authentication.
* This approach should not be used on public terminals or in cases where the
user's home directory cannot be kept confidential.

## Initialize Session - CLI Login
Session login can be performed using the following command. This command can
be used to initialize sessions using any of the supported authentication methods,
and will default to creating an OAuth2 user session.
Refer to the command's `--help` for more information.

<a name="planet-auth-login"></a>
```shell title="Initialize session using planet CLI."
planet auth login
```

A particular configuration may be selected by using the `--auth-profile` option.
`planet-user` is the default, but may be [overridden](../auth-sdk/#configuration)
by the runtime environment.

<a name="planet-auth-login-planet-user"></a>
```shell title="Initialize session using planet CLI, forcing the built-in user interactive OAuth2 login flow."
planet auth login --auth-profile planet-user
```

<a name="planet-auth-login-planet-m2m"></a>
```shell title="Initialize session using planet CLI, forcing the use of the specified service principal."
planet auth login --auth-client-id <your-client-id> --auth-client-secret <your-client-secret>
```

<a name="planet-auth-login-planet-apikey"></a>
```shell title="Initialize session using planet CLI, forcing the use of a legacy Planet API key."
planet auth login --auth-api-key <your-api-key>
```

## Using Saved Session
Using a CLI managed session is the default behavior for SDK functions.
Developing an application that uses a CLI managed session requires no additional
action by the developer. When a developer chooses to create an application
that behaves in this way, it will most often be done implicitly by relying
on SDK default behavior, but it may also be done explicitly.

### CLI Selected Session
The default behavior of the SDK is to defer which session is loaded to CLI.

<a name="use-cli-session-implicit"></a>
```python linenums="1" title="Implicitly use CLI managed login sessions, deferring session selection to the user and the CLI."
{% include 'auth-session-management/cli_managed_auth_state__implicit.py' %}
```
<a name="use-cli-session-explicit"></a>
```python linenums="1" title="Explicitly use CLI managed login sessions, deferring session selection to the user and the CLI."
{% include 'auth-session-management/cli_managed_auth_state__explicit.py' %}
```

### Application Selected Session
Applications may be developed to always select a specific CLI managed profile.
This may be useful in cases where an application wishes to guide the user
experience towards expecting an auth session that is separate from the default
sessions used by the CLI.

In cases where the application has access to the
user's home directory and saved sessions, forcing the use of a particular
profile circumvents the user's CLI managed preferences.

<a name="use-cli-session-force-custom"></a>
Note: This first example does not create the session `my-app-profile`.
This must be created either through a separate code path as show in
the [Application Managed Sessions](../auth-dev-app-managed-oauth) guide,
or by using a CLI command to copy an existing profile such as
`planet auth profile copy planet-user my-app-profile`.

```python linenums="1" title="Use a specific session that is shared with the CLI."
{% include 'auth-session-management/cli_managed_auth_state__specific_auth_profile.py' %}
```

<a name="use-cli-session-force-builtin"></a>
It is also possible to force the use of the SDK's built-in OAuth2 application ID
for interactive user applications. This capability is provided for developer
convenience, primarily for smaller programs and scripts. Larger applications
developed for multiple users should
[register](../auth-dev-app-managed-oauth/#oauth2-user-client-registration)
a unique application ID.

This second example also initiates a login and does not save session state to storage.
This means this example does not depend on the CLI, and may be considered a simple
example of an [Application Managed Session](../auth-dev-app-managed-oauth).

```python linenums="1" title="Use the Planet SDK with an OAuth2 user session initialized by the application and utilizing the SDK's built-in OAuth2 application ID."
{% include 'auth-session-management/app_managed_auth_state__using_sdk_app_id.py' %}
```

---
126 changes: 126 additions & 0 deletions docs/auth/auth-overview.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
# Client Authentication Overview

## Introduction
All calls to Planet APIs must be authenticated. Only authorized clients may
use Planet Platform APIs.

For general information on how to authenticate to Planet APIs, please see
the [Authentication](https://docs.planet.com/develop/authentication/) section of Planet's platform documentation.
This documentation focuses on the use of the Planet Python SDK and
[`planet`](../../cli/cli-reference) CLI.

!!! info
Work to unify authentication practices between `api.planet.com` and `services.sentinel-hub.com`
is ongoing and being rolled out in phases over time. Documentation referring
to work in progress is marked as such 🚧.

Of particular note is the general shift towards OAuth2 based authentication,
and a corresponding move away from Planet API keys.

----

## Authentication Protocols
At the HTTP protocol level underneath the SDK, there are several distinct
ways a client may authenticate to the Planet APIs, depending on the use case.
See [Authentication Protocols](https://docs.planet.com/develop/authentication/#authentication-protocols) for a
complete discussion of when to choose a particular method.

* **OAuth2 user access tokens** - API access as the end-user, using OAuth2
user access tokens. This is the preferred way for user-interactive
applications to authenticate to Planet APIs. A registered client application
and a web browser are required to initialize a session. A web browser is not
required for continued operation. The SDK itself is a registered
client application that may be used for this purpose.

Examples of applications that fall into this category include
[ArcGIS Pro](https://www.esri.com/en-us/arcgis/products/arcgis-pro/overview),
[QGIS](https://qgis.org/), and the SDK's own [`planet`](../../cli/cli-reference)
CLI program. All Planet first-party web applications also use this method.

* **OAuth2 M2M access tokens** (🚧 _Work in progress_) - API access as a service user, using OAuth2
M2M access tokens. This is the new preferred way for automated processes
to authenticate to Planet APIs that must operate without a human user.
No web browser is required, but this method carries some additional
security considerations.

* **Planet API keys** (⚠️ _Pending future deprecation_) - API access as a Planet end-user using a simple
fixed string bearer key. This is the method that has historically been
documented and recommended for developers using Planet APIs.

### OAuth2
OAuth2 authentication requires that the client possess an access token
in order to make API calls. Access tokens are obtained by the client from
the Planet authorization server, which is separate from the API servers, and are
presented by the client to API services to assert the client's right to make
API calls.

Unlike Planet API keys, access tokens do not last forever for a variety of
reasons and must be regularly refreshed by the client before their expiration.
When using the Planet SDK, many of the details of obtaining and refreshing
OAuth2 access tokens will be taken care of for you.

OAuth2 defines many different ways to obtain access tokens, and a full discussion
is beyond the scope of this SDK user guide. Please refer to the [Resources](#resources)
below for more information. Planet broadly divides OAuth2 use cases into
user-interactive and machine-to-machine use cases, as described in this guide.

**SDK Examples:**

* **OAuth2 user access tokens**
* [Using the CLI (Quick start)](../auth-dev-cli-managed/#planet-auth-login-planet-user)
* [Forcing use of SDK Built-in Application ID in code (Quick start)](../auth-dev-cli-managed/#use-cli-session-force-builtin)
* [Using a custom registered application ID](../auth-dev-app-managed-oauth/#oauth2-session-for-users)
* **OAuth2 M2M access tokens**
* [Using the CLI (Quick start)](../auth-dev-cli-managed/#planet-auth-login-planet-m2m)
* [Using a M2M Access Token in code](../auth-dev-app-managed-oauth/#oauth2-session-for-service-accounts)

!!! info
OAuth2 user access tokens currently work for all Planet APIs under both
the `api.planet.com` and `services.sentinel-hub.com` domains.

🚧 OAuth2 machine-to-machine (M2M) access tokens are currently available for use
with `services.sentinel-hub.com` APIs. Work to support `api.planet.com` is
ongoing. It should also be noted that at this time no API clients for
`services.sentinel-hub.com` APIs have been incorporated into this SDK.
The SDK may still be used to obtain and manage M2M access tokens to
support external applications.

### Planet API Keys
Planet API keys are simple fixed strings that may be presented by the client
to API services to assert the client's right to access APIs. API keys are
obtained by the user from their [Account](https://www.planet.com/account) page
under the [_My Settings_](https://www.planet.com/account/#/user-settings) tab.

**SDK Examples:**

* **Planet API keys**
* [Using the CLI (Quick start)](../auth-dev-cli-managed/#planet-auth-login-planet-apikey)
* [Using a Planet API Key in code](../auth-dev-app-managed-apikey)


!!! warning
Planet API keys are being targeted for eventual deprecation in favor
of OAuth2 mechanisms for most use cases. No specific timeframe has been
set for disabling API keys, but new development should use OAuth2
mechanisms where possible.

Planet API keys will work for Planet APIs underneath `api.planet.com`, but
will **NOT** work for APIs underneath `services.sentinel-hub.com`.

There is no plan for API keys to ever be supported by APIs underneath
`services.sentinel-hub.com`.

----

## Resources
More information regarding Authentication to Planet APIs, OAuth2, and JWTs
may be found here:

* [Planet Authentication](https://docs.planet.com/develop/authentication/)
* [RFC 6749 - The OAuth 2.0 Authorization Framework](https://datatracker.ietf.org/doc/html/rfc6749)
* [RFC 8628 - OAuth 2.0 Device Authorization Grant](https://datatracker.ietf.org/doc/html/rfc8628)
* [RFC 7519 - JSON Web Token (JWT)](https://datatracker.ietf.org/doc/html/rfc7519)
* [RFC 9068 - JSON Web Token (JWT) Profile for OAuth 2.0 Access Tokens](https://datatracker.ietf.org/doc/html/rfc9068)
* [RFC 6819 - OAuth 2.0 Threat Model and Security Considerations](https://datatracker.ietf.org/doc/html/rfc6819)

----
133 changes: 133 additions & 0 deletions docs/auth/auth-sdk.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
# Authentication with the SDK

## Overview
The [`planet.Auth`](../../python/sdk-reference/#planet.auth.Auth) class is the
main class that is responsible for managing how clients built with the SDK
authenticate to the Planet Insights Platform API services. By default,
API clients provided by the SDK will create an `Auth` instance that is connected
to login sessions managed by the [`planet auth`](../../cli/cli-reference/#auth)
CLI utility, with state saved to the `.planet.json` file and `.planet`
directory in the user's home directory.

When applications require more control over the authentication process,
constructor methods on the [`planet.Auth`](../../python/sdk-reference/#planet.auth.Auth)
class may be used to create instances with specific configurations.
`Auth` instances may then be wrapped in [`planet.Session`](../../python/sdk-reference/#planet.http.Session)
objects so they can be attached to the
[`planet.Planet`](../../python/sdk-reference/#planet.client.Planet) synchronous
client, or various [asynchronous API clients](../../python/async-sdk-guide/) provided by the SDK.

## Configuration

When determining how to authenticate requests made against the Planet
APIs, the default behavior of the SDK and the Planet CLI is to load
configuration from a number of sources at runtime:

- Highest priority is given to arguments passed to the [`Auth`](../../python/sdk-reference/#planet.auth.Auth)
class (when using the SDK) or via the command line (when using the CLI).
When saving preferences using the CLI, configuration is saved to
configuration files (below).
- Next, environment variables are checked.
Of these, `PL_API_KEY` has been used by Planet software for many years,
and is the most likely to be set in a user's environment.
The other environment variables are new to version 3 of the Planet Python SDK.
**Note**: This means that environment variables override configuration
saved by the `planet` CLI program. See [Environment Variables](#environment-variables)
below.
- Then, the configuration file `.planet.json` and files underneath
the `.planet` directory in the user's home directory are consulted.
These configuration files may be managed with the
[`planet auth profile`](../../cli/cli-reference/#profile) CLI command.
- Finally, built-in defaults will be used.

### Environment Variables
When the SDK is not otherwise explicitly configured by an application,
or behavior is not overridden by command-line arguments, the following
environment variables will be used:

| Variable | Description |
|-----------------------------|-------------------------------------------------------------------------------------------------------------------------------|
| **`PL_AUTH_PROFILE`** | Specify a custom CLI managed auth client profile by name. This must name a valid CLI managed profile or an error will occur. |
| **`PL_AUTH_CLIENT_ID`** | Specify an OAuth2 M2M client ID. `PL_AUTH_CLIENT_SECRET` must also be specified, or this will be ignored. |
| **`PL_AUTH_CLIENT_SECRET`** | Specify an OAuth2 M2M client secret. `PL_AUTH_CLIENT_ID` must also be specified, or this will be ignored. |
| **`PL_AUTH_API_KEY`** | Specify a legacy Planet API key. |

When multiple conflicting environment variables are set, `PL_AUTH_PROFILE` is
preferred over `PL_AUTH_CLIENT_ID` and `PL_AUTH_CLIENT_SECRET`, which are
preferred over `PL_AUTH_API_KEY`.

### Reset User Configuration
The following commands may be used to clear an environment of any
previously configured settings:

```sh title="Clear saved authentication settings"
unset PL_API_KEY
unset PL_AUTH_PROFILE
unset PL_AUTH_CLIENT_ID
unset PL_AUTH_CLIENT_SECRET
planet auth reset
```

## Profiles
Collectively, the configuration of the SDK to use a specific authentication
protocol (see [overview](../auth-overview#authentication-protocols)) and a
working set of session state information is termed a _profile_ by the SDK
and the CLI. Profiles are an abstraction of the SDK and the CLI, and are
not inherent to authentication to the Planet platform generally.

The [`planet auth profile`](../../cli/cli-reference/#profile) CLI command
is provided to manage persistent profiles and sessions in the user's home
directory. These home directory persisted profiles are shared between the CLI
and applications built using the SDK.

Applications built using the SDK may be configured to bypass home directory
profile and session storage, if this better suits the needs of the application.
See [Applicaiton Managed Sessions](../auth-dev-app-managed-oauth) for detailed
examples.

## Sessions

Before any calls can be made to a Planet API using the SDK, it is
necessary for the user to login and establish an authentication session.
Exactly how this should be done with the SDK depends on the
application's complexity and needs.

In simple cases, this may be managed external to the application
by using the [`planet auth`](../../cli/cli-reference/#auth)
command-line utility. See [CLI Managed Sessions](../auth-dev-cli-managed)
for examples.

In more complex cases, an application may need to manage the
stored session itself independent of utilities provided by the CLI. In such
cases, the application will be responsible for instantiating a `planet.Auth`
object, initiating user login, and saving the resulting session information.
Session information may contain sensitive information such as access and
refresh tokens, and must be stored securely by the application. Session
information will also be regularly updated during SDK operations, so the
application must handle callbacks to store updated session information.
See [Application Managed Sessions](../auth-dev-app-managed-oauth)
for examples.

### Session Persistence

Once a user login session is established using any method, the state should be
saved to secure persistent storage to allow for continued access to the Planet
platform without the need to perform the login repeatedly. If state cannot
be persisted in the application environment, the application can operate in
in-memory mode, but will be forced to create a new login session every time the
application is run. If the rate of repeated logins is too great, this may
result in throttling by the authorization service. Particular attention should
be paid to this when creating automated processes that utilize service users.

The SDK provides the option to save session state in the user's
home directory in a way that is compatible with the CLI.
When [CLI Managed Sessions](../auth-dev-cli-managed) are used, no additional
steps should be required of the application developer.

The SDK also provides a way for the application to provide its own secure
storage. Applications needing to use their own storage will do so by
providing the `Auth` layer in the SDK with a custom implementation of the
[`planet_auth.ObjectStorageProvider`](https://planet-auth.readthedocs.io/en/latest/api-planet-auth/#planet_auth.ObjectStorageProvider)
abstract base class.

----
49 changes: 17 additions & 32 deletions docs/cli/cli-guide.md
Original file line number Diff line number Diff line change
@@ -35,67 +35,53 @@ Yes. Even if you’re not writing code—and only using the "no code" CLI part o
Install the Planet SDK for Python using [pip](https://pip.pypa.io):

```console
$ pip install planet
pip install planet
```

## Step 3: Check the Planet SDK for Python version

```console
$ planet --version
planet --version
```

You should be on some version 2 of the Planet SDK for Python.

## Step 4: Sign on to your account

Planet SDK for Python, like the Planet APIs, requires an account for use.

### Have your Planet account username and password ready

To confirm your Planet account, or to get one if you don’t already have one, see [Get your Planet Account](../get-started/get-your-planet-account.md).

### Authenticate with the Planet server

Just as you log in when you browse to https://account.planet.com, you’ll want to sign on to your account so you have access to your account and orders.
Planet SDK for Python, like the Planet APIs, requires an account for use. Just as you log in when you browse to https://planet.com/account, you’ll want to sign on to your account so you have access to your account and orders.

At a terminal console, type the following Planet command:

```console
$ planet auth init
planet auth login
```

You’ll be prompted for the email and password you use to access [your account](https://account.planet.com). When you type in your password, you won’t see any indication that the characters are being accepted. But when you hit enter, you’ll know that you’ve succeeded because you’ll see on the command line:
A browser window should be opened, and you will be directed to login to your account. This
command will wait for the browser login to complete, and should exit shortly afterwards.
When this process succeeds, you will see the following message on the console:

```console
Initialized
Login succeeded.
```

### Get your API key

Now that you’ve logged in, you can easily retrieve your API key that is being used for requests with the following command:

If you are in an environment where the `planet` command line utility cannot open a browser (such
as a remote shell on a cloud service provider), use the following command and follow the instructions:
```console
planet auth value
planet auth login --no-open-browser
```

Many `planet` calls you make require an API key. This is a very convenient way to quickly grab your API key.

#### Your API Key as an Environment Variable
### Get your Access Token

You can also set the value of your API Key as an environment variable in your terminal at the command line:
Now that you’ve logged in, you can easily retrieve an Access Token that is being used for requests with the following command:

```console
export PL_API_KEY=<your api key>
planet auth print-access-token
```

And you can see that the value was stored successfully as an environment variable with the following command:

```console
echo $PL_API_KEY
```
Many `planet` calls you make require an access token. This is a very convenient way to quickly grab the current access token.

!!!note "The API Key environment variable is ignored by the CLI but used by the Python library"
If you do create a `PL_API_KEY` environment variable, the CLI will be unaffected but the Planet library will use this as the source for authorization instead of the value stored in `planet auth init`.
**Note** : As a security measure, access tokens are time limited. They have a relatively short lifespan, and must
be refreshed. The `print-access-token` command takes care of this transparently for the user.

## Step 5: Search for Planet Imagery

@@ -147,4 +133,3 @@ As The Planet SDK (V2) is in active development, features & functionality will c
If there's something you're missing or are stuck, the development team would love to hear from you.

- To report a bug or suggest a feature, [raise an issue on GitHub](https://github.com/planetlabs/planet-client-python/issues/new)
- To get in touch with the development team, email [developers@planet.com](mailto:developers@planet.com)
2 changes: 2 additions & 0 deletions docs/cli/cli-reference.md
Original file line number Diff line number Diff line change
@@ -4,8 +4,10 @@ title: CLI Reference

This page provides documentation for our command line tools.

{% raw %}
::: mkdocs-click
:module: planet.cli.cli
:command: main
:prog_name: planet
:depth: 1
{% endraw %}
23 changes: 11 additions & 12 deletions docs/cli/cli-subscriptions.md
Original file line number Diff line number Diff line change
@@ -451,22 +451,21 @@ planet subscriptions request-catalog \
--filter filter.json > request-catalog.json
```

### Planetary Variable Request

Subscribing to Planetary Variables is much like subscribing to imagery from
Planet's catalog. The `planet subscriptions request-pv` command can construct the source
part of a Planetary Variable request like `request-catalog` does for cataloged
imagery. Planetary Variable subscriptions come in 4 types and are further
subdivided within these types by an identifier. See [Subscribing to Planetary
Variables](https://docs.planet.com/develop/apis/subscriptions/sources/#planetary-variable-and-analysis-ready-source-types)
for details. To constrain data delivery by space and time, you will use the
### Planetary Variable and Analysis-Ready Source Requests

Subscribing to Planetary Variables and Analysis-Ready data is much like subscribing to imagery from
Planet's catalog. The `planet subscriptions request-source` command can construct the source
part of a Planetary Variable or Analysis-Ready source request like `request-catalog` does for cataloged
imagery. See [Subscribing to Planetary
Variables and Analysis Ready sources](https://docs.planet.com/develop/apis/subscriptions/sources/#planetary-variable-and-analysis-ready-source-types)
for details about different product options. To constrain data delivery by space and time, you will use the
`--geometry`, `start-time`, and `end-time` options described above.

```sh
planet subscriptions request-pv \
--var-id BIOMASS-PROXY_V3.0_10 \
planet subscriptions request-source \
--source-id BIOMASS-PROXY_V3.0_10 \
--geometry geometry.geojson \
--start-time 2022-08-24T00:00:00-07:00 > request-pv.json
--start-time 2022-08-24T00:00:00-07:00 > request-source.json
```

### Subscription Tools
3 changes: 0 additions & 3 deletions docs/custom_theme/home.html
Original file line number Diff line number Diff line change
@@ -14,9 +14,6 @@ <h1>
<a href="./{{ 'get-started/quick-start-guide' | url }}" title="Get Started" class="md-button md-button--primary md-button--teriary">
Get started
</a>
<a href="./{{ 'get-started/get-your-planet-account' | url }}" title="Get your Planet account" class="md-button md-button--secondary">
Get a Planet account
</a>
</div>
</div>
</div>
34 changes: 0 additions & 34 deletions docs/get-started/get-your-planet-account.md

This file was deleted.

12 changes: 7 additions & 5 deletions docs/get-started/quick-start-guide.md
Original file line number Diff line number Diff line change
@@ -13,7 +13,7 @@ Your feedback on this version of our client is appreciated. Please raise an issu

This package requires [Python 3.9 or greater](https://python.org/downloads/). A virtual environment is strongly recommended.

You will need your Planet API credentials. You can find your API key in [Planet Explorer](https://planet.com/explorer) under Account Settings.
You will need Planet credentials to use this SDK. You can learn more about authentication options and where to find your credentials in our [authentication documentation](https://docs.planet.com/develop/authentication/).

## Installation

@@ -27,10 +27,13 @@ pip install planet

### Authentication

Use the `PL_API_KEY` environment variable to authenticate with the Planet API. For other authentication options, see the [SDK guide](../python/sdk-guide.md).
Use the [`planet auth`](../../cli/cli-reference/#auth) CLI command to establish
a user login session that will be saved to the user's home directory. This
session will be picked up by SDK library functions by default. For other
authentication options, see the [Client Authentication Guide](../auth/auth-overview.md).

```bash
export PL_API_KEY=your_api_key
planet auth login
```

### The Planet client
@@ -39,7 +42,7 @@ The `Planet` class is the main entry point for the Planet SDK. It provides acces

```python
from planet import Planet
pl = Planet() # automatically detects PL_API_KEY
pl = Planet() # automatically detects authentication configured by `planet auth login`
```

The Planet client has members `data`, `orders`, and `subscriptions`, which allow you to interact with the Data API, Orders API, and Subscriptions API. Usage examples for searching, ordering and creating subscriptions can be found in the [SDK guide](../python/sdk-guide.md).
@@ -51,4 +54,3 @@ As The Planet SDK (V2) is in active development, features & functionality will c
If there's something you're missing or are stuck, the development team would love to hear from you.

- To report a bug or suggest a feature, [raise an issue on GitHub](https://github.com/planetlabs/planet-client-python/issues/new)
- To get in touch with the development team, email [developers@planet.com](mailto:developers@planet.com)
File renamed without changes.
100 changes: 100 additions & 0 deletions docs/get-started/upgrading-v3.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
# Upgrade from Version 2 to Version 3

Version 3 of the Planet SDK for Python is a major update of the SDK offering
new features, not all of which are backwards compatible with version 2.

## Authentication
Version 3 of the SDK removes support for Planet's legacy authentication network
protocols in favor of OAuth2 based mechanisms. The legacy protocols
were never a [documented Planet API](https://docs.planet.com/develop/apis/), but could
easily be understood by inspection of the SDK code.

Specifically, what is being deprecated in version 3 are the paths where the SDK
handled a username and password to obtain the user's API key for forward
operations. Users may still operate with an API key by retrieving it from the
Planet user interface under [My Settings](https://www.planet.com/account/#/user-settings)
and providing it to the SDK. While API keys remain supported for machine-to-machine
API use cases using `api.planet.com` APIs, OAuth2 mechanisms should be preferred
where the use case allows for it.

Users may also continue to initialize SDK and CLI sessions with their username
and password, but rather than being processed by the SDK itself a browser must
be invoked to complete OAuth2 client session initialization.
This new method is intended to offer a number of long-term benefits, including:

* The new method provides the SDK and the CLI with access tokens that may be
used with both `api.planet.com` and `services.sentinel-hub.com` endpoints. The method
used by version 2 of the SDK was specific to `api.planet.com` endpoints, and
will never be supported by `services.sentinel-hub.com` endpoints.
* The new method extends (currently optional) multifactor authentication (MFA)
to SDK and CLI client use cases.
* The new method is compatible with other platform enhancements currently under
development by Planet's software engineering team.

For complete details on the new mechanisms, see the [Client Authentication Guide](../auth/auth-overview.md).

### CLI Usage
The [`planet auth`](../../cli/cli-reference/#auth) command has been substantially
revised to align to the new authentication mechanisms. For migration from version 2
of the SDK, the following changes are the most important to note:

* The `planet auth init` command has been replaced with [`planet auth login`](../../cli/cli-reference/#login).
By default, this command will open a browser window to allow the user to log
in to their Planet account and authorize the SDK or CLI to access their account.
Other options are available to support a variety of use cases, including a
`--no-open-browser` option for remote shells. See `planet auth login --help`
for complete details.
* The `planet auth value` command has been deprecated. Depending on whether the SDK
has been initialized with OAuth2 or API key authentication,
[`planet auth print-access-token`](../../cli/cli-reference/#print-access-token)
or [`planet auth print-api-key`](../../cli/cli-reference/#print-api-key) may
be used. OAuth2 sessions should be preferred where possible.
* The `planet auth store` command has been deprecated. The various options to the
`planet auth login` command should provide suitable alternatives for all use cases.
OAuth2 sessions should be favored for user interactive use cases, such as CLI usage.
`planet auth login --auth-api-key YOUR_API_KEY` may be used to initialize the SDK
with API key based authentication where the use case requires it.

### Session Persistence
Both version 2 and version 3 of the SDK use the `~/.planet.json` file in the user's
home directory to store the user's API key. If this file is present and was configured
by version 2 of the SDK, it should continue to work.

While the `~/.planet.json` file continues to be used by version 3, and version 3
understands files written by version 2, version 3 will not write the same information
to this file that version 2 did. Version 3 uses this file in conjunction with the
`~/.planet` directory and subdirectories to store OAuth2 tokens and additional
session information needed for a smooth user experience.

Version 3 of the SDK provides a [`planet auth reset`](../../cli/cli-reference/#reset)
command to reset all saved state should it become corrupted. When this command is run,
the old files are moved aside rather than deleted.

### SDK Session Initialization
See the [Client Authentication Guide](../auth/auth-overview.md) for a complete
discussion of all options now available.

Basic SDK use cases should work with no alterations.
User sessions initialized by [`planet auth login`](../../cli/cli-reference/#login)
will be detected by an application using a default Planet client when
run in an environment with access to the user's home directory. For example:

```python linenums="1"
{% include 'auth-session-management/cli_managed_auth_state__implicit.py' %}
```

Applications may also continue to initialize the SDK with a specific API key as follows:
```python linenums="1"
{% include 'auth-session-management/app_managed_auth_state__in_memory__api_key.py' %}
```

Users developing new applications should consult the [Client Authentication Guide](../auth/auth-overview.md)
for a complete discussion of all OAuth2 based mechanisms. OAuth2 mechanisms
should be preferred to the use of Planet API keys.

## Additional Breaking Changes

* Deprecated `planet.subscription_request.clip_tool()` method for defining custom clip AOIs with requests to create subscriptions. Subscriptions API no longer supports custom clip AOIs; instead users can opt-in to clip to their subscription source geometry by including kwarg `clip_to_source=True` when constructing requests via `planet.subscription_request.build_request()`. See [PR #1169](https://github.com/planetlabs/planet-client-python/pull/1169) for implementation details.
* Renamed `planet.cli.subscriptions.request_pv()` to `planet.cli.subscriptions.request_source()`, and removed `var_type` positional argument from the signature. This change, in effect renames the CLI argument `planet subscriptions request-pv` to `planet subscriptions request-source`. Also renamed `planet.subscription_request.planetary_variable_source()` to `planet.subscription_request.subscription_source()`. Source type positional arguments are removed from these methods in favor of `source_id`. See [PR #1170](https://github.com/planetlabs/planet-client-python/pull/1170) for implementation details.

----
1 change: 1 addition & 0 deletions docs/hooks/mkdocs_hooks.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from planet import __version__ as _pl_sdk_version


def on_config(config):
"""
This is for injecting the package version into mkdocs
66 changes: 25 additions & 41 deletions docs/python/async-sdk-guide.md
Original file line number Diff line number Diff line change
@@ -6,7 +6,7 @@ This guide is for the Planet Async SDK for Python users who want to use asynchro

This guide walks you through the steps:

* **[Authenticate](#authenticate-with-planet-services)**pass your username and password to Planet services to verify your permissions to data.
* **[Authenticate](#authenticate-with-planet-services)**authenticate to Planet services to verify your permissions to data.
* **[Create a session](#create-a-session)**—set up a context for calling on Planet servers and receiving data back.
* **[Create an order](#create-an-order)**—build an orders client, send the request within the session context, and download it when it’s ready.
* **[Collect and list data](#collecting-results)**—handle the potentially large number of results from a search for imagery.
@@ -22,52 +22,36 @@ pip install planet

## Authenticate with Planet services

An SDK `Session` requires authentication to communicate with Planet services. This
authentication information is retrieved when a `Session` is created. By default,
a `Session` retrieves authorization key from the environment variable `PL_API_KEY` or a secret file, in that order of priority.

The SDK provides the `auth.Auth` class for managing authentication information.
This module can be used to obtain authentication information from the username
and password with `Auth.from_login()`. Additionally, it can be created with
the API key obtained directly from the Planet account site with `Auth.from_key(<API_KEY>)`.

Once you have provided the authentication information (in other words, the username and API key), it can be accessed by way of the `Auth.value`. The most convenient way of managing it for local use is to write it to a secret file using `Auth.write()`. For example, to obtain and store authentication information:

Once you have provided the authentication information (in other words, the account username and password), it can be accessed by way of `Auth.value`. The most convenient way of managing it for local use is to write it to a secret file using `Auth.write()`.
It can also be accessed, for example, to store in an environment variable, such as
`Auth.value`.

Here is an example of retrieving and storing authentication information:

```python
# Get the user account name and password
# from the command line and environment,
# and store credentials in an Auth object
import getpass
from planet import Auth

user = input("Username: ")
pw = getpass.getpass()
auth = Auth.from_login(user,pw)
auth.store()
```

The default authentication behavior of the `Session` can be modified by specifying
`Auth` explicitly using the methods `Auth.from_file()` and `Auth.from_env()`.
While `Auth.from_key()` and `Auth.from_login` can be used, it is recommended
that those functions be used in authentication initialization. Authentication
information should be stored using `Auth.store()`.

You can customize the manner of retrieval and location to read from when retrieving the authorization information. The file and environment variable read from can be customized in the respective functions. For example, authentication can be read from a custom
environment variable, as in the following code:
An SDK `Session` requires authentication to communicate with Planet services. The
details of authentication are managed with the [`planet.Auth`](../../python/sdk-reference/#planet.auth.Auth)
class, and are configured when a `Session` is created. Default behavior
shares the responsibility of managing authentication sessions with the [`planet auth`](../../cli/cli-reference/#auth)
CLI utility, which stores authentication sessions in the user's home directory.

The default authentication behavior of the `Session` can be modified by providing an
`Auth` instance when creating the `Session`. There are many different ways to
create an `Auth` instance, depending on the use case. See
[Client Authentication Overview](../../auth/auth-overview/)
and [Authentication with the SDK](../../auth/auth-sdk/) for more details concerning
Planet Insights Platform authentication with the SDK. For general information on
how to authenticate to Planet APIs, please see the
[Authentication](https://docs.planet.com/develop/authentication/) section of Planet's
platform documentation.

For example, a program may wish create the `Auth` instance prior to setting up
the `Session` to guide the user towards external setup steps:

```python
import asyncio
import os
import sys
from planet import Auth, Session

auth = Auth.from_env('ALTERNATE_VAR')
auth = Auth.from_user_default_session()
async def main():
if not auth.is_initialized():
print("Login required. Execute the following command:\n\n\tplanet auth login\n")
sys.exit(99)

async with Session(auth=auth) as sess:
# perform operations here
pass
15 changes: 15 additions & 0 deletions docs/python/sdk-client-auth.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Authentication SDK Guide

For general information on how to authenticate to Planet APIs, see the
[Authentication](https://docs.planet.com/develop/authentication/) section of Planet's
Insights Platform documentation.

See [Client Authentication Overview](../../auth/auth-overview) for an overview
of authentication to the Planet Insights Platform that is geared towards SDK
users, and includes a discussion of authentication protocols that are under
construction and available for early access to SDK users.

[Authentication with the SDK](../../auth/auth-sdk) provides a primer
on how to use the Planet SDK for Python to authenticate to Planet APIs.

----
29 changes: 11 additions & 18 deletions docs/python/sdk-guide.md
Original file line number Diff line number Diff line change
@@ -23,32 +23,26 @@ The `Planet` class is the main entry point for the Planet SDK. It provides acces

```python
from planet import Planet
pl = Planet() # automatically detects PL_API_KEY
pl = Planet() # automatically detects authentication configured by `planet auth login`
```

The Planet client has members `data`, `orders`, and `subscriptions`, which allow you to interact with the Data API, Orders API, and Subscriptions API.


### Authentication

Use the `PL_API_KEY` environment variable to authenticate with the Planet API.
To establish a user session that will be saved to the user's home directory
and will be picked up by the SDK, execute the following command:

```bash
export PL_API_KEY=your_api_key
planet auth login
```

These examples will assume you are using the `PL_API_KEY` environment variable. If you are, you can skip to the next section.

#### Authenticate using the Session class

Alternately, you can also authenticate using the `Session` class:

```python
from planet import Auth, Session, Auth
from planet.auth import APIKeyAuth

pl = Planet(session=Session(auth=APIKeyAuth(key='your_api_key')))
```
These examples will assume you have done this, and are using the SDK's default
client authentication mechanisms. For more advanced use cases, see the
[Client Authentication Guide](../auth/auth-overview.md) for a complete discussion of
all authentication options provided by the SDK. This includes user
authentication with a web browser, service account authentication for detached
workloads using OAuth2, and support for legacy applications using Planet API keys.

### Search

@@ -231,7 +225,7 @@ You will need your ACCESS_KEY_ID, SECRET_ACCESS_KEY, bucket and region name.
To subscribe to scenes that match a filter, use the `subscription_request` module to build a request, and
pass it to the `subscriptions.create_subscription()` method of the client.

By default, a request to create a subscription will not clip matching imagery which intersects the source geometry. To clip to the subscription source geometry, set `planet.subscription_request.build_request()` keyword argument `clip_to_source = True` as in the example below. To clip to a custom geometry, set `planet.subscription_request.build_request()` keyword argument `clip_to_source = False` (or omit it entirely to fall back on the default value), and instead configure the custom clip AOI with `planet.subscription_request.clip_tool()`.
By default, a request to create a subscription will not clip matching imagery which intersects the source geometry. To clip to the subscription source geometry, set `planet.subscription_request.build_request()` keyword argument `clip_to_source = True` as in the example below. Custom clip AOIs are no longer supported in subscriptions.

Warning: the following code will create a subscription, consuming quota based on your plan.

@@ -333,4 +327,3 @@ As The Planet SDK (V2) is in active development, features & functionality will c
If there's something you're missing or are stuck, the development team would love to hear from you.

- To report a bug or suggest a feature, [raise an issue on GitHub](https://github.com/planetlabs/planet-client-python/issues/new)
- To get in touch with the development team, email [developers@planet.com](mailto:developers@planet.com)
4 changes: 4 additions & 0 deletions docs/python/sdk-reference.md
Original file line number Diff line number Diff line change
@@ -10,6 +10,10 @@ title: Python SDK API Reference
rendering:
show_root_full_path: false

## ::: planet.MosaicsClient
rendering:
show_root_full_path: false

## ::: planet.OrdersClient
rendering:
show_root_full_path: false
5 changes: 1 addition & 4 deletions docs/resources/index.md
Original file line number Diff line number Diff line change
@@ -27,9 +27,6 @@ This pre-release SDK has implemented interfaces for several Planet APIs. Check o
* [Orders](https://docs.planet.com/develop/apis/orders/)
* [Subscriptions](https://docs.planet.com/develop/apis/subscriptions/)

## Email Developer Relations

We are eager to share this pre-release with you and encourage you to test your workflows rigorously. Based on your feedback, we may roll out additional updates to improve your experience. Besides joining the discussion, and filing issues and pull requests here, feel free to share your general feedback with us at developers@planet.com.
## Contribute to this open source project

To contribute or develop with this library, see
@@ -43,4 +40,4 @@ To contribute or develop with this library, see

## Version 1 of this SDK

[Version 1 of this SDK](https://github.com/planetlabs/planet-client-python/tree/1.5.2) is significantly different (see the [documentation](https://planet-sdk-for-python.readthedocs.io/en/latest/)). Version 2 is not backward compatible. Make sure to create a separate virtual environment if you need to work with both versions. For more information on how to do this, see the [Virtual Environments and the Planet SDK for Python](https://planet-sdk-for-python-v2.readthedocs.io/en/latest/get-started/venv-tutorial/).
[Version 1 of this SDK](https://github.com/planetlabs/planet-client-python/tree/1.5.2) is significantly different (see the [documentation](https://planet-sdk-for-python.readthedocs.io/en/latest/)). Version 2 was not backward compatible. Make sure to create a separate virtual environment if you need to work with both versions. For more information on how to do this, see the [Virtual Environments and the Planet SDK for Python](https://planet-sdk-for-python.readthedocs.io/en/latest/get-started/venv-tutorial/).
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# No example of this use case provided at this time.
# The use of M2M OAuth sessions is encouraged over the use of API keys.
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import json
import logging
import os
import pathlib
import stat

import planet

from planet_auth import ObjectStorageProvider, ObjectStorageProvider_KeyType

logging.basicConfig(level=logging.CRITICAL)


class DemoStorageProvider(ObjectStorageProvider):
"""
Simple demo custom storage provider that uses
~/.planet-demo as a storage home for saving object.
As a practical matter, ObjectStorageProvider_KeyType is defined
to be pathlib.Path, and we leverage that in this example.
But, storage providers are not required to use the local file
system to store objects.
"""

def __init__(self):
self._demo_storage_root = pathlib.Path.home() / ".planet-demo"

def load_obj(self, key: ObjectStorageProvider_KeyType) -> dict:
demo_obj_filepath = self._demo_obj_filepath(key)
return self._load_file(file_path=demo_obj_filepath)

def save_obj(self, key: ObjectStorageProvider_KeyType, data: dict) -> None:
demo_obj_filepath = self._demo_obj_filepath(key)
self._save_file(file_path=demo_obj_filepath, data=data)

def obj_exists(self, key: ObjectStorageProvider_KeyType) -> bool:
demo_obj_filepath = self._demo_obj_filepath(key)
return demo_obj_filepath.exists()

def mtime(self, key: ObjectStorageProvider_KeyType) -> float:
obj_filepath = self._demo_obj_filepath(key)
return obj_filepath.stat().st_mtime

def obj_rename(self,
src: ObjectStorageProvider_KeyType,
dst: ObjectStorageProvider_KeyType) -> None:
src_filepath = self._demo_obj_filepath(src)
dst_filepath = self._demo_obj_filepath(dst)
src_filepath.rename(dst_filepath)

def _demo_obj_filepath(self, obj_key):
if obj_key.is_absolute():
obj_path = self._demo_storage_root / obj_key.relative_to("/")
else:
obj_path = self._demo_storage_root / obj_key
return obj_path

@staticmethod
def _load_file(file_path: pathlib.Path) -> dict:
logging.debug(msg="Loading JSON data from file {}".format(file_path))
with open(file_path, mode="r", encoding="UTF-8") as file_r:
return json.load(file_r)

@staticmethod
def _save_file(file_path: pathlib.Path, data: dict):
file_path.parent.mkdir(parents=True, exist_ok=True)
logging.debug(msg="Writing JSON data to file {}".format(file_path))
with open(file_path, mode="w", encoding="UTF-8") as file_w:
os.chmod(file_path, stat.S_IREAD | stat.S_IWRITE)
_no_none_data = {
key: value
for key, value in data.items() if value is not None
}
file_w.write(json.dumps(_no_none_data, indent=2, sort_keys=True))


def example_main():
# Create an auth context with the client ID and secret of the service account.
plsdk_auth = planet.Auth.from_oauth_m2m(
client_id="__MUST_BE_END_USER_SUPPLIED__",
client_secret="__MUST_BE_END_USER_SUPPLIED__",
profile_name="my-example-name-m2m-with-custom-storage",
save_state_to_storage=True,
storage_provider=DemoStorageProvider(),
)

# Explicit login is not required for M2M client use. The above sufficient.
# plsdk_auth.user_login()

# Create a Planet SDK object that uses the loaded auth session.
sess = planet.Session(plsdk_auth)
pl = planet.Planet(sess)

# Use the SDK to call Planet APIs.
# Refreshing access tokens will be managed automatically by the SDK.
for item in pl.data.list_searches():
print(json.dumps(item, indent=2, sort_keys=True))


if __name__ == '__main__':
example_main()
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import json
import logging
import os
import pathlib
import stat

import planet

from planet_auth import ObjectStorageProvider, ObjectStorageProvider_KeyType

logging.basicConfig(level=logging.CRITICAL)


class DemoStorageProvider(ObjectStorageProvider):
"""
Simple demo custom storage provider that uses
~/.planet-demo as a storage home for saving object.
As a practical matter, ObjectStorageProvider_KeyType is defined
to be pathlib.Path, and we leverage that in this example.
But, storage providers are not required to use the local file
system to store objects.
"""

def __init__(self):
self._demo_storage_root = pathlib.Path.home() / ".planet-demo"

def load_obj(self, key: ObjectStorageProvider_KeyType) -> dict:
demo_obj_filepath = self._demo_obj_filepath(key)
return self._load_file(file_path=demo_obj_filepath)

def save_obj(self, key: ObjectStorageProvider_KeyType, data: dict) -> None:
demo_obj_filepath = self._demo_obj_filepath(key)
self._save_file(file_path=demo_obj_filepath, data=data)

def obj_exists(self, key: ObjectStorageProvider_KeyType) -> bool:
demo_obj_filepath = self._demo_obj_filepath(key)
return demo_obj_filepath.exists()

def mtime(self, key: ObjectStorageProvider_KeyType) -> float:
obj_filepath = self._demo_obj_filepath(key)
return obj_filepath.stat().st_mtime

def obj_rename(self,
src: ObjectStorageProvider_KeyType,
dst: ObjectStorageProvider_KeyType) -> None:
src_filepath = self._demo_obj_filepath(src)
dst_filepath = self._demo_obj_filepath(dst)
src_filepath.rename(dst_filepath)

def _demo_obj_filepath(self, obj_key):
if obj_key.is_absolute():
obj_path = self._demo_storage_root / obj_key.relative_to("/")
else:
obj_path = self._demo_storage_root / obj_key
return obj_path

@staticmethod
def _load_file(file_path: pathlib.Path) -> dict:
logging.debug(msg="Loading JSON data from file {}".format(file_path))
with open(file_path, mode="r", encoding="UTF-8") as file_r:
return json.load(file_r)

@staticmethod
def _save_file(file_path: pathlib.Path, data: dict):
file_path.parent.mkdir(parents=True, exist_ok=True)
logging.debug(msg="Writing JSON data to file {}".format(file_path))
with open(file_path, mode="w", encoding="UTF-8") as file_w:
os.chmod(file_path, stat.S_IREAD | stat.S_IWRITE)
_no_none_data = {
key: value
for key, value in data.items() if value is not None
}
file_w.write(json.dumps(_no_none_data, indent=2, sort_keys=True))


def example_main():
# Create an auth context with a client ID that
# is unique to this application.
plsdk_auth = planet.Auth.from_oauth_user_auth_code(
client_id="__MUST_BE_APP_DEVELOPER_SUPPLIED__",
requested_scopes=[
# Request access to Planet APIs
planet.PlanetOAuthScopes.PLANET,
# Request a refresh token so repeated browser logins are not required
planet.PlanetOAuthScopes.OFFLINE_ACCESS,
],
callback_url="http://localhost:8080",
profile_name="my-example-name-auth-code-with-custom-storage",
save_state_to_storage=True,
storage_provider=DemoStorageProvider(),
)

# In contrast to an in-memory only application that must initialize a login every
# time, an app with persistent storage can skip this when it is not needed.
if not plsdk_auth.is_initialized():
plsdk_auth.user_login(allow_open_browser=True)

# Create a Planet SDK object that uses the loaded auth session.
sess = planet.Session(plsdk_auth)
pl = planet.Planet(sess)

# Use the SDK to call Planet APIs.
# Refreshing access tokens will be managed automatically by the SDK.
for item in pl.data.list_searches():
print(json.dumps(item, indent=2, sort_keys=True))


if __name__ == '__main__':
example_main()
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
import json
import logging
import os
import pathlib
import stat

import planet

from planet_auth import ObjectStorageProvider, ObjectStorageProvider_KeyType

logging.basicConfig(level=logging.CRITICAL)


class DemoStorageProvider(ObjectStorageProvider):
"""
Simple demo custom storage provider that uses
~/.planet-demo as a storage home for saving object.
As a practical matter, ObjectStorageProvider_KeyType is defined
to be pathlib.Path, and we leverage that in this example.
But, storage providers are not required to use the local file
system to store objects.
"""

def __init__(self):
self._demo_storage_root = pathlib.Path.home() / ".planet-demo"

def load_obj(self, key: ObjectStorageProvider_KeyType) -> dict:
demo_obj_filepath = self._demo_obj_filepath(key)
return self._load_file(file_path=demo_obj_filepath)

def save_obj(self, key: ObjectStorageProvider_KeyType, data: dict) -> None:
demo_obj_filepath = self._demo_obj_filepath(key)
self._save_file(file_path=demo_obj_filepath, data=data)

def obj_exists(self, key: ObjectStorageProvider_KeyType) -> bool:
demo_obj_filepath = self._demo_obj_filepath(key)
return demo_obj_filepath.exists()

def mtime(self, key: ObjectStorageProvider_KeyType) -> float:
obj_filepath = self._demo_obj_filepath(key)
return obj_filepath.stat().st_mtime

def obj_rename(self,
src: ObjectStorageProvider_KeyType,
dst: ObjectStorageProvider_KeyType) -> None:
src_filepath = self._demo_obj_filepath(src)
dst_filepath = self._demo_obj_filepath(dst)
src_filepath.rename(dst_filepath)

def _demo_obj_filepath(self, obj_key):
if obj_key.is_absolute():
obj_path = self._demo_storage_root / obj_key.relative_to("/")
else:
obj_path = self._demo_storage_root / obj_key
return obj_path

@staticmethod
def _load_file(file_path: pathlib.Path) -> dict:
logging.debug(msg="Loading JSON data from file {}".format(file_path))
with open(file_path, mode="r", encoding="UTF-8") as file_r:
return json.load(file_r)

@staticmethod
def _save_file(file_path: pathlib.Path, data: dict):
file_path.parent.mkdir(parents=True, exist_ok=True)
logging.debug(msg="Writing JSON data to file {}".format(file_path))
with open(file_path, mode="w", encoding="UTF-8") as file_w:
os.chmod(file_path, stat.S_IREAD | stat.S_IWRITE)
_no_none_data = {
key: value
for key, value in data.items() if value is not None
}
file_w.write(json.dumps(_no_none_data, indent=2, sort_keys=True))


def initialize_user_session(plsdk_auth):
# Example of initiating a user session where the app is 100%
# responsible for the user experience.

# 1. Initiate the login
login_initialization_info = plsdk_auth.device_user_login_initiate()

# 2. Display necessary instructions to the user.
#
# "verification_uri" and "user_code" are required under RFC 8628.
# "verification_uri_complete" is optional under the RFC.
#
# If the user is expected to type in the URL, verification_uri will be
# shorter. If the URL may be presented in a clickable means (such as a
# link, button, or QR code) the verification_uri_complete may offer a
# better user experience.
verification_uri_complete = login_initialization_info.get(
"verification_uri_complete")
verification_uri = login_initialization_info.get("verification_uri")
user_code = login_initialization_info.get("user_code")

print("Please activate your client.")
if verification_uri_complete:
print(f"Visit the activation site:\n"
f"\n\t{verification_uri_complete}\n"
f"\nand confirm the authorization code:\n"
f"\n\t{user_code}\n")
else:
print(f"Visit the activation site:\n"
f"\n\t{verification_uri}\n"
f"\nand enter the authorization code:\n"
f"\n\t{user_code}\n")

# 3. Return control to the SDK. This will block until the user
# completes login.
plsdk_auth.device_user_login_complete(login_initialization_info)


def example_main():
# Create an auth context with a client ID that
# is unique to this application.
plsdk_auth = planet.Auth.from_oauth_user_device_code(
client_id="__MUST_BE_APP_DEVELOPER_SUPPLIED__",
requested_scopes=[
# Request access to Planet APIs
planet.PlanetOAuthScopes.PLANET,
# Request a refresh token so repeated browser logins are not required
planet.PlanetOAuthScopes.OFFLINE_ACCESS,
],
profile_name="my-example-name-device-code-with-custom-storage",
save_state_to_storage=True,
storage_provider=DemoStorageProvider(),
)

# In contrast to an in-memory only application that must initialize a login every
# time, an app with persistent storage can skip this when it is not needed.
if not plsdk_auth.is_initialized():
initialize_user_session(plsdk_auth)

# Create a Planet SDK object that uses the loaded auth session.
sess = planet.Session(plsdk_auth)
pl = planet.Planet(sess)

# Use the SDK to call Planet APIs.
# Refreshing access tokens will be managed automatically by the SDK.
for item in pl.data.list_searches():
print(json.dumps(item, indent=2, sort_keys=True))


if __name__ == '__main__':
example_main()
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import json
import planet


def example_main():
# Create an auth context with the specified API key
plsdk_auth = planet.Auth.from_key(
key="__PLANET_API_KEY_MUST_BE_END_USER_SUPPLIED__")

# Explicit login is not required for API key use. The above sufficient.
# plsdk_auth.user_login()

# Create a Planet SDK object that uses the loaded auth session
sess = planet.Session(plsdk_auth)
pl = planet.Planet(sess)

# Use the SDK to call Planet APIs
for item in pl.data.list_searches():
print(json.dumps(item, indent=2, sort_keys=True))


if __name__ == '__main__':
example_main()
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import json
import planet


def example_main():
# Create an auth context with the client ID and secret of the service account.
plsdk_auth = planet.Auth.from_oauth_m2m(
client_id="__MUST_BE_END_USER_SUPPLIED__",
client_secret="__MUST_BE_END_USER_SUPPLIED__",
save_state_to_storage=False,
)

# Explicit login is not required for M2M client use. The above is sufficient.
# plsdk_auth.user_login()

# Create a Planet SDK object that uses the loaded auth session.
sess = planet.Session(plsdk_auth)
pl = planet.Planet(sess)

# Use the SDK to call Planet APIs.
# Refreshing access tokens will be managed automatically by the SDK.
for item in pl.data.list_searches():
print(json.dumps(item, indent=2, sort_keys=True))


if __name__ == '__main__':
example_main()
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import json
import planet


def example_main():
# Create an auth context with a client ID that
# is unique to this application.
plsdk_auth = planet.Auth.from_oauth_user_auth_code(
client_id="__MUST_BE_APP_DEVELOPER_SUPPLIED__",
requested_scopes=[
# Request access to Planet APIs
planet.PlanetOAuthScopes.PLANET,
# Request a refresh token so repeated browser logins are not required
planet.PlanetOAuthScopes.OFFLINE_ACCESS,
],
callback_url="http://localhost:8080",
save_state_to_storage=False,
)

# An application with no persistent storage must
# initialize a login every time. This is not smooth user experience.
plsdk_auth.user_login(allow_open_browser=True)

# Create a Planet SDK object that uses the loaded auth session.
sess = planet.Session(plsdk_auth)
pl = planet.Planet(sess)

# Use the SDK to call Planet APIs.
# Refreshing access tokens will be managed automatically by the SDK.
for item in pl.data.list_searches():
print(json.dumps(item, indent=2, sort_keys=True))


if __name__ == '__main__':
example_main()
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import json
import planet


def initialize_user_session(plsdk_auth):
# Example of initiating a user session where the app is 100%
# responsible for the user experience.

# 1. Initiate the login
login_initialization_info = plsdk_auth.device_user_login_initiate()

# 2. Display necessary instructions to the user.
#
# "verification_uri" and "user_code" are required under RFC 8628.
# "verification_uri_complete" is optional under the RFC.
#
# If the user is expected to type in the URL, verification_uri will be
# shorter. If the URL may be presented in a clickable means (such as a
# link, button, or QR code) the verification_uri_complete may offer a
# better user experience.
verification_uri_complete = login_initialization_info.get(
"verification_uri_complete")
verification_uri = login_initialization_info.get("verification_uri")
user_code = login_initialization_info.get("user_code")

print("Please activate your client.")
if verification_uri_complete:
print(f"Visit the activation site:\n"
f"\n\t{verification_uri_complete}\n"
f"\nand confirm the authorization code:\n"
f"\n\t{user_code}\n")
else:
print(f"Visit the activation site:\n"
f"\n\t{verification_uri}\n"
f"\nand enter the authorization code:\n"
f"\n\t{user_code}\n")

# 3. Return control to the SDK. This will block until the user
# completes login.
plsdk_auth.device_user_login_complete(login_initialization_info)


def example_main():
# Create an auth context with a client ID that
# is unique to this application.
plsdk_auth = planet.Auth.from_oauth_user_device_code(
client_id="__MUST_BE_APP_DEVELOPER_SUPPLIED__",
requested_scopes=[
# Request access to Planet APIs
planet.PlanetOAuthScopes.PLANET,
# Request a refresh token so repeated browser logins are not required
planet.PlanetOAuthScopes.OFFLINE_ACCESS,
],
save_state_to_storage=False,
)

# An application with no persistent storage must initialize a login every
# time. This is not smooth user experience.
initialize_user_session(plsdk_auth)

# Create a Planet SDK object that uses the loaded auth session.
sess = planet.Session(plsdk_auth)
pl = planet.Planet(sess)

# Use the SDK to call Planet APIs.
# Refreshing access tokens will be managed automatically by the SDK.
for item in pl.data.list_searches():
print(json.dumps(item, indent=2, sort_keys=True))


if __name__ == '__main__':
example_main()
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# No example of this use case provided at this time.
# The use of M2M OAuth sessions is encouraged over the use of API keys.
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import json
import planet


def example_main():
# Create an auth context with the client ID and secret of the service account.
plsdk_auth = planet.Auth.from_oauth_m2m(
client_id="__MUST_BE_END_USER_SUPPLIED__",
client_secret="__MUST_BE_END_USER_SUPPLIED__",
profile_name="my-name-for-example-m2m-auth-profile",
save_state_to_storage=True,
)

# Explicit login is not required for M2M client use. The above is sufficient.
# plsdk_auth.user_login()

# Create a Planet SDK object that uses the loaded auth session.
sess = planet.Session(plsdk_auth)
pl = planet.Planet(sess)

# Use the SDK to call Planet APIs.
# Refreshing access tokens will be managed automatically by the SDK.
for item in pl.data.list_searches():
print(json.dumps(item, indent=2, sort_keys=True))


if __name__ == '__main__':
example_main()
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import json
import planet


def example_main():
# Create an auth context with a client ID that
# is unique to this application.
plsdk_auth = planet.Auth.from_oauth_user_auth_code(
client_id="__MUST_BE_APP_DEVELOPER_SUPPLIED__",
requested_scopes=[
# Request access to Planet APIs
planet.PlanetOAuthScopes.PLANET,
# Request a refresh token so repeated browser logins are not required
planet.PlanetOAuthScopes.OFFLINE_ACCESS,
],
callback_url="http://localhost:8080",
profile_name="my-name-for-example-user-session-with-local-browser",
save_state_to_storage=True,
)

# In contrast to an in-memory only application that must initialize a login every
# time, an app with persistent storage can skip this when it is not needed.
if not plsdk_auth.is_initialized():
plsdk_auth.user_login(allow_open_browser=True)

# Create a Planet SDK object that uses the loaded auth session.
sess = planet.Session(plsdk_auth)
pl = planet.Planet(sess)

# Use the SDK to call Planet APIs.
# Refreshing access tokens will be managed automatically by the SDK.
for item in pl.data.list_searches():
print(json.dumps(item, indent=2, sort_keys=True))


if __name__ == '__main__':
example_main()
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import json
import planet


def initialize_user_session(plsdk_auth):
# Example of initiating a user session where the app is 100%
# responsible for the user experience.

# 1. Initiate the login
login_initialization_info = plsdk_auth.device_user_login_initiate()

# 2. Display necessary instructions to the user.
#
# "verification_uri" and "user_code" are required under RFC 8628.
# "verification_uri_complete" is optional under the RFC.
#
# If the user is expected to type in the URL, verification_uri will be
# shorter. If the URL may be presented in a clickable means (such as a
# link, button, or QR code) the verification_uri_complete may offer a
# better user experience.
verification_uri_complete = login_initialization_info.get(
"verification_uri_complete")
verification_uri = login_initialization_info.get("verification_uri")
user_code = login_initialization_info.get("user_code")

print("Please activate your client.")
if verification_uri_complete:
print(f"Visit the activation site:\n"
f"\n\t{verification_uri_complete}\n"
f"\nand confirm the authorization code:\n"
f"\n\t{user_code}\n")
else:
print(f"Visit the activation site:\n"
f"\n\t{verification_uri}\n"
f"\nand enter the authorization code:\n"
f"\n\t{user_code}\n")

# 3. Return control to the SDK. This will block until the user
# completes login.
plsdk_auth.device_user_login_complete(login_initialization_info)


def example_main():
# Create an auth context with a client ID that
# is unique to this application.
plsdk_auth = planet.Auth.from_oauth_user_device_code(
client_id="__MUST_BE_APP_DEVELOPER_SUPPLIED__",
requested_scopes=[
# Request access to Planet APIs
planet.PlanetOAuthScopes.PLANET,
# Request a refresh token so repeated browser logins are not required
planet.PlanetOAuthScopes.OFFLINE_ACCESS,
],
profile_name="my-name-example-user-auth-with-external-browser",
save_state_to_storage=True,
)

# In contrast to an in-memory only application that must initialize a login every
# time, an app with persistent storage can skip this when it is not needed.
if not plsdk_auth.is_initialized():
initialize_user_session(plsdk_auth)

# Create a Planet SDK object that uses the loaded auth session.
sess = planet.Session(plsdk_auth)
pl = planet.Planet(sess)

# Use the SDK to call Planet APIs.
# Refreshing access tokens will be managed automatically by the SDK.
for item in pl.data.list_searches():
print(json.dumps(item, indent=2, sort_keys=True))


if __name__ == '__main__':
example_main()
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import json
import planet


def example_main():
# Create an auth context with a Planet API key loaded from the
# specified file that was created with older versions of the SDK
plsdk_auth = planet.Auth.from_file("legacy_api_key_file.json")

# Explicit login is not required for API key use. The above sufficient.
# plsdk_auth.user_login()

# Create a Planet SDK object that uses the loaded auth session
sess = planet.Session(plsdk_auth)
pl = planet.Planet(sess)

# Use the SDK to call Planet APIs.
for item in pl.data.list_searches():
print(json.dumps(item, indent=2, sort_keys=True))


if __name__ == '__main__':
example_main()
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import json
import planet


def example_main():
# Load the OAuth2 user-interactive client configration that is built-into the SDK.
# This configuration is shared with the `planet` CLI command.
# When save_state_to_storage is true, sessions will be shared with the
# CLI and saved to the user's home directory. When save_state_to_storage
# is false, the state will only be persistent in memory and the
# user will need to login each time the application is run.
plsdk_auth = planet.Auth.from_profile("planet-user",
save_state_to_storage=False)

if not plsdk_auth.is_initialized():
plsdk_auth.user_login(allow_open_browser=True, allow_tty_prompt=True)

# Create a Planet SDK object that uses the loaded auth session.
sess = planet.Session(plsdk_auth)
pl = planet.Planet(sess)

# Use the SDK to call Planet APIs.
# Refreshing access tokens will be managed automatically by the SDK.
for item in pl.data.list_searches():
print(json.dumps(item, indent=2, sort_keys=True))


if __name__ == "__main__":
example_main()
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import json
import planet
import sys


def example_main():
# Explicitly load the user's auth session from disk. The user must have
# invoked `planet auth login` before this program is run, or the API calls
# will fail. This will not initialize a new session.
plsdk_auth = planet.Auth.from_user_default_session()

if not plsdk_auth.is_initialized():
print(
"Login required. Execute the following command:\n\n\tplanet auth login\n"
)
sys.exit(99)

# Create a Planet SDK object that uses the loaded auth session.
sess = planet.Session(plsdk_auth)
pl = planet.Planet(sess)

# Use the SDK to call Planet APIs.
# Refreshing access tokens will be managed automatically by the SDK.
for item in pl.data.list_searches():
print(json.dumps(item, indent=2, sort_keys=True))


if __name__ == '__main__':
example_main()
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import json
import planet


def example_main():
# By default, the Planet SDK will be instantiated with the default auth
# session configured by `planet auth` and saved to disk. This default
# initialization will also inspect environment variables for configuration.
pl = planet.Planet()

# Use the SDK to call Planet APIs.
# Refreshing OAuth2 access tokens will be managed automatically by the SDK.
for item in pl.data.list_searches():
print(json.dumps(item, indent=2, sort_keys=True))


if __name__ == '__main__':
example_main()
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import json
import planet
import sys


def example_main():
# Explicitly load the user's auth session from disk for a specific
# authentication session ("profile"). The user must have invoked
# `planet auth login` before this program is run or the program
# must have performed a login() elsewhere prior to this example.
# If this has not been done, the API calls will fail. This example
# does not initialize a new session.
plsdk_auth = planet.Auth.from_profile(profile_name="my-app-profile")

# If required, how to login depends on what is configured in the specific
# profile. See other examples for login calls.
if not plsdk_auth.is_initialized():
print(
"Login required. Execute the following command:\n\n\tplanet auth login --auth-profile my-cli-managed-profile\n"
)
sys.exit(99)

# Create a Planet SDK object that uses the loaded auth session.
sess = planet.Session(plsdk_auth)
pl = planet.Planet(sess)

# Use the SDK to call Planet APIs.
# Refreshing access tokens will be managed automatically by the SDK.
for item in pl.data.list_searches():
print(json.dumps(item, indent=2, sort_keys=True))


if __name__ == '__main__':
example_main()
3 changes: 3 additions & 0 deletions examples/auth-session-management/legacy_api_key_file.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"key": "__PLANET_API_KEY_MUST_BE_END_USER_SUPPLIED__"
}
16 changes: 16 additions & 0 deletions examples/mosaics-cli.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#!/bin/bash

echo -e "List the mosaic series that have the word Global in their name"
planet mosaics series list --name-contains=Global | jq .[].name

echo -e "\nWhat is the latest mosaic in the series named Global Monthly, with output indented"
planet mosaics series list-mosaics "Global Monthly" --latest --pretty

echo -e "\nHow many quads are in the mosaic with this ID (name also accepted!)?"
planet mosaics search 09462e5a-2af0-4de3-a710-e9010d8d4e58 --bbox=-100,40,-100,40.1 | jq .[].id

echo -e "\nWhat scenes contributed to this quad in the mosaic with this ID (name also accepted)?"
planet mosaics contributions 09462e5a-2af0-4de3-a710-e9010d8d4e58 455-1273

echo -e "\nDownload them to a directory named quads!"
planet mosaics download 09462e5a-2af0-4de3-a710-e9010d8d4e58 --bbox=-100,40,-100,40.1 --output-dir=quads
22 changes: 16 additions & 6 deletions mkdocs.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
site_name: Planet SDK for Python
site_url: https://planet-sdk-for-python-v2.readthedocs.io/en/latest/
site_url: https://planet-sdk-for-python.readthedocs.io/en/latest/
site_author: https://docs.planet.com
site_description: >-
A Python library to discover and retrieve earth observation data from Planet Labs PBC.
@@ -50,6 +50,9 @@ extra_css:

plugins:
- search
- macros:
include_dir: 'examples'
on_error_fail: true
- mkdocstrings:
handlers:
python:
@@ -59,7 +62,7 @@ plugins:
selection:
inherited_members: true
filters:
- "!^_" # exlude all members starting with _
- "!^_" # exclude all members starting with _
- "^__init__$" # but always include __init__ modules and methods
watch:
- planet
@@ -71,9 +74,10 @@ hooks:
nav:
- "Get Started":
- get-started/quick-start-guide.md
- get-started/get-your-planet-account.md
- get-started/venv-tutorial.md
- get-started/upgrading.md
- "Upgrade Guides":
- get-started/upgrading-v3.md
- get-started/upgrading-v2.md
- "No Code CLI":
- cli/cli-guide.md
- cli/cli-intro.md
@@ -85,12 +89,18 @@ nav:
- cli/cli-reference.md
- "Python":
- python/sdk-guide.md
- python/sdk-client-auth.md
- python/async-sdk-guide.md
- python/sdk-reference.md
- "Client Authentication":
- auth/auth-overview.md
- auth/auth-sdk.md
- auth/auth-dev-cli-managed.md
- auth/auth-dev-app-managed-oauth.md
- auth/auth-dev-app-managed-apikey.md
- "Resources":
- resources/index.md
- "Home": 'index.md'


markdown_extensions:
- pymdownx.highlight
- pymdownx.superfences
1 change: 1 addition & 0 deletions noxfile.py
Original file line number Diff line number Diff line change
@@ -55,6 +55,7 @@ def test(session):
'-v',
'-Werror',
'-Wignore::DeprecationWarning:tqdm.std',
'-Wignore::PendingDeprecationWarning:planet.auth',
*options)


5 changes: 4 additions & 1 deletion planet/__init__.py
Original file line number Diff line number Diff line change
@@ -16,17 +16,20 @@
from . import data_filter, order_request, reporting, subscription_request
from .__version__ import __version__ # NOQA
from .auth import Auth
from .clients import DataClient, DestinationsClient, FeaturesClient, OrdersClient, SubscriptionsClient # NOQA
from .auth_builtins import PlanetOAuthScopes
from .clients import DataClient, DestinationsClient, FeaturesClient, MosaicsClient, OrdersClient, SubscriptionsClient # NOQA
from .io import collect
from .sync import Planet

__all__ = [
'Auth',
'PlanetOAuthScopes',
'collect',
'DataClient',
'data_filter',
'DestinationsClient',
'FeaturesClient',
'MosaicsClient',
'OrdersClient',
'order_request',
'Planet',
Loading