diff --git a/.gitignore b/.gitignore index b7faf40..0c386d5 100644 --- a/.gitignore +++ b/.gitignore @@ -205,3 +205,6 @@ cython_debug/ marimo/_static/ marimo/_lsp/ __marimo__/ + +# macOS +.DS_Store diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..dc55d89 --- /dev/null +++ b/Dockerfile @@ -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"] diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..8ba3ebf --- /dev/null +++ b/Makefile @@ -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 diff --git a/README.md b/README.md index 6a57275..05588b2 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,179 @@ -# microservicio +# 👋 Streamlit Hello Microservice -A python microservicio. +![Python](https://img.shields.io/badge/python-3.11-blue.svg) +![Streamlit](https://img.shields.io/badge/streamlit-1.40.2-red.svg) +![License](https://img.shields.io/badge/license-MIT-green.svg) -## 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, ") +- 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` diff --git a/app.py b/app.py new file mode 100644 index 0000000..b571d10 --- /dev/null +++ b/app.py @@ -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.") diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..7473a9b --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +streamlit==1.40.2 +pytest==8.3.4 diff --git a/service/__init__.py b/service/__init__.py new file mode 100644 index 0000000..9c2e8f3 --- /dev/null +++ b/service/__init__.py @@ -0,0 +1,4 @@ +"""Greeting service module.""" +from .greeting import greet + +__all__ = ['greet'] diff --git a/service/greeting.py b/service/greeting.py new file mode 100644 index 0000000..fcb4041 --- /dev/null +++ b/service/greeting.py @@ -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}" diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..38bb211 --- /dev/null +++ b/tests/__init__.py @@ -0,0 +1 @@ +"""Test package.""" diff --git a/tests/test_greeting.py b/tests/test_greeting.py new file mode 100644 index 0000000..5a993e2 --- /dev/null +++ b/tests/test_greeting.py @@ -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 caplog.records[0].levelname == "INFO" + assert "Greeting generated for: Test" in caplog.text