Edwin Salguero commited on
Commit
10d71ba
·
1 Parent(s): 832348e

Enterprise: Clean up directory structure and add proper CI/CD, monitoring, and deployment configurations

Browse files
.github/workflows/ci-cd.yml ADDED
@@ -0,0 +1,109 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ name: CI/CD Pipeline
2
+
3
+ on:
4
+ push:
5
+ branches: [ main, develop ]
6
+ pull_request:
7
+ branches: [ main ]
8
+
9
+ jobs:
10
+ test:
11
+ runs-on: ubuntu-latest
12
+ strategy:
13
+ matrix:
14
+ python-version: [3.9, 3.10, 3.11]
15
+
16
+ steps:
17
+ - uses: actions/checkout@v4
18
+
19
+ - name: Set up Python ${{ matrix.python-version }}
20
+ uses: actions/setup-python@v4
21
+ with:
22
+ python-version: ${{ matrix.python-version }}
23
+
24
+ - name: Install dependencies
25
+ run: |
26
+ python -m pip install --upgrade pip
27
+ pip install -r requirements.txt
28
+ pip install pre-commit
29
+
30
+ - name: Run pre-commit hooks
31
+ run: pre-commit run --all-files
32
+
33
+ - name: Run tests
34
+ run: |
35
+ pytest tests/ -v --cov=src --cov-report=xml
36
+
37
+ - name: Upload coverage to Codecov
38
+ uses: codecov/codecov-action@v3
39
+ with:
40
+ file: ./coverage.xml
41
+
42
+ lint:
43
+ runs-on: ubuntu-latest
44
+ steps:
45
+ - uses: actions/checkout@v4
46
+
47
+ - name: Set up Python
48
+ uses: actions/setup-python@v4
49
+ with:
50
+ python-version: 3.9
51
+
52
+ - name: Install dependencies
53
+ run: |
54
+ pip install flake8 black isort mypy
55
+
56
+ - name: Run linting
57
+ run: |
58
+ flake8 src/ tests/
59
+ black --check src/ tests/
60
+ isort --check-only src/ tests/
61
+ mypy src/
62
+
63
+ security:
64
+ runs-on: ubuntu-latest
65
+ steps:
66
+ - uses: actions/checkout@v4
67
+
68
+ - name: Run security scan
69
+ uses: snyk/actions/python@master
70
+ env:
71
+ SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
72
+ with:
73
+ args: --severity-threshold=high
74
+
75
+ build:
76
+ needs: [test, lint, security]
77
+ runs-on: ubuntu-latest
78
+ if: github.ref == 'refs/heads/main'
79
+
80
+ steps:
81
+ - uses: actions/checkout@v4
82
+
83
+ - name: Set up Docker Buildx
84
+ uses: docker/setup-buildx-action@v3
85
+
86
+ - name: Build and push Docker image
87
+ uses: docker/build-push-action@v5
88
+ with:
89
+ context: .
90
+ push: true
91
+ tags: |
92
+ ghcr.io/${{ github.repository }}:latest
93
+ ghcr.io/${{ github.repository }}:${{ github.sha }}
94
+ cache-from: type=gha
95
+ cache-to: type=gha,mode=max
96
+
97
+ deploy:
98
+ needs: build
99
+ runs-on: ubuntu-latest
100
+ if: github.ref == 'refs/heads/main'
101
+ environment: production
102
+
103
+ steps:
104
+ - uses: actions/checkout@v4
105
+
106
+ - name: Deploy to Kubernetes
107
+ run: |
108
+ echo "Deploying to production..."
109
+ # Add your deployment commands here
Makefile CHANGED
@@ -7,11 +7,12 @@ help: ## Show this help message
7
  @awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z_-]+:.*?## / {printf " %-15s %s\n", $$1, $$2}' $(MAKEFILE_LIST)
8
 
9
  install: ## Install dependencies
10
- pip install -r requirements.txt
 
11
  pre-commit install
12
 
13
  test: ## Run tests
14
- pytest tests/ -v --cov=src --cov-report=html
15
 
16
  lint: ## Run linting
17
  flake8 src/ tests/
@@ -26,6 +27,9 @@ clean: ## Clean build artifacts
26
  find . -type d -name "__pycache__" -delete
27
  rm -rf .pytest_cache/
28
  rm -rf htmlcov/
 
 
 
29
 
30
  build: ## Build Docker image
31
  docker build -t fred-ml .
@@ -33,20 +37,33 @@ build: ## Build Docker image
33
  run: ## Run application locally
34
  uvicorn src.main:app --reload --host 0.0.0.0 --port 8000
35
 
36
- run-docker: ## Run with Docker Compose
37
- docker-compose up --build
 
 
 
38
 
39
  deploy: ## Deploy to Kubernetes
40
- kubectl apply -f kubernetes/
41
- helm install fred-ml helm/
 
 
42
 
43
  logs: ## View application logs
44
- docker-compose logs -f fred-ml
45
 
46
  shell: ## Open shell in container
47
- docker-compose exec fred-ml bash
48
 
49
  migrate: ## Run database migrations
50
  alembic upgrade head
51
 
52
- setup-dev: install format lint test ## Setup development environment
 
 
 
 
 
 
 
 
 
7
  @awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z_-]+:.*?## / {printf " %-15s %s\n", $$1, $$2}' $(MAKEFILE_LIST)
8
 
9
  install: ## Install dependencies
10
+ pip install -e .
11
+ pip install -e ".[dev]"
12
  pre-commit install
13
 
14
  test: ## Run tests
15
+ pytest tests/ -v --cov=src --cov-report=html --cov-report=xml
16
 
17
  lint: ## Run linting
18
  flake8 src/ tests/
 
27
  find . -type d -name "__pycache__" -delete
28
  rm -rf .pytest_cache/
29
  rm -rf htmlcov/
30
+ rm -rf build/
31
+ rm -rf dist/
32
+ rm -rf *.egg-info/
33
 
34
  build: ## Build Docker image
35
  docker build -t fred-ml .
 
37
  run: ## Run application locally
38
  uvicorn src.main:app --reload --host 0.0.0.0 --port 8000
39
 
40
+ run-docker: ## Run with Docker Compose (development)
41
+ docker-compose -f deploy/docker/docker-compose.dev.yml up --build
42
+
43
+ run-prod: ## Run with Docker Compose (production)
44
+ docker-compose -f deploy/docker/docker-compose.prod.yml up --build
45
 
46
  deploy: ## Deploy to Kubernetes
47
+ kubectl apply -f deploy/kubernetes/
48
+
49
+ deploy-helm: ## Deploy with Helm
50
+ helm install fred-ml deploy/helm/
51
 
52
  logs: ## View application logs
53
+ docker-compose -f deploy/docker/docker-compose.dev.yml logs -f fred-ml
54
 
55
  shell: ## Open shell in container
56
+ docker-compose -f deploy/docker/docker-compose.dev.yml exec fred-ml bash
57
 
58
  migrate: ## Run database migrations
59
  alembic upgrade head
60
 
61
+ setup-dev: install format lint test ## Setup development environment
62
+
63
+ ci: test lint format ## Run CI checks locally
64
+
65
+ package: clean build ## Build package for distribution
66
+ python -m build
67
+
68
+ publish: package ## Publish to PyPI
69
+ twine upload dist/*
alerts/alertmanager.yml DELETED
@@ -1,21 +0,0 @@
1
- global:
2
- resolve_timeout: 5m
3
-
4
- route:
5
- group_by: ['alertname']
6
- group_wait: 10s
7
- group_interval: 10s
8
- repeat_interval: 1h
9
- receiver: 'web.hook'
10
-
11
- receivers:
12
- - name: 'web.hook'
13
- webhook_configs:
14
- - url: 'http://127.0.0.1:5001/'
15
-
16
- inhibit_rules:
17
- - source_match:
18
- severity: 'critical'
19
- target_match:
20
- severity: 'warning'
21
- equal: ['alertname', 'dev', 'instance']
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
docker-compose.yml → deploy/docker/docker-compose.dev.yml RENAMED
File without changes
deploy/docker/docker-compose.prod.yml ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ version: '3.8'
2
+
3
+ services:
4
+ fred-ml:
5
+ image: ghcr.io/eaname/fredml:latest
6
+ ports:
7
+ - "8000:8000"
8
+ environment:
9
+ - FRED_API_KEY=${FRED_API_KEY}
10
+ - ENVIRONMENT=production
11
+ - LOG_LEVEL=INFO
12
+ volumes:
13
+ - ./data:/app/data
14
+ - ./logs:/app/logs
15
+ depends_on:
16
+ - redis
17
+ - postgres
18
+ networks:
19
+ - fred-ml-network
20
+ restart: unless-stopped
21
+
22
+ redis:
23
+ image: redis:7-alpine
24
+ ports:
25
+ - "6379:6379"
26
+ volumes:
27
+ - redis_data:/data
28
+ networks:
29
+ - fred-ml-network
30
+ restart: unless-stopped
31
+
32
+ postgres:
33
+ image: postgres:15-alpine
34
+ environment:
35
+ POSTGRES_DB: fred_ml
36
+ POSTGRES_USER: fred_user
37
+ POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
38
+ ports:
39
+ - "5432:5432"
40
+ volumes:
41
+ - postgres_data:/var/lib/postgresql/data
42
+ networks:
43
+ - fred-ml-network
44
+ restart: unless-stopped
45
+
46
+ nginx:
47
+ image: nginx:alpine
48
+ ports:
49
+ - "80:80"
50
+ - "443:443"
51
+ volumes:
52
+ - ./nginx.conf:/etc/nginx/nginx.conf
53
+ depends_on:
54
+ - fred-ml
55
+ networks:
56
+ - fred-ml-network
57
+ restart: unless-stopped
58
+
59
+ volumes:
60
+ redis_data:
61
+ postgres_data:
62
+
63
+ networks:
64
+ fred-ml-network:
65
+ driver: bridge
{kubernetes → deploy/kubernetes}/deployment.yaml RENAMED
@@ -4,6 +4,7 @@ metadata:
4
  name: fred-ml
5
  labels:
6
  app: fred-ml
 
7
  spec:
8
  replicas: 3
9
  selector:
@@ -13,12 +14,14 @@ spec:
13
  metadata:
14
  labels:
15
  app: fred-ml
 
16
  spec:
17
  containers:
18
  - name: fred-ml
19
- image: fred-ml:latest
20
  ports:
21
  - containerPort: 8000
 
22
  env:
23
  - name: FRED_API_KEY
24
  valueFrom:
@@ -27,6 +30,8 @@ spec:
27
  key: fred-api-key
28
  - name: ENVIRONMENT
29
  value: "production"
 
 
30
  resources:
31
  requests:
32
  memory: "256Mi"
@@ -40,17 +45,35 @@ spec:
40
  port: 8000
41
  initialDelaySeconds: 30
42
  periodSeconds: 10
 
 
43
  readinessProbe:
44
  httpGet:
45
  path: /ready
46
  port: 8000
47
  initialDelaySeconds: 5
48
  periodSeconds: 5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
49
  ---
50
  apiVersion: v1
51
  kind: Service
52
  metadata:
53
  name: fred-ml-service
 
 
54
  spec:
55
  selector:
56
  app: fred-ml
@@ -58,4 +81,27 @@ spec:
58
  - protocol: TCP
59
  port: 80
60
  targetPort: 8000
61
- type: LoadBalancer
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
  name: fred-ml
5
  labels:
6
  app: fred-ml
7
+ version: v1.0.0
8
  spec:
9
  replicas: 3
10
  selector:
 
14
  metadata:
15
  labels:
16
  app: fred-ml
17
+ version: v1.0.0
18
  spec:
19
  containers:
20
  - name: fred-ml
21
+ image: ghcr.io/eaname/fredml:latest
22
  ports:
23
  - containerPort: 8000
24
+ name: http
25
  env:
26
  - name: FRED_API_KEY
27
  valueFrom:
 
30
  key: fred-api-key
31
  - name: ENVIRONMENT
32
  value: "production"
33
+ - name: LOG_LEVEL
34
+ value: "INFO"
35
  resources:
36
  requests:
37
  memory: "256Mi"
 
45
  port: 8000
46
  initialDelaySeconds: 30
47
  periodSeconds: 10
48
+ timeoutSeconds: 5
49
+ failureThreshold: 3
50
  readinessProbe:
51
  httpGet:
52
  path: /ready
53
  port: 8000
54
  initialDelaySeconds: 5
55
  periodSeconds: 5
56
+ timeoutSeconds: 3
57
+ failureThreshold: 3
58
+ volumeMounts:
59
+ - name: data-volume
60
+ mountPath: /app/data
61
+ - name: logs-volume
62
+ mountPath: /app/logs
63
+ volumes:
64
+ - name: data-volume
65
+ persistentVolumeClaim:
66
+ claimName: fred-ml-data-pvc
67
+ - name: logs-volume
68
+ persistentVolumeClaim:
69
+ claimName: fred-ml-logs-pvc
70
  ---
71
  apiVersion: v1
72
  kind: Service
73
  metadata:
74
  name: fred-ml-service
75
+ labels:
76
+ app: fred-ml
77
  spec:
78
  selector:
79
  app: fred-ml
 
81
  - protocol: TCP
82
  port: 80
83
  targetPort: 8000
84
+ name: http
85
+ type: LoadBalancer
86
+ ---
87
+ apiVersion: v1
88
+ kind: PersistentVolumeClaim
89
+ metadata:
90
+ name: fred-ml-data-pvc
91
+ spec:
92
+ accessModes:
93
+ - ReadWriteOnce
94
+ resources:
95
+ requests:
96
+ storage: 10Gi
97
+ ---
98
+ apiVersion: v1
99
+ kind: PersistentVolumeClaim
100
+ metadata:
101
+ name: fred-ml-logs-pvc
102
+ spec:
103
+ accessModes:
104
+ - ReadWriteOnce
105
+ resources:
106
+ requests:
107
+ storage: 5Gi
helm/Chart.yaml DELETED
@@ -1,17 +0,0 @@
1
- apiVersion: v2
2
- name: fred-ml
3
- description: A Helm chart for FRED ML Economic Data Analysis
4
- type: application
5
- version: 1.0.0
6
- appVersion: "1.0.0"
7
- keywords:
8
- - economics
9
- - data-analysis
10
- - machine-learning
11
- - fred
12
- home: https://github.com/EAName/FREDML
13
- sources:
14
- - https://github.com/EAName/FREDML
15
- maintainers:
16
- - name: Edwin Salguero
17
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
infrastructure/alerts/alerts.yml ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ groups:
2
+ - name: fred-ml
3
+ rules:
4
+ - alert: FredMLHighErrorRate
5
+ expr: rate(http_requests_total{status=~"5.."}[5m]) > 0.1
6
+ for: 2m
7
+ labels:
8
+ severity: critical
9
+ annotations:
10
+ summary: "High error rate detected"
11
+ description: "Error rate is {{ $value }} errors per second"
12
+
13
+ - alert: FredMLHighResponseTime
14
+ expr: histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m])) > 2
15
+ for: 2m
16
+ labels:
17
+ severity: warning
18
+ annotations:
19
+ summary: "High response time detected"
20
+ description: "95th percentile response time is {{ $value }} seconds"
21
+
22
+ - alert: FredMLDown
23
+ expr: up{job="fred-ml"} == 0
24
+ for: 1m
25
+ labels:
26
+ severity: critical
27
+ annotations:
28
+ summary: "FredML service is down"
29
+ description: "FredML service has been down for more than 1 minute"
30
+
31
+ - alert: FredMLHighMemoryUsage
32
+ expr: (container_memory_usage_bytes{container="fred-ml"} / container_spec_memory_limit_bytes{container="fred-ml"}) > 0.8
33
+ for: 5m
34
+ labels:
35
+ severity: warning
36
+ annotations:
37
+ summary: "High memory usage detected"
38
+ description: "Memory usage is {{ $value | humanizePercentage }}"
39
+
40
+ - alert: FredMLHighCPUUsage
41
+ expr: rate(container_cpu_usage_seconds_total{container="fred-ml"}[5m]) > 0.8
42
+ for: 5m
43
+ labels:
44
+ severity: warning
45
+ annotations:
46
+ summary: "High CPU usage detected"
47
+ description: "CPU usage is {{ $value | humanizePercentage }}"
48
+
49
+ - alert: FredMLAPIRateLimit
50
+ expr: increase(fred_api_rate_limit_exceeded_total[5m]) > 0
51
+ for: 1m
52
+ labels:
53
+ severity: warning
54
+ annotations:
55
+ summary: "FRED API rate limit exceeded"
56
+ description: "API rate limit has been exceeded in the last 5 minutes"
infrastructure/monitoring/prometheus.yml ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ global:
2
+ scrape_interval: 15s
3
+ evaluation_interval: 15s
4
+ external_labels:
5
+ cluster: fred-ml-cluster
6
+ job: fred-ml
7
+
8
+ rule_files:
9
+ - "alerts.yml"
10
+
11
+ scrape_configs:
12
+ - job_name: 'fred-ml'
13
+ static_configs:
14
+ - targets: ['fred-ml-service:8000']
15
+ metrics_path: '/metrics'
16
+ scrape_interval: 5s
17
+ scrape_timeout: 3s
18
+ honor_labels: true
19
+
20
+ - job_name: 'kubernetes-pods'
21
+ kubernetes_sd_configs:
22
+ - role: pod
23
+ relabel_configs:
24
+ - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]
25
+ action: keep
26
+ regex: true
27
+ - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path]
28
+ action: replace
29
+ target_label: __metrics_path__
30
+ regex: (.+)
31
+ - source_labels: [__address__, __meta_kubernetes_pod_annotation_prometheus_io_port]
32
+ action: replace
33
+ regex: ([^:]+)(?::\d+)?;(\d+)
34
+ replacement: $1:$2
35
+ target_label: __address__
36
+
37
+ - job_name: 'kubernetes-service-endpoints'
38
+ kubernetes_sd_configs:
39
+ - role: endpoints
40
+ relabel_configs:
41
+ - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape]
42
+ action: keep
43
+ regex: true
44
+ - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scheme]
45
+ action: replace
46
+ target_label: __scheme__
47
+ regex: (https?)
48
+ - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_path]
49
+ action: replace
50
+ target_label: __metrics_path__
51
+ regex: (.+)
52
+ - source_labels: [__address__, __meta_kubernetes_service_annotation_prometheus_io_port]
53
+ action: replace
54
+ regex: ([^:]+)(?::\d+)?;(\d+)
55
+ replacement: $1:$2
56
+ target_label: __address__
57
+
58
+ alerting:
59
+ alertmanagers:
60
+ - static_configs:
61
+ - targets:
62
+ - alertmanager:9093
monitoring/prometheus.yml DELETED
@@ -1,18 +0,0 @@
1
- global:
2
- scrape_interval: 15s
3
- evaluation_interval: 15s
4
-
5
- rule_files:
6
- # - "first_rules.yml"
7
- # - "second_rules.yml"
8
-
9
- scrape_configs:
10
- - job_name: 'fred-ml'
11
- static_configs:
12
- - targets: ['localhost:8000']
13
- metrics_path: '/metrics'
14
- scrape_interval: 5s
15
-
16
- - job_name: 'prometheus'
17
- static_configs:
18
- - targets: ['localhost:9090']
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
pyproject.toml ADDED
@@ -0,0 +1,127 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [build-system]
2
+ requires = ["setuptools>=61.0", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "fred-ml"
7
+ version = "1.0.0"
8
+ description = "Enterprise-grade economic data analysis platform using FRED API"
9
+ readme = "README.md"
10
+ license = {text = "MIT"}
11
+ authors = [
12
+ {name = "Edwin Salguero", email = "[email protected]"}
13
+ ]
14
+ maintainers = [
15
+ {name = "Edwin Salguero", email = "[email protected]"}
16
+ ]
17
+ keywords = ["economics", "data-analysis", "machine-learning", "fred", "api"]
18
+ classifiers = [
19
+ "Development Status :: 5 - Production/Stable",
20
+ "Intended Audience :: Financial and Insurance Industry",
21
+ "License :: OSI Approved :: MIT License",
22
+ "Operating System :: OS Independent",
23
+ "Programming Language :: Python :: 3",
24
+ "Programming Language :: Python :: 3.9",
25
+ "Programming Language :: Python :: 3.10",
26
+ "Programming Language :: Python :: 3.11",
27
+ "Topic :: Scientific/Engineering :: Information Analysis",
28
+ "Topic :: Software Development :: Libraries :: Python Modules",
29
+ ]
30
+ requires-python = ">=3.9"
31
+ dependencies = [
32
+ "fredapi==0.4.2",
33
+ "pandas==2.1.4",
34
+ "numpy==1.24.3",
35
+ "matplotlib==3.7.2",
36
+ "seaborn==0.12.2",
37
+ "jupyter==1.0.0",
38
+ "python-dotenv==1.0.0",
39
+ "requests==2.31.0",
40
+ "PyYAML==6.0.2",
41
+ "APScheduler==3.10.4",
42
+ "scikit-learn==1.3.0",
43
+ "scipy==1.11.1",
44
+ "statsmodels==0.14.0",
45
+ "fastapi==0.104.1",
46
+ "uvicorn[standard]==0.24.0",
47
+ "pydantic==1.10.13",
48
+ "redis==5.0.1",
49
+ "psycopg2-binary==2.9.9",
50
+ "sqlalchemy==2.0.23",
51
+ "alembic==1.13.0",
52
+ "prometheus-client==0.19.0",
53
+ "structlog==23.2.0",
54
+ ]
55
+
56
+ [project.optional-dependencies]
57
+ dev = [
58
+ "pytest==7.4.0",
59
+ "pytest-asyncio==0.21.1",
60
+ "httpx==0.25.2",
61
+ "black==23.11.0",
62
+ "flake8==6.1.0",
63
+ "mypy==1.7.1",
64
+ "pre-commit==3.6.0",
65
+ "isort==5.12.0",
66
+ ]
67
+
68
+ [project.urls]
69
+ Homepage = "https://github.com/EAName/FREDML"
70
+ Documentation = "https://github.com/EAName/FREDML#readme"
71
+ Repository = "https://github.com/EAName/FREDML.git"
72
+ "Bug Tracker" = "https://github.com/EAName/FREDML/issues"
73
+
74
+ [project.scripts]
75
+ fred-ml = "src.main:main"
76
+
77
+ [tool.black]
78
+ line-length = 88
79
+ target-version = ['py39']
80
+ include = '\.pyi?$'
81
+ extend-exclude = '''
82
+ /(
83
+ # directories
84
+ \.eggs
85
+ | \.git
86
+ | \.hg
87
+ | \.mypy_cache
88
+ | \.tox
89
+ | \.venv
90
+ | build
91
+ | dist
92
+ )/
93
+ '''
94
+
95
+ [tool.isort]
96
+ profile = "black"
97
+ multi_line_output = 3
98
+ line_length = 88
99
+ known_first_party = ["src"]
100
+
101
+ [tool.mypy]
102
+ python_version = "3.9"
103
+ warn_return_any = true
104
+ warn_unused_configs = true
105
+ disallow_untyped_defs = true
106
+ disallow_incomplete_defs = true
107
+ check_untyped_defs = true
108
+ disallow_untyped_decorators = true
109
+ no_implicit_optional = true
110
+ warn_redundant_casts = true
111
+ warn_unused_ignores = true
112
+ warn_no_return = true
113
+ warn_unreachable = true
114
+ strict_equality = true
115
+
116
+ [tool.pytest.ini_options]
117
+ minversion = "6.0"
118
+ addopts = "-ra -q --strict-markers --strict-config"
119
+ testpaths = ["tests"]
120
+ python_files = ["test_*.py", "*_test.py"]
121
+ python_classes = ["Test*"]
122
+ python_functions = ["test_*"]
123
+ markers = [
124
+ "slow: marks tests as slow (deselect with '-m \"not slow\"')",
125
+ "integration: marks tests as integration tests",
126
+ "unit: marks tests as unit tests",
127
+ ]