Files
litellm/tests/code_coverage_tests/check_unsafe_enterprise_import.py
T
Krish Dholakia a44bc9f613 Remove + Check for unsafe enterprise/ folder imports (#11107)
* refactor(litellm/): wrap enterprise package usage in safe try-excepts

prevents missing package error for OSS users

Fixes https://github.com/BerriAI/litellm/issues/10795

* ci(config.yml): add script to check for unsafe imports to ci/cd

Closes https://github.com/BerriAI/litellm/issues/10795

* fix: add missing docs

* test: test_openai_image_edit_litellm_sdk

* use n 4 for mapped tests (#11109)

* Fix/background health check (#10887)

* fix: improve health check logic by deep copying model list on each iteration

* test: add async test for background health check reflecting model list changes

* fix: validate health check interval before executing background health check

* fix: specify type for health check results dictionary

* fix(user_api_key_auth.py): handle user custom auth set with no custom settings

* bump: version 0.1.21 → 0.2.0

* ci(config.yml): run enterprise and litellm tests separately

* fix: fix linting error

* docs: add missing docs

* [Feat] Add content policy violation error mapping for image editd (#11113)

* feat: add image edit mapping for content policy violations

* test fix

* Expose `/list` and `/info` endpoints for Audit Log events (#11102)

* feat(audit_logging_endpoints.py): expose list endpoint to show all audit logs

make it easier for user to retrieve individual endpoints

* feat(enterprise/): add audit logging endpoint

* feat(audit_logging_endpoints.py): expose new GET `/audit/{id}` endpoint

make it easier to retrieve view individual audit logs

* feat(key_management_event_hooks.py): correctly show the key of the user who initiated the change

* fix(key_management_event_hooks.py): add key rotations as an audit log event

'

* test(test_audit_logging_endpoints.py): add simple unit testing for audit log endpoint

* fix: testing fixes

* fix: fix ruff check

* [Feat] Use aiohttp transport by default - 97% lower median latency  (#11097)

* fix: add flag for disabling use_aiohttp_transport

* feat: add _create_async_transport

* feat: fixes for transport

* add httpx-aiohttp

* feat: fixes for transport

* refactor: fixes for transport

* build: fix deps

* fixes: test fixes

* fix: ensure aiohttp does not auto set content type

* test: test fixes

* feat: add LiteLLMAiohttpTransport

* fix: fixes for responses API handling

* test: fixes for responses API handling

* test: fixes for responses API handling

* feat: fixes for transport

* fix: base embedding handler

* test: test_async_http_handler_force_ipv4

* test: fix failing deepeval test

* fix: add YARL for bedrock urls

* fix: issues with transport

* fix: comment out linting issues

* test fix

* test: XAI is unstable

* test: fixes for using respx

* test: XAI fixes

* test: XAI fixes

* test: infinity testing fixes

* docs(config_settings.md): document param

* test: test_openai_image_edit_litellm_sdk

* test: remove deprecated test

* bump respx==0.22.0

* test: test_xai_message_name_filtering

* test: fix anthropic test after bumping httpx

* use n 4 for mapped tests (#11109)

* fix: use 1 session per event loop

* test: test_client_session_helper

* fix: linting error

* fix: resolving GET requests on httpx 0.28.1

* test fixes proxy unit tests

* fix: add ssl verify settings

* fix: proxy unit tests

* fix: refactor

* tests: basic unit tests for aiohttp transports

* tests: fixes xai

---------

Co-authored-by: Krrish Dholakia <krrishdholakia@gmail.com>

* test: cleanup redundant test

* fix: fix import

* fix: fix linting errors

---------

Co-authored-by: Ishaan Jaff <ishaanjaffer0324@gmail.com>
Co-authored-by: JuHyun Bae <jhyun0408@nate.com>
2025-05-24 08:59:02 -07:00

96 lines
3.4 KiB
Python

import ast
import os
class EnterpriseImportFinder(ast.NodeVisitor):
def __init__(self):
self.unsafe_imports = []
self.current_file = None
self.in_try_block = False
self.try_blocks = []
def visit_Try(self, node):
# Track that we're entering a try block
self.in_try_block = True
self.try_blocks.append(node)
# Visit all nodes in the try block
for item in node.body:
self.visit(item)
# Visit except blocks
for handler in node.handlers:
for item in handler.body:
self.visit(item)
# Visit else block if it exists
for item in node.orelse:
self.visit(item)
# Visit finally block if it exists
for item in node.finalbody:
self.visit(item)
# We're leaving the try block
self.try_blocks.pop()
self.in_try_block = len(self.try_blocks) > 0
def visit_Import(self, node):
# Check for direct imports of litellm_enterprise
for name in node.names:
if "litellm_enterprise" in name.name or "enterprise" in name.name:
if not self.in_try_block:
self.unsafe_imports.append({
"file": self.current_file,
"line": node.lineno,
"import": name.name,
"context": "direct import"
})
self.generic_visit(node)
def visit_ImportFrom(self, node):
# Check for from litellm_enterprise imports
if node.module and ("litellm_enterprise" in node.module or "enterprise" in node.module):
if not self.in_try_block:
self.unsafe_imports.append({
"file": self.current_file,
"line": node.lineno,
"import": f"from {node.module}",
"context": "from import"
})
self.generic_visit(node)
def find_unsafe_enterprise_imports_in_file(file_path):
with open(file_path, "r") as file:
tree = ast.parse(file.read(), filename=file_path)
finder = EnterpriseImportFinder()
finder.current_file = file_path
finder.visit(tree)
return finder.unsafe_imports
def find_unsafe_enterprise_imports_in_directory(directory):
unsafe_imports = []
for root, _, files in os.walk(directory):
for file in files:
if file.endswith(".py"):
file_path = os.path.join(root, file)
imports = find_unsafe_enterprise_imports_in_file(file_path)
if imports:
unsafe_imports.extend(imports)
return unsafe_imports
if __name__ == "__main__":
# Check for unsafe enterprise imports in the litellm directory
directory_path = "./litellm"
unsafe_imports = find_unsafe_enterprise_imports_in_directory(directory_path)
if unsafe_imports:
print("🚨 UNSAFE ENTERPRISE IMPORTS FOUND (not in try-except blocks):")
for imp in unsafe_imports:
print(f"File: {imp['file']}")
print(f"Line: {imp['line']}")
print(f"Import: {imp['import']}")
print(f"Context: {imp['context']}")
print("---")
# Raise exception to fail CI/CD
raise Exception(
"🚨 Unsafe enterprise imports found. All enterprise imports must be wrapped in try-except blocks."
)
else:
print("✅ No unsafe enterprise imports found.")