keycycle 0.2.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. keycycle-0.2.1/MANIFEST.in +1 -0
  2. keycycle-0.2.1/PKG-INFO +44 -0
  3. keycycle-0.2.1/keycycle/__init__.py +51 -0
  4. keycycle-0.2.1/keycycle/adapters/__init__.py +26 -0
  5. keycycle-0.2.1/keycycle/adapters/generic_adapter.py +618 -0
  6. keycycle-0.2.1/keycycle/adapters/openai_adapter.py +337 -0
  7. keycycle-0.2.1/keycycle/config/__init__.py +25 -0
  8. keycycle-0.2.1/keycycle/config/constants.py +35 -0
  9. keycycle-0.2.1/keycycle/config/dataclasses.py +212 -0
  10. keycycle-0.2.1/keycycle/config/enums.py +5 -0
  11. keycycle-0.2.1/keycycle/config/loader.py +54 -0
  12. keycycle-0.2.1/keycycle/config/log_config.py +53 -0
  13. keycycle-0.2.1/keycycle/config/models/cerebras.yaml +55 -0
  14. keycycle-0.2.1/keycycle/config/models/cohere.yaml +14 -0
  15. keycycle-0.2.1/keycycle/config/models/gemini.yaml +69 -0
  16. keycycle-0.2.1/keycycle/config/models/groq.yaml +161 -0
  17. keycycle-0.2.1/keycycle/config/models/openrouter.yaml +4 -0
  18. keycycle-0.2.1/keycycle/config/models/openrouter_models.yaml +97 -0
  19. keycycle-0.2.1/keycycle/config/models.py +47 -0
  20. keycycle-0.2.1/keycycle/core/__init__.py +40 -0
  21. keycycle-0.2.1/keycycle/core/backoff.py +79 -0
  22. keycycle-0.2.1/keycycle/core/exceptions.py +94 -0
  23. keycycle-0.2.1/keycycle/core/utils.py +406 -0
  24. keycycle-0.2.1/keycycle/key_rotation/__init__.py +7 -0
  25. keycycle-0.2.1/keycycle/key_rotation/rotating_mixin.py +339 -0
  26. keycycle-0.2.1/keycycle/key_rotation/rotation_manager.py +231 -0
  27. keycycle-0.2.1/keycycle/legacy_multi_provider_wrapper.py +734 -0
  28. keycycle-0.2.1/keycycle/multi_client_wrapper.py +372 -0
  29. keycycle-0.2.1/keycycle/py.typed +0 -0
  30. keycycle-0.2.1/keycycle/usage/__init__.py +6 -0
  31. keycycle-0.2.1/keycycle/usage/db_logic.py +98 -0
  32. keycycle-0.2.1/keycycle/usage/usage_logger.py +89 -0
  33. keycycle-0.2.1/keycycle/utils.py +26 -0
  34. keycycle-0.2.1/keycycle.egg-info/PKG-INFO +44 -0
  35. keycycle-0.2.1/keycycle.egg-info/SOURCES.txt +46 -0
  36. keycycle-0.2.1/keycycle.egg-info/dependency_links.txt +1 -0
  37. keycycle-0.2.1/keycycle.egg-info/requires.txt +42 -0
  38. keycycle-0.2.1/keycycle.egg-info/top_level.txt +1 -0
  39. keycycle-0.2.1/pyproject.toml +121 -0
  40. keycycle-0.2.1/setup.cfg +4 -0
  41. keycycle-0.2.1/tests/test_api_key_pinning.py +115 -0
  42. keycycle-0.2.1/tests/test_api_key_retrieval.py +261 -0
  43. keycycle-0.2.1/tests/test_cerebras_direct.py +85 -0
  44. keycycle-0.2.1/tests/test_custom_key_limits.py +344 -0
  45. keycycle-0.2.1/tests/test_multi_client_wrapper.py +517 -0
  46. keycycle-0.2.1/tests/test_rate_limit_logic.py +255 -0
  47. keycycle-0.2.1/tests/test_specific_key_retrieval.py +84 -0
  48. keycycle-0.2.1/tests/test_streams_recording.py +166 -0
@@ -0,0 +1 @@
1
+ recursive-include keycycle/config/models *.yaml
@@ -0,0 +1,44 @@
1
+ Metadata-Version: 2.4
2
+ Name: keycycle
3
+ Version: 0.2.1
4
+ Summary: A thread-safe key rotation and rate limiting manager for API keys.
5
+ Author-email: William Jin <jinwilliam.jin@gmail.com>
6
+ Classifier: Programming Language :: Python :: 3
7
+ Classifier: License :: OSI Approved :: MIT License
8
+ Classifier: Operating System :: OS Independent
9
+ Classifier: Development Status :: 3 - Alpha
10
+ Requires-Python: >=3.9
11
+ Description-Content-Type: text/markdown
12
+ Requires-Dist: python-dotenv
13
+ Requires-Dist: sqlalchemy
14
+ Requires-Dist: pymysql
15
+ Requires-Dist: rich
16
+ Requires-Dist: PyYAML
17
+ Provides-Extra: openai
18
+ Requires-Dist: openai; extra == "openai"
19
+ Provides-Extra: agno
20
+ Requires-Dist: agno; extra == "agno"
21
+ Provides-Extra: cohere
22
+ Requires-Dist: cohere; extra == "cohere"
23
+ Provides-Extra: cerebras
24
+ Requires-Dist: cerebras-cloud-sdk; extra == "cerebras"
25
+ Provides-Extra: groq
26
+ Requires-Dist: groq; extra == "groq"
27
+ Provides-Extra: openrouter
28
+ Requires-Dist: openrouter; extra == "openrouter"
29
+ Provides-Extra: all
30
+ Requires-Dist: openai; extra == "all"
31
+ Requires-Dist: agno; extra == "all"
32
+ Requires-Dist: cohere; extra == "all"
33
+ Requires-Dist: cerebras-cloud-sdk; extra == "all"
34
+ Requires-Dist: groq; extra == "all"
35
+ Requires-Dist: openrouter; extra == "all"
36
+ Provides-Extra: test
37
+ Requires-Dist: pytest>=7.4.0; extra == "test"
38
+ Requires-Dist: pytest-cov>=4.1.0; extra == "test"
39
+ Requires-Dist: pytest-asyncio>=0.21.0; extra == "test"
40
+ Requires-Dist: pytest-timeout>=2.2.0; extra == "test"
41
+ Provides-Extra: dev
42
+ Requires-Dist: keycycle[test]; extra == "dev"
43
+ Requires-Dist: mypy>=1.5.0; extra == "dev"
44
+ Requires-Dist: types-PyYAML; extra == "dev"
@@ -0,0 +1,51 @@
1
+ from .legacy_multi_provider_wrapper import MultiProviderWrapper
2
+ from .multi_client_wrapper import MultiClientWrapper, ProviderEnvConfig
3
+ from .key_rotation.rotation_manager import RotatingKeyManager
4
+ from .config.dataclasses import RateLimits, KeyLimitOverride
5
+ from .core.utils import KeyEntry
6
+ from .core.exceptions import (
7
+ KeycycleError,
8
+ NoAvailableKeyError,
9
+ KeyNotFoundError,
10
+ InvalidKeyError,
11
+ RateLimitError,
12
+ ConfigurationError,
13
+ )
14
+ from .adapters.generic_adapter import (
15
+ create_rotating_client,
16
+ detect_async_client,
17
+ get_valid_constructor_kwargs,
18
+ GenericClientConfig,
19
+ SyncGenericRotatingClient,
20
+ AsyncGenericRotatingClient,
21
+ )
22
+ from .adapters.openai_adapter import RotatingAsyncOpenAIClient, RotatingOpenAIClient
23
+
24
+ __all__ = [
25
+ # New primary wrapper (multi-provider support)
26
+ "MultiClientWrapper",
27
+ "ProviderEnvConfig",
28
+ # Legacy wrapper (single provider, backward compatible)
29
+ "MultiProviderWrapper",
30
+ # Main classes
31
+ "RateLimits",
32
+ "KeyLimitOverride",
33
+ "KeyEntry",
34
+ "RotatingKeyManager",
35
+ "RotatingAsyncOpenAIClient",
36
+ "RotatingOpenAIClient",
37
+ # Generic rotating client
38
+ "create_rotating_client",
39
+ "detect_async_client",
40
+ "get_valid_constructor_kwargs",
41
+ "GenericClientConfig",
42
+ "SyncGenericRotatingClient",
43
+ "AsyncGenericRotatingClient",
44
+ # Exceptions
45
+ "KeycycleError",
46
+ "NoAvailableKeyError",
47
+ "KeyNotFoundError",
48
+ "InvalidKeyError",
49
+ "RateLimitError",
50
+ "ConfigurationError",
51
+ ]
@@ -0,0 +1,26 @@
1
+ from .openai_adapter import RotatingOpenAIClient, RotatingAsyncOpenAIClient
2
+ from .generic_adapter import (
3
+ create_rotating_client,
4
+ detect_async_client,
5
+ default_usage_extractor,
6
+ GenericClientConfig,
7
+ SyncGenericRotatingClient,
8
+ AsyncGenericRotatingClient,
9
+ SyncGenericProxyHelper,
10
+ AsyncGenericProxyHelper,
11
+ )
12
+
13
+ __all__ = [
14
+ # OpenAI-specific
15
+ "RotatingOpenAIClient",
16
+ "RotatingAsyncOpenAIClient",
17
+ # Generic adapter
18
+ "create_rotating_client",
19
+ "detect_async_client",
20
+ "default_usage_extractor",
21
+ "GenericClientConfig",
22
+ "SyncGenericRotatingClient",
23
+ "AsyncGenericRotatingClient",
24
+ "SyncGenericProxyHelper",
25
+ "AsyncGenericProxyHelper",
26
+ ]