spring-ready-python 0.1.0__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 (41) hide show
  1. spring_ready_python-0.1.0/.github/workflows/python-publish.yml +69 -0
  2. spring_ready_python-0.1.0/.gitignore +70 -0
  3. spring_ready_python-0.1.0/Dockerfile +29 -0
  4. spring_ready_python-0.1.0/PKG-INFO +459 -0
  5. spring_ready_python-0.1.0/README.md +421 -0
  6. spring_ready_python-0.1.0/docker-compose.yml +38 -0
  7. spring_ready_python-0.1.0/example.py +170 -0
  8. spring_ready_python-0.1.0/pyproject.toml +73 -0
  9. spring_ready_python-0.1.0/spring_ready/__init__.py +30 -0
  10. spring_ready_python-0.1.0/spring_ready/actuator/__init__.py +68 -0
  11. spring_ready_python-0.1.0/spring_ready/actuator/auditevents.py +114 -0
  12. spring_ready_python-0.1.0/spring_ready/actuator/beans.py +141 -0
  13. spring_ready_python-0.1.0/spring_ready/actuator/caches.py +111 -0
  14. spring_ready_python-0.1.0/spring_ready/actuator/configprops.py +109 -0
  15. spring_ready_python-0.1.0/spring_ready/actuator/discovery.py +131 -0
  16. spring_ready_python-0.1.0/spring_ready/actuator/env.py +205 -0
  17. spring_ready_python-0.1.0/spring_ready/actuator/health.py +145 -0
  18. spring_ready_python-0.1.0/spring_ready/actuator/heapdump.py +80 -0
  19. spring_ready_python-0.1.0/spring_ready/actuator/httptrace.py +138 -0
  20. spring_ready_python-0.1.0/spring_ready/actuator/info.py +123 -0
  21. spring_ready_python-0.1.0/spring_ready/actuator/logfile.py +201 -0
  22. spring_ready_python-0.1.0/spring_ready/actuator/loggers.py +184 -0
  23. spring_ready_python-0.1.0/spring_ready/actuator/mappings.py +88 -0
  24. spring_ready_python-0.1.0/spring_ready/actuator/metrics.py +260 -0
  25. spring_ready_python-0.1.0/spring_ready/actuator/prometheus.py +354 -0
  26. spring_ready_python-0.1.0/spring_ready/actuator/refresh.py +86 -0
  27. spring_ready_python-0.1.0/spring_ready/actuator/scheduledtasks.py +95 -0
  28. spring_ready_python-0.1.0/spring_ready/actuator/threaddump.py +116 -0
  29. spring_ready_python-0.1.0/spring_ready/config/__init__.py +5 -0
  30. spring_ready_python-0.1.0/spring_ready/config/loader.py +215 -0
  31. spring_ready_python-0.1.0/spring_ready/core.py +479 -0
  32. spring_ready_python-0.1.0/spring_ready/eureka/__init__.py +15 -0
  33. spring_ready_python-0.1.0/spring_ready/eureka/client.py +291 -0
  34. spring_ready_python-0.1.0/spring_ready/eureka/discovery.py +198 -0
  35. spring_ready_python-0.1.0/spring_ready/eureka/instance.py +200 -0
  36. spring_ready_python-0.1.0/spring_ready/eureka/registry.py +191 -0
  37. spring_ready_python-0.1.0/spring_ready/exceptions.py +26 -0
  38. spring_ready_python-0.1.0/spring_ready/integrations/__init__.py +8 -0
  39. spring_ready_python-0.1.0/spring_ready/integrations/fastapi.py +521 -0
  40. spring_ready_python-0.1.0/spring_ready/retry.py +97 -0
  41. spring_ready_python-0.1.0/tests/test_basic.py +155 -0
@@ -0,0 +1,69 @@
1
+ # This workflow will upload a Python Package to PyPI when a release is created
2
+ # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python#publishing-to-package-registries
3
+
4
+ # This workflow uses actions that are not certified by GitHub.
5
+ # They are provided by a third-party and are governed by
6
+ # separate terms of service, privacy policy, and support
7
+ # documentation.
8
+
9
+ name: Upload Python Package
10
+
11
+ on:
12
+ release:
13
+ types: [published]
14
+
15
+ permissions:
16
+ contents: read
17
+
18
+ jobs:
19
+ release-build:
20
+ runs-on: ubuntu-latest
21
+
22
+ steps:
23
+ - uses: actions/checkout@v4
24
+
25
+ - uses: actions/setup-python@v5
26
+ with:
27
+ python-version: "3.x"
28
+
29
+ - name: Build release distributions
30
+ run: |
31
+ python -m pip install build
32
+ python -m build
33
+
34
+ - name: Upload distributions
35
+ uses: actions/upload-artifact@v4
36
+ with:
37
+ name: release-dists
38
+ path: dist/
39
+
40
+ pypi-publish:
41
+ runs-on: ubuntu-latest
42
+ needs:
43
+ - release-build
44
+ permissions:
45
+ # IMPORTANT: this permission is mandatory for trusted publishing
46
+ id-token: write
47
+
48
+ # Dedicated environments with protections for publishing are strongly recommended.
49
+ # For more information, see: https://docs.github.com/en/actions/deployment/targeting-different-environments/using-environments-for-deployment#deployment-protection-rules
50
+ environment:
51
+ name: pypi
52
+ # OPTIONAL: uncomment and update to include your PyPI project URL in the deployment status:
53
+ # url: https://pypi.org/p/YOURPROJECT
54
+ #
55
+ # ALTERNATIVE: if your GitHub Release name is the PyPI project version string
56
+ # ALTERNATIVE: exactly, uncomment the following line instead:
57
+ # url: https://pypi.org/project/YOURPROJECT/${{ github.event.release.name }}
58
+
59
+ steps:
60
+ - name: Retrieve release distributions
61
+ uses: actions/download-artifact@v4
62
+ with:
63
+ name: release-dists
64
+ path: dist/
65
+
66
+ - name: Publish release distributions to PyPI
67
+ uses: pypa/gh-action-pypi-publish@release/v1
68
+ with:
69
+ packages-dir: dist/
@@ -0,0 +1,70 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ pip-wheel-metadata/
24
+ share/python-wheels/
25
+ *.egg-info/
26
+ .installed.cfg
27
+ *.egg
28
+ MANIFEST
29
+
30
+ # PyInstaller
31
+ *.manifest
32
+ *.spec
33
+
34
+ # Unit test / coverage reports
35
+ htmlcov/
36
+ .tox/
37
+ .nox/
38
+ .coverage
39
+ .coverage.*
40
+ .cache
41
+ nosetests.xml
42
+ coverage.xml
43
+ *.cover
44
+ *.py,cover
45
+ .hypothesis/
46
+ .pytest_cache/
47
+
48
+ # Environments
49
+ .env
50
+ .venv
51
+ env/
52
+ venv/
53
+ ENV/
54
+ env.bak/
55
+ venv.bak/
56
+
57
+ # IDEs
58
+ .idea/
59
+ .vscode/
60
+ *.swp
61
+ *.swo
62
+ *~
63
+
64
+ # macOS
65
+ .DS_Store
66
+
67
+ # Project specific
68
+ *.log
69
+ /logs/
70
+ /.claude/
@@ -0,0 +1,29 @@
1
+ FROM python:3.11-slim
2
+
3
+ LABEL maintainer="your-email@example.com"
4
+ LABEL description="Spring-Ready Python Microservice"
5
+
6
+ WORKDIR /app
7
+
8
+ # Install dependencies
9
+ COPY requirements.txt .
10
+ RUN pip install --no-cache-dir -r requirements.txt
11
+
12
+ # Copy application code
13
+ COPY . .
14
+
15
+ # Environment variables (can be overridden)
16
+ ENV SPRING_APPLICATION_NAME=python-service
17
+ ENV APP_PORT=8080
18
+ ENV SPRING_PROFILES_ACTIVE=production
19
+ ENV EUREKA_SERVER_URL=http://eureka:8761/eureka/
20
+
21
+ # Expose port
22
+ EXPOSE 8080
23
+
24
+ # Health check
25
+ HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \
26
+ CMD python -c "import requests; requests.get('http://localhost:8080/actuator/health').raise_for_status()"
27
+
28
+ # Run the application
29
+ CMD ["uvicorn", "example:app", "--host", "0.0.0.0", "--port", "8080"]
@@ -0,0 +1,459 @@
1
+ Metadata-Version: 2.4
2
+ Name: spring-ready-python
3
+ Version: 0.1.0
4
+ Summary: Make Python FastAPI apps work with Spring Boot ecosystem (Eureka, Config Server, Actuator)
5
+ Project-URL: Homepage, https://github.com/tcivie/spring-ready-python
6
+ Project-URL: Issues, https://github.com/tcivie/spring-ready-python/issues
7
+ Author-email: Gleb Tcivie <gleb@tcivie.com>
8
+ License-Expression: MIT
9
+ Keywords: actuator,config-server,eureka,fastapi,microservices,prometheus,spring-boot
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Framework :: FastAPI
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.9
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
21
+ Requires-Python: >=3.9
22
+ Requires-Dist: fastapi>=0.100.0
23
+ Requires-Dist: requests>=2.31.0
24
+ Provides-Extra: all
25
+ Requires-Dist: prometheus-client>=0.19.0; extra == 'all'
26
+ Requires-Dist: spring-config-client-python>=0.1.0; extra == 'all'
27
+ Provides-Extra: config
28
+ Requires-Dist: spring-config-client-python>=0.1.0; extra == 'config'
29
+ Provides-Extra: dev
30
+ Requires-Dist: httpx>=0.24.0; extra == 'dev'
31
+ Requires-Dist: pytest-asyncio>=0.21.0; extra == 'dev'
32
+ Requires-Dist: pytest-cov>=4.1.0; extra == 'dev'
33
+ Requires-Dist: pytest>=7.4.0; extra == 'dev'
34
+ Requires-Dist: uvicorn>=0.23.0; extra == 'dev'
35
+ Provides-Extra: metrics
36
+ Requires-Dist: prometheus-client>=0.19.0; extra == 'metrics'
37
+ Description-Content-Type: text/markdown
38
+
39
+ # Spring-Ready Python
40
+
41
+ Make your Python FastAPI app work seamlessly with Spring Boot ecosystem: Eureka, Config Server, Spring Boot Admin, and Prometheus.
42
+
43
+ ## Why This Exists
44
+
45
+ You have a Spring Boot microservices architecture with Eureka, Config Server, Spring Boot Admin, and Prometheus monitoring. You want to add a Python service but keep everything working together. This library makes that dead simple.
46
+
47
+ ## Features
48
+
49
+ ✅ **Eureka Service Registration** - Automatic registration with heartbeat
50
+ ✅ **Config Server Integration** - Load config from Spring Cloud Config with Eureka discovery
51
+ ✅ **Actuator Endpoints** - `/actuator/health`, `/actuator/info`, `/actuator/prometheus`
52
+ ✅ **FastAPI Integration** - Drop-in support for FastAPI apps
53
+ ✅ **Fail-Fast Behavior** - Matches Spring Boot's startup failure handling
54
+ ✅ **Exponential Backoff Retry** - Retry logic for Eureka and Config Server
55
+ ✅ **Zero Magic** - Own implementation, no hidden dependencies
56
+
57
+ ## Installation
58
+
59
+ ```bash
60
+ pip install spring-ready-python
61
+ ```
62
+
63
+ Optional dependencies:
64
+ ```bash
65
+ # For Config Server support
66
+ pip install spring-config-client-python
67
+
68
+ # For Prometheus metrics
69
+ pip install prometheus-client
70
+ ```
71
+
72
+ ## Quick Start
73
+
74
+ ```python
75
+ from spring_ready import SpringReadyApp
76
+ from fastapi import FastAPI
77
+
78
+ # Create FastAPI app
79
+ app = FastAPI()
80
+
81
+ # Add Spring integration
82
+ spring_app = SpringReadyApp(app)
83
+ spring_app.start()
84
+
85
+ # Your routes
86
+ @app.get("/")
87
+ def read_root():
88
+ return {"message": "Hello from Spring-Ready Python!"}
89
+
90
+ # Run with uvicorn
91
+ if __name__ == "__main__":
92
+ import uvicorn
93
+ uvicorn.run(app, host="0.0.0.0", port=8080)
94
+ ```
95
+
96
+ That's it. Your app now:
97
+ - Registers with Eureka
98
+ - Loads config from Config Server (discovered via Eureka)
99
+ - Exposes `/actuator/health`, `/actuator/info`, `/actuator/prometheus`
100
+ - Shows up in Spring Boot Admin
101
+
102
+ ## Configuration
103
+
104
+ Set via environment variables (matching Spring Boot conventions):
105
+
106
+ ```bash
107
+ # Application
108
+ SPRING_APPLICATION_NAME=my-python-service
109
+ APP_PORT=8080
110
+ SPRING_PROFILES_ACTIVE=production
111
+
112
+ # Eureka
113
+ EUREKA_SERVER_URL=http://eureka:8761/eureka/
114
+ EUREKA_INSTANCE_IP=192.168.1.100 # Optional: custom IP for registration
115
+ EUREKA_INSTANCE_HOSTNAME=my-service.example.com # Optional: custom hostname
116
+
117
+ # Config Server (optional - will be discovered from Eureka)
118
+ CONFIG_SERVER_URI=http://config-server:8888
119
+ CONFIG_SERVER_USERNAME=admin
120
+ CONFIG_SERVER_PASSWORD=secret
121
+ ```
122
+
123
+ ### Environment Variables Reference
124
+
125
+ | Variable | Description | Default | Example |
126
+ |----------|-------------|---------|---------|
127
+ | `SPRING_APPLICATION_NAME` | Application name | `python-service` | `my-python-service` |
128
+ | `APP_PORT` | Application port | `8080` | `8080` |
129
+ | `SPRING_PROFILES_ACTIVE` | Active profile | `default` | `production` |
130
+ | `EUREKA_SERVER_URL` | Eureka server URL(s) | `http://localhost:8761/eureka/` | `http://eureka:8761/eureka/` |
131
+ | `EUREKA_INSTANCE_IP` | Custom IP for registration | Auto-detected | `192.168.1.100` |
132
+ | `EUREKA_INSTANCE_HOSTNAME` | Custom hostname | Auto-detected | `my-service.local` |
133
+ | `CONFIG_SERVER_URI` | Config Server URL | Discovered from Eureka | `http://config:8888` |
134
+ | `CONFIG_SERVER_SERVICE_ID` | Config Server service ID | `CONFIG-SERVER` | `CONFIG-SERVER` |
135
+ | `CONFIG_SERVER_USERNAME` | Config Server username | None | `admin` |
136
+ | `CONFIG_SERVER_PASSWORD` | Config Server password | None | `secret` |
137
+
138
+ ## Docker Example
139
+
140
+ ```dockerfile
141
+ FROM python:3.11-slim
142
+
143
+ WORKDIR /app
144
+ COPY requirements.txt .
145
+ RUN pip install -r requirements.txt
146
+
147
+ COPY . .
148
+
149
+ ENV SPRING_APPLICATION_NAME=my-service
150
+ ENV EUREKA_SERVER_URL=http://eureka:8761/eureka/
151
+ ENV SPRING_PROFILES_ACTIVE=production
152
+
153
+ CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8080"]
154
+ ```
155
+
156
+ ```yaml
157
+ # docker-compose.yml
158
+ services:
159
+ my-service:
160
+ build: .
161
+ environment:
162
+ - EUREKA_SERVER_URL=http://eureka:8761/eureka/
163
+ - SPRING_PROFILES_ACTIVE=production
164
+ ports:
165
+ - "8080:8080"
166
+ ```
167
+
168
+ ## Advanced Usage
169
+
170
+ ### Custom Health Checks
171
+
172
+ ```python
173
+ from spring_ready import SpringReadyApp
174
+
175
+ spring_app = SpringReadyApp(app)
176
+ spring_app.start()
177
+
178
+ # Add custom health check
179
+ def check_database():
180
+ # Your database check logic
181
+ return database.is_connected()
182
+
183
+ spring_app.health_endpoint.add_check("database", check_database)
184
+ ```
185
+
186
+ ### Service Discovery
187
+
188
+ ```python
189
+ # Find another service registered in Eureka
190
+ config_server_url = spring_app.service_discovery.get_service_url("CONFIG-SERVER")
191
+
192
+ # Get all instances of a service
193
+ instances = spring_app.service_discovery.get_instances("my-other-service")
194
+
195
+ for instance in instances:
196
+ print(f"Instance: {instance.base_url}")
197
+ ```
198
+
199
+ ### Manual Configuration
200
+
201
+ ```python
202
+ from spring_ready import SpringReadyApp
203
+
204
+ spring_app = SpringReadyApp(
205
+ app=app,
206
+ app_name="my-service",
207
+ app_port=8080,
208
+ eureka_servers=["http://eureka1:8761/eureka/", "http://eureka2:8761/eureka/"],
209
+ profile="production",
210
+ fail_fast=True,
211
+ prefer_ip_address=True
212
+ )
213
+ spring_app.start()
214
+ ```
215
+
216
+ ### Custom IP Address Registration
217
+
218
+ ```python
219
+ from spring_ready import SpringReadyApp
220
+
221
+ # Specify a custom IP address for Eureka registration
222
+ # Useful in Docker/Kubernetes when you need to advertise a specific IP
223
+ spring_app = SpringReadyApp(
224
+ app=app,
225
+ app_name="my-service",
226
+ instance_ip="192.168.1.100", # Custom IP address
227
+ instance_hostname="my-service.example.com" # Optional: custom hostname
228
+ )
229
+ spring_app.start()
230
+ ```
231
+
232
+ Or via environment variables:
233
+ ```bash
234
+ export EUREKA_INSTANCE_IP=192.168.1.100
235
+ export EUREKA_INSTANCE_HOSTNAME=my-service.example.com
236
+ ```
237
+
238
+ ## How It Works
239
+
240
+ ### Startup Sequence
241
+
242
+ 1. **Eureka Registration**: Registers with Eureka (with retry/backoff)
243
+ 2. **Config Discovery**: Discovers Config Server from Eureka
244
+ 3. **Config Loading**: Loads configuration into `os.environ`
245
+ 4. **Actuator Setup**: Exposes health, info, and metrics endpoints
246
+ 5. **Heartbeat**: Starts background thread for Eureka heartbeats (every 30s)
247
+
248
+ ### Shutdown Sequence
249
+
250
+ 1. Stops heartbeat thread
251
+ 2. Deregisters from Eureka
252
+ 3. Clean exit
253
+
254
+ ### Behavior Matching Spring Boot
255
+
256
+ | Feature | Spring Boot | spring-ready-python |
257
+ |---------|-------------|---------------------|
258
+ | Fail-fast on startup | ✓ | ✓ |
259
+ | Exponential backoff retry | ✓ | ✓ |
260
+ | Eureka heartbeat (30s) | ✓ | ✓ |
261
+ | Config Server discovery | ✓ | ✓ |
262
+ | Actuator endpoints | ✓ | ✓ |
263
+ | Graceful shutdown | ✓ | ✓ |
264
+
265
+ ## Actuator Endpoints
266
+
267
+ ### GET /actuator/health
268
+
269
+ Returns application health status:
270
+
271
+ ```json
272
+ {
273
+ "status": "UP",
274
+ "components": {
275
+ "diskSpace": {"status": "UP"},
276
+ "eureka": {"status": "UP"},
277
+ "ping": {"status": "UP"}
278
+ }
279
+ }
280
+ ```
281
+
282
+ ### GET /actuator/info
283
+
284
+ Returns application metadata:
285
+
286
+ ```json
287
+ {
288
+ "app": {
289
+ "name": "my-python-service",
290
+ "version": "1.0.0"
291
+ },
292
+ "python": {
293
+ "version": "3.11.5",
294
+ "runtime": {
295
+ "name": "CPython",
296
+ "version": "3.11.5"
297
+ }
298
+ }
299
+ }
300
+ ```
301
+
302
+ ### GET /actuator/prometheus
303
+
304
+ Returns Prometheus metrics in exposition format:
305
+
306
+ ```
307
+ # HELP python_info Python platform information
308
+ # TYPE python_info gauge
309
+ python_info{implementation="CPython",version="3.11.5"} 1.0
310
+ ...
311
+ ```
312
+
313
+ ## Troubleshooting
314
+
315
+ ### No Registration Attempts to Eureka Server
316
+
317
+ **Symptom**: You don't see any connection attempts to your Eureka server in logs or network monitoring.
318
+
319
+ **Cause**: The application is likely using the default Eureka URL (`http://localhost:8761/eureka/`) instead of your server.
320
+
321
+ **Solution**:
322
+
323
+ 1. **Set the environment variable** (Recommended):
324
+ ```bash
325
+ export EUREKA_SERVER_URL=http://10.10.0.1:8761/eureka/
326
+ python your_app.py
327
+ ```
328
+
329
+ 2. **Or pass it explicitly in code**:
330
+ ```python
331
+ spring_app = SpringReadyApp(
332
+ app,
333
+ eureka_servers=["http://10.10.0.1:8761/eureka/"]
334
+ )
335
+ ```
336
+
337
+ 3. **Verify your configuration**:
338
+ ```python
339
+ import os
340
+ print(f"EUREKA_SERVER_URL: {os.getenv('EUREKA_SERVER_URL')}")
341
+ ```
342
+
343
+ 4. **Check the startup logs**: Look for this message:
344
+ ```
345
+ INFO:spring_ready.core:Configured Eureka server(s): http://10.10.0.1:8761/eureka/
346
+ ```
347
+
348
+ If you see:
349
+ ```
350
+ WARNING:spring_ready.core:Using default Eureka server URL (http://localhost:8761/eureka/)
351
+ ```
352
+ Then you need to set `EUREKA_SERVER_URL`.
353
+
354
+ 5. **Enable debug logging** to see detailed registration attempts:
355
+ ```python
356
+ import logging
357
+ logging.basicConfig(level=logging.DEBUG)
358
+ ```
359
+
360
+ 6. **Verify network connectivity**:
361
+ ```bash
362
+ curl http://10.10.0.1:8761/eureka/apps
363
+ ```
364
+ Should return XML/JSON with registered applications.
365
+
366
+ **Common mistakes**:
367
+ - Forgetting to set `EUREKA_SERVER_URL` in Docker/Kubernetes deployments
368
+ - Setting the variable in your IDE but not in the runtime environment
369
+ - Using `localhost` when running in containers (use service names or IPs instead)
370
+
371
+ ### Eureka Registration Fails
372
+
373
+ Check Eureka server is reachable:
374
+ ```bash
375
+ curl http://eureka:8761/eureka/apps
376
+ ```
377
+
378
+ Set `fail_fast=False` to start anyway:
379
+ ```python
380
+ spring_app = SpringReadyApp(app, fail_fast=False)
381
+ ```
382
+
383
+ ### Config Server Not Found
384
+
385
+ Ensure Config Server is registered in Eureka:
386
+ ```bash
387
+ curl http://eureka:8761/eureka/apps/CONFIG-SERVER
388
+ ```
389
+
390
+ Or provide direct URL:
391
+ ```bash
392
+ export CONFIG_SERVER_URI=http://config-server:8888
393
+ ```
394
+
395
+ ### Port Already in Use
396
+
397
+ Change the port:
398
+ ```python
399
+ spring_app = SpringReadyApp(app, app_port=8081)
400
+ ```
401
+
402
+ Or via environment:
403
+ ```bash
404
+ export APP_PORT=8081
405
+ ```
406
+
407
+ ## Differences from Spring Boot
408
+
409
+ | Aspect | Spring Boot | Python |
410
+ |--------|-------------|---------|
411
+ | Metrics names | `jvm.memory.used` | `process_virtual_memory_bytes` |
412
+ | Runtime info | Java/JVM | Python/CPython |
413
+ | Config refresh | `/actuator/refresh` | Not supported (restart required) |
414
+ | Auto-configuration | Annotations | Explicit initialization |
415
+
416
+ ## Requirements
417
+
418
+ - Python 3.9+
419
+ - FastAPI
420
+ - requests
421
+
422
+ Optional:
423
+ - `spring-config-client-python` for Config Server support
424
+ - `prometheus-client` for metrics
425
+
426
+ ## License
427
+
428
+ MIT
429
+
430
+ ## Contributing
431
+
432
+ Contributions welcome! This library is intentionally simple and focused. See [CONTRIBUTING.md](CONTRIBUTING.md).
433
+
434
+ ## Comparison with Spring Boot
435
+
436
+ ```kotlin
437
+ // Spring Boot (Kotlin)
438
+ @SpringBootApplication
439
+ @EnableDiscoveryClient
440
+ class MyApplication
441
+
442
+ // Configuration in application.yml
443
+ ```
444
+
445
+ ```python
446
+ # Python equivalent
447
+ from spring_ready import SpringReadyApp
448
+ from fastapi import FastAPI
449
+
450
+ app = FastAPI()
451
+ spring_app = SpringReadyApp(app)
452
+ spring_app.start()
453
+
454
+ # Configuration from environment variables
455
+ ```
456
+
457
+ ---
458
+
459
+ **Note**: This library focuses on making Python apps work with existing Spring Boot infrastructure. It's not a replacement for Spring Boot itself.