Files
mdrs-client-python/CHANGELOG.md
T
orrisroot 0cac30ccf8 fix(auth): serialise the token refresh across processes
The login cache is shared by every mdrs process, but the refresh was
guarded by a lock that only reaches inside one. Concurrent runs each
sent the same refresh token, and a provider that rotates them accepts
the first and refuses the rest.

- hold a lock that spans processes across the whole read-refresh-
  write, checking cheaply first so ordinary requests never take it
- write the cache through a temporary file: opening it for writing
  truncates it, and a reader landing in that window found it empty
  and threw the session away
- take the lock for every write, not just the refresh, so a login
  running beside one cannot be silently reverted
- wait for a busy lock on Windows rather than giving up after the ten
  attempts msvcrt allows, and retry the rename it refuses while a
  reader still holds the file open
- bound the refresh request on its own, so a provider that goes quiet
  cannot hold the lock indefinitely
- accept bare hostnames such as localhost, store URLs without the
  trailing slash, and join download paths through one helper
2026-08-14 16:36:50 +09:00

4.8 KiB

Changelog

All notable changes to this project will be documented in this file.

[Unreleased]

Fixed

  • Serialised the token refresh across processes. Concurrent mdrs invocations shared one refresh token and each sent it, so a provider that rotates refresh tokens accepted the first and refused the rest.
  • Wrote the login cache through a temporary file so a reader can no longer catch it mid-truncation and discard the session.
  • Joined the base URL and the API's relative path correctly in ls --json output, which produced a doubled separator when the configured URL ended with one.

Changed

  • Accepted bare hostnames such as localhost in config create/config update, and stored the URL without its trailing slash, matching the Rust client so both can share config.ini.
  • Bounded the token refresh request with its own timeout, so a provider that stops answering cannot hold the cross-process lock indefinitely.
  • Breaking for embedders: CacheInterface now requires lock() and reload(). A cache passed to MdrsClient.from_remote(..., cache=...) must provide both; InMemoryCache implements them as no-ops.

[1.3.18] - 2026-07-02

Added

  • Added a comprehensive unit test suite in tests/test_commands.py checking registration, parsing, and execution flow of all 16 commands.

Refactored

  • Abstracted configuration storage (introducing ConfigInterface, InMemoryConfig, and updating ConfigFile) to enable dependency injection.
  • Modularized transfer operations (upload and download) to decouple them from the service layer.
  • Decoupled commands from direct file system configurations and migrated all subcommands to use abstract config classes.

Changed

  • Upgraded dependencies including pydantic-settings to 2.14.2 and pyright to 1.1.411.

Fixed

  • Fixed duplicate __all__ definitions in package initialization file mdrsclient/__init__.py that caused __version__ export to be overwritten.

[1.3.17] - 2026-07-02

Refactored

  • Decoupled core logic from CLI interface and introduced MdrsClient service layer to improve library portability.
  • Migrated all CLI commands to utilize MdrsClient for execution.

Added

  • Abstract authentication state using CacheInterface and InMemoryCache.

[1.3.16] - 2026-06-12

Fixed

  • Retrieve the full Folder object from FoldersApi instead of using the FolderSimple returned by find_sub_folder when resolving DOI subfolders. This fixes a type checker error under the upgraded pyright and avoids a potential AttributeError at runtime due to FolderSimple lacking the path attribute.

Changed

  • Upgraded dependencies and bumped version to 1.3.16 in pyproject.toml.

[1.3.15] - 2026-05-01

Fixed

  • Apply NFC normalization to filenames and folder names sent to the server.

[1.3.14] - 2026-04-17

Changed

  • Simplified config list command (removed -l/--long option, always display URL).
  • Renamed --quick option to --quiet for ls subcommand.

Added

  • Added subcommand aliases for config commands (e.g. ls alias for list, rm alias for delete).
  • Added version command.

[1.3.13] - 2025-07-02

Fixed

  • Fixed pagination logic for the file.list API.

[1.3.12] - 2025-05-20

Fixed

  • Fixed bug where file downloading was skipped incorrectly when -s/--skip-if-file-exists option was present.

[1.3.11] - 2025-01-21

Fixed

  • Follow-up fixes for User API specification changes.

[1.3.10] - 2024-12-23

Added

  • Delete broken files and show a summary when a file download fails.

Changed

  • Updated dependency libraries.

[1.3.9] - 2024-10-23

Fixed

  • Fixed compatibility with Python 3.10.

[1.3.8] - 2024-09-18

Added

  • Implemented -s/--skip-if-file-exists option for download command.

Fixed

  • Added exception handling for unexpected responses from the server.

[1.3.7] - 2024-07-22

Added

  • Implemented --exclude argument for download subcommand.

[1.3.6] - 2024-07-08

Added

  • Support cancelling recursive downloads if downloading some files fails.

[1.3.5] - 2024-07-08

Added

  • Added authorization token validation checks for file download operations.

Removed

  • Removed unnecessary debug code.

[1.3.4] - 2024-07-04

Added

  • Added some aliases for config sub command.

Fixed

  • Fixed bug when uploading large files.

[1.3.3] - 2024-02-13

Added

  • Implemented -s/--skip-if-file-exists option for upload command.

[1.3.2] - 2024-02-09

Added

  • Added -u and -p options to login command.

[1.3.1] - 2023-12-20

Fixed

  • Fixed bug to resolve local files for recursive file upload.

[1.3.0] - 2023-12-18

Changed

  • Removed debug comments.

[1.2.0] - 2023-10-04

Changed

  • Follow-up recent specification changes about folder access level.

[1.1.1] - 2023-07-26

Changed

  • Set destination folder name using name attribute of folder copy API.