-
Notifications
You must be signed in to change notification settings - Fork 0
Add Streamlit Hello World microservice with modular structure #2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -205,3 +205,6 @@ cython_debug/ | |
| marimo/_static/ | ||
| marimo/_lsp/ | ||
| __marimo__/ | ||
|
|
||
| # macOS | ||
| .DS_Store | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| FROM python:3.11-slim | ||
|
|
||
| WORKDIR /app | ||
|
|
||
| # Copy requirements first for better caching | ||
| COPY requirements.txt . | ||
|
|
||
| # Install dependencies | ||
| RUN pip install --no-cache-dir -r requirements.txt | ||
|
|
||
| # Copy application code | ||
| COPY . . | ||
|
|
||
| # Expose Streamlit default port | ||
| EXPOSE 8501 | ||
|
|
||
| # Run Streamlit | ||
| CMD ["streamlit", "run", "app.py", "--server.address=0.0.0.0"] |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| .PHONY: install run test docker-build docker-run help | ||
|
|
||
| help: | ||
| @echo "Available targets:" | ||
| @echo " install - Install dependencies from requirements.txt" | ||
| @echo " run - Run the Streamlit application locally" | ||
| @echo " test - Run tests with pytest" | ||
| @echo " docker-build - Build Docker image" | ||
| @echo " docker-run - Run application in Docker container" | ||
|
|
||
| install: | ||
| pip install -r requirements.txt | ||
|
|
||
| run: | ||
| streamlit run app.py | ||
|
|
||
| test: | ||
| pytest -q | ||
|
|
||
| docker-build: | ||
| docker build -t streamlit-hello-microservice . | ||
|
|
||
| docker-run: | ||
| docker run -p 8501:8501 streamlit-hello-microservice |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,18 +1,179 @@ | ||
| # microservicio | ||
| # 👋 Streamlit Hello Microservice | ||
|
|
||
| A python microservicio. | ||
|  | ||
|  | ||
|  | ||
|
|
||
| ## Getting Started | ||
| Microservicio simple con Streamlit que muestra "Hello World" y permite saludar de forma personalizada. | ||
|
|
||
| TODO: Add instructions for setting up and running this microservicio. | ||
| ## ✨ Características | ||
|
|
||
| ## Contributing | ||
| - Muestra "Hello World" en la interfaz | ||
| - Permite ingresar un nombre para recibir un saludo personalizado ("Hola, <nombre>") | ||
| - Logging básico de saludos generados | ||
| - Estructura modular lista para extender como microservicio | ||
| - Totalmente dockerizado | ||
| - Tests con pytest | ||
|
|
||
| 1. Fork the repository | ||
| 2. Create a feature branch | ||
| 3. Make your changes | ||
| 4. Submit a pull request | ||
| ## 🚀 Inicio Rápido | ||
|
|
||
| ## License | ||
| ### Opción 1: Ejecución Local | ||
|
|
||
| MIT License | ||
| ```bash | ||
| # Clonar el repositorio | ||
| git clone https://github.com/svg153-org/streamlit-hello-microservice.git | ||
| cd streamlit-hello-microservice | ||
|
|
||
| # Instalar dependencias | ||
| make install | ||
|
|
||
| # Ejecutar la aplicación | ||
| make run | ||
| ``` | ||
|
|
||
| La aplicación estará disponible en http://localhost:8501 | ||
|
|
||
| ### Opción 2: Docker | ||
|
|
||
| ```bash | ||
| # Construir la imagen | ||
| make docker-build | ||
|
|
||
| # Ejecutar el contenedor | ||
| make docker-run | ||
| ``` | ||
|
|
||
| La aplicación estará disponible en http://localhost:8501 | ||
|
|
||
| ## 📦 Instalación | ||
|
|
||
| ### Requisitos | ||
|
|
||
| - Python 3.11+ | ||
| - pip | ||
|
|
||
| ### Dependencias | ||
|
|
||
| ```bash | ||
| pip install -r requirements.txt | ||
| ``` | ||
|
|
||
| Las dependencias principales son: | ||
| - `streamlit==1.40.2` - Framework web para la interfaz | ||
| - `pytest==8.3.4` - Framework de testing | ||
|
|
||
| ## 🔧 Uso | ||
|
|
||
| ### Ejecución Manual | ||
|
|
||
| ```bash | ||
| streamlit run app.py | ||
| ``` | ||
|
|
||
| ### Uso Programático | ||
|
|
||
| ```python | ||
| from service import greet | ||
|
|
||
| # Generar un saludo | ||
| mensaje = greet("Juan") | ||
| print(mensaje) # Output: Hola, Juan | ||
| ``` | ||
|
|
||
| ## 🧪 Tests | ||
|
|
||
| Ejecutar los tests: | ||
|
|
||
| ```bash | ||
| make test | ||
| ``` | ||
|
|
||
| O directamente con pytest: | ||
|
|
||
| ```bash | ||
| pytest -q | ||
| ``` | ||
|
|
||
| ## 📁 Estructura del Proyecto | ||
|
|
||
| ``` | ||
| streamlit-hello-microservice/ | ||
| ├── app.py # Aplicación Streamlit principal | ||
| ├── service/ | ||
| │ ├── __init__.py | ||
| │ └── greeting.py # Lógica del servicio de saludos | ||
| ├── tests/ | ||
| │ ├── __init__.py | ||
| │ └── test_greeting.py # Tests del servicio | ||
| ├── requirements.txt # Dependencias Python | ||
| ├── Dockerfile # Configuración Docker | ||
| ├── Makefile # Comandos útiles | ||
| ├── .gitignore # Archivos ignorados por git | ||
| ├── LICENSE # Licencia MIT | ||
| └── README.md # Este archivo | ||
| ``` | ||
|
|
||
| ## 🐳 Docker | ||
|
|
||
| ### Construcción | ||
|
|
||
| ```bash | ||
| docker build -t streamlit-hello-microservice . | ||
| ``` | ||
|
|
||
| ### Ejecución | ||
|
|
||
| ```bash | ||
| docker run -p 8501:8501 streamlit-hello-microservice | ||
| ``` | ||
|
|
||
| El Dockerfile usa `python:3.11-slim` como base e instala todas las dependencias necesarias. | ||
|
|
||
| ## 📝 Makefile Targets | ||
|
|
||
| | Target | Descripción | | ||
| |--------|-------------| | ||
| | `make install` | Instala las dependencias desde requirements.txt | | ||
| | `make run` | Ejecuta la aplicación Streamlit localmente | | ||
| | `make test` | Ejecuta los tests con pytest | | ||
| | `make docker-build` | Construye la imagen Docker | | ||
| | `make docker-run` | Ejecuta el contenedor Docker | | ||
| | `make help` | Muestra todos los targets disponibles | | ||
|
|
||
| ## 🔍 Logging | ||
|
|
||
| La aplicación incluye logging básico que registra cada saludo generado: | ||
|
|
||
| ``` | ||
| 2025-11-15 12:00:00 - service.greeting - INFO - Greeting generated for: Juan | ||
| ``` | ||
|
|
||
| ## 🚧 Próximos Pasos | ||
|
|
||
| Este proyecto está estructurado para facilitar su extensión como microservicio completo: | ||
|
|
||
| - [ ] Agregar API REST con FastAPI | ||
| - [ ] Implementar más funcionalidades de saludo | ||
| - [ ] Agregar base de datos para persistencia | ||
| - [ ] Implementar CI/CD | ||
| - [ ] Agregar más tests de integración | ||
|
|
||
| ## 🤝 Contribución | ||
|
|
||
| 1. Fork el repositorio | ||
| 2. Crea una rama para tu feature (`git checkout -b feature/nueva-funcionalidad`) | ||
| 3. Commit tus cambios (`git commit -m 'Agrega nueva funcionalidad'`) | ||
| 4. Push a la rama (`git push origin feature/nueva-funcionalidad`) | ||
| 5. Abre un Pull Request | ||
|
|
||
| ## 📄 Licencia | ||
|
|
||
| Este proyecto está bajo la Licencia MIT. Ver el archivo [LICENSE](LICENSE) para más detalles. | ||
|
|
||
| ## 👥 Autores | ||
|
|
||
| - svg153-org - [GitHub](https://github.com/svg153-org) | ||
|
|
||
| --- | ||
|
|
||
| ⚡ **Demo en menos de 1 minuto**: `git clone && make install && make run` |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| """Streamlit Hello World Microservice.""" | ||
| import streamlit as st | ||
| from service import greet | ||
|
|
||
| # Set page config | ||
| st.set_page_config( | ||
| page_title="Hello Microservice", | ||
| page_icon="👋", | ||
| ) | ||
|
|
||
| # Title and description | ||
| st.title("👋 Hello World Microservice") | ||
| st.write("Bienvenido a este microservicio de saludo simple.") | ||
|
|
||
| # Display Hello World | ||
| st.header("Hello World") | ||
| st.success("¡Hello World!") | ||
|
|
||
| # Name input section | ||
| st.header("Saludo Personalizado") | ||
| name = st.text_input("Ingresa tu nombre:", placeholder="Tu nombre aquí") | ||
|
|
||
| if name: | ||
| greeting = greet(name) | ||
| st.success(greeting) | ||
| else: | ||
| st.info("👆 Ingresa tu nombre arriba para recibir un saludo personalizado.") |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| streamlit==1.40.2 | ||
| pytest==8.3.4 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| """Greeting service module.""" | ||
| from .greeting import greet | ||
|
|
||
| __all__ = ['greet'] |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| """Greeting service with logging.""" | ||
| import logging | ||
|
|
||
| # Configure logging | ||
| logging.basicConfig( | ||
| level=logging.INFO, | ||
| format='%(asctime)s - %(name)s - %(levelname)s - %(message)s' | ||
| ) | ||
| logger = logging.getLogger(__name__) | ||
|
|
||
|
|
||
| def greet(name: str) -> str: | ||
| """ | ||
| Generate a greeting message for the given name. | ||
|
|
||
| Args: | ||
| name: The name to greet | ||
|
|
||
| Returns: | ||
| A greeting message string | ||
| """ | ||
| logger.info(f"Greeting generated for: {name}") | ||
| return f"Hola, {name}" | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| """Test package.""" |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,32 @@ | ||||||
| """Tests for the greeting service.""" | ||||||
| import logging | ||||||
| from service.greeting import greet | ||||||
|
|
||||||
|
|
||||||
| def test_greet_returns_correct_format(): | ||||||
| """Test that greet returns the correct format.""" | ||||||
| result = greet("Juan") | ||||||
| assert result == "Hola, Juan" | ||||||
|
|
||||||
|
|
||||||
| def test_greet_with_different_names(): | ||||||
| """Test greet with various names.""" | ||||||
| assert greet("María") == "Hola, María" | ||||||
| assert greet("Pedro") == "Hola, Pedro" | ||||||
| assert greet("Ana") == "Hola, Ana" | ||||||
|
|
||||||
|
|
||||||
| def test_greet_with_empty_string(): | ||||||
| """Test greet with empty string.""" | ||||||
| result = greet("") | ||||||
| assert result == "Hola, " | ||||||
|
|
||||||
|
|
||||||
| def test_greet_logs_info(caplog): | ||||||
| """Test that greet logs an INFO message.""" | ||||||
| with caplog.at_level(logging.INFO): | ||||||
| greet("Test") | ||||||
|
|
||||||
| assert len(caplog.records) == 1 | ||||||
|
||||||
| assert len(caplog.records) == 1 | |
| assert len(caplog.records) >= 1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Calling
logging.basicConfig()at module level can cause conflicts when the module is imported into applications that configure their own logging (like Streamlit). This may lead to duplicate log messages or configuration conflicts. Consider removing the basicConfig call and letting the application configure logging, or check if logging is already configured before calling basicConfig usingif not logging.getLogger().hasHandlers().