Skip to content

Feat/login - #1477

Merged
SAKURA-CAT merged 14 commits into
mainfrom
feat/login
Mar 8, 2026
Merged

SAKURA-CAT merged 14 commits into
mainfrom
feat/login

Conversation

@SAKURA-CAT

Copy link
Copy Markdown
Member
  1. 将api host、web host等参数重新规划,现在在settings初始化时会尝试加载api host、web host等参数
  2. 完成swanlab.login命令,删除web_host接口
  3. 提供了一个上下文接收器 scope,这在一些需要获取底层数据的场景非常好用

SAKURA-CAT and others added 5 commits March 8, 2026 14:27
Major refactor: extract loading animation to swanlab.sdk.pkg.helper.rich, add a Scope context manager, and restructure client and settings.

Key changes:
- Introduced internal/pkg/scope.py (Scope context manager) and exported Scope/get_context/set_context via internal/pkg.__init__.
- Moved with_loading_animation into swanlab.sdk.pkg.helper.rich and exposed it via swanlab.sdk.pkg.helper.
- Refactored core_python.client API: added new/exists/reset/_get_client, added timeout handling, store login response into Scope via set_context, and simplified global proxy helpers.
- Moved strip_none into internal.settings, added a pre-validator to clean empty values, and introduced an interactive setting flag.
- Updated apikey and console imports to use internal.pkg helpers.
- Reworked login flow to use Scope, prompt/save API keys, and create client with loading animation.
- Updated and added unit tests to cover Scope, settings.strip_none, and the updated client lifecycle and behaviors.
Refactor login flow and API key prompting: login.py now returns early if already logged in, defaults host from current settings, and annotates the login steps with clearer comments. The interactive-mode check for missing API keys was moved from login.py into internal/apikey.prompt(), which now raises a RuntimeError when interactive mode is disabled (and documents terminal password limitations). This centralizes responsibility for interactive prompting and simplifies the login logic.
Move netrc read/write helpers into swanlab.sdk.internal.pkg.netrc and centralize netrc operations (get_nrc_path, read_netrc_by_host, write_netrc, remove_host_suffix). Update apikey module to use the new netrc utilities and sync API key into Settings; simplify get/exists to rely on current Settings. Add use_temp_context/RunConfig in internal.context and update swanlab.sdk.cmd.login to run login inside a temporary RunContext, prevent relogin when a global context is active, and export login from package init files. Add a Settings model validator to load .netrc as a fallback for unset fields and tighten console import path. Update and add unit tests to cover netrc utilities, Settings netrc fallback, and apikey flows; minor test fixture adjustments and renames for scope/settings modules.
Import remove_host_suffix and use it to ensure the client's base_url consistently ends with a single "/api" (avoids duplicate suffixes when composing URLs). Also return the full login response from login_by_api_key instead of None so callers can access returned metadata (e.g. expiredAt). No behavioral changes to session handling.
Add web_host to the temporary login Settings and default it from existing settings. The change updates Settings.model_validate to include "web_host" (derived from host or settings.web_host) and uses web_host when saving the API key instead of using the username from the login response. This ensures credentials are saved/scoped by the web host.
@SAKURA-CAT
SAKURA-CAT requested a review from Nexisato March 8, 2026 08:21
@SAKURA-CAT SAKURA-CAT self-assigned this Mar 8, 2026
@SAKURA-CAT SAKURA-CAT added the 💪 enhancement New feature or request label Mar 8, 2026
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

此拉取请求旨在通过引入 swanlab.login 命令来简化用户认证流程,并对 SDK 内部的配置管理和数据传递机制进行了重大改进。通过统一 API 和 Web 主机参数的加载逻辑,并引入创新的 Scope 上下文管理器,显著提升了代码的清晰度、可维护性和功能性,为后续的开发奠定了更坚实的基础。

Highlights

  • 登录命令重构: 引入了新的 swanlab.login 命令,用于集中处理 API 密钥认证、重新登录逻辑以及 API 和 Web 主机配置,并移除了旧的 web_host 接口。
  • 设置参数统一管理: 重构了内部设置管理,现在 Settings 初始化时会尝试从环境变量、配置文件以及新增的 .netrc 文件中自动加载 API 和 Web 主机等参数,确保配置的灵活性和优先级。
  • 引入上下文接收器 Scope: 新增了一个基于 contextvars 的 Scope 上下文管理器,允许在不修改函数签名的情况下,从深层函数中安全地获取和传递临时数据,解决了“透传污染”问题。
  • API 客户端与凭证管理优化: 重构了内部 API 客户端的生命周期管理,并优化了 API 密钥的存储和读取逻辑,现在统一通过 swanlab.sdk.internal.pkg.netrc 模块处理 .netrc 文件,并支持旧版兼容。

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • swanlab/init.py
    • 导入并暴露了新的 login 函数。
  • swanlab/sdk/init.py
    • 导入并暴露了 login 函数。
  • swanlab/sdk/cmd/init.py
    • 移除了 with_loading_animation 装饰器和 strip_none 函数,这些功能已被重构到其他模块。
  • swanlab/sdk/cmd/login.py
    • 新增文件,实现了 swanlab.login 命令的核心逻辑,包括 API 密钥处理、客户端创建和临时上下文管理。
    • 移除了 login 函数签名中的 web_host 参数。
  • swanlab/sdk/internal/apikey/init.py
    • 重构了 API 密钥管理逻辑,现在依赖 swanlab.sdk.internal.pkg.netrc 进行文件操作。
    • 更新了 save、exists 和 get 函数,使其直接与 Settings 实例交互。
  • swanlab/sdk/internal/apikey/helper.py
    • 移除了 get_nrc_path 函数,该功能已迁移至 swanlab.sdk.internal.pkg.netrc。
  • swanlab/sdk/internal/context/init.py
    • 为 RunConfig 添加了 @dataclass 装饰器。
    • 新增了 use_temp_context 上下文管理器,用于临时激活和清理 RunContext。
  • swanlab/sdk/internal/core_python/client/init.py
    • 将客户端初始化和管理函数 (init_client, get_client, reset_client) 重构为 new, exists, reset, _get_client。
    • 客户端构造函数现在接受 timeout 参数,并在初始化时将登录响应设置到 Scope 中。
  • swanlab/sdk/internal/pkg/netrc/init.py
    • 新增模块,提供了 .netrc 文件的读取、写入和路径获取工具函数,支持旧版兼容和全局单点登录原则。
  • swanlab/sdk/internal/pkg/scope/init.py
    • 新增模块,实现了 Scope 上下文管理器,用于跨层级安全地传递和收集数据。
  • swanlab/sdk/internal/pkg/settings/init.py
    • 文件从 swanlab/sdk/internal/pkg/settings.py 重命名为 swanlab/sdk/internal/pkg/settings/__init__.py。
  • swanlab/sdk/internal/settings/init.py
    • 将 strip_none 函数从 swanlab/sdk/cmd/init.py 迁移至此。
    • 在 Settings 类中新增了 interactive 配置项。
    • 添加了 strip_non_empty 模型验证器,用于在加载前剔除空值和空字典。
    • 新增了 load_netrc_fallback 模型验证器,作为兜底机制从 .netrc 文件加载 API 密钥和主机信息。
  • swanlab/sdk/pkg/helper/init.py
    • 导出了 rich 子模块。
  • swanlab/sdk/pkg/helper/rich.py
    • 新增模块,包含了 with_loading_animation 装饰器。
  • tests/unit/sdk/internal/apikey/test_apikey.py
    • 更新了测试用例,以适应 API 密钥管理模块的重构,并模拟了 Settings 实例的更新。
  • tests/unit/sdk/internal/core_python/client/test_client.py
    • 更新了客户端测试,以使用新的客户端生命周期管理函数,并精确捕获 ApiError。
  • tests/unit/sdk/internal/pkg/test_netrc.py
    • 新增测试文件,全面测试了 netrc 工具模块的功能,包括路径获取、后缀移除、读取和写入操作。
  • tests/unit/sdk/internal/pkg/test_scope.py
    • 新增测试文件,验证了 Scope 上下文管理器的隔离性、嵌套行为和冒泡机制。
  • tests/unit/sdk/internal/settings/test_settings.py
    • 新增了 strip_none 函数的测试用例。
    • 新增了 .netrc 兜底加载逻辑的测试用例,验证了优先级和兼容性。
  • tests/unit/sdk/test_init.py
    • 移除了 strip_none 函数的测试用例,因为该函数已迁移。
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution. ↩

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This Pull Request significantly refactors configuration processing and authentication workflows. Key changes include implementing the swanlab.login command, centralizing configuration management within the Settings class with .netrc support, and introducing a Scope context manager for clean data passing. While these changes improve code quality and maintainability, a critical security vulnerability has been identified: the current implementation for saving credentials to the .netrc file is susceptible to Netrc Injection. This is due to a lack of validation or escaping of newlines in API key or host parameters, which could allow an attacker to inject malicious entries into the shared configuration file. It is strongly recommended to add validation to prevent newlines or control characters in usernames and passwords. Additionally, the code review identified a minor bug and an area for improvement, which are detailed in the specific comments.

Comment thread swanlab/sdk/cmd/login.py Outdated
Comment thread swanlab/sdk/internal/pkg/netrc/__init__.py
Comment thread swanlab/sdk/internal/settings/__init__.py Outdated
Update settings package docs to include settings.root in the config load priority and renumber items accordingly. Refactor client unit tests: rename mock_url -> mock_base_url, add mock_api_url fixture (base + "/api"), update client fixture to use mock_base_url, and change assertions/response stubs to expect the client to force-append "/api" to base URLs. Also refine token refresh and global proxy tests and adjust responses URLs to use the composed mock_api_url.
Pass web_host into Settings.model_validate during login so the client is created with the correct web host. Also broaden netrc parsing error handling to include PermissionError (to accommodate Windows permission/dir-as-file cases) and improve the netrc access/parse error message.
Add input validation for host, username, and password when writing the netrc file. The code now rejects values containing newlines, carriage returns, spaces, or tabs and raises ValueError, preventing malformed .netrc entries or injection via credential fields. Existing path conflict check (raising IOError if the target is a directory) remains unchanged.
Rename Makefile test target to `unit` (runs tests/unit) and add comprehensive test isolation and login tests. Update tests/unit/conftest.py to provide an autouse fixture that isolates file-system/env (SWANLAB_SAVE_DIR), resets the Settings singleton (including Pydantic internal state), clears the global client and RunContext. Add tests/unit/sdk/cmd/test_login.py with E2E-style tests for login behavior (skip when already logged in, blocked when context active, successful login flows with explicit/prompted keys, custom hosts/relogin, and network failure handling) using responses and monkeypatch to stub network and env. These changes ensure unit tests run in a hermetic environment and avoid cross-test leakage.
Rename and centralize exceptions to swanlab.exceptions and add AuthenticationError. Update login flow to use the new AuthenticationError, fix api_host variable handling, and raise on missing login response. Improve API key prompt: add secure getpass input, interactive-environment checks, richer console guidance, Windows paste hint, and graceful interrupt handling; introduce swanlab.sdk.pkg.helper.env.is_interactive. Add a console.print wrapper to gate plain prints. Make client._refresh_auth optionally silent (warning flag) and adjust session imports to use swanlab.exceptions.ApiError. Update helper exports and unit tests to reflect these changes.
Expand and clarify documentation for swanlab.sdk.cmd.login and swanlab.sdk.cmd.merge_settings: add usage examples, reformat and clarify parameter descriptions (api_key, relogin, host, save, timeout), and make the raised exceptions more explicit. merge_settings docstring now includes an Examples section. These are documentation-only edits to improve developer UX; no functional logic changes were made.
Normalize and validate host input in login(): strip whitespace/trailing slashes, add https:// if missing, and remove path/query by using urllib.parse.urlparse. Prevent relogin while a RunContext is active and call client.reset() when relogin=True and a client exists. Protect the official api.swanlab.cn case so passing an api host does not overwrite the default web_host. Add a global declaration in client.exists() to avoid local/global issues. Update and add unit tests to cover host cleaning and official-host protection, and adjust existing tests to patch client.reset().
Remove the debug field from Settings and decouple the console logger from settings. The console module now determines debug mode from the SWANLAB_DEBUG environment variable and no longer imports settings.get_current_settings. Settings imports the console to emit a warning when .netrc loading fails instead of silently passing. Update unit test to stop asserting settings.debug and adjust expectations accordingly. These changes reduce cross-module coupling and centralize debug control via an environment variable.
@SAKURA-CAT
SAKURA-CAT merged commit f9bca2b into main Mar 8, 2026
21 checks passed
@SAKURA-CAT
SAKURA-CAT deleted the feat/login branch March 8, 2026 10:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

💪 enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant