Hacktoberfest 2026:メンテナが10月に向けて印を付けた、オープンで初心者向けの issue。 Hacktoberfest の issue を見る

feat: add configurable JsonClient class for dependency injection

オープン 初心者向け
#19 コメント 0 件 リアクション 0 件 担当者 0 名 GitHub で見る

まだ誰も着手していません。

評価

難易度
2/5
見積もり時間
1〜3時間
初心者へのやさしさ
76/100
issue の種類
機能追加
明瞭さ
明確に書かれている
活発さ
静か
技術スタック
python
領域
api

調査の方向性

campus_python/init.py から始め、Campus クラスとその auth および api プロパティに注目してください。次に tests/flask_test/campus_request.py を確認して、注入されるクライアントの形状を確認し、両方のプロパティが設定されたクラスを使用し、デフォルトは CampusRequest のままであることを検証してください。ドキュメントの例とマイナーバージョンのリリースは、追加のチェックリスト項目として記載されています。

索引モデルが issue の本文から書いたものです。

説明

Feature Request: Configurable JsonClient Class for Dependency Injection

Problem

When testing Campus services that use campus_python.Campus, we need to replace the default CampusRequest with a test-compatible version that routes to Flask test clients instead of making real HTTP requests.

Current Workaround: Monkey-Patching

Currently, we have to monkey-patch the CampusRequest class:

import campus_python
from tests.flask_test import TestCampusRequest

# Replace CampusRequest globally
campus_python.json_client.CampusRequest = TestCampusRequest
campus_python.CampusRequest = TestCampusRequest  # Also patch module reference

Problems with this approach:

  • ❌ Fragile - requires patching multiple module-level references
  • ❌ Hard to debug - changes global state
  • ❌ Confusing - not obvious that CampusRequest has been replaced
  • ❌ Brittle - may break if campus-api-python internals change

Proposed Solution

Add a configurable class attribute to allow dependency injection of the JsonClient class:

class Campus:
    """Unified Campus client interface."""
    
    # Configurable JsonClient class
    json_client_class: type[JsonClient] = CampusRequest
    
    @property
    def auth(self) -> AuthRoot:
        if not hasattr(self, "_auth"):
            # Use json_client_class instead of hardcoded CampusRequest
            self._auth = AuthRoot(
                json_client=self.json_client_class(
                    base_url=base_url,
                    timeout=self.timeout,
                )
            )
        return self._auth
    
    @property
    def api(self) -> ApiRoot:
        if not hasattr(self, "_api"):
            self._api = ApiRoot(
                json_client=self.json_client_class(
                    base_url=base_url,
                    timeout=self.timeout,
                )
            )
        return self._api
Usage in Tests
import campus_python
from tests.flask_test import TestCampusRequest

def setup():
    # Configure campus_python to use test client
    campus_python.Campus.json_client_class = TestCampusRequest
    
    # Now all Campus instances use TestCampusRequest
    campus = campus_python.Campus(timeout=60)
    campus.auth.root.authenticate(...)  # Uses Flask test clients!

Benefits

  1. ✅ Clean dependency injection - No monkey-patching required
  2. ✅ Explicit configuration - Clear what JsonClient is being used
  3. ✅ Backward compatible - Defaults to CampusRequest
  4. ✅ Test-friendly - Easy to inject test doubles
  5. ✅ Flexible - Allows custom JsonClient implementations for:
    • Testing (Flask test clients)
    • Mocking (for unit tests)
    • Custom HTTP backends (async, retry logic, etc.)

Implementation Details

Changes Required

File: campus_python/__init__.py

  1. Add class attribute:

    class Campus:
        json_client_class: type[JsonClient] = CampusRequest
    
  2. Replace hardcoded CampusRequest(...) with self.json_client_class(...):

    • In auth property (line ~81)
    • In api property (line ~107)
Example Custom JsonClient
from campus_python.json_client.interface import JsonClient, JsonResponse

class CustomJsonClient(JsonClient):
    """Custom JsonClient with special behavior."""
    
    def __init__(self, base_url: str | None = None, **kwargs):
        self.base_url = base_url or ""
        # ... custom initialization ...
    
    def get(self, path: str, query: dict | None = None) -> JsonResponse:
        # ... custom implementation ...
        pass
    
    # ... implement other methods ...

# Use it
campus_python.Campus.json_client_class = CustomJsonClient

Backward Compatibility

✅ Fully backward compatible - Default value is CampusRequest, so existing code continues to work without changes.

Related

Alternatives Considered

  1. Constructor parameter (Campus(json_client_class=...))

    • ❌ Doesn't work for services that instantiate Campus() internally (campus.auth, campus.api)
  2. Global function (set_json_client_class())

    • ❌ More verbose than class attribute
    • ❌ Requires additional function to maintain
  3. Keep monkey-patching

    • ❌ Fragile and confusing

Implementation Checklist

  • Add json_client_class class attribute to Campus
  • Update auth property to use self.json_client_class
  • Update api property to use self.json_client_class
  • Add docstring explaining the configuration option
  • Add example to README or documentation
  • Release as minor version bump (e.g., v2.1.0)
主要言語
Python
スター
0
フォーク
0
PR マージ指標
30日以内にマージされた PR はありません

コントリビューションガイド

このリポジトリのコントリビューションガイドは索引されていません

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

nyjc-computing/campus-api-python のほかの issue

nyjc-computing/campus-api-python の issue をすべて見る

似ている issue

Python の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。