-
Notifications
You must be signed in to change notification settings - Fork 2
Fix/consistent path normalization #73
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
21 commits
Select commit
Hold shift + click to select a range
44a124e
fix: improve path handling in sync client pull operation
AlePouroullis 83fb88d
Improve and make path handling more consistent in call and log overloads
AlePouroullis fb292db
refactor(tests): update normalize_path test to cover strip_extension …
AlePouroullis c0a200a
fix: improve path validation for SDK calls
AlePouroullis 32f0b1b
feat: add path utils for centralized path validation
AlePouroullis 9b7c809
Further refined path handling and added more tests
AlePouroullis e5314f2
refactor: use pytest tmp_path fixture to isolate test file operations
AlePouroullis 4965c7b
test: fix type errors in local file operations test by using proper C…
AlePouroullis cdf449f
docs(cli): clarify SyncClient log level control and OpenTelemetry iso…
AlePouroullis 25fce50
refactor: simplified path processing to use pathlib where possible
AlePouroullis d21020a
docs: improve comment clarity
AlePouroullis 2504e51
test: improve path normalization tests with parametrize and edge cases
AlePouroullis a9de255
docs: clarify pull_file docstring with failure example
AlePouroullis 08e9a4f
docs: expand normalize_path docstring with usage and examples
AlePouroullis 5f481f0
Merge branch 'master' of github.com:humanloop/humanloop-python into f…
AlePouroullis 44a95b1
refactor: SyncClient -> FileSyncer
AlePouroullis 9a703b9
fix(sync): Convert base_dir to string in FileSyncer fixture
AlePouroullis 6b2e5a0
fix(dosc): correct logger namespace reference
AlePouroullis 0a2dd2e
docs: Improve error messages and comments in FileSyncer
AlePouroullis c5bec0a
refactor(test): use pytest.mark.parametrize for path validation tests
AlePouroullis 14294eb
fix(test): use proper typing.Callable for path generator
AlePouroullis File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,54 @@ | ||
| from pathlib import Path | ||
|
|
||
|
|
||
| def normalize_path(path: str, strip_extension: bool = False) -> str: | ||
| """Normalize a path to the standard Humanloop API format. | ||
|
|
||
| This function is primarily used when interacting with the Humanloop API to ensure paths | ||
| follow the standard format: 'path/to/resource' without leading/trailing slashes. | ||
| It's used when pulling files from Humanloop to local filesystem (see FileSyncer.pull) | ||
|
|
||
| The function: | ||
| - Converts Windows backslashes to forward slashes | ||
| - Normalizes consecutive slashes | ||
| - Optionally strips file extensions (e.g. .prompt, .agent) | ||
| - Removes leading/trailing slashes to match API conventions | ||
|
|
||
| Leading/trailing slashes are stripped because the Humanloop API expects paths in the | ||
| format 'path/to/resource' without them. This is consistent with how the API stores | ||
| and references files, and ensures paths work correctly in both API calls and local | ||
| filesystem operations. | ||
|
|
||
| Args: | ||
| path: The path to normalize. Can be a Windows or Unix-style path. | ||
| strip_extension: If True, removes the file extension (e.g. .prompt, .agent) | ||
|
|
||
| Returns: | ||
| Normalized path string in the format 'path/to/resource' | ||
|
|
||
| Examples: | ||
| >>> normalize_path("path/to/file.prompt") | ||
| 'path/to/file.prompt' | ||
| >>> normalize_path("path/to/file.prompt", strip_extension=True) | ||
| 'path/to/file' | ||
| >>> normalize_path("\\windows\\style\\path.prompt") | ||
| 'windows/style/path.prompt' | ||
| >>> normalize_path("/leading/slash/path/") | ||
| 'leading/slash/path' | ||
| >>> normalize_path("multiple//slashes//path") | ||
| 'multiple/slashes/path' | ||
| """ | ||
| # Handle backslashes for Windows paths before passing to PurePosixPath | ||
| # This is needed because some backslash sequences are treated as escape chars | ||
| path = path.replace("\\", "/") | ||
|
|
||
| # Use PurePosixPath to normalize the path (handles consecutive slashes) | ||
| path_obj = Path(path) | ||
|
|
||
| # Strip extension if requested | ||
| if strip_extension: | ||
| path_obj = path_obj.with_suffix("") | ||
|
|
||
| # Convert to string and remove any leading/trailing slashes | ||
| # We use the path as a string and not as_posix() since we've already normalized separators | ||
| return str(path_obj).strip("/") |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,3 @@ | ||
| from humanloop.sync.sync_client import SyncClient | ||
| from humanloop.sync.file_syncer import FileSyncer | ||
|
|
||
| __all__ = ["SyncClient"] | ||
| __all__ = ["FileSyncer"] |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.