11#!/usr/bin/env python3
2- """Smoke test for minimal (base-only) installation of a2a-sdk.
2+ """Smoke test for installations of a2a-sdk with various extras .
33
4- This script verifies that all core public API modules can be imported
5- when only the base dependencies are installed (no optional extras).
4+ This script verifies that the public API modules associated with a
5+ given installation profile can be imported without pulling in modules
6+ that belong to other (uninstalled) optional extras.
67
78It is designed to run WITHOUT pytest or any dev dependencies -- just
8- a clean venv with `pip install a2a-sdk`.
9+ a clean venv with `pip install a2a-sdk[<profile>] `.
910
1011Usage:
11- python scripts/test_minimal_install.py
12+ python scripts/test_install_smoke.py [profile]
13+
14+ profile defaults to "base" and selects which set of modules to
15+ smoke-test. Available profiles:
16+ base -- `pip install a2a-sdk`
17+ http-server -- `pip install a2a-sdk[http-server]`
1218
1319Exit codes:
14- 0 - All core imports succeeded
15- 1 - One or more core imports failed
20+ 0 - All imports for the profile succeeded
21+ 1 - One or more imports failed
1622"""
1723
1824from __future__ import annotations
5864 'a2a.helpers.proto_helpers' ,
5965]
6066
67+ # Modules that MUST be importable with only the base + `http-server`
68+ # extras installed (no `grpc`, `sql`, `signing`, `telemetry`, etc.).
69+ #
70+ # A user building a Starlette/FastAPI A2A server with
71+ # `pip install a2a-sdk[http-server]` should be able to import these
72+ # without the gRPC stack being present on the system.
73+ HTTP_SERVER_MODULES = [
74+ 'a2a.server.routes' ,
75+ 'a2a.server.routes.agent_card_routes' ,
76+ 'a2a.server.routes.common' ,
77+ 'a2a.server.routes.jsonrpc_dispatcher' ,
78+ 'a2a.server.routes.jsonrpc_routes' ,
79+ 'a2a.server.routes.rest_dispatcher' ,
80+ 'a2a.server.routes.rest_routes' ,
81+ ]
82+
83+
84+ PROFILES : dict [str , list [str ]] = {
85+ 'base' : CORE_MODULES ,
86+ 'http-server' : CORE_MODULES + HTTP_SERVER_MODULES ,
87+ }
88+
6189
6290def main () -> int :
91+ profile = sys .argv [1 ] if len (sys .argv ) > 1 else 'base'
92+ if profile not in PROFILES :
93+ print (f'Unknown profile { profile !r} . Available: { sorted (PROFILES )} ' )
94+ return 1
95+
96+ modules = PROFILES [profile ]
6397 failures : list [str ] = []
6498 successes : list [str ] = []
6599
66- for module_name in CORE_MODULES :
100+ for module_name in modules :
67101 try :
68102 importlib .import_module (module_name )
69103 successes .append (module_name )
70104 except Exception as e : # noqa: BLE001, PERF203
71105 failures .append (f'{ module_name } : { e } ' )
72106
73- print (f'Tested { len (CORE_MODULES )} core modules' )
107+ print (f'Profile: { profile } ' )
108+ print (f'Tested { len (modules )} modules' )
74109 print (f' Passed: { len (successes )} ' )
75110 print (f' Failed: { len (failures )} ' )
76111
@@ -80,7 +115,7 @@ def main() -> int:
80115 print (f' - { failure } ' )
81116 return 1
82117
83- print ('\n All core modules imported successfully.' )
118+ print ('\n All modules imported successfully.' )
84119 return 0
85120
86121
0 commit comments