Skip to content

Conversation

@lindsay-stevens
Copy link
Contributor

@lindsay-stevens lindsay-stevens commented Oct 23, 2025

Closes #123

What has been done to verify that this works as intended?

Added tests in test_client with patches to check for API stability and skippable E2E tests that were run against staging.

Why is this the best possible solution? Were any other approaches considered?

The absence of auth parameters on the Client was a design choice to discourage putting credentials directly into scripts (e.g. in a notebook file like in the docs/examples directories) and instead encourage using a home/private directory since one of the motivating use cases for pyodk is the analyst and/or new coder.

However there have been requests from some more advanced library users that want to manage the auth data in memory and/or avoid writing files. Since pyodk writes the auth token to a cache file, a solution needs to account for that as well. So this PR implements a new pattern for passing in a Config object, which can optionally not cache the session to a file and thereby not touch any files at all. As noted in test_client.py it seems like Central caches sessions as well anyway.

How does this change affect users? Describe intentional changes to behavior and behavior that could have accidentally been affected by code changes. In other words, what are the regression risks?

Should be backwards compatible - I think the only clash would be if someone was importing config from pyodk.client, which is now aliased to cfg to avoid a name clash with the new config parameter. If that is a problem then the fix is just to replace config with cfg in the user's code import statement.

Do we need any specific form for testing your changes? If so, please attach one.

Some of the tests require a Central instance but these are skipped for CI.

Does this change require updates to documentation? If so, please file an issue here and include the link below.

As mentioned above the new functionality is intended for advanced use cases so maybe it's better to not document it in the readme? It is at least demonstrated in the tests.

Before submitting this PR, please make sure you have:

  • included test cases for core behavior and edge cases in tests
  • run python -m unittest and verified all tests pass
  • run ruff format pyodk tests and ruff check pyodk tests to lint code
  • verified that any code or assets from external sources are properly credited in comments

- supported init patterns shown in test_client.py
@juliemacdonell
Copy link

Hi @lindsay-stevens – thanks so much for the quick review of the issue and these changes!

The absence of auth parameters on the Client was a design choice to discourage putting credentials directly into scripts (e.g. in a notebook file like in the docs/examples directories) and instead encourage using a home/private directory since one of the motivating use cases for pyodk is the analyst and/or new coder.

Got it, thanks for sharing the rationale behind that design.

Since pyodk writes the auth token to a cache file, a solution needs to account for that as well.

Yes! I also was hoping to write a separate issue for that one, since I felt they could be handled separately for ease of implementation and review. Nice that this PR tackles them both, though! I can update the issue accordingly, if that'd be useful.

@lognaturel
Copy link
Member

lognaturel commented Oct 23, 2025

Thanks for filing a detailed issue and proposing a solution, @juliemacdonell! If I understand correctly, @lindsay-stevens' alternative here fully satisfies your needs, right? If so, let's go for this. The Config object feels in line with the original intent of adding some friction to putting credentials inline.

Even though it's not a preferred path, I do think we should have some documentation. My suggestion:

How does that sound to you two?

I can update the issue accordingly, if that'd be useful.

My feeling is that this PR explains the issue and solution well so it's not necessary!



def get_config_path(config_path: str | None = None) -> Path:
def get_config_path(config_path: str | Path | None = None) -> Path:
Copy link

@juliemacdonell juliemacdonell Oct 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

non-blocking: I think this function is not used anywhere. Perhaps it can be removed?

@juliemacdonell
Copy link

If I understand correctly, @lindsay-stevens' alternative here fully satisfies your needs, right?

Yes! Thanks, @lognaturel and @lindsay-stevens.

@lindsay-stevens lindsay-stevens merged commit 6c9f0cb into getodk:master Oct 27, 2025
14 checks passed
@lindsay-stevens lindsay-stevens deleted the pyodk-123 branch October 27, 2025 08:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add support passing authentication credentials directly into Client

3 participants