Spaces:
Sleeping
Sleeping
Upload 1892 files
Browse filesThis view is limited to 50 files because it contains too many changes. See raw diff
- .gitattributes +41 -0
- Dockerfile +18 -0
- README.md +26 -4
- app.py +45 -0
- requirements.txt +12 -0
- run_docker.ps1 +35 -0
- run_docker.sh +82 -0
- sktime/mcp_output/README_MCP.md +57 -0
- sktime/mcp_output/analysis.json +0 -0
- sktime/mcp_output/diff_report.md +67 -0
- sktime/mcp_output/mcp_plugin/__init__.py +0 -0
- sktime/mcp_output/mcp_plugin/adapter.py +185 -0
- sktime/mcp_output/mcp_plugin/main.py +13 -0
- sktime/mcp_output/mcp_plugin/mcp_service.py +72 -0
- sktime/mcp_output/requirements.txt +12 -0
- sktime/mcp_output/start_mcp.py +30 -0
- sktime/mcp_output/workflow_summary.json +220 -0
- sktime/source/.all-contributorsrc +0 -0
- sktime/source/.binder/Dockerfile +22 -0
- sktime/source/.codecov.yml +30 -0
- sktime/source/.coveragerc +10 -0
- sktime/source/.dockerignore +15 -0
- sktime/source/.pre-commit-config.yaml +39 -0
- sktime/source/.readthedocs.yml +19 -0
- sktime/source/CHANGELOG.md +3 -0
- sktime/source/CODEOWNERS +14 -0
- sktime/source/CODE_OF_CONDUCT.md +3 -0
- sktime/source/CONTRIBUTING.md +3 -0
- sktime/source/CONTRIBUTORS.md +0 -0
- sktime/source/ESTIMATOR_OVERVIEW.md +5 -0
- sktime/source/GOVERNANCE.md +3 -0
- sktime/source/LICENSE +30 -0
- sktime/source/MANIFEST.in +8 -0
- sktime/source/Makefile +111 -0
- sktime/source/README.md +248 -0
- sktime/source/__init__.py +4 -0
- sktime/source/build_tools/changelog.py +364 -0
- sktime/source/build_tools/check_backticks.py +120 -0
- sktime/source/build_tools/check_install_from_test_pypi.sh +35 -0
- sktime/source/build_tools/docker/py310.dockerfile +9 -0
- sktime/source/build_tools/docker/py311.dockerfile +9 -0
- sktime/source/build_tools/docker/py312.dockerfile +9 -0
- sktime/source/build_tools/docker/py313.dockerfile +9 -0
- sktime/source/build_tools/docker/py314.dockerfile +9 -0
- sktime/source/build_tools/fail_on_missing_init_files.sh +13 -0
- sktime/source/build_tools/make_release.py +350 -0
- sktime/source/build_tools/nb_json_formatter.py +52 -0
- sktime/source/build_tools/run_blogposts.sh +11 -0
- sktime/source/build_tools/run_examples.sh +11 -0
- sktime/source/conftest.py +48 -0
.gitattributes
CHANGED
|
@@ -33,3 +33,44 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
|
| 33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
| 36 |
+
sktime/source/docs/source/examples/img/annotation_tree.png filter=lfs diff=lfs merge=lfs -text
|
| 37 |
+
sktime/source/docs/source/examples/img/arrow-heads.png filter=lfs diff=lfs merge=lfs -text
|
| 38 |
+
sktime/source/docs/source/examples/img/estimator-conceptual-model.jpg filter=lfs diff=lfs merge=lfs -text
|
| 39 |
+
sktime/source/docs/source/examples/img/estimator-search.png filter=lfs diff=lfs merge=lfs -text
|
| 40 |
+
sktime/source/docs/source/examples/img/forecasting.png filter=lfs diff=lfs merge=lfs -text
|
| 41 |
+
sktime/source/docs/source/examples/img/OSULeaf.jpg filter=lfs diff=lfs merge=lfs -text
|
| 42 |
+
sktime/source/docs/source/examples/img/segmentation_use_cases.png filter=lfs diff=lfs merge=lfs -text
|
| 43 |
+
sktime/source/docs/source/examples/img/sklearn-unified-interface.jpg filter=lfs diff=lfs merge=lfs -text
|
| 44 |
+
sktime/source/docs/source/examples/img/sktime-composable.png filter=lfs diff=lfs merge=lfs -text
|
| 45 |
+
sktime/source/docs/source/examples/img/sktime-doc-estimator-overview.png filter=lfs diff=lfs merge=lfs -text
|
| 46 |
+
sktime/source/docs/source/examples/img/sktime-interoperable.png filter=lfs diff=lfs merge=lfs -text
|
| 47 |
+
sktime/source/docs/source/examples/img/ts-fragmentation.png filter=lfs diff=lfs merge=lfs -text
|
| 48 |
+
sktime/source/docs/source/examples/img/unified_framework.png filter=lfs diff=lfs merge=lfs -text
|
| 49 |
+
sktime/source/docs/source/examples/transformation/fracdiff/fig/nky.png filter=lfs diff=lfs merge=lfs -text
|
| 50 |
+
sktime/source/docs/source/examples/transformation/fracdiff/fig/spx.png filter=lfs diff=lfs merge=lfs -text
|
| 51 |
+
sktime/source/docs/source/images/sktime-logo-no-text.jpg filter=lfs diff=lfs merge=lfs -text
|
| 52 |
+
sktime/source/docs/source/images/sktime-logo.jpg filter=lfs diff=lfs merge=lfs -text
|
| 53 |
+
sktime/source/examples/img/annotation_tree.png filter=lfs diff=lfs merge=lfs -text
|
| 54 |
+
sktime/source/examples/img/arrow-heads.png filter=lfs diff=lfs merge=lfs -text
|
| 55 |
+
sktime/source/examples/img/estimator-conceptual-model.jpg filter=lfs diff=lfs merge=lfs -text
|
| 56 |
+
sktime/source/examples/img/estimator-search.png filter=lfs diff=lfs merge=lfs -text
|
| 57 |
+
sktime/source/examples/img/forecasting.png filter=lfs diff=lfs merge=lfs -text
|
| 58 |
+
sktime/source/examples/img/OSULeaf.jpg filter=lfs diff=lfs merge=lfs -text
|
| 59 |
+
sktime/source/examples/img/segmentation_use_cases.png filter=lfs diff=lfs merge=lfs -text
|
| 60 |
+
sktime/source/examples/img/sklearn-unified-interface.jpg filter=lfs diff=lfs merge=lfs -text
|
| 61 |
+
sktime/source/examples/img/sktime-composable.png filter=lfs diff=lfs merge=lfs -text
|
| 62 |
+
sktime/source/examples/img/sktime-doc-estimator-overview.png filter=lfs diff=lfs merge=lfs -text
|
| 63 |
+
sktime/source/examples/img/sktime-interoperable.png filter=lfs diff=lfs merge=lfs -text
|
| 64 |
+
sktime/source/examples/img/ts-fragmentation.png filter=lfs diff=lfs merge=lfs -text
|
| 65 |
+
sktime/source/examples/img/unified_framework.png filter=lfs diff=lfs merge=lfs -text
|
| 66 |
+
sktime/source/examples/transformation/fracdiff/fig/nky.png filter=lfs diff=lfs merge=lfs -text
|
| 67 |
+
sktime/source/examples/transformation/fracdiff/fig/spx.png filter=lfs diff=lfs merge=lfs -text
|
| 68 |
+
sktime/source/sktime/_contrib/notebooks/img/windows_installation/08_sktime_in_pycharm_no_interpreter.png filter=lfs diff=lfs merge=lfs -text
|
| 69 |
+
sktime/source/sktime/_contrib/notebooks/img/windows_installation/15_pycharm_interpreter_settings.png filter=lfs diff=lfs merge=lfs -text
|
| 70 |
+
sktime/source/sktime/_contrib/notebooks/img/windows_installation/18_run_tests_to_verify.png filter=lfs diff=lfs merge=lfs -text
|
| 71 |
+
sktime/source/sktime/_contrib/notebooks/img/windows_installation/19_test_success.png filter=lfs diff=lfs merge=lfs -text
|
| 72 |
+
sktime/source/sktime/_contrib/notebooks/img/windows_installation/21_pre-commit_examples.png filter=lfs diff=lfs merge=lfs -text
|
| 73 |
+
sktime/source/sktime/_contrib/notebooks/img/windows_installation/22_create_new_commit.png filter=lfs diff=lfs merge=lfs -text
|
| 74 |
+
sktime/source/sktime/_contrib/notebooks/img/windows_installation/23_ensure_check_hooks_ticket.png filter=lfs diff=lfs merge=lfs -text
|
| 75 |
+
sktime/source/sktime/_contrib/notebooks/img/windows_installation/24_failed_commit_with_errors_and_automatic_correction.png filter=lfs diff=lfs merge=lfs -text
|
| 76 |
+
sktime/source/sktime/libs/pykalman/datasets/data/robot.mat filter=lfs diff=lfs merge=lfs -text
|
Dockerfile
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
FROM python:3.10
|
| 2 |
+
|
| 3 |
+
RUN useradd -m -u 1000 user && python -m pip install --upgrade pip
|
| 4 |
+
USER user
|
| 5 |
+
ENV PATH="/home/user/.local/bin:$PATH"
|
| 6 |
+
|
| 7 |
+
WORKDIR /app
|
| 8 |
+
|
| 9 |
+
COPY --chown=user ./requirements.txt requirements.txt
|
| 10 |
+
RUN pip install --no-cache-dir --upgrade -r requirements.txt
|
| 11 |
+
|
| 12 |
+
COPY --chown=user . /app
|
| 13 |
+
ENV MCP_TRANSPORT=http
|
| 14 |
+
ENV MCP_PORT=7860
|
| 15 |
+
|
| 16 |
+
EXPOSE 7860
|
| 17 |
+
|
| 18 |
+
CMD ["python", "sktime/mcp_output/start_mcp.py"]
|
README.md
CHANGED
|
@@ -1,10 +1,32 @@
|
|
| 1 |
---
|
| 2 |
-
title: Sktime
|
| 3 |
-
emoji:
|
| 4 |
-
colorFrom:
|
| 5 |
colorTo: purple
|
| 6 |
sdk: docker
|
|
|
|
|
|
|
| 7 |
pinned: false
|
| 8 |
---
|
| 9 |
|
| 10 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
---
|
| 2 |
+
title: Sktime MCP
|
| 3 |
+
emoji: 🤖
|
| 4 |
+
colorFrom: blue
|
| 5 |
colorTo: purple
|
| 6 |
sdk: docker
|
| 7 |
+
sdk_version: "4.26.0"
|
| 8 |
+
app_file: app.py
|
| 9 |
pinned: false
|
| 10 |
---
|
| 11 |
|
| 12 |
+
# Sktime MCP Service
|
| 13 |
+
|
| 14 |
+
Auto-generated MCP service for sktime.
|
| 15 |
+
|
| 16 |
+
## Usage
|
| 17 |
+
|
| 18 |
+
```
|
| 19 |
+
https://None-sktime-mcp.hf.space/mcp
|
| 20 |
+
```
|
| 21 |
+
|
| 22 |
+
## Connect with Cursor
|
| 23 |
+
|
| 24 |
+
```json
|
| 25 |
+
{
|
| 26 |
+
"mcpServers": {
|
| 27 |
+
"sktime": {
|
| 28 |
+
"url": "https://None-sktime-mcp.hf.space/mcp"
|
| 29 |
+
}
|
| 30 |
+
}
|
| 31 |
+
}
|
| 32 |
+
```
|
app.py
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from fastapi import FastAPI
|
| 2 |
+
import os
|
| 3 |
+
import sys
|
| 4 |
+
|
| 5 |
+
mcp_plugin_path = os.path.join(os.path.dirname(__file__), "sktime", "mcp_output", "mcp_plugin")
|
| 6 |
+
sys.path.insert(0, mcp_plugin_path)
|
| 7 |
+
|
| 8 |
+
app = FastAPI(
|
| 9 |
+
title="Sktime MCP Service",
|
| 10 |
+
description="Auto-generated MCP service for sktime",
|
| 11 |
+
version="1.0.0"
|
| 12 |
+
)
|
| 13 |
+
|
| 14 |
+
@app.get("/")
|
| 15 |
+
def root():
|
| 16 |
+
return {
|
| 17 |
+
"service": "Sktime MCP Service",
|
| 18 |
+
"version": "1.0.0",
|
| 19 |
+
"status": "running",
|
| 20 |
+
"transport": os.environ.get("MCP_TRANSPORT", "http")
|
| 21 |
+
}
|
| 22 |
+
|
| 23 |
+
@app.get("/health")
|
| 24 |
+
def health_check():
|
| 25 |
+
return {"status": "healthy", "service": "sktime MCP"}
|
| 26 |
+
|
| 27 |
+
@app.get("/tools")
|
| 28 |
+
def list_tools():
|
| 29 |
+
try:
|
| 30 |
+
from mcp_service import create_app
|
| 31 |
+
mcp_app = create_app()
|
| 32 |
+
tools = []
|
| 33 |
+
for tool_name, tool_func in mcp_app.tools.items():
|
| 34 |
+
tools.append({
|
| 35 |
+
"name": tool_name,
|
| 36 |
+
"description": tool_func.__doc__ or "No description available"
|
| 37 |
+
})
|
| 38 |
+
return {"tools": tools}
|
| 39 |
+
except Exception as e:
|
| 40 |
+
return {"error": f"Failed to load tools: {str(e)}"}
|
| 41 |
+
|
| 42 |
+
if __name__ == "__main__":
|
| 43 |
+
import uvicorn
|
| 44 |
+
port = int(os.environ.get("PORT", 7860))
|
| 45 |
+
uvicorn.run(app, host="0.0.0.0", port=port)
|
requirements.txt
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
fastmcp
|
| 2 |
+
fastapi
|
| 3 |
+
uvicorn[standard]
|
| 4 |
+
pydantic>=2.0.0
|
| 5 |
+
joblib>=1.2.0,<1.6
|
| 6 |
+
numpy>=1.21,<2.4
|
| 7 |
+
packaging
|
| 8 |
+
pandas<2.4.0,>=1.1
|
| 9 |
+
scikit-base>=0.6.1,<0.14.0
|
| 10 |
+
scikit-learn>=0.24,<1.8.0
|
| 11 |
+
scipy<2.0.0,>=1.2
|
| 12 |
+
pandas
|
run_docker.ps1
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
cd $PSScriptRoot
|
| 2 |
+
|
| 3 |
+
$ErrorActionPreference = "Stop"
|
| 4 |
+
|
| 5 |
+
$entryName = if ($env:MCP_ENTRY_NAME) { $env:MCP_ENTRY_NAME } else { "sktime" }
|
| 6 |
+
$entryUrl = if ($env:MCP_ENTRY_URL) { $env:MCP_ENTRY_URL } else { "http://localhost:7860/mcp" }
|
| 7 |
+
$imageName = if ($env:MCP_IMAGE_NAME) { $env:MCP_IMAGE_NAME } else { "sktime-mcp" }
|
| 8 |
+
|
| 9 |
+
$mcpDir = Join-Path $env:USERPROFILE ".cursor"
|
| 10 |
+
$mcpPath = Join-Path $mcpDir "mcp.json"
|
| 11 |
+
if (!(Test-Path $mcpDir)) { New-Item -ItemType Directory -Path $mcpDir | Out-Null }
|
| 12 |
+
|
| 13 |
+
$config = @{}
|
| 14 |
+
if (Test-Path $mcpPath) {
|
| 15 |
+
try { $config = Get-Content $mcpPath -Raw | ConvertFrom-Json } catch { $config = @{} }
|
| 16 |
+
}
|
| 17 |
+
|
| 18 |
+
# Rebuild mcpServers as ordered and append the entry last
|
| 19 |
+
$serversOrdered = [ordered]@{}
|
| 20 |
+
if ($config -and ($config.PSObject.Properties.Name -contains "mcpServers") -and $config.mcpServers) {
|
| 21 |
+
$existing = $config.mcpServers
|
| 22 |
+
if ($existing -is [pscustomobject]) {
|
| 23 |
+
foreach ($p in $existing.PSObject.Properties) { if ($p.Name -ne $entryName) { $serversOrdered[$p.Name] = $p.Value } }
|
| 24 |
+
} elseif ($existing -is [System.Collections.IDictionary]) {
|
| 25 |
+
foreach ($k in $existing.Keys) { if ($k -ne $entryName) { $serversOrdered[$k] = $existing[$k] } }
|
| 26 |
+
}
|
| 27 |
+
}
|
| 28 |
+
$serversOrdered[$entryName] = @{ url = $entryUrl }
|
| 29 |
+
$config = @{ mcpServers = $serversOrdered }
|
| 30 |
+
|
| 31 |
+
$config | ConvertTo-Json -Depth 10 | Set-Content -Path $mcpPath -Encoding UTF8
|
| 32 |
+
Write-Host ("Updated $entryName in " + $mcpPath + " -> " + $entryUrl)
|
| 33 |
+
|
| 34 |
+
docker build -t $imageName .
|
| 35 |
+
docker run --rm -p 7860:7860 $imageName
|
run_docker.sh
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env bash
|
| 2 |
+
set -euo pipefail
|
| 3 |
+
|
| 4 |
+
# Switch to the directory where this script is located
|
| 5 |
+
cd "$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
| 6 |
+
|
| 7 |
+
mcp_entry_name="${MCP_ENTRY_NAME:-sktime}"
|
| 8 |
+
mcp_entry_url="${MCP_ENTRY_URL:-http://localhost:7860/mcp}"
|
| 9 |
+
mcp_dir="${HOME}/.cursor"
|
| 10 |
+
mcp_path="${mcp_dir}/mcp.json"
|
| 11 |
+
mkdir -p "${mcp_dir}"
|
| 12 |
+
|
| 13 |
+
if command -v python3 >/dev/null 2>&1; then
|
| 14 |
+
python3 - "${mcp_path}" "${mcp_entry_name}" "${mcp_entry_url}" <<'PY'
|
| 15 |
+
import json, os, sys
|
| 16 |
+
path, name, url = sys.argv[1:4]
|
| 17 |
+
cfg = {"mcpServers": {}}
|
| 18 |
+
if os.path.exists(path):
|
| 19 |
+
try:
|
| 20 |
+
with open(path, "r", encoding="utf-8") as f:
|
| 21 |
+
cfg = json.load(f)
|
| 22 |
+
except Exception:
|
| 23 |
+
cfg = {"mcpServers": {}}
|
| 24 |
+
if not isinstance(cfg, dict):
|
| 25 |
+
cfg = {"mcpServers": {}}
|
| 26 |
+
servers = cfg.get("mcpServers")
|
| 27 |
+
if not isinstance(servers, dict):
|
| 28 |
+
servers = {}
|
| 29 |
+
ordered = {}
|
| 30 |
+
for k, v in servers.items():
|
| 31 |
+
if k != name:
|
| 32 |
+
ordered[k] = v
|
| 33 |
+
ordered[name] = {"url": url}
|
| 34 |
+
cfg = {"mcpServers": ordered}
|
| 35 |
+
with open(path, "w", encoding="utf-8") as f:
|
| 36 |
+
json.dump(cfg, f, indent=2, ensure_ascii=False)
|
| 37 |
+
PY
|
| 38 |
+
elif command -v python >/dev/null 2>&1; then
|
| 39 |
+
python - "${mcp_path}" "${mcp_entry_name}" "${mcp_entry_url}" <<'PY'
|
| 40 |
+
import json, os, sys
|
| 41 |
+
path, name, url = sys.argv[1:4]
|
| 42 |
+
cfg = {"mcpServers": {}}
|
| 43 |
+
if os.path.exists(path):
|
| 44 |
+
try:
|
| 45 |
+
with open(path, "r", encoding="utf-8") as f:
|
| 46 |
+
cfg = json.load(f)
|
| 47 |
+
except Exception:
|
| 48 |
+
cfg = {"mcpServers": {}}
|
| 49 |
+
if not isinstance(cfg, dict):
|
| 50 |
+
cfg = {"mcpServers": {}}
|
| 51 |
+
servers = cfg.get("mcpServers")
|
| 52 |
+
if not isinstance(servers, dict):
|
| 53 |
+
servers = {}
|
| 54 |
+
ordered = {}
|
| 55 |
+
for k, v in servers.items():
|
| 56 |
+
if k != name:
|
| 57 |
+
ordered[k] = v
|
| 58 |
+
ordered[name] = {"url": url}
|
| 59 |
+
cfg = {"mcpServers": ordered}
|
| 60 |
+
with open(path, "w", encoding="utf-8") as f:
|
| 61 |
+
json.dump(cfg, f, indent=2, ensure_ascii=False)
|
| 62 |
+
PY
|
| 63 |
+
elif command -v jq >/dev/null 2>&1; then
|
| 64 |
+
name="${mcp_entry_name}"; url="${mcp_entry_url}"
|
| 65 |
+
if [ -f "${mcp_path}" ]; then
|
| 66 |
+
tmp="$(mktemp)"
|
| 67 |
+
jq --arg name "$name" --arg url "$url" '
|
| 68 |
+
.mcpServers = (.mcpServers // {})
|
| 69 |
+
| .mcpServers as $s
|
| 70 |
+
| ($s | with_entries(select(.key != $name))) as $base
|
| 71 |
+
| .mcpServers = ($base + {($name): {"url": $url}})
|
| 72 |
+
' "${mcp_path}" > "${tmp}" && mv "${tmp}" "${mcp_path}"
|
| 73 |
+
else
|
| 74 |
+
printf '{ "mcpServers": { "%s": { "url": "%s" } } }
|
| 75 |
+
' "$name" "$url" > "${mcp_path}"
|
| 76 |
+
fi
|
| 77 |
+
else
|
| 78 |
+
echo "Warning: neither python nor jq found; skipped updating ~/.cursor/mcp.json" >&2
|
| 79 |
+
fi
|
| 80 |
+
|
| 81 |
+
docker build -t sktime-mcp .
|
| 82 |
+
docker run --rm -p 7860:7860 sktime-mcp
|
sktime/mcp_output/README_MCP.md
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# sktime MCP (Model Context Protocol) Service
|
| 2 |
+
|
| 3 |
+
## Project Introduction
|
| 4 |
+
|
| 5 |
+
sktime is a unified framework for machine learning with time series data. It provides a comprehensive suite of tools and algorithms for forecasting, classification, regression, clustering, and transformations. The framework is designed to be modular and extensible, allowing developers to build complex machine learning pipelines with ease. Core functionalities include base classes for forecasters, classifiers, and transformers, ensuring a consistent interface across different time series learning tasks.
|
| 6 |
+
|
| 7 |
+
## Installation Method
|
| 8 |
+
|
| 9 |
+
To install sktime, ensure you have Python installed and then use pip to install the package along with its dependencies:
|
| 10 |
+
|
| 11 |
+
- Required dependencies: numpy, pandas, scikit-learn
|
| 12 |
+
- Optional dependencies for extended functionalities: matplotlib, tensorflow
|
| 13 |
+
|
| 14 |
+
Install sktime using pip:
|
| 15 |
+
|
| 16 |
+
pip install sktime
|
| 17 |
+
|
| 18 |
+
## Quick Start
|
| 19 |
+
|
| 20 |
+
Here's a quick example of how to use sktime for a simple forecasting task:
|
| 21 |
+
|
| 22 |
+
1. Import the necessary modules:
|
| 23 |
+
|
| 24 |
+
from sktime.forecasting.model_selection import temporal_train_test_split
|
| 25 |
+
from sktime.forecasting.arima import AutoARIMA
|
| 26 |
+
from sktime.performance_metrics.forecasting import mean_absolute_percentage_error
|
| 27 |
+
|
| 28 |
+
2. Load your time series data and split it into training and testing sets:
|
| 29 |
+
|
| 30 |
+
y_train, y_test = temporal_train_test_split(y)
|
| 31 |
+
|
| 32 |
+
3. Initialize and fit a forecaster:
|
| 33 |
+
|
| 34 |
+
forecaster = AutoARIMA()
|
| 35 |
+
forecaster.fit(y_train)
|
| 36 |
+
|
| 37 |
+
4. Make predictions and evaluate:
|
| 38 |
+
|
| 39 |
+
y_pred = forecaster.predict(fh=len(y_test))
|
| 40 |
+
mape = mean_absolute_percentage_error(y_test, y_pred)
|
| 41 |
+
|
| 42 |
+
## Available Tools and Endpoints List
|
| 43 |
+
|
| 44 |
+
- **BaseForecaster**: Core forecasting functionalities including methods for fitting and predicting time series data.
|
| 45 |
+
- **BaseClassifier**: Core classification functionalities including methods for fitting and predicting classification tasks.
|
| 46 |
+
- **BaseTransformer**: Core transformation functionalities including methods for transforming time series data.
|
| 47 |
+
- **sktime-forecast**: Command-line interface for running forecasting models on time series data.
|
| 48 |
+
|
| 49 |
+
## Common Issues and Notes
|
| 50 |
+
|
| 51 |
+
- Ensure all required dependencies are installed to avoid import errors.
|
| 52 |
+
- For optimal performance, consider using optional dependencies like tensorflow for deep learning models.
|
| 53 |
+
- The framework is designed to handle various time series formats, but ensure your data is preprocessed correctly to match expected input types.
|
| 54 |
+
|
| 55 |
+
## Reference Links or Documentation
|
| 56 |
+
|
| 57 |
+
For more detailed information, visit the [sktime GitHub repository](https://github.com/sktime/sktime) and the [official documentation](https://www.sktime.org/en/stable/). These resources provide comprehensive guides on system architecture, core components, and usage examples.
|
sktime/mcp_output/analysis.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
sktime/mcp_output/diff_report.md
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Difference Report for sktime Project
|
| 2 |
+
|
| 3 |
+
## Project Overview
|
| 4 |
+
|
| 5 |
+
**Repository:** sktime
|
| 6 |
+
**Project Type:** Python Library
|
| 7 |
+
**Main Features:** Basic functionality for time series analysis and forecasting
|
| 8 |
+
**Report Generated On:** February 7, 2026, 13:18:25
|
| 9 |
+
|
| 10 |
+
The sktime project is a Python library designed to provide a unified framework for time series analysis and forecasting. It offers a variety of tools and algorithms to facilitate the development and deployment of time series models.
|
| 11 |
+
|
| 12 |
+
## Difference Analysis
|
| 13 |
+
|
| 14 |
+
### Summary of Changes
|
| 15 |
+
|
| 16 |
+
- **New Files Added:** 8
|
| 17 |
+
- **Modified Files:** 0
|
| 18 |
+
- **Intrusiveness:** None
|
| 19 |
+
- **Workflow Status:** Success
|
| 20 |
+
- **Test Status:** Failed
|
| 21 |
+
|
| 22 |
+
### New Files
|
| 23 |
+
|
| 24 |
+
The addition of 8 new files indicates an expansion in the project's functionality or structure. However, without modifications to existing files, these changes are likely isolated to new features or modules.
|
| 25 |
+
|
| 26 |
+
### Workflow and Test Status
|
| 27 |
+
|
| 28 |
+
- **Workflow Status:** The workflow has been executed successfully, indicating that the integration and deployment processes are functioning as expected.
|
| 29 |
+
- **Test Status:** The test status is marked as failed, suggesting that the new additions or existing functionalities are not meeting the expected outcomes during testing.
|
| 30 |
+
|
| 31 |
+
## Technical Analysis
|
| 32 |
+
|
| 33 |
+
### New Files
|
| 34 |
+
|
| 35 |
+
The introduction of new files could imply the addition of new features, modules, or enhancements to existing functionalities. It is crucial to review these files to understand their purpose and integration within the existing codebase.
|
| 36 |
+
|
| 37 |
+
### Test Failures
|
| 38 |
+
|
| 39 |
+
The failure in testing could be due to several reasons, including:
|
| 40 |
+
- Incompatibility of new features with existing functionalities.
|
| 41 |
+
- Insufficient test coverage for the new additions.
|
| 42 |
+
- Potential bugs or errors in the newly added code.
|
| 43 |
+
|
| 44 |
+
## Recommendations and Improvements
|
| 45 |
+
|
| 46 |
+
1. **Review New Files:** Conduct a thorough review of the newly added files to ensure they align with the project's objectives and coding standards.
|
| 47 |
+
2. **Enhance Test Coverage:** Increase the test coverage for the new features to identify and rectify any issues.
|
| 48 |
+
3. **Debugging:** Investigate the cause of test failures and implement necessary fixes.
|
| 49 |
+
4. **Documentation:** Update the project documentation to include information about the new features and any changes in usage or API.
|
| 50 |
+
|
| 51 |
+
## Deployment Information
|
| 52 |
+
|
| 53 |
+
Given the successful workflow status, the deployment process appears to be functioning correctly. However, due to the test failures, it is advisable to delay any production deployment until the issues are resolved.
|
| 54 |
+
|
| 55 |
+
## Future Planning
|
| 56 |
+
|
| 57 |
+
1. **Stability Improvements:** Focus on stabilizing the current build by addressing test failures and ensuring all functionalities work as intended.
|
| 58 |
+
2. **Feature Expansion:** Plan for future feature expansions based on user feedback and project goals.
|
| 59 |
+
3. **Community Engagement:** Engage with the community to gather insights and suggestions for further improvements.
|
| 60 |
+
|
| 61 |
+
## Conclusion
|
| 62 |
+
|
| 63 |
+
The sktime project has seen the addition of new files, indicating growth and potential new features. However, the test failures highlight the need for immediate attention to ensure the stability and reliability of the library. By addressing these issues and enhancing test coverage, the project can continue to provide valuable tools for time series analysis and forecasting.
|
| 64 |
+
|
| 65 |
+
---
|
| 66 |
+
|
| 67 |
+
This report provides a comprehensive overview of the current state of the sktime project, highlighting areas for improvement and future development opportunities.
|
sktime/mcp_output/mcp_plugin/__init__.py
ADDED
|
File without changes
|
sktime/mcp_output/mcp_plugin/adapter.py
ADDED
|
@@ -0,0 +1,185 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import sys
|
| 3 |
+
|
| 4 |
+
# Set the source path for imports
|
| 5 |
+
source_path = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))), "source")
|
| 6 |
+
sys.path.insert(0, source_path)
|
| 7 |
+
|
| 8 |
+
# Import necessary modules and classes
|
| 9 |
+
try:
|
| 10 |
+
from sktime.forecasting.base import BaseForecaster
|
| 11 |
+
from sktime.forecasting.compose import EnsembleForecaster
|
| 12 |
+
from sktime.forecasting.model_selection import ForecastingGridSearchCV
|
| 13 |
+
from sktime.forecasting.model_evaluation import evaluate
|
| 14 |
+
from sktime.forecasting.naive import NaiveForecaster
|
| 15 |
+
from sktime.forecasting.arima import ARIMA
|
| 16 |
+
from sktime.forecasting.fbprophet import Prophet
|
| 17 |
+
from sktime.forecasting.statsforecast import StatsForecast
|
| 18 |
+
from sktime.forecasting.tbats import TBATS
|
| 19 |
+
from sktime.forecasting.var import VAR
|
| 20 |
+
from sktime.forecasting.varmax import VARMAX
|
| 21 |
+
from sktime.forecasting.vecm import VECM
|
| 22 |
+
from sktime.forecasting.theta import ThetaForecaster
|
| 23 |
+
from sktime.forecasting.exp_smoothing import ExponentialSmoothing
|
| 24 |
+
from sktime.forecasting.ets import ETS
|
| 25 |
+
from sktime.forecasting.croston import Croston
|
| 26 |
+
from sktime.forecasting.bats import BATS
|
| 27 |
+
from sktime.forecasting.auto_reg import AutoReg
|
| 28 |
+
from sktime.forecasting.arch import ARCH
|
| 29 |
+
from sktime.forecasting.ardl import ARDL
|
| 30 |
+
from sktime.forecasting.autots import AutoTS
|
| 31 |
+
from sktime.forecasting.darts import Darts
|
| 32 |
+
from sktime.forecasting.dynamic_factor import DynamicFactor
|
| 33 |
+
from sktime.forecasting.enbpi import ENBPI
|
| 34 |
+
from sktime.forecasting.es_rnn import ESRNN
|
| 35 |
+
from sktime.forecasting.greykite import Greykite
|
| 36 |
+
from sktime.forecasting.hf_momentfm_forecaster import HFMomentFMForecaster
|
| 37 |
+
from sktime.forecasting.hf_transformers_forecaster import HFTransformersForecaster
|
| 38 |
+
from sktime.forecasting.ltsf import LTSF
|
| 39 |
+
from sktime.forecasting.mapa import MAPA
|
| 40 |
+
from sktime.forecasting.moirai_forecaster import MoiraiForecaster
|
| 41 |
+
from sktime.forecasting.neuralforecast import NeuralForecast
|
| 42 |
+
from sktime.forecasting.pytorchforecasting import PyTorchForecasting
|
| 43 |
+
from sktime.forecasting.pykan_forecaster import PyKanForecaster
|
| 44 |
+
from sktime.forecasting.rbf_forecaster import RBFForecaster
|
| 45 |
+
from sktime.forecasting.reconcile import Reconcile
|
| 46 |
+
from sktime.forecasting.residual_booster import ResidualBooster
|
| 47 |
+
from sktime.forecasting.scinet import SCINet
|
| 48 |
+
from sktime.forecasting.squaring_residuals import SquaringResiduals
|
| 49 |
+
from sktime.forecasting.stream import Stream
|
| 50 |
+
from sktime.forecasting.structural import Structural
|
| 51 |
+
from sktime.forecasting.tirex import Tirex
|
| 52 |
+
from sktime.forecasting.toto import Toto
|
| 53 |
+
from sktime.forecasting.trend import TrendForecaster
|
| 54 |
+
from sktime.forecasting.tsfeatures import TSFeatures
|
| 55 |
+
from sktime.forecasting.tsb import TSB
|
| 56 |
+
from sktime.forecasting.ttm import TTM
|
| 57 |
+
from sktime.forecasting.varreduce import VarReduce
|
| 58 |
+
from sktime.forecasting.window_forecasters import WindowForecasters
|
| 59 |
+
except ImportError as e:
|
| 60 |
+
print(f"Import error: {e}. Some functionalities may not be available.")
|
| 61 |
+
|
| 62 |
+
class Adapter:
|
| 63 |
+
"""
|
| 64 |
+
Adapter class for sktime forecasting functionalities.
|
| 65 |
+
Provides methods to instantiate and utilize various forecasting models.
|
| 66 |
+
"""
|
| 67 |
+
|
| 68 |
+
def __init__(self):
|
| 69 |
+
self.mode = "import"
|
| 70 |
+
|
| 71 |
+
# ------------------- Forecasting Model Methods -------------------
|
| 72 |
+
|
| 73 |
+
def create_naive_forecaster(self, strategy='mean'):
|
| 74 |
+
"""
|
| 75 |
+
Create an instance of NaiveForecaster.
|
| 76 |
+
|
| 77 |
+
Parameters:
|
| 78 |
+
strategy (str): Strategy for naive forecasting. Options are 'mean', 'last', 'seasonal_last'.
|
| 79 |
+
|
| 80 |
+
Returns:
|
| 81 |
+
dict: Contains the status and the NaiveForecaster instance or error message.
|
| 82 |
+
"""
|
| 83 |
+
try:
|
| 84 |
+
forecaster = NaiveForecaster(strategy=strategy)
|
| 85 |
+
return {"status": "success", "forecaster": forecaster}
|
| 86 |
+
except Exception as e:
|
| 87 |
+
return {"status": "error", "message": str(e)}
|
| 88 |
+
|
| 89 |
+
def create_arima_forecaster(self, order=(1, 0, 0)):
|
| 90 |
+
"""
|
| 91 |
+
Create an instance of ARIMA forecaster.
|
| 92 |
+
|
| 93 |
+
Parameters:
|
| 94 |
+
order (tuple): The (p, d, q) order of the model for the number of AR parameters, differences, and MA parameters.
|
| 95 |
+
|
| 96 |
+
Returns:
|
| 97 |
+
dict: Contains the status and the ARIMA instance or error message.
|
| 98 |
+
"""
|
| 99 |
+
try:
|
| 100 |
+
forecaster = ARIMA(order=order)
|
| 101 |
+
return {"status": "success", "forecaster": forecaster}
|
| 102 |
+
except Exception as e:
|
| 103 |
+
return {"status": "error", "message": str(e)}
|
| 104 |
+
|
| 105 |
+
def create_prophet_forecaster(self):
|
| 106 |
+
"""
|
| 107 |
+
Create an instance of Prophet forecaster.
|
| 108 |
+
|
| 109 |
+
Returns:
|
| 110 |
+
dict: Contains the status and the Prophet instance or error message.
|
| 111 |
+
"""
|
| 112 |
+
try:
|
| 113 |
+
forecaster = Prophet()
|
| 114 |
+
return {"status": "success", "forecaster": forecaster}
|
| 115 |
+
except Exception as e:
|
| 116 |
+
return {"status": "error", "message": str(e)}
|
| 117 |
+
|
| 118 |
+
# ------------------- Evaluation and Grid Search Methods -------------------
|
| 119 |
+
|
| 120 |
+
def evaluate_forecaster(self, forecaster, y, X=None, cv=None, strategy='refit'):
|
| 121 |
+
"""
|
| 122 |
+
Evaluate a forecaster using cross-validation.
|
| 123 |
+
|
| 124 |
+
Parameters:
|
| 125 |
+
forecaster (BaseForecaster): The forecaster to evaluate.
|
| 126 |
+
y (pd.Series): The target time series.
|
| 127 |
+
X (pd.DataFrame, optional): Exogenous variables.
|
| 128 |
+
cv (cross-validation generator, optional): Cross-validation splitting strategy.
|
| 129 |
+
strategy (str): Strategy for refitting the forecaster.
|
| 130 |
+
|
| 131 |
+
Returns:
|
| 132 |
+
dict: Contains the status and evaluation results or error message.
|
| 133 |
+
"""
|
| 134 |
+
try:
|
| 135 |
+
results = evaluate(forecaster, y, X=X, cv=cv, strategy=strategy)
|
| 136 |
+
return {"status": "success", "results": results}
|
| 137 |
+
except Exception as e:
|
| 138 |
+
return {"status": "error", "message": str(e)}
|
| 139 |
+
|
| 140 |
+
def grid_search_forecaster(self, forecaster, param_grid, y, X=None, cv=None):
|
| 141 |
+
"""
|
| 142 |
+
Perform grid search to find the best parameters for a forecaster.
|
| 143 |
+
|
| 144 |
+
Parameters:
|
| 145 |
+
forecaster (BaseForecaster): The forecaster to tune.
|
| 146 |
+
param_grid (dict): Dictionary with parameters names as keys and lists of parameter settings to try as values.
|
| 147 |
+
y (pd.Series): The target time series.
|
| 148 |
+
X (pd.DataFrame, optional): Exogenous variables.
|
| 149 |
+
cv (cross-validation generator, optional): Cross-validation splitting strategy.
|
| 150 |
+
|
| 151 |
+
Returns:
|
| 152 |
+
dict: Contains the status and best parameters or error message.
|
| 153 |
+
"""
|
| 154 |
+
try:
|
| 155 |
+
grid_search = ForecastingGridSearchCV(forecaster, param_grid, cv=cv)
|
| 156 |
+
grid_search.fit(y, X=X)
|
| 157 |
+
return {"status": "success", "best_params": grid_search.best_params_}
|
| 158 |
+
except Exception as e:
|
| 159 |
+
return {"status": "error", "message": str(e)}
|
| 160 |
+
|
| 161 |
+
# ------------------- Fallback Handling -------------------
|
| 162 |
+
|
| 163 |
+
def handle_import_failure(self, module_name):
|
| 164 |
+
"""
|
| 165 |
+
Handle import failure gracefully.
|
| 166 |
+
|
| 167 |
+
Parameters:
|
| 168 |
+
module_name (str): The name of the module that failed to import.
|
| 169 |
+
|
| 170 |
+
Returns:
|
| 171 |
+
dict: Contains the status and fallback message.
|
| 172 |
+
"""
|
| 173 |
+
return {
|
| 174 |
+
"status": "error",
|
| 175 |
+
"message": f"Failed to import {module_name}. Please ensure it is installed and available."
|
| 176 |
+
}
|
| 177 |
+
|
| 178 |
+
# Example usage
|
| 179 |
+
if __name__ == "__main__":
|
| 180 |
+
adapter = Adapter()
|
| 181 |
+
result = adapter.create_naive_forecaster()
|
| 182 |
+
if result["status"] == "success":
|
| 183 |
+
print("NaiveForecaster created successfully.")
|
| 184 |
+
else:
|
| 185 |
+
print(result["message"])
|
sktime/mcp_output/mcp_plugin/main.py
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
MCP Service Auto-Wrapper - Auto-generated
|
| 3 |
+
"""
|
| 4 |
+
from mcp_service import create_app
|
| 5 |
+
|
| 6 |
+
def main():
|
| 7 |
+
"""Main entry point"""
|
| 8 |
+
app = create_app()
|
| 9 |
+
return app
|
| 10 |
+
|
| 11 |
+
if __name__ == "__main__":
|
| 12 |
+
app = main()
|
| 13 |
+
app.run()
|
sktime/mcp_output/mcp_plugin/mcp_service.py
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import sys
|
| 3 |
+
|
| 4 |
+
# Path settings to include the local source directory
|
| 5 |
+
source_path = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))), "source")
|
| 6 |
+
if source_path not in sys.path:
|
| 7 |
+
sys.path.insert(0, source_path)
|
| 8 |
+
|
| 9 |
+
from fastmcp import FastMCP
|
| 10 |
+
|
| 11 |
+
# Import core modules from sktime
|
| 12 |
+
from sktime.forecasting.base import BaseForecaster
|
| 13 |
+
from sktime.classification.base import BaseClassifier
|
| 14 |
+
from sktime.transformations.base import BaseTransformer
|
| 15 |
+
|
| 16 |
+
# Create the FastMCP service application
|
| 17 |
+
mcp = FastMCP("sktime_service")
|
| 18 |
+
|
| 19 |
+
@mcp.tool(name="forecasting_tool", description="Tool for forecasting time series data")
|
| 20 |
+
def forecasting_tool(forecaster: BaseForecaster, data) -> dict:
|
| 21 |
+
"""
|
| 22 |
+
Perform forecasting on the provided time series data using the specified forecaster.
|
| 23 |
+
|
| 24 |
+
:param forecaster: An instance of a sktime BaseForecaster.
|
| 25 |
+
:param data: The time series data to forecast.
|
| 26 |
+
:return: A dictionary with success, result, and error fields.
|
| 27 |
+
"""
|
| 28 |
+
try:
|
| 29 |
+
result = forecaster.fit_predict(data)
|
| 30 |
+
return {"success": True, "result": result, "error": None}
|
| 31 |
+
except Exception as e:
|
| 32 |
+
return {"success": False, "result": None, "error": str(e)}
|
| 33 |
+
|
| 34 |
+
@mcp.tool(name="classification_tool", description="Tool for classifying time series data")
|
| 35 |
+
def classification_tool(classifier: BaseClassifier, data, labels) -> dict:
|
| 36 |
+
"""
|
| 37 |
+
Perform classification on the provided time series data using the specified classifier.
|
| 38 |
+
|
| 39 |
+
:param classifier: An instance of a sktime BaseClassifier.
|
| 40 |
+
:param data: The time series data to classify.
|
| 41 |
+
:param labels: The labels for the classification task.
|
| 42 |
+
:return: A dictionary with success, result, and error fields.
|
| 43 |
+
"""
|
| 44 |
+
try:
|
| 45 |
+
classifier.fit(data, labels)
|
| 46 |
+
predictions = classifier.predict(data)
|
| 47 |
+
return {"success": True, "result": predictions, "error": None}
|
| 48 |
+
except Exception as e:
|
| 49 |
+
return {"success": False, "result": None, "error": str(e)}
|
| 50 |
+
|
| 51 |
+
@mcp.tool(name="transformation_tool", description="Tool for transforming time series data")
|
| 52 |
+
def transformation_tool(transformer: BaseTransformer, data) -> dict:
|
| 53 |
+
"""
|
| 54 |
+
Apply transformations to the provided time series data using the specified transformer.
|
| 55 |
+
|
| 56 |
+
:param transformer: An instance of a sktime BaseTransformer.
|
| 57 |
+
:param data: The time series data to transform.
|
| 58 |
+
:return: A dictionary with success, result, and error fields.
|
| 59 |
+
"""
|
| 60 |
+
try:
|
| 61 |
+
transformed_data = transformer.fit_transform(data)
|
| 62 |
+
return {"success": True, "result": transformed_data, "error": None}
|
| 63 |
+
except Exception as e:
|
| 64 |
+
return {"success": False, "result": None, "error": str(e)}
|
| 65 |
+
|
| 66 |
+
def create_app() -> FastMCP:
|
| 67 |
+
"""
|
| 68 |
+
Create and return the FastMCP service instance.
|
| 69 |
+
|
| 70 |
+
:return: An instance of FastMCP configured with the sktime service tools.
|
| 71 |
+
"""
|
| 72 |
+
return mcp
|
sktime/mcp_output/requirements.txt
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
fastmcp
|
| 2 |
+
fastapi
|
| 3 |
+
uvicorn[standard]
|
| 4 |
+
pydantic>=2.0.0
|
| 5 |
+
joblib>=1.2.0,<1.6
|
| 6 |
+
numpy>=1.21,<2.4
|
| 7 |
+
packaging
|
| 8 |
+
pandas<2.4.0,>=1.1
|
| 9 |
+
scikit-base>=0.6.1,<0.14.0
|
| 10 |
+
scikit-learn>=0.24,<1.8.0
|
| 11 |
+
scipy<2.0.0,>=1.2
|
| 12 |
+
pandas
|
sktime/mcp_output/start_mcp.py
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
|
| 2 |
+
"""
|
| 3 |
+
MCP Service Startup Entry
|
| 4 |
+
"""
|
| 5 |
+
import sys
|
| 6 |
+
import os
|
| 7 |
+
|
| 8 |
+
project_root = os.path.dirname(os.path.abspath(__file__))
|
| 9 |
+
mcp_plugin_dir = os.path.join(project_root, "mcp_plugin")
|
| 10 |
+
if mcp_plugin_dir not in sys.path:
|
| 11 |
+
sys.path.insert(0, mcp_plugin_dir)
|
| 12 |
+
|
| 13 |
+
from mcp_service import create_app
|
| 14 |
+
|
| 15 |
+
def main():
|
| 16 |
+
"""Start FastMCP service"""
|
| 17 |
+
app = create_app()
|
| 18 |
+
# Use environment variable to configure port, default 8000
|
| 19 |
+
port = int(os.environ.get("MCP_PORT", "8000"))
|
| 20 |
+
|
| 21 |
+
# Choose transport mode based on environment variable
|
| 22 |
+
transport = os.environ.get("MCP_TRANSPORT", "stdio")
|
| 23 |
+
if transport == "http":
|
| 24 |
+
app.run(transport="http", host="0.0.0.0", port=port)
|
| 25 |
+
else:
|
| 26 |
+
# Default to STDIO mode
|
| 27 |
+
app.run()
|
| 28 |
+
|
| 29 |
+
if __name__ == "__main__":
|
| 30 |
+
main()
|
sktime/mcp_output/workflow_summary.json
ADDED
|
@@ -0,0 +1,220 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"repository": {
|
| 3 |
+
"name": "sktime",
|
| 4 |
+
"url": "https://github.com/sktime/sktime",
|
| 5 |
+
"local_path": "/export/zxcpu1/shiweijie/code/ghh/Code2MCP/workspace/sktime",
|
| 6 |
+
"description": "Python library",
|
| 7 |
+
"features": "Basic functionality",
|
| 8 |
+
"tech_stack": "Python",
|
| 9 |
+
"stars": 0,
|
| 10 |
+
"forks": 0,
|
| 11 |
+
"language": "Python",
|
| 12 |
+
"last_updated": "",
|
| 13 |
+
"complexity": "medium",
|
| 14 |
+
"intrusiveness_risk": "low"
|
| 15 |
+
},
|
| 16 |
+
"execution": {
|
| 17 |
+
"start_time": 1770441313.3248858,
|
| 18 |
+
"end_time": 1770441431.6350722,
|
| 19 |
+
"duration": 118.31018948554993,
|
| 20 |
+
"status": "success",
|
| 21 |
+
"workflow_status": "success",
|
| 22 |
+
"nodes_executed": [
|
| 23 |
+
"download",
|
| 24 |
+
"analysis",
|
| 25 |
+
"env",
|
| 26 |
+
"generate",
|
| 27 |
+
"run",
|
| 28 |
+
"review",
|
| 29 |
+
"finalize"
|
| 30 |
+
],
|
| 31 |
+
"total_files_processed": 26,
|
| 32 |
+
"environment_type": "unknown",
|
| 33 |
+
"llm_calls": 0,
|
| 34 |
+
"deepwiki_calls": 0
|
| 35 |
+
},
|
| 36 |
+
"tests": {
|
| 37 |
+
"original_project": {
|
| 38 |
+
"passed": false,
|
| 39 |
+
"details": {},
|
| 40 |
+
"test_coverage": "100%",
|
| 41 |
+
"execution_time": 0,
|
| 42 |
+
"test_files": []
|
| 43 |
+
},
|
| 44 |
+
"mcp_plugin": {
|
| 45 |
+
"passed": true,
|
| 46 |
+
"details": {},
|
| 47 |
+
"service_health": "healthy",
|
| 48 |
+
"startup_time": 0,
|
| 49 |
+
"transport_mode": "stdio",
|
| 50 |
+
"fastmcp_version": "unknown",
|
| 51 |
+
"mcp_version": "unknown"
|
| 52 |
+
}
|
| 53 |
+
},
|
| 54 |
+
"analysis": {
|
| 55 |
+
"structure": {
|
| 56 |
+
"packages": [
|
| 57 |
+
"source.sktime",
|
| 58 |
+
"source.sktime._contrib",
|
| 59 |
+
"source.sktime.alignment",
|
| 60 |
+
"source.sktime.base",
|
| 61 |
+
"source.sktime.benchmarking",
|
| 62 |
+
"source.sktime.catalogues",
|
| 63 |
+
"source.sktime.classification",
|
| 64 |
+
"source.sktime.clustering",
|
| 65 |
+
"source.sktime.datasets",
|
| 66 |
+
"source.sktime.datatypes",
|
| 67 |
+
"source.sktime.detection",
|
| 68 |
+
"source.sktime.distances",
|
| 69 |
+
"source.sktime.dists_kernels",
|
| 70 |
+
"source.sktime.forecasting",
|
| 71 |
+
"source.sktime.libs",
|
| 72 |
+
"source.sktime.networks",
|
| 73 |
+
"source.sktime.param_est",
|
| 74 |
+
"source.sktime.performance_metrics",
|
| 75 |
+
"source.sktime.pipeline",
|
| 76 |
+
"source.sktime.registry",
|
| 77 |
+
"source.sktime.regression",
|
| 78 |
+
"source.sktime.series_as_features",
|
| 79 |
+
"source.sktime.split",
|
| 80 |
+
"source.sktime.tests",
|
| 81 |
+
"source.sktime.transformations",
|
| 82 |
+
"source.sktime.utils"
|
| 83 |
+
]
|
| 84 |
+
},
|
| 85 |
+
"dependencies": {
|
| 86 |
+
"has_environment_yml": false,
|
| 87 |
+
"has_requirements_txt": false,
|
| 88 |
+
"pyproject": true,
|
| 89 |
+
"setup_cfg": true,
|
| 90 |
+
"setup_py": false
|
| 91 |
+
},
|
| 92 |
+
"entry_points": {
|
| 93 |
+
"imports": [],
|
| 94 |
+
"cli": [],
|
| 95 |
+
"modules": []
|
| 96 |
+
},
|
| 97 |
+
"risk_assessment": {
|
| 98 |
+
"import_feasibility": 0.9,
|
| 99 |
+
"intrusiveness_risk": "low",
|
| 100 |
+
"complexity": "medium"
|
| 101 |
+
},
|
| 102 |
+
"deepwiki_analysis": {
|
| 103 |
+
"repo_url": "https://github.com/sktime/sktime",
|
| 104 |
+
"repo_name": "sktime",
|
| 105 |
+
"content": "sktime/sktime\nCore Concepts\nInstallation\nBase Estimator Framework\nBaseObject and BaseEstimator\nData Types System\nTesting Framework\nForecasting\nBaseForecaster\nForecasting Pipelines\nReduction Approaches\nEnsemble Forecasting\nModel Evaluation\nExternal Library Adapters\nPerformance Metrics\nClassification\nBaseClassifier\nDictionary-based Classifiers\nDistance-based Classifiers\nTransformations\nDataset Handling\nDataset Loaders\nData Validation\nDevelopment Guide\nContributing\nCI/CD Pipeline\nExtension Templates\nDocumentation\n.all-contributorsrc\nCONTRIBUTORS.md\ndocs/source/about/team.rst\ndocs/source/api_reference/classification.rst\ndocs/source/api_reference/clustering.rst\ndocs/source/api_reference/detection.rst\ndocs/source/api_reference/forecasting.rst\ndocs/source/api_reference/regression.rst\ndocs/source/api_reference/transformations.rst\ndocs/source/changelog.rst\ndocs/source/changelog_header_template.rst\npyproject.toml\nsktime/__init__.py\nsktime/forecasting/compose/__init__.py\nThis document provides a comprehensive overview of the sktime codebase architecture, core components, and system design. sktime is a unified framework for machine learning with time series, providing algorithms and tools for forecasting, classification, regression, clustering, transformations, and other time series learning tasks.\nFor specific implementation details of individual learning tasks, see the respective pages:Forecasting,Classification,Transformations, etc. For information about the foundational framework that all estimators build upon, seeBase Estimator Framework.\nSystem Architecture\nsktime is built as a modular, extensible framework with a layered architecture centered around a unified estimator interface.\nArchitecture Overview\nSources:pyproject.toml1-61README.md1-249sktime/__init__.py1-11\nCore Framework Components\nThe foundation of sktime is built on several key framework components that provide the unified interface and common functionality.\nBase Class Hierarchy\nBaseObject(sktime.base)BaseEstimator(sktime.base)BaseForecaster(sktime.forecasting.base)BaseClassifier(sktime.classification)BaseTransformer(sktime.transformations.base)BaseRegressor(sktime.regression.base)BaseClusterer(sktime.clustering.base)\nBaseObject(sktime.base)\nBaseEstimator(sktime.base)\nBaseForecaster(sktime.forecasting.base)\nBaseClassifier(sktime.classification)\nBaseTransformer(sktime.transformations.base)\nBaseRegressor(sktime.regression.base)\nBaseClusterer(sktime.clustering.base)\nBase Class Structure\nSources:docs/source/api_reference/forecasting.rst20-31docs/source/api_reference/classification.rst246-256docs/source/api_reference/regression.rst121-131\nData Type System\nsktime implements a sophisticated data type system that handles various time series formats and provides automatic conversion between them.\nConversion SystemMachine Types (mtypes)Scientific Types (scitypes)SeriesPanelHierarchicalTablepd.DataFramepd.Seriesnumpy.ndarraypd.MultiIndex DataFramenested pd.DataFramecheck_is_scitypeconvert_toconvert\nConversion System\nMachine Types (mtypes)\nScientific Types (scitypes)\nHierarchical\npd.DataFrame\nnumpy.ndarray\npd.MultiIndex DataFrame\nnested pd.DataFrame\ncheck_is_scitype\nData Type Conversion System\nSources:docs/source/api_reference/transformations.rst283-285pyproject.toml51-61\nML Task Module Architecture\nEach machine learning task in sktime follows a consistent modular pattern with specialized base classes and composition tools.\nForecasting Module Structure\nForecasting Module Architecture\nSources:docs/source/api_reference/forecasting.rst20-31sktime/forecasting/compose/__init__.py1-81\nClassification and Regression Modules\nClassification and Regression Architecture\nSources:docs/source/api_reference/classification.rst95-226docs/source/api_reference/regression.rst54-119\nData Flow and Processing Pipeline\nsktime implements a unified data processing pipeline that handles various time series formats and applies transformations consistently across all learning tasks.\nData Processing Pipeline\nSources:docs/source/api_reference/transformations.rst1-47pyproject.toml53-61\nComposition and Extension Framework\nsktime provides extensive composition tools for building complex machine learning pipelines and extending the framework with custom estimators.\nPipeline Composition System\nComposition Framework Architecture\nSources:docs/source/api_reference/forecasting.rst32-86docs/source/api_reference/transformations.rst48-129\nExtension and Testing Framework\nExtension and Community Framework\nSources:CODEOWNERS1-14docs/source/about/team.rst1-165README.md204-249\nThis architecture enables sktime to provide a unified interface for diverse time series learning tasks while maintaining extensibility and consistency across the framework. The modular design allows users to compose complex machine learning pipelines while ensuring compatibility and reliability through comprehensive testing and validation systems.\nRefresh this wiki\nOn this page\nSystem Architecture\nCore Framework Components\nBase Class Hierarchy\nData Type System\nML Task Module Architecture\nForecasting Module Structure\nClassification and Regression Modules\nData Flow and Processing Pipeline\nComposition and Extension Framework\nPipeline Composition System\nExtension and Testing Framework",
|
| 106 |
+
"model": "gpt-4o-2024-08-06",
|
| 107 |
+
"source": "selenium",
|
| 108 |
+
"success": true
|
| 109 |
+
},
|
| 110 |
+
"code_complexity": {
|
| 111 |
+
"cyclomatic_complexity": "medium",
|
| 112 |
+
"cognitive_complexity": "medium",
|
| 113 |
+
"maintainability_index": 75
|
| 114 |
+
},
|
| 115 |
+
"security_analysis": {
|
| 116 |
+
"vulnerabilities_found": 0,
|
| 117 |
+
"security_score": 85,
|
| 118 |
+
"recommendations": []
|
| 119 |
+
}
|
| 120 |
+
},
|
| 121 |
+
"plugin_generation": {
|
| 122 |
+
"files_created": [
|
| 123 |
+
"mcp_output/start_mcp.py",
|
| 124 |
+
"mcp_output/mcp_plugin/__init__.py",
|
| 125 |
+
"mcp_output/mcp_plugin/mcp_service.py",
|
| 126 |
+
"mcp_output/mcp_plugin/adapter.py",
|
| 127 |
+
"mcp_output/mcp_plugin/main.py",
|
| 128 |
+
"mcp_output/requirements.txt",
|
| 129 |
+
"mcp_output/README_MCP.md"
|
| 130 |
+
],
|
| 131 |
+
"main_entry": "start_mcp.py",
|
| 132 |
+
"requirements": [
|
| 133 |
+
"fastmcp>=0.1.0",
|
| 134 |
+
"pydantic>=2.0.0"
|
| 135 |
+
],
|
| 136 |
+
"readme_path": "/export/zxcpu1/shiweijie/code/ghh/Code2MCP/workspace/sktime/mcp_output/README_MCP.md",
|
| 137 |
+
"adapter_mode": "import",
|
| 138 |
+
"total_lines_of_code": 0,
|
| 139 |
+
"generated_files_size": 0,
|
| 140 |
+
"tool_endpoints": 0,
|
| 141 |
+
"supported_features": [
|
| 142 |
+
"Basic functionality"
|
| 143 |
+
],
|
| 144 |
+
"generated_tools": [
|
| 145 |
+
"Basic tools",
|
| 146 |
+
"Health check tools",
|
| 147 |
+
"Version info tools"
|
| 148 |
+
]
|
| 149 |
+
},
|
| 150 |
+
"code_review": {},
|
| 151 |
+
"errors": [],
|
| 152 |
+
"warnings": [],
|
| 153 |
+
"recommendations": [
|
| 154 |
+
"Improve test coverage by adding more unit tests for critical modules",
|
| 155 |
+
"streamline the CI/CD pipeline to ensure faster build and deployment times",
|
| 156 |
+
"enhance documentation for better clarity and user guidance",
|
| 157 |
+
"optimize large files for better performance and maintainability",
|
| 158 |
+
"implement dependency management to handle missing `requirements.txt` and `environment.yml`",
|
| 159 |
+
"improve modularity by refactoring large modules into smaller",
|
| 160 |
+
"more manageable components",
|
| 161 |
+
"enhance error handling and logging for better debugging and maintenance",
|
| 162 |
+
"conduct a code review to identify potential areas for refactoring and optimization",
|
| 163 |
+
"ensure consistent coding standards across the codebase",
|
| 164 |
+
"consider adding more examples and tutorials to help new users understand the framework better."
|
| 165 |
+
],
|
| 166 |
+
"performance_metrics": {
|
| 167 |
+
"memory_usage_mb": 0,
|
| 168 |
+
"cpu_usage_percent": 0,
|
| 169 |
+
"response_time_ms": 0,
|
| 170 |
+
"throughput_requests_per_second": 0
|
| 171 |
+
},
|
| 172 |
+
"deployment_info": {
|
| 173 |
+
"supported_platforms": [
|
| 174 |
+
"Linux",
|
| 175 |
+
"Windows",
|
| 176 |
+
"macOS"
|
| 177 |
+
],
|
| 178 |
+
"python_versions": [
|
| 179 |
+
"3.8",
|
| 180 |
+
"3.9",
|
| 181 |
+
"3.10",
|
| 182 |
+
"3.11",
|
| 183 |
+
"3.12"
|
| 184 |
+
],
|
| 185 |
+
"deployment_methods": [
|
| 186 |
+
"Docker",
|
| 187 |
+
"pip",
|
| 188 |
+
"conda"
|
| 189 |
+
],
|
| 190 |
+
"monitoring_support": true,
|
| 191 |
+
"logging_configuration": "structured"
|
| 192 |
+
},
|
| 193 |
+
"execution_analysis": {
|
| 194 |
+
"success_factors": [
|
| 195 |
+
"Comprehensive package structure analysis",
|
| 196 |
+
"Successful execution of all workflow nodes"
|
| 197 |
+
],
|
| 198 |
+
"failure_reasons": [],
|
| 199 |
+
"overall_assessment": "excellent",
|
| 200 |
+
"node_performance": {
|
| 201 |
+
"download_time": "Efficient, completed without issues",
|
| 202 |
+
"analysis_time": "Thorough, covered all necessary components",
|
| 203 |
+
"generation_time": "Swift, generated necessary files effectively",
|
| 204 |
+
"test_time": "Limited due to lack of original project test execution"
|
| 205 |
+
},
|
| 206 |
+
"resource_usage": {
|
| 207 |
+
"memory_efficiency": "Memory usage not explicitly measured, assumed efficient due to lack of issues",
|
| 208 |
+
"cpu_efficiency": "CPU usage not explicitly measured, assumed efficient due to lack of issues",
|
| 209 |
+
"disk_usage": "Minimal, as indicated by generated files size"
|
| 210 |
+
}
|
| 211 |
+
},
|
| 212 |
+
"technical_quality": {
|
| 213 |
+
"code_quality_score": 85,
|
| 214 |
+
"architecture_score": 90,
|
| 215 |
+
"performance_score": 80,
|
| 216 |
+
"maintainability_score": 75,
|
| 217 |
+
"security_score": 85,
|
| 218 |
+
"scalability_score": 80
|
| 219 |
+
}
|
| 220 |
+
}
|
sktime/source/.all-contributorsrc
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
sktime/source/.binder/Dockerfile
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# This Dockerfile is used to build sktime when launching binder.
|
| 2 |
+
# Find out more at: https://mybinder.readthedocs.io/en/latest/index.html
|
| 3 |
+
|
| 4 |
+
FROM jupyter/scipy-notebook:python-3.11.6
|
| 5 |
+
# Set up user to avoid running as root
|
| 6 |
+
ARG NB_USER
|
| 7 |
+
ARG NB_UID
|
| 8 |
+
ENV USER ${NB_USER}
|
| 9 |
+
ENV HOME /home/${NB_USER}
|
| 10 |
+
|
| 11 |
+
# Binder will automatically clone the repo, but we need to make sure the
|
| 12 |
+
# contents of our repo are in the ${HOME} directory
|
| 13 |
+
COPY . ${HOME}
|
| 14 |
+
USER root
|
| 15 |
+
RUN chown -R ${NB_UID} ${HOME}
|
| 16 |
+
|
| 17 |
+
# Switch user and directory
|
| 18 |
+
USER ${USER}
|
| 19 |
+
WORKDIR ${HOME}
|
| 20 |
+
|
| 21 |
+
# Install extra requirements and sktime based on master branch
|
| 22 |
+
RUN pip install --upgrade pip --no-cache-dir && pip install .[binder]
|
sktime/source/.codecov.yml
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# paths to ignore
|
| 2 |
+
ignore:
|
| 3 |
+
- "docs/**/*"
|
| 4 |
+
- "build_tools/**/*"
|
| 5 |
+
- "examples/*"
|
| 6 |
+
- ".github/*"
|
| 7 |
+
- ".binder/*"
|
| 8 |
+
- "extension_templates/*"
|
| 9 |
+
- "sktime/_contrib/**/*"
|
| 10 |
+
- "*.md"
|
| 11 |
+
- "*.yml"
|
| 12 |
+
- "*.yaml"
|
| 13 |
+
|
| 14 |
+
# PR status check
|
| 15 |
+
coverage:
|
| 16 |
+
status:
|
| 17 |
+
project:
|
| 18 |
+
default:
|
| 19 |
+
# threshold: 1%
|
| 20 |
+
informational: true
|
| 21 |
+
patch:
|
| 22 |
+
default:
|
| 23 |
+
informational: true
|
| 24 |
+
|
| 25 |
+
# post coverage report as comment on PR
|
| 26 |
+
comment: false
|
| 27 |
+
|
| 28 |
+
# enable codecov to report to GitHub status checks
|
| 29 |
+
github_checks:
|
| 30 |
+
annotations: false
|
sktime/source/.coveragerc
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[report]
|
| 2 |
+
show_missing = True
|
| 3 |
+
|
| 4 |
+
[run]
|
| 5 |
+
source = sktime
|
| 6 |
+
omit =
|
| 7 |
+
*/setup.py
|
| 8 |
+
*/sktime/__init__.py
|
| 9 |
+
*/sktime/setup.py
|
| 10 |
+
*/sktime/_contrib/*
|
sktime/source/.dockerignore
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
.binder
|
| 2 |
+
.eggs
|
| 3 |
+
.git
|
| 4 |
+
.github
|
| 5 |
+
.ipynb_checkpoints
|
| 6 |
+
.pytest_cache
|
| 7 |
+
.vscode
|
| 8 |
+
build
|
| 9 |
+
dist
|
| 10 |
+
docs/_build
|
| 11 |
+
htmlcov
|
| 12 |
+
sktime.egg-info
|
| 13 |
+
testdir
|
| 14 |
+
**/*.pyc
|
| 15 |
+
**/__pycache__
|
sktime/source/.pre-commit-config.yaml
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
repos:
|
| 2 |
+
- repo: https://github.com/pre-commit/pre-commit-hooks
|
| 3 |
+
rev: v6.0.0
|
| 4 |
+
hooks:
|
| 5 |
+
- id: check-added-large-files
|
| 6 |
+
args:
|
| 7 |
+
- --maxkb=1000
|
| 8 |
+
- id: check-case-conflict
|
| 9 |
+
- id: check-merge-conflict
|
| 10 |
+
- id: check-symlinks
|
| 11 |
+
- id: check-yaml
|
| 12 |
+
- id: debug-statements
|
| 13 |
+
- id: end-of-file-fixer
|
| 14 |
+
exclude: "^docs/source/examples/"
|
| 15 |
+
- id: requirements-txt-fixer
|
| 16 |
+
- id: trailing-whitespace
|
| 17 |
+
- id: mixed-line-ending
|
| 18 |
+
args: ['--fix=lf']
|
| 19 |
+
|
| 20 |
+
- repo: https://github.com/astral-sh/ruff-pre-commit
|
| 21 |
+
rev: v0.13.1
|
| 22 |
+
hooks:
|
| 23 |
+
- id: ruff-format
|
| 24 |
+
- id: ruff-check
|
| 25 |
+
args: [--fix]
|
| 26 |
+
|
| 27 |
+
- repo: https://github.com/mgedmin/check-manifest
|
| 28 |
+
rev: "0.50"
|
| 29 |
+
hooks:
|
| 30 |
+
- id: check-manifest
|
| 31 |
+
stages: [manual]
|
| 32 |
+
|
| 33 |
+
# We use the Python version instead of the original version which seems to require Docker
|
| 34 |
+
# https://github.com/koalaman/shellcheck-precommit
|
| 35 |
+
- repo: https://github.com/shellcheck-py/shellcheck-py
|
| 36 |
+
rev: v0.11.0.1
|
| 37 |
+
hooks:
|
| 38 |
+
- id: shellcheck
|
| 39 |
+
name: shellcheck
|
sktime/source/.readthedocs.yml
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Read the Docs configuration file
|
| 2 |
+
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
|
| 3 |
+
|
| 4 |
+
version: 2
|
| 5 |
+
|
| 6 |
+
python:
|
| 7 |
+
install:
|
| 8 |
+
- method: pip
|
| 9 |
+
path: .
|
| 10 |
+
extra_requirements:
|
| 11 |
+
- docs
|
| 12 |
+
build:
|
| 13 |
+
os: ubuntu-22.04
|
| 14 |
+
tools:
|
| 15 |
+
python: "3.12"
|
| 16 |
+
|
| 17 |
+
sphinx:
|
| 18 |
+
configuration: docs/source/conf.py
|
| 19 |
+
# fail_on_warning: True
|
sktime/source/CHANGELOG.md
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Changelog
|
| 2 |
+
|
| 3 |
+
You can find the sktime changelog on our [website](https://www.sktime.net/en/latest/changelog.html).
|
sktime/source/CODEOWNERS
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# The file specifies framework level core developers for automated review requests
|
| 2 |
+
#
|
| 3 |
+
# Note: historically, this file has been used to maintain a list of
|
| 4 |
+
# algorithm maintainers as specified in GOVERNANCE.md.
|
| 5 |
+
# This is no longer the case, algorithm maintainers are now
|
| 6 |
+
# specified directly in the estimator,
|
| 7 |
+
# in the "maintainers" tag of the respective scikit-base object.
|
| 8 |
+
#
|
| 9 |
+
# Algorithm maintainers are programmatically queryable
|
| 10 |
+
# via Estimator.get_class_tag("maintainers").
|
| 11 |
+
# Further lookup such as "which algorithms does M maintain"
|
| 12 |
+
# can be carried out using registry.all_estimators
|
| 13 |
+
|
| 14 |
+
* @benheid @felipeangelimvieira @fkiraly @fnhirwa @geetu040 @pranavvp16 @SaiRevanth25 @XinyuWuu @yarnabrina
|
sktime/source/CODE_OF_CONDUCT.md
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Code of Conduct
|
| 2 |
+
|
| 3 |
+
You can find our Code of Conduct on our [website](https://www.sktime.net/en/latest/get_involved/code_of_conduct.html).
|
sktime/source/CONTRIBUTING.md
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Contributing guide
|
| 2 |
+
|
| 3 |
+
You can find our contributing guide on our [website](https://www.sktime.net/en/latest/get_involved/contributing.html).
|
sktime/source/CONTRIBUTORS.md
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
sktime/source/ESTIMATOR_OVERVIEW.md
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
This file is outdated and present only for downwards compatibility of links.
|
| 2 |
+
|
| 3 |
+
Please visit instead:
|
| 4 |
+
* the [sktime API reference](https://www.sktime.net/en/stable/api_reference.html)
|
| 5 |
+
* the [tabular estimator overview](https://www.sktime.net/en/stable/estimator_overview.html)
|
sktime/source/GOVERNANCE.md
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Governance
|
| 2 |
+
|
| 3 |
+
You can find our governance guidelines on our [website](https://www.sktime.net/en/latest/get_involved/governance.html).
|
sktime/source/LICENSE
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
BSD 3-Clause License
|
| 2 |
+
|
| 3 |
+
Copyright (c) 2019 - present, The sktime developers.
|
| 4 |
+
|
| 5 |
+
All rights reserved.
|
| 6 |
+
|
| 7 |
+
Redistribution and use in source and binary forms, with or without
|
| 8 |
+
modification, are permitted provided that the following conditions are met:
|
| 9 |
+
|
| 10 |
+
* Redistributions of source code must retain the above copyright notice, this
|
| 11 |
+
list of conditions and the following disclaimer.
|
| 12 |
+
|
| 13 |
+
* Redistributions in binary form must reproduce the above copyright notice,
|
| 14 |
+
this list of conditions and the following disclaimer in the documentation
|
| 15 |
+
and/or other materials provided with the distribution.
|
| 16 |
+
|
| 17 |
+
* Neither the name of the copyright holder nor the names of its
|
| 18 |
+
contributors may be used to endorse or promote products derived from
|
| 19 |
+
this software without specific prior written permission.
|
| 20 |
+
|
| 21 |
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
| 22 |
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
| 23 |
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
| 24 |
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
| 25 |
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
| 26 |
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
| 27 |
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
| 28 |
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
| 29 |
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
| 30 |
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
sktime/source/MANIFEST.in
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
include *.rst
|
| 2 |
+
recursive-include docs *
|
| 3 |
+
include *.md
|
| 4 |
+
recursive-include examples *
|
| 5 |
+
recursive-include sktime *.py
|
| 6 |
+
recursive-include sktime *.c *.h *.pyx *.pxd *.pxi *.tp
|
| 7 |
+
recursive-include sktime/datasets *.csv *.csv.gz *.arff *.arff.gz *.txt *.ts *.tsv *.tsf
|
| 8 |
+
include LICENSE
|
sktime/source/Makefile
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Makefile for easier installation and cleanup.
|
| 2 |
+
#
|
| 3 |
+
# Uses self-documenting macros from here:
|
| 4 |
+
# http://marmelab.com/blog/2016/02/29/auto-documented-makefile.html
|
| 5 |
+
|
| 6 |
+
PACKAGE=sktime
|
| 7 |
+
DOC_DIR=./docs
|
| 8 |
+
BUILD_TOOLS=./build_tools
|
| 9 |
+
TEST_DIR=testdir
|
| 10 |
+
|
| 11 |
+
.PHONY: help release install test lint clean dist doc docs
|
| 12 |
+
|
| 13 |
+
.DEFAULT_GOAL := help
|
| 14 |
+
|
| 15 |
+
help:
|
| 16 |
+
@grep -E '^[0-9a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) |\
|
| 17 |
+
awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-15s\033[0m\
|
| 18 |
+
%s\n", $$1, $$2}'
|
| 19 |
+
|
| 20 |
+
release: ## Make a release
|
| 21 |
+
python3 $(BUILD_TOOLS)/make_release.py
|
| 22 |
+
|
| 23 |
+
install: ## Install for the current user using the default python command
|
| 24 |
+
python3 setup.py build_ext --inplace && python setup.py install --user
|
| 25 |
+
|
| 26 |
+
test: ## Run unit tests
|
| 27 |
+
-rm -rf ${TEST_DIR}
|
| 28 |
+
mkdir -p ${TEST_DIR}
|
| 29 |
+
cp .coveragerc ${TEST_DIR}
|
| 30 |
+
cp setup.cfg ${TEST_DIR}
|
| 31 |
+
python -m pytest
|
| 32 |
+
|
| 33 |
+
full_test: ## Run all tests
|
| 34 |
+
-rm -rf ${TEST_DIR}
|
| 35 |
+
mkdir -p ${TEST_DIR}
|
| 36 |
+
cp .coveragerc ${TEST_DIR}
|
| 37 |
+
cp setup.cfg ${TEST_DIR}
|
| 38 |
+
python -m pytest --only_changed_modules False
|
| 39 |
+
|
| 40 |
+
test_without_datasets: ## Run unit tests skipping sktime/datasets
|
| 41 |
+
-rm -rf ${TEST_DIR}
|
| 42 |
+
mkdir -p ${TEST_DIR}
|
| 43 |
+
cp .coveragerc ${TEST_DIR}
|
| 44 |
+
cp setup.cfg ${TEST_DIR}
|
| 45 |
+
python -m pytest --ignore sktime/datasets
|
| 46 |
+
|
| 47 |
+
test_check_suite: ## run only estimator contract tests in TestAll classes
|
| 48 |
+
-rm -rf ${TEST_DIR}
|
| 49 |
+
mkdir -p ${TEST_DIR}
|
| 50 |
+
cp .coveragerc ${TEST_DIR}
|
| 51 |
+
cp setup.cfg ${TEST_DIR}
|
| 52 |
+
python -m pytest -k 'TestAll' $(PYTESTOPTIONS)
|
| 53 |
+
|
| 54 |
+
test_softdeps: ## Run unit tests to check soft dependency handling in estimators
|
| 55 |
+
-rm -rf ${TEST_DIR}
|
| 56 |
+
mkdir -p ${TEST_DIR}
|
| 57 |
+
cp setup.cfg ${TEST_DIR}
|
| 58 |
+
cd ${TEST_DIR}
|
| 59 |
+
python -m pytest -v -n auto --showlocals -k 'test_all_estimators' $(PYTESTOPTIONS) --pyargs sktime.registry
|
| 60 |
+
python -m pytest -v -n auto --showlocals -k 'test_check_estimator_does_not_raise' $(PYTESTOPTIONS) --pyargs sktime.utils.tests
|
| 61 |
+
python -m pytest -v -n auto --showlocals $(PYTESTOPTIONS) --pyargs sktime.tests.test_softdeps
|
| 62 |
+
|
| 63 |
+
test_softdeps_full: ## Run all non-suite unit tests without soft dependencies or downloading datasets
|
| 64 |
+
-rm -rf ${TEST_DIR}
|
| 65 |
+
mkdir -p ${TEST_DIR}
|
| 66 |
+
cp setup.cfg ${TEST_DIR}
|
| 67 |
+
cd ${TEST_DIR}
|
| 68 |
+
python -m pytest -v --showlocals --ignore sktime/datasets -k 'not TestAll' $(PYTESTOPTIONS)
|
| 69 |
+
|
| 70 |
+
test_mlflow: ## Run mlflow integration tests
|
| 71 |
+
-rm -rf ${TEST_DIR}
|
| 72 |
+
mkdir -p ${TEST_DIR}
|
| 73 |
+
cp setup.cfg ${TEST_DIR}
|
| 74 |
+
cd ${TEST_DIR}
|
| 75 |
+
python -m pytest -v --showlocals $(PYTESTOPTIONS) --pyargs sktime.utils.tests.test_mlflow_sktime_model_export
|
| 76 |
+
|
| 77 |
+
tests: test
|
| 78 |
+
|
| 79 |
+
clean: ## Clean build dist and egg directories left after install
|
| 80 |
+
rm -rf ./dist
|
| 81 |
+
rm -rf ./build
|
| 82 |
+
rm -rf ./pytest_cache
|
| 83 |
+
rm -rf ./htmlcov
|
| 84 |
+
rm -rf ./junit
|
| 85 |
+
rm -rf ./$(PACKAGE).egg-info
|
| 86 |
+
rm -rf coverage.xml
|
| 87 |
+
rm -f MANIFEST
|
| 88 |
+
rm -rf ./wheelhouse/*
|
| 89 |
+
find . -type f -iname "*.so" -delete
|
| 90 |
+
find . -type f -iname '*.pyc' -delete
|
| 91 |
+
find . -type d -name '__pycache__' -empty -delete
|
| 92 |
+
|
| 93 |
+
dist: ## Make Python source distribution
|
| 94 |
+
python3 setup.py sdist bdist_wheel
|
| 95 |
+
|
| 96 |
+
build:
|
| 97 |
+
python -m build --sdist --wheel --outdir wheelhouse
|
| 98 |
+
|
| 99 |
+
docs: doc
|
| 100 |
+
|
| 101 |
+
doc: ## Build documentation with Sphinx
|
| 102 |
+
$(MAKE) -C $(DOC_DIR) html
|
| 103 |
+
|
| 104 |
+
nb: clean
|
| 105 |
+
rm -rf .venv || true
|
| 106 |
+
python3 -m venv .venv
|
| 107 |
+
. .venv/bin/activate && python -m pip install .[all_extras,binder] && ./build_tools/run_examples.sh
|
| 108 |
+
|
| 109 |
+
dockertest:
|
| 110 |
+
docker build -t sktime -f build_tools/docker/$(PYTHON_VERSION).dockerfile .
|
| 111 |
+
docker run -it --name sktime sktime bash -c "make full_test"
|
sktime/source/README.md
ADDED
|
@@ -0,0 +1,248 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
|
| 2 |
+
## Welcome to sktime
|
| 3 |
+
|
| 4 |
+
<a href="https://www.sktime.net"><img src="https://github.com/sktime/sktime/blob/main/docs/source/images/sktime-logo.svg" width="175" align="right" /></a>
|
| 5 |
+
|
| 6 |
+
> A unified interface for machine learning with time series
|
| 7 |
+
|
| 8 |
+
:rocket: **Version 0.40.1 out now!** [Check out the release notes here](https://www.sktime.net/en/latest/changelog.html).
|
| 9 |
+
|
| 10 |
+
sktime is a library for time series analysis in Python. It provides a unified interface for multiple time series learning tasks. Currently, this includes forecasting, time series classification, clustering, anomaly/changepoint detection, and other tasks. It comes with [time series algorithms](https://www.sktime.net/en/stable/estimator_overview.html) and [scikit-learn] compatible tools to build, tune, and validate time series models.
|
| 11 |
+
|
| 12 |
+
[scikit-learn]: https://scikit-learn.org/stable/
|
| 13 |
+
|
| 14 |
+
| | **[Documentation](https://www.sktime.net/en/stable/users.html)** · **[Tutorials](https://www.sktime.net/en/stable/examples.html)** · **[Release Notes](https://www.sktime.net/en/stable/changelog.html)** |
|
| 15 |
+
|---|---|
|
| 16 |
+
| **Open Source** | [](https://github.com/sktime/sktime/blob/main/LICENSE) [](https://gc-os-ai.github.io/) |
|
| 17 |
+
| **Tutorials** | [](https://mybinder.org/v2/gh/sktime/sktime/main?filepath=examples) [](https://www.youtube.com/playlist?list=PLKs3UgGjlWHqNzu0LEOeLKvnjvvest2d0) |
|
| 18 |
+
| **Community** | [](https://discord.com/invite/54ACzaFsn7) [](https://www.linkedin.com/company/scikit-time/) |
|
| 19 |
+
| **CI/CD** | [](https://github.com/sktime/sktime/actions/workflows/wheels.yml) [](https://www.sktime.net/en/latest/?badge=latest) [](https://github.com/sktime/sktime) |
|
| 20 |
+
| **Code** | [](https://pypi.org/project/sktime/) [](https://anaconda.org/conda-forge/sktime) [](https://www.python.org/) [](https://github.com/psf/black) |
|
| 21 |
+
| **Downloads** |   [)](https://pepy.tech/project/sktime) |
|
| 22 |
+
| **Citation** | [](https://doi.org/10.5281/zenodo.3749000) |
|
| 23 |
+
|
| 24 |
+
## :books: Documentation
|
| 25 |
+
|
| 26 |
+
| Documentation | |
|
| 27 |
+
|--------------------------------------| -------------------------------------------------------------- |
|
| 28 |
+
| :star: **[Tutorials]** | New to sktime? Here's everything you need to know! |
|
| 29 |
+
| :clipboard: **[Binder Notebooks]** | Example notebooks to play with in your browser. |
|
| 30 |
+
| :woman_technologist: **[Examples]** | How to use sktime and its features. |
|
| 31 |
+
| :scissors: **[Extension Templates]** | How to build your own estimator using sktime's API. |
|
| 32 |
+
| :control_knobs: **[API Reference]** | The detailed reference for sktime's API. |
|
| 33 |
+
| :tv: **[Video Tutorial]** | Our video tutorial from 2021 PyData Global. |
|
| 34 |
+
| :hammer_and_wrench: **[Changelog]** | Changes and version history. |
|
| 35 |
+
| :deciduous_tree: **[Roadmap]** | sktime's software and community development plan. |
|
| 36 |
+
| :pencil: **[Related Software]** | A list of related software. |
|
| 37 |
+
|
| 38 |
+
[tutorials]: https://www.sktime.net/en/latest/tutorials.html
|
| 39 |
+
[binder notebooks]: https://mybinder.org/v2/gh/sktime/sktime/main?filepath=examples
|
| 40 |
+
[examples]: https://www.sktime.net/en/latest/examples.html
|
| 41 |
+
[video tutorial]: https://github.com/sktime/sktime-tutorial-pydata-global-2021
|
| 42 |
+
[api reference]: https://www.sktime.net/en/latest/api_reference.html
|
| 43 |
+
[changelog]: https://www.sktime.net/en/latest/changelog.html
|
| 44 |
+
[roadmap]: https://www.sktime.net/en/latest/roadmap.html
|
| 45 |
+
[related software]: https://www.sktime.net/en/latest/related_software.html
|
| 46 |
+
|
| 47 |
+
## :speech_balloon: Where to ask questions
|
| 48 |
+
|
| 49 |
+
Questions and feedback are extremely welcome! We strongly believe in the value of sharing help publicly, as it allows a wider audience to benefit from it.
|
| 50 |
+
|
| 51 |
+
| Type | Platforms |
|
| 52 |
+
| ------------------------------- | --------------------------------------- |
|
| 53 |
+
| :bug: **Bug Reports** | [GitHub Issue Tracker] |
|
| 54 |
+
| :sparkles: **Feature Requests & Ideas** | [GitHub Issue Tracker] |
|
| 55 |
+
| :woman_technologist: **Usage Questions** | [GitHub Discussions] · [Stack Overflow] |
|
| 56 |
+
| :speech_balloon: **General Discussion** | [GitHub Discussions] |
|
| 57 |
+
| :factory: **Contribution & Development** | `dev-chat` channel · [Discord] |
|
| 58 |
+
| :globe_with_meridians: **Meet-ups and collaboration sessions** | [Discord] - Fridays 13 UTC, dev/meet-ups channel |
|
| 59 |
+
|
| 60 |
+
[github issue tracker]: https://github.com/sktime/sktime/issues
|
| 61 |
+
[github discussions]: https://github.com/sktime/sktime/discussions
|
| 62 |
+
[stack overflow]: https://stackoverflow.com/questions/tagged/sktime
|
| 63 |
+
[discord]: https://discord.com/invite/54ACzaFsn7
|
| 64 |
+
|
| 65 |
+
## :dizzy: Features
|
| 66 |
+
Our objective is to enhance the interoperability and usability of the time series analysis ecosystem in its entirety. sktime provides a __unified interface for distinct but related time series learning tasks__. It features [__dedicated time series algorithms__](https://www.sktime.net/en/stable/estimator_overview.html) and __tools for composite model building__, such as pipelining, ensembling, tuning, and reduction, empowering users to apply algorithms designed for one task to another.
|
| 67 |
+
|
| 68 |
+
sktime also provides **interfaces to related libraries**, for example [scikit-learn], [statsmodels], [tsfresh], [PyOD], and [fbprophet], among others.
|
| 69 |
+
|
| 70 |
+
[statsmodels]: https://www.statsmodels.org/stable/index.html
|
| 71 |
+
[tsfresh]: https://tsfresh.readthedocs.io/en/latest/
|
| 72 |
+
[pyod]: https://pyod.readthedocs.io/en/latest/
|
| 73 |
+
[fbprophet]: https://facebook.github.io/prophet/
|
| 74 |
+
|
| 75 |
+
| Module | Status | Links |
|
| 76 |
+
|---|---|---|
|
| 77 |
+
| **[Forecasting]** | stable | [Tutorial](https://www.sktime.net/en/latest/examples/01_forecasting.html) · [API Reference](https://www.sktime.net/en/latest/api_reference/forecasting.html) · [Extension Template](https://github.com/sktime/sktime/blob/main/extension_templates/forecasting.py) |
|
| 78 |
+
| **[Time Series Classification]** | stable | [Tutorial](https://github.com/sktime/sktime/blob/main/examples/02_classification.ipynb) · [API Reference](https://www.sktime.net/en/latest/api_reference/classification.html) · [Extension Template](https://github.com/sktime/sktime/blob/main/extension_templates/classification.py) |
|
| 79 |
+
| **[Time Series Regression]** | stable | [API Reference](https://www.sktime.net/en/latest/api_reference/regression.html) |
|
| 80 |
+
| **[Transformations]** | stable | [Tutorial](https://github.com/sktime/sktime/blob/main/examples/03_transformers.ipynb) · [API Reference](https://www.sktime.net/en/latest/api_reference/transformations.html) · [Extension Template](https://github.com/sktime/sktime/blob/main/extension_templates/transformer.py) |
|
| 81 |
+
| **[Detection tasks]** | maturing | [Extension Template](https://github.com/sktime/sktime/blob/main/extension_templates/detection.py) |
|
| 82 |
+
| **[Parameter fitting]** | maturing | [API Reference](https://www.sktime.net/en/latest/api_reference/param_est.html) · [Extension Template](https://github.com/sktime/sktime/blob/main/extension_templates/transformer.py) |
|
| 83 |
+
| **[Time Series Clustering]** | maturing | [API Reference](https://www.sktime.net/en/latest/api_reference/clustering.html) · [Extension Template](https://github.com/sktime/sktime/blob/main/extension_templates/clustering.py) |
|
| 84 |
+
| **[Time Series Distances/Kernels]** | maturing | [Tutorial](https://github.com/sktime/sktime/blob/main/examples/03_transformers.ipynb) · [API Reference](https://www.sktime.net/en/latest/api_reference/dists_kernels.html) · [Extension Template](https://github.com/sktime/sktime/blob/main/extension_templates/dist_kern_panel.py) |
|
| 85 |
+
| **[Time Series Alignment]** | experimental | [API Reference](https://www.sktime.net/en/latest/api_reference/alignment.html) · [Extension Template](https://github.com/sktime/sktime/blob/main/extension_templates/alignment.py) |
|
| 86 |
+
| **[Time Series Splitters]** | maturing | [Extension Template](https://github.com/sktime/sktime/blob/main/extension_templates/split.py) | |
|
| 87 |
+
| **[Distributions and simulation]** | experimental | |
|
| 88 |
+
|
| 89 |
+
[forecasting]: https://github.com/sktime/sktime/tree/main/sktime/forecasting
|
| 90 |
+
[time series classification]: https://github.com/sktime/sktime/tree/main/sktime/classification
|
| 91 |
+
[time series regression]: https://github.com/sktime/sktime/tree/main/sktime/regression
|
| 92 |
+
[time series clustering]: https://github.com/sktime/sktime/tree/main/sktime/clustering
|
| 93 |
+
[detection tasks]: https://github.com/sktime/sktime/tree/main/sktime/detection
|
| 94 |
+
[time series distances/kernels]: https://github.com/sktime/sktime/tree/main/sktime/dists_kernels
|
| 95 |
+
[time series alignment]: https://github.com/sktime/sktime/tree/main/sktime/alignment
|
| 96 |
+
[transformations]: https://github.com/sktime/sktime/tree/main/sktime/transformations
|
| 97 |
+
[distributions and simulation]: https://github.com/sktime/sktime/tree/main/sktime/proba
|
| 98 |
+
[time series splitters]: https://github.com/sktime/sktime/tree/main/sktime/split
|
| 99 |
+
[parameter fitting]: https://github.com/sktime/sktime/tree/main/sktime/param_est
|
| 100 |
+
|
| 101 |
+
|
| 102 |
+
## :hourglass_flowing_sand: Install sktime
|
| 103 |
+
For troubleshooting and detailed installation instructions, see the [documentation](https://www.sktime.net/en/latest/installation.html).
|
| 104 |
+
|
| 105 |
+
- **Operating system**: macOS X · Linux · Windows 8.1 or higher
|
| 106 |
+
- **Python version**: Python 3.10, 3.11, 3.12, and 3.13 (only 64-bit)
|
| 107 |
+
- **Package managers**: [pip] · [conda] (via `conda-forge`)
|
| 108 |
+
|
| 109 |
+
[pip]: https://pip.pypa.io/en/stable/
|
| 110 |
+
[conda]: https://docs.conda.io/en/latest/
|
| 111 |
+
|
| 112 |
+
### pip
|
| 113 |
+
Using pip, sktime releases are available as source packages and binary wheels.
|
| 114 |
+
Available wheels are listed [here](https://pypi.org/simple/sktime/).
|
| 115 |
+
|
| 116 |
+
```bash
|
| 117 |
+
pip install sktime
|
| 118 |
+
```
|
| 119 |
+
|
| 120 |
+
or, with maximum dependencies,
|
| 121 |
+
|
| 122 |
+
```bash
|
| 123 |
+
pip install sktime[all_extras]
|
| 124 |
+
```
|
| 125 |
+
|
| 126 |
+
For curated sets of soft dependencies for specific learning tasks:
|
| 127 |
+
|
| 128 |
+
```bash
|
| 129 |
+
pip install sktime[forecasting] # for selected forecasting dependencies
|
| 130 |
+
pip install sktime[forecasting,transformations] # forecasters and transformers
|
| 131 |
+
```
|
| 132 |
+
|
| 133 |
+
or similar. Valid sets are:
|
| 134 |
+
|
| 135 |
+
* `forecasting`
|
| 136 |
+
* `transformations`
|
| 137 |
+
* `classification`
|
| 138 |
+
* `regression`
|
| 139 |
+
* `clustering`
|
| 140 |
+
* `param_est`
|
| 141 |
+
* `networks`
|
| 142 |
+
* `detection`
|
| 143 |
+
* `alignment`
|
| 144 |
+
|
| 145 |
+
Cave: in general, not all soft dependencies for a learning task are installed,
|
| 146 |
+
only a curated selection.
|
| 147 |
+
|
| 148 |
+
### conda
|
| 149 |
+
You can also install sktime from `conda` via the `conda-forge` channel.
|
| 150 |
+
The feedstock including the build recipe and configuration is maintained
|
| 151 |
+
in [this conda-forge repository](https://github.com/conda-forge/sktime-feedstock).
|
| 152 |
+
|
| 153 |
+
```bash
|
| 154 |
+
conda install -c conda-forge sktime
|
| 155 |
+
```
|
| 156 |
+
|
| 157 |
+
or, with maximum dependencies,
|
| 158 |
+
|
| 159 |
+
```bash
|
| 160 |
+
conda install -c conda-forge sktime-all-extras
|
| 161 |
+
```
|
| 162 |
+
|
| 163 |
+
(as `conda` does not support dependency sets,
|
| 164 |
+
flexible choice of soft dependencies is unavailable via `conda`)
|
| 165 |
+
|
| 166 |
+
## :zap: Quickstart
|
| 167 |
+
|
| 168 |
+
### Forecasting
|
| 169 |
+
|
| 170 |
+
``` python
|
| 171 |
+
from sktime.datasets import load_airline
|
| 172 |
+
from sktime.forecasting.base import ForecastingHorizon
|
| 173 |
+
from sktime.forecasting.theta import ThetaForecaster
|
| 174 |
+
from sktime.split import temporal_train_test_split
|
| 175 |
+
from sktime.performance_metrics.forecasting import mean_absolute_percentage_error
|
| 176 |
+
|
| 177 |
+
y = load_airline()
|
| 178 |
+
y_train, y_test = temporal_train_test_split(y)
|
| 179 |
+
fh = ForecastingHorizon(y_test.index, is_relative=False)
|
| 180 |
+
forecaster = ThetaForecaster(sp=12) # monthly seasonal periodicity
|
| 181 |
+
forecaster.fit(y_train)
|
| 182 |
+
y_pred = forecaster.predict(fh)
|
| 183 |
+
mean_absolute_percentage_error(y_test, y_pred)
|
| 184 |
+
>>> 0.08661467738190656
|
| 185 |
+
```
|
| 186 |
+
|
| 187 |
+
### Time Series Classification
|
| 188 |
+
|
| 189 |
+
```python
|
| 190 |
+
from sktime.classification.interval_based import TimeSeriesForestClassifier
|
| 191 |
+
from sktime.datasets import load_arrow_head
|
| 192 |
+
from sklearn.model_selection import train_test_split
|
| 193 |
+
from sklearn.metrics import accuracy_score
|
| 194 |
+
|
| 195 |
+
X, y = load_arrow_head()
|
| 196 |
+
X_train, X_test, y_train, y_test = train_test_split(X, y)
|
| 197 |
+
classifier = TimeSeriesForestClassifier()
|
| 198 |
+
classifier.fit(X_train, y_train)
|
| 199 |
+
y_pred = classifier.predict(X_test)
|
| 200 |
+
accuracy_score(y_test, y_pred)
|
| 201 |
+
>>> 0.8679245283018868
|
| 202 |
+
```
|
| 203 |
+
|
| 204 |
+
## :wave: How to get involved
|
| 205 |
+
|
| 206 |
+
There are many ways to join the sktime community. We follow the [all-contributors](https://github.com/all-contributors/all-contributors) specification: all kinds of contributions are welcome - not just code.
|
| 207 |
+
|
| 208 |
+
| Documentation | |
|
| 209 |
+
| -------------------------- | -------------------------------------------------------------- |
|
| 210 |
+
| :gift_heart: **[Contribute]** | How to contribute to sktime. |
|
| 211 |
+
| :school_satchel: **[Mentoring]** | New to open source? Apply to our mentoring program! |
|
| 212 |
+
| :date: **[Meetings]** | Join our discussions, tutorials, workshops, and sprints! |
|
| 213 |
+
| :woman_mechanic: **[Developer Guides]** | How to further develop sktime's code base. |
|
| 214 |
+
| :construction: **[Enhancement Proposals]** | Design a new feature for sktime. |
|
| 215 |
+
| :medal_sports: **[Contributors]** | A list of all contributors. |
|
| 216 |
+
| :raising_hand: **[Roles]** | An overview of our core community roles. |
|
| 217 |
+
| :money_with_wings: **[Donate]** | Fund sktime maintenance and development. |
|
| 218 |
+
| :classical_building: **[Governance]** | How and by whom decisions are made in sktime's community. |
|
| 219 |
+
|
| 220 |
+
[contribute]: https://www.sktime.net/en/latest/get_involved/contributing.html
|
| 221 |
+
[donate]: https://opencollective.com/sktime
|
| 222 |
+
[extension templates]: https://github.com/sktime/sktime/tree/main/extension_templates
|
| 223 |
+
[developer guides]: https://www.sktime.net/en/latest/developer_guide.html
|
| 224 |
+
[contributors]: https://github.com/sktime/sktime/blob/main/CONTRIBUTORS.md
|
| 225 |
+
[governance]: https://www.sktime.net/en/latest/get_involved/governance.html
|
| 226 |
+
[mentoring]: https://github.com/sktime/mentoring
|
| 227 |
+
[meetings]: https://calendar.google.com/calendar/u/0/embed?src=sktime.toolbox@gmail.com&ctz=UTC
|
| 228 |
+
[enhancement proposals]: https://github.com/sktime/enhancement-proposals
|
| 229 |
+
[roles]: https://www.sktime.net/en/latest/about/team.html
|
| 230 |
+
|
| 231 |
+
## :trophy: Hall of fame
|
| 232 |
+
|
| 233 |
+
Thanks to all our community for all your wonderful contributions, PRs, issues, ideas.
|
| 234 |
+
|
| 235 |
+
<a href="https://github.com/sktime/sktime/graphs/contributors">
|
| 236 |
+
<img src="https://opencollective.com/sktime/contributors.svg?width=600&button=false" />
|
| 237 |
+
</a>
|
| 238 |
+
<br>
|
| 239 |
+
|
| 240 |
+
## :bulb: Project vision
|
| 241 |
+
|
| 242 |
+
* **By the community, for the community** -- developed by a friendly and collaborative community.
|
| 243 |
+
* The **right tool for the right task** -- helping users to diagnose their learning problem and suitable scientific model types.
|
| 244 |
+
* **Embedded in state-of-art ecosystems** and **provider of interoperable interfaces** -- interoperable with [scikit-learn], [statsmodels], [tsfresh], and other community favorites.
|
| 245 |
+
* **Rich model composition and reduction functionality** -- build tuning and feature extraction pipelines, solve forecasting tasks with [scikit-learn] regressors.
|
| 246 |
+
* **Clean, descriptive specification syntax** -- based on modern object-oriented design principles for data science.
|
| 247 |
+
* **Fair model assessment and benchmarking** -- build your models, inspect your models, check your models, and avoid pitfalls.
|
| 248 |
+
* **Easily extensible** -- easy extension templates to add your own algorithms compatible with sktime's API.
|
sktime/source/__init__.py
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# -*- coding: utf-8 -*-
|
| 2 |
+
"""
|
| 3 |
+
sktime Project Package Initialization File
|
| 4 |
+
"""
|
sktime/source/build_tools/changelog.py
ADDED
|
@@ -0,0 +1,364 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""RestructuredText changelog generator."""
|
| 2 |
+
|
| 3 |
+
import os
|
| 4 |
+
from collections import defaultdict
|
| 5 |
+
|
| 6 |
+
HEADERS = {
|
| 7 |
+
"Accept": "application/vnd.github.v3+json",
|
| 8 |
+
}
|
| 9 |
+
|
| 10 |
+
if os.getenv("GITHUB_TOKEN") is not None:
|
| 11 |
+
HEADERS["Authorization"] = f"token {os.getenv('GITHUB_TOKEN')}"
|
| 12 |
+
|
| 13 |
+
OWNER = "sktime"
|
| 14 |
+
REPO = "sktime"
|
| 15 |
+
GITHUB_REPOS = "https://api.github.com/repos"
|
| 16 |
+
|
| 17 |
+
|
| 18 |
+
def fetch_merged_pull_requests(page: int = 1) -> list[dict]:
|
| 19 |
+
"""Fetch a page of merged pull requests.
|
| 20 |
+
|
| 21 |
+
Parameters
|
| 22 |
+
----------
|
| 23 |
+
page : int, optional
|
| 24 |
+
Page number to fetch, by default 1.
|
| 25 |
+
Returns all merged pull request from the ``page``-th page of closed PRs,
|
| 26 |
+
where pages are in descending order of last update.
|
| 27 |
+
|
| 28 |
+
Returns
|
| 29 |
+
-------
|
| 30 |
+
list
|
| 31 |
+
List of merged pull requests from the ``page``-th page of closed PRs.
|
| 32 |
+
Elements of list are dictionaries with PR details, as obtained
|
| 33 |
+
from the GitHub API via ``httpx.get``, from the ``pulls`` endpoint.
|
| 34 |
+
"""
|
| 35 |
+
import httpx
|
| 36 |
+
|
| 37 |
+
params = {
|
| 38 |
+
"base": "main",
|
| 39 |
+
"state": "closed",
|
| 40 |
+
"page": page,
|
| 41 |
+
"per_page": 50,
|
| 42 |
+
"sort": "updated",
|
| 43 |
+
"direction": "desc",
|
| 44 |
+
}
|
| 45 |
+
r = httpx.get(
|
| 46 |
+
f"{GITHUB_REPOS}/{OWNER}/{REPO}/pulls",
|
| 47 |
+
headers=HEADERS,
|
| 48 |
+
params=params,
|
| 49 |
+
)
|
| 50 |
+
return [pr for pr in r.json() if pr["merged_at"]]
|
| 51 |
+
|
| 52 |
+
|
| 53 |
+
def fetch_latest_release(): # noqa: D103
|
| 54 |
+
"""Fetch the latest release from the GitHub API.
|
| 55 |
+
|
| 56 |
+
Returns
|
| 57 |
+
-------
|
| 58 |
+
dict
|
| 59 |
+
Dictionary with details of the latest release.
|
| 60 |
+
Dictionary is as obtained from the GitHub API via ``httpx.get``,
|
| 61 |
+
for ``releases/latest`` endpoint.
|
| 62 |
+
"""
|
| 63 |
+
import httpx
|
| 64 |
+
|
| 65 |
+
response = httpx.get(
|
| 66 |
+
f"{GITHUB_REPOS}/{OWNER}/{REPO}/releases/latest", headers=HEADERS
|
| 67 |
+
)
|
| 68 |
+
|
| 69 |
+
if response.status_code == 200:
|
| 70 |
+
return response.json()
|
| 71 |
+
else:
|
| 72 |
+
raise ValueError(response.text, response.status_code)
|
| 73 |
+
|
| 74 |
+
|
| 75 |
+
def fetch_pull_requests_since_last_release() -> list[dict]:
|
| 76 |
+
"""Fetch all pull requests merged since last release.
|
| 77 |
+
|
| 78 |
+
Returns
|
| 79 |
+
-------
|
| 80 |
+
list
|
| 81 |
+
List of pull requests merged since the latest release.
|
| 82 |
+
Elements of list are dictionaries with PR details, as obtained
|
| 83 |
+
from the GitHub API via ``httpx.get``, through ``fetch_merged_pull_requests``.
|
| 84 |
+
"""
|
| 85 |
+
from dateutil import parser
|
| 86 |
+
|
| 87 |
+
release = fetch_latest_release()
|
| 88 |
+
published_at = parser.parse(release["published_at"])
|
| 89 |
+
print(f"Latest release {release['tag_name']} was published at {published_at}")
|
| 90 |
+
|
| 91 |
+
is_exhausted = False
|
| 92 |
+
page = 1
|
| 93 |
+
all_pulls = []
|
| 94 |
+
while not is_exhausted:
|
| 95 |
+
pulls = fetch_merged_pull_requests(page=page)
|
| 96 |
+
all_pulls.extend(
|
| 97 |
+
[p for p in pulls if parser.parse(p["merged_at"]) > published_at]
|
| 98 |
+
)
|
| 99 |
+
is_exhausted = any(parser.parse(p["updated_at"]) < published_at for p in pulls)
|
| 100 |
+
page += 1
|
| 101 |
+
return all_pulls
|
| 102 |
+
|
| 103 |
+
|
| 104 |
+
def github_compare_tags(tag_left: str, tag_right: str = "HEAD"):
|
| 105 |
+
"""Compare commit between two tags."""
|
| 106 |
+
import httpx
|
| 107 |
+
|
| 108 |
+
response = httpx.get(
|
| 109 |
+
f"{GITHUB_REPOS}/{OWNER}/{REPO}/compare/{tag_left}...{tag_right}"
|
| 110 |
+
)
|
| 111 |
+
if response.status_code == 200:
|
| 112 |
+
return response.json()
|
| 113 |
+
else:
|
| 114 |
+
raise ValueError(response.text, response.status_code)
|
| 115 |
+
|
| 116 |
+
|
| 117 |
+
def render_row(pr):
|
| 118 |
+
"""Render a single row with PR in restructuredText format."""
|
| 119 |
+
# Process the title to handle user credits at beginning of title
|
| 120 |
+
title = pr["title"]
|
| 121 |
+
extra_users = []
|
| 122 |
+
|
| 123 |
+
# Check for prefixed user credits like &username
|
| 124 |
+
if title.startswith("&"):
|
| 125 |
+
parts = title.split(" ", 1)
|
| 126 |
+
user_part = parts[0].strip()
|
| 127 |
+
if len(parts) > 1:
|
| 128 |
+
title = parts[1].strip()
|
| 129 |
+
# Extract username without the & prefix
|
| 130 |
+
username = user_part[1:]
|
| 131 |
+
extra_users.append(username)
|
| 132 |
+
|
| 133 |
+
# Handle dependabot PRs: enclose package names and versions in double backticks
|
| 134 |
+
if "dependabot" in pr["user"]["login"].lower():
|
| 135 |
+
# Match patterns like "Update package requirement from <1.0.0 to <2.0.0"
|
| 136 |
+
import re
|
| 137 |
+
|
| 138 |
+
# Pattern to match package name and version bounds
|
| 139 |
+
pattern = r"Update ([\w\-\.]+) requirement from (<[\d\.]+,?>?[>=]*[\d\.]+) to ([>=]*[\d\.]+,?<[\d\.]+)" # noqa: E501
|
| 140 |
+
match = re.search(pattern, title)
|
| 141 |
+
|
| 142 |
+
pattern2 = r"Bump ([\w\-/]+) from (\d+(?:\.\d+)*) to (\d+(?:\.\d+)*)" # noqa: E501
|
| 143 |
+
match2 = re.search(pattern2, title)
|
| 144 |
+
|
| 145 |
+
if match or match2:
|
| 146 |
+
m = match if match else match2
|
| 147 |
+
package, from_ver, to_ver = m.groups()
|
| 148 |
+
|
| 149 |
+
# add double backticks if not already present
|
| 150 |
+
def add_backticks(text):
|
| 151 |
+
if not text.startswith("``") and not text.endswith("``"):
|
| 152 |
+
return f"`{text}`"
|
| 153 |
+
return text
|
| 154 |
+
|
| 155 |
+
package = add_backticks(package)
|
| 156 |
+
from_ver = add_backticks(from_ver)
|
| 157 |
+
to_ver = add_backticks(to_ver)
|
| 158 |
+
|
| 159 |
+
# Replace with proper backticks
|
| 160 |
+
if match:
|
| 161 |
+
title = f"Update {package} requirement from {from_ver} to {to_ver}"
|
| 162 |
+
elif match2:
|
| 163 |
+
title = f"Bump {package} from {from_ver} to {to_ver}"
|
| 164 |
+
|
| 165 |
+
# Replace single backticks with double backticks
|
| 166 |
+
title = title.replace("`", "``")
|
| 167 |
+
# Replace quadruple backticks with double backticks,
|
| 168 |
+
# in case double backticks were already present
|
| 169 |
+
title = title.replace("````", "``")
|
| 170 |
+
|
| 171 |
+
# Print the PR line
|
| 172 |
+
print(
|
| 173 |
+
f"* {title} "
|
| 174 |
+
f"(:pr:`{pr['number']}`)"
|
| 175 |
+
+ ", ".join([f":user:`{user}`" for user in extra_users])
|
| 176 |
+
+ (", " if extra_users else "")
|
| 177 |
+
+ f" :user:`{pr['user']['login']}`"
|
| 178 |
+
)
|
| 179 |
+
|
| 180 |
+
|
| 181 |
+
def assign_prs(prs, categs: list[dict[str, list[str]]]):
|
| 182 |
+
"""Assign PR to categories based on labels."""
|
| 183 |
+
assigned = defaultdict(list)
|
| 184 |
+
|
| 185 |
+
for i, pr in enumerate(prs):
|
| 186 |
+
for cat in categs:
|
| 187 |
+
pr_labels = [label["name"] for label in pr["labels"]]
|
| 188 |
+
if not set(cat["labels"]).isdisjoint(set(pr_labels)):
|
| 189 |
+
assigned[cat["title"]].append(i)
|
| 190 |
+
|
| 191 |
+
# if any(l.startswith("module") for l in pr_labels):
|
| 192 |
+
# print(i, pr_labels)
|
| 193 |
+
|
| 194 |
+
# Assign unmatched PRs to "Other" category
|
| 195 |
+
assigned["Other"] = list(
|
| 196 |
+
set(range(len(prs))) - {i for _, j in assigned.items() for i in j}
|
| 197 |
+
)
|
| 198 |
+
|
| 199 |
+
return assigned
|
| 200 |
+
|
| 201 |
+
|
| 202 |
+
def render_changelog(prs, assigned, label_to_subsection=None, module_order=None):
|
| 203 |
+
"""Render changelog with subsections based on module tags.
|
| 204 |
+
|
| 205 |
+
Parameters
|
| 206 |
+
----------
|
| 207 |
+
prs : list
|
| 208 |
+
List of pull requests.
|
| 209 |
+
assigned : dict
|
| 210 |
+
Dictionary mapping category titles to list of PR indices.
|
| 211 |
+
label_to_subsection : dict, optional
|
| 212 |
+
Dictionary mapping module tags to subsection titles.
|
| 213 |
+
module_order : list, optional
|
| 214 |
+
List of subsection titles in the desired order.
|
| 215 |
+
"""
|
| 216 |
+
from dateutil import parser
|
| 217 |
+
|
| 218 |
+
SECTION_ORDER = ["Enhancements", "Documentation", "Maintenance", "Fixes", "Other"]
|
| 219 |
+
for title in SECTION_ORDER:
|
| 220 |
+
if title not in assigned:
|
| 221 |
+
continue
|
| 222 |
+
|
| 223 |
+
pr_group = [prs[i] for i in assigned[title]]
|
| 224 |
+
if not pr_group:
|
| 225 |
+
continue
|
| 226 |
+
print()
|
| 227 |
+
print(title)
|
| 228 |
+
print("~" * len(title))
|
| 229 |
+
|
| 230 |
+
# Group PRs by module labels
|
| 231 |
+
def group_prs_by_module(pr_group: list[dict]) -> dict[str, list[dict]]:
|
| 232 |
+
"""Group PRs by module labels and return a dictionary."""
|
| 233 |
+
subsection_map: dict[str, list[dict]] = defaultdict(list)
|
| 234 |
+
|
| 235 |
+
for pr in pr_group:
|
| 236 |
+
labels = [label["name"] for label in pr["labels"]]
|
| 237 |
+
added = False
|
| 238 |
+
|
| 239 |
+
for label in labels:
|
| 240 |
+
if label in LABEL_TO_SUBSECTION:
|
| 241 |
+
subsection_map[LABEL_TO_SUBSECTION[label]].append(pr)
|
| 242 |
+
added = True
|
| 243 |
+
if not added:
|
| 244 |
+
subsection_map["Other"].append(pr)
|
| 245 |
+
|
| 246 |
+
return subsection_map
|
| 247 |
+
|
| 248 |
+
def render_subsection(subsection_map: dict[str, list[dict]]) -> None:
|
| 249 |
+
"""Render subsections and their PRs in order."""
|
| 250 |
+
# Render subsections
|
| 251 |
+
for subsection_title in MODULE_ORDER:
|
| 252 |
+
pr_list = subsection_map.get(subsection_title, [])
|
| 253 |
+
if pr_list is None or not pr_list:
|
| 254 |
+
continue
|
| 255 |
+
print()
|
| 256 |
+
print(subsection_title)
|
| 257 |
+
print("^" * len(subsection_title))
|
| 258 |
+
print()
|
| 259 |
+
for pr in sorted(pr_list, key=lambda x: parser.parse(x["merged_at"])):
|
| 260 |
+
render_row(pr)
|
| 261 |
+
|
| 262 |
+
if title in ["Enhancements", "Fixes"]:
|
| 263 |
+
subsection_map = group_prs_by_module(pr_group)
|
| 264 |
+
render_subsection(subsection_map)
|
| 265 |
+
else:
|
| 266 |
+
for pr in sorted(pr_group, key=lambda x: parser.parse(x["merged_at"])):
|
| 267 |
+
render_row(pr)
|
| 268 |
+
|
| 269 |
+
|
| 270 |
+
def render_contributors(prs: list, fmt: str = "rst"):
|
| 271 |
+
"""Find unique authors and print a list in given format.
|
| 272 |
+
|
| 273 |
+
Parameters
|
| 274 |
+
----------
|
| 275 |
+
prs : list
|
| 276 |
+
List of pull requests
|
| 277 |
+
fmt : str, default="rst"
|
| 278 |
+
Format of the output, either "github" or "rst"
|
| 279 |
+
"""
|
| 280 |
+
authors = sorted({pr["user"]["login"] for pr in prs}, key=lambda x: x.lower())
|
| 281 |
+
|
| 282 |
+
header = "Contributors"
|
| 283 |
+
if fmt == "github":
|
| 284 |
+
print(f"### {header}")
|
| 285 |
+
print(", ".join(f"@{user}" for user in authors))
|
| 286 |
+
elif fmt == "rst":
|
| 287 |
+
print(header)
|
| 288 |
+
print("~" * len(header), end="\n\n")
|
| 289 |
+
print(",\n".join(f":user:`{user}`" for user in authors))
|
| 290 |
+
|
| 291 |
+
|
| 292 |
+
if __name__ == "__main__":
|
| 293 |
+
# configuration of categories, sections, label mapping, and order
|
| 294 |
+
# ---------------------------------------------------------------
|
| 295 |
+
categories = [
|
| 296 |
+
{"title": "Enhancements", "labels": ["feature", "enhancement"]},
|
| 297 |
+
{"title": "Documentation", "labels": ["documentation"]},
|
| 298 |
+
{"title": "Maintenance", "labels": ["maintenance", "chore"]},
|
| 299 |
+
{"title": "Fixes", "labels": ["bug", "fix", "bugfix"]},
|
| 300 |
+
]
|
| 301 |
+
|
| 302 |
+
# sourcery skip: use-named-expression
|
| 303 |
+
LABEL_TO_SUBSECTION = {
|
| 304 |
+
"module:base-framework": "BaseObject and base framework",
|
| 305 |
+
"module:deep-learning&networks": "Other",
|
| 306 |
+
"module:detection": "Time series anomalies, changepoints, segmentation",
|
| 307 |
+
"module:distances&kernels": "Time series anomalies, changepoints, segmentation",
|
| 308 |
+
"module:datasets&loaders": "Data sets and data loaders",
|
| 309 |
+
"module:datatypes": "Datatypes, checks, conversions",
|
| 310 |
+
"module:forecasting": "Forecasting",
|
| 311 |
+
"module:metrics&benchmarking": "Benchmarking, Metrics, Splitters",
|
| 312 |
+
"module:parameter-estimators": "Parameter estimation and hypothesis testing",
|
| 313 |
+
"module:plotting&utilities": "Other",
|
| 314 |
+
"module:probability&simulation": "Other",
|
| 315 |
+
"module:splitters&resamplers": "Benchmarking, Metrics, Splitter",
|
| 316 |
+
"module:classification": "Time series classification",
|
| 317 |
+
"module:clustering": "Time series clustering",
|
| 318 |
+
"module:regression": "Time series regression",
|
| 319 |
+
"module:transformations": "Transformations",
|
| 320 |
+
"module:tests": "Test framework",
|
| 321 |
+
}
|
| 322 |
+
# labels start with module
|
| 323 |
+
# Subsection title comes after label
|
| 324 |
+
|
| 325 |
+
MODULE_ORDER = [
|
| 326 |
+
"BaseObject and base framework",
|
| 327 |
+
"Benchmarking, Metrics, Splitters",
|
| 328 |
+
"Data sets and data loaders",
|
| 329 |
+
"Datatypes, checks, conversions",
|
| 330 |
+
"Forecasting",
|
| 331 |
+
"Parameter estimation and hypothesis testing",
|
| 332 |
+
"Registry and search",
|
| 333 |
+
"Time series alignment",
|
| 334 |
+
"Time series anomalies, changepoints, segmentation",
|
| 335 |
+
"Time series classification",
|
| 336 |
+
"Time series clustering",
|
| 337 |
+
"Time series regression",
|
| 338 |
+
"Transformations",
|
| 339 |
+
"Test framework",
|
| 340 |
+
"Other",
|
| 341 |
+
]
|
| 342 |
+
|
| 343 |
+
# end configuration
|
| 344 |
+
|
| 345 |
+
pulls = fetch_pull_requests_since_last_release()
|
| 346 |
+
print(f"Found {len(pulls)} merged PRs since last release")
|
| 347 |
+
assigned = assign_prs(pulls, categories)
|
| 348 |
+
render_changelog(
|
| 349 |
+
pulls,
|
| 350 |
+
assigned,
|
| 351 |
+
label_to_subsection=LABEL_TO_SUBSECTION,
|
| 352 |
+
module_order=MODULE_ORDER,
|
| 353 |
+
)
|
| 354 |
+
print()
|
| 355 |
+
render_contributors(pulls)
|
| 356 |
+
|
| 357 |
+
release = fetch_latest_release()
|
| 358 |
+
diff = github_compare_tags(release["tag_name"])
|
| 359 |
+
if diff["total_commits"] != len(pulls):
|
| 360 |
+
raise ValueError(
|
| 361 |
+
"Something went wrong and not all PR were fetched. "
|
| 362 |
+
f"There are {len(pulls)} PRs but {diff['total_commits']} in the diff. "
|
| 363 |
+
"Please verify that all PRs are included in the changelog."
|
| 364 |
+
)
|
sktime/source/build_tools/check_backticks.py
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3 -u
|
| 2 |
+
# copyright: sktime developers, BSD-3-Clause License (see LICENSE file)
|
| 3 |
+
|
| 4 |
+
"""Test script to check for invalid use of single-backticks."""
|
| 5 |
+
|
| 6 |
+
__author__ = ["geetu040"]
|
| 7 |
+
|
| 8 |
+
import argparse
|
| 9 |
+
import ast
|
| 10 |
+
import glob
|
| 11 |
+
import re
|
| 12 |
+
|
| 13 |
+
|
| 14 |
+
def find_py_files(folder_path):
|
| 15 |
+
"""Find all Python files in a given folder path."""
|
| 16 |
+
return glob.glob(f"{folder_path}/**/*.py", recursive=True)
|
| 17 |
+
|
| 18 |
+
|
| 19 |
+
def extract_docstrings(filename):
|
| 20 |
+
"""Extract docstrings from a Python file."""
|
| 21 |
+
# create abstract syntax tree from the file
|
| 22 |
+
with open(filename) as f:
|
| 23 |
+
tree = ast.parse(f.read())
|
| 24 |
+
|
| 25 |
+
# walk through all nodes in the tree
|
| 26 |
+
docstrings = {}
|
| 27 |
+
for node in ast.walk(tree):
|
| 28 |
+
if (
|
| 29 |
+
isinstance(node, ast.Expr)
|
| 30 |
+
and isinstance(node.value, ast.Constant)
|
| 31 |
+
and isinstance(node.value.value, str)
|
| 32 |
+
):
|
| 33 |
+
# if the node is an expression and
|
| 34 |
+
# its value is a constant and
|
| 35 |
+
# constant's value is a string
|
| 36 |
+
# the node represents a docstring
|
| 37 |
+
# See https://docs.python.org/3/library/ast.html#abstract-grammar
|
| 38 |
+
docstring = node.value.value
|
| 39 |
+
lineno = node.value.lineno
|
| 40 |
+
docstrings[lineno] = docstring
|
| 41 |
+
|
| 42 |
+
return docstrings
|
| 43 |
+
|
| 44 |
+
|
| 45 |
+
def find_invalid_backtick_text(docstring):
|
| 46 |
+
"""Find invalid backtick text in a docstring."""
|
| 47 |
+
# remove all multiple backticks to avoid interference
|
| 48 |
+
# we are looking only for invalid single-backtick
|
| 49 |
+
docstring = re.sub(r"`{2,}.*?`{2,}", "", docstring, flags=re.DOTALL)
|
| 50 |
+
|
| 51 |
+
all_backtick_text = re.findall(r"`.*?`", docstring, flags=re.DOTALL)
|
| 52 |
+
# expressions like :math:`d(x, y):= (x-y)^2` are valid cases
|
| 53 |
+
valid_backtick_text = re.findall(r":.*?:(`.*?`)", docstring, flags=re.DOTALL)
|
| 54 |
+
|
| 55 |
+
# find all the invalid backtick code snippets
|
| 56 |
+
invalid_backtick_text = set()
|
| 57 |
+
for text in all_backtick_text:
|
| 58 |
+
if text in valid_backtick_text:
|
| 59 |
+
continue
|
| 60 |
+
# rst hyperlinks are valid cases
|
| 61 |
+
if re.match(r"`.*?<http.*?>`", text, flags=re.DOTALL):
|
| 62 |
+
continue
|
| 63 |
+
invalid_backtick_text.add(text)
|
| 64 |
+
|
| 65 |
+
return invalid_backtick_text
|
| 66 |
+
|
| 67 |
+
|
| 68 |
+
def main():
|
| 69 |
+
"""Execute the main function of the script."""
|
| 70 |
+
# parse command line arguments
|
| 71 |
+
parser = argparse.ArgumentParser(
|
| 72 |
+
description="Test script to check for invalid use of single-backticks."
|
| 73 |
+
)
|
| 74 |
+
parser.add_argument(
|
| 75 |
+
"folder_path",
|
| 76 |
+
nargs="?",
|
| 77 |
+
default="./sktime",
|
| 78 |
+
help="Folder path to search for Python files",
|
| 79 |
+
)
|
| 80 |
+
args = parser.parse_args()
|
| 81 |
+
|
| 82 |
+
folder_path = args.folder_path
|
| 83 |
+
results = {}
|
| 84 |
+
|
| 85 |
+
# list all the python files in the project
|
| 86 |
+
py_files = find_py_files(folder_path)
|
| 87 |
+
|
| 88 |
+
for file in py_files:
|
| 89 |
+
docstrings = extract_docstrings(file)
|
| 90 |
+
results_on_file = {}
|
| 91 |
+
|
| 92 |
+
for lineno, docstring in docstrings.items():
|
| 93 |
+
invalid_backtick_text = find_invalid_backtick_text(docstring)
|
| 94 |
+
|
| 95 |
+
if len(invalid_backtick_text) > 0:
|
| 96 |
+
results_on_file[lineno] = invalid_backtick_text
|
| 97 |
+
|
| 98 |
+
if len(results_on_file) > 0:
|
| 99 |
+
results[file] = results_on_file
|
| 100 |
+
|
| 101 |
+
# print the lines along with the invalid backticks text
|
| 102 |
+
print(f'Results in "{folder_path}"') # noqa: T201
|
| 103 |
+
if len(results) > 0:
|
| 104 |
+
print(f"Total Files with invalid backticks: {len(results)}") # noqa: T201
|
| 105 |
+
for filename, result in results.items():
|
| 106 |
+
for lineno, errors in result.items():
|
| 107 |
+
print(f"{filename}:{lineno} {' '.join(errors)}") # noqa: T201
|
| 108 |
+
else:
|
| 109 |
+
print("No invalid backticks found") # noqa: T201
|
| 110 |
+
|
| 111 |
+
|
| 112 |
+
if __name__ == "__main__":
|
| 113 |
+
"""
|
| 114 |
+
Usage: defaults to "./sktime"
|
| 115 |
+
python build_tools/check_backticks.py
|
| 116 |
+
|
| 117 |
+
Usage: folder path as argument
|
| 118 |
+
python build_tools/check_backticks.py sktime/classification/distance_based
|
| 119 |
+
"""
|
| 120 |
+
main()
|
sktime/source/build_tools/check_install_from_test_pypi.sh
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/bin/bash
|
| 2 |
+
|
| 3 |
+
# Helper script to download and install sktime from test PyPI to check wheel
|
| 4 |
+
# and upload prior to new release
|
| 5 |
+
|
| 6 |
+
set -e
|
| 7 |
+
|
| 8 |
+
# Version to test, passed as input argument to script
|
| 9 |
+
VERSION=$1
|
| 10 |
+
|
| 11 |
+
# Make temporary directory
|
| 12 |
+
echo "Making test directory ..."
|
| 13 |
+
mkdir "$HOME"/testdir
|
| 14 |
+
cd "$HOME"/testdir
|
| 15 |
+
|
| 16 |
+
# Create test environment
|
| 17 |
+
echo "Creating test environment ..."
|
| 18 |
+
|
| 19 |
+
# shellcheck disable=SC1091
|
| 20 |
+
source "$(conda info --base)"/etc/profile.d/conda.sh # set up conda
|
| 21 |
+
conda create -n sktime_testenv python=3.8
|
| 22 |
+
conda activate sktime_testenv
|
| 23 |
+
|
| 24 |
+
# Install from test PyPI
|
| 25 |
+
echo "Installing sktime from Test PyPI ..."
|
| 26 |
+
pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple sktime=="$VERSION"
|
| 27 |
+
echo "Successfully installed sktime from Test PyPI."
|
| 28 |
+
|
| 29 |
+
# Clean up test directory and environment
|
| 30 |
+
echo "Cleaning up ..."
|
| 31 |
+
conda deactivate
|
| 32 |
+
conda remove -n sktime_testenv --all -y
|
| 33 |
+
rm -r "$HOME"/testdir
|
| 34 |
+
|
| 35 |
+
echo "Done."
|
sktime/source/build_tools/docker/py310.dockerfile
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
FROM python:3.10-slim
|
| 2 |
+
|
| 3 |
+
WORKDIR /usr/src/sktime
|
| 4 |
+
|
| 5 |
+
COPY . .
|
| 6 |
+
|
| 7 |
+
RUN apt-get update && apt-get install --no-install-recommends -y build-essential gcc git && apt-get clean
|
| 8 |
+
RUN python -m pip install -U pip
|
| 9 |
+
RUN python -m pip install .[all_extras_pandas2,dev,binder]
|
sktime/source/build_tools/docker/py311.dockerfile
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
FROM python:3.11-slim
|
| 2 |
+
|
| 3 |
+
WORKDIR /usr/src/sktime
|
| 4 |
+
|
| 5 |
+
COPY . .
|
| 6 |
+
|
| 7 |
+
RUN apt-get update && apt-get install --no-install-recommends -y build-essential gcc git && apt-get clean
|
| 8 |
+
RUN python -m pip install -U pip
|
| 9 |
+
RUN python -m pip install .[all_extras_pandas2,dev,binder]
|
sktime/source/build_tools/docker/py312.dockerfile
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
FROM python:3.12-slim
|
| 2 |
+
|
| 3 |
+
WORKDIR /usr/src/sktime
|
| 4 |
+
|
| 5 |
+
COPY . .
|
| 6 |
+
|
| 7 |
+
RUN apt-get update && apt-get install --no-install-recommends -y build-essential gcc git && apt-get clean
|
| 8 |
+
RUN python -m pip install -U pip
|
| 9 |
+
RUN python -m pip install .[all_extras_pandas2,dev,binder]
|
sktime/source/build_tools/docker/py313.dockerfile
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
FROM python:3.13-slim
|
| 2 |
+
|
| 3 |
+
WORKDIR /usr/src/sktime
|
| 4 |
+
|
| 5 |
+
COPY . .
|
| 6 |
+
|
| 7 |
+
RUN apt-get update && apt-get install --no-install-recommends -y build-essential gcc git && apt-get clean
|
| 8 |
+
RUN python -m pip install -U pip
|
| 9 |
+
RUN python -m pip install .[all_extras_pandas2,dev,binder]
|
sktime/source/build_tools/docker/py314.dockerfile
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
FROM python:3.14-slim
|
| 2 |
+
|
| 3 |
+
WORKDIR /usr/src/sktime
|
| 4 |
+
|
| 5 |
+
COPY . .
|
| 6 |
+
|
| 7 |
+
RUN apt-get update && apt-get install --no-install-recommends -y build-essential gcc git && apt-get clean
|
| 8 |
+
RUN python -m pip install -U pip
|
| 9 |
+
RUN python -m pip install .[all_extras_pandas2,dev,binder]
|
sktime/source/build_tools/fail_on_missing_init_files.sh
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/bin/bash
|
| 2 |
+
|
| 3 |
+
# Script to search for missing init FILES.
|
| 4 |
+
set -euxo pipefail
|
| 5 |
+
|
| 6 |
+
FILES=$( find ./sktime -type d '!' -exec test -e "{}/__init__.py" ";" -not -path "**/__pycache__" -not -path "**/datasets/data*" -not -path "**/contrib/*" -print )
|
| 7 |
+
|
| 8 |
+
if [[ -n "$FILES" ]]
|
| 9 |
+
then
|
| 10 |
+
echo "Missing __init__.py files detected in the following modules:"
|
| 11 |
+
echo "$FILES"
|
| 12 |
+
exit 1
|
| 13 |
+
fi
|
sktime/source/build_tools/make_release.py
ADDED
|
@@ -0,0 +1,350 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3 -u
|
| 2 |
+
# copyright: sktime developers, BSD-3-Clause License (see LICENSE file)
|
| 3 |
+
"""Do-nothing script for making a release.
|
| 4 |
+
|
| 5 |
+
This idea comes from here:
|
| 6 |
+
- https://blog.danslimmon.com/2019/07/15/do-nothing-scripting-the-key-to
|
| 7 |
+
-gradual-automation/
|
| 8 |
+
|
| 9 |
+
The script is adapted from:
|
| 10 |
+
- https://github.com/alan-turing-institute/CleverCSV/blob/master
|
| 11 |
+
/make_release.py
|
| 12 |
+
"""
|
| 13 |
+
|
| 14 |
+
__author__ = ["mloning"]
|
| 15 |
+
|
| 16 |
+
import codecs
|
| 17 |
+
import os
|
| 18 |
+
import re
|
| 19 |
+
import webbrowser
|
| 20 |
+
|
| 21 |
+
import colorama
|
| 22 |
+
|
| 23 |
+
ROOT_DIR = os.path.abspath(os.path.dirname(__file__)).replace("build_tools", "")
|
| 24 |
+
PACKAGE_NAME = "sktime"
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
class URLs:
|
| 28 |
+
"""Container class for URLs."""
|
| 29 |
+
|
| 30 |
+
DOCS_LOCAL = "file://" + os.path.realpath(
|
| 31 |
+
os.path.join(ROOT_DIR, "docs/_build/html/index.html")
|
| 32 |
+
)
|
| 33 |
+
DOCS_ONLINE = "https://www.sktime.net"
|
| 34 |
+
PYPI = f"https://pypi.org/simple/{PACKAGE_NAME}/"
|
| 35 |
+
|
| 36 |
+
|
| 37 |
+
def read(*parts):
|
| 38 |
+
"""Read from parts."""
|
| 39 |
+
# intentionally *not* adding an encoding option to open, See:
|
| 40 |
+
# https://github.com/pypa/virtualenv/issues/201#issuecomment-3145690
|
| 41 |
+
with codecs.open(os.path.join(ROOT_DIR, *parts), "r") as fp:
|
| 42 |
+
return fp.read()
|
| 43 |
+
|
| 44 |
+
|
| 45 |
+
def find_version(*file_paths):
|
| 46 |
+
"""Find version string."""
|
| 47 |
+
version_file = read(*file_paths)
|
| 48 |
+
version_match = re.search(r"^__version__ = ['\"]([^'\"]*)['\"]", version_file, re.M)
|
| 49 |
+
if version_match:
|
| 50 |
+
return version_match.group(1)
|
| 51 |
+
else:
|
| 52 |
+
raise RuntimeError("Unable to find version string.")
|
| 53 |
+
|
| 54 |
+
|
| 55 |
+
def open_website(website):
|
| 56 |
+
"""Open website."""
|
| 57 |
+
webbrowser.open(website, new=1)
|
| 58 |
+
|
| 59 |
+
|
| 60 |
+
def colored(msg, color=None, style=None):
|
| 61 |
+
"""Print message with colors."""
|
| 62 |
+
colors = {
|
| 63 |
+
"red": colorama.Fore.RED,
|
| 64 |
+
"green": colorama.Fore.GREEN,
|
| 65 |
+
"cyan": colorama.Fore.CYAN,
|
| 66 |
+
"yellow": colorama.Fore.YELLOW,
|
| 67 |
+
"magenta": colorama.Fore.MAGENTA,
|
| 68 |
+
None: "",
|
| 69 |
+
}
|
| 70 |
+
styles = {
|
| 71 |
+
"bright": colorama.Style.BRIGHT,
|
| 72 |
+
"dim": colorama.Style.DIM,
|
| 73 |
+
None: "",
|
| 74 |
+
}
|
| 75 |
+
pre = colors[color] + styles[style]
|
| 76 |
+
post = colorama.Style.RESET_ALL
|
| 77 |
+
return f"{pre}{msg}{post}"
|
| 78 |
+
|
| 79 |
+
|
| 80 |
+
def cprint(msg, color=None, style=None):
|
| 81 |
+
"""Coloured printing."""
|
| 82 |
+
print(colored(msg, color=color, style=style))
|
| 83 |
+
|
| 84 |
+
|
| 85 |
+
def wait_for_enter():
|
| 86 |
+
"""Wait for Enter."""
|
| 87 |
+
input(colored("\nPress Enter to continue", style="dim"))
|
| 88 |
+
print()
|
| 89 |
+
|
| 90 |
+
|
| 91 |
+
class Step:
|
| 92 |
+
"""Abstraction for release step."""
|
| 93 |
+
|
| 94 |
+
def pre(self, context):
|
| 95 |
+
"""Pre-step."""
|
| 96 |
+
|
| 97 |
+
def post(self, context):
|
| 98 |
+
"""Post-step."""
|
| 99 |
+
wait_for_enter()
|
| 100 |
+
|
| 101 |
+
def run(self, context):
|
| 102 |
+
"""Run step."""
|
| 103 |
+
try:
|
| 104 |
+
self.pre(context)
|
| 105 |
+
self.action(context)
|
| 106 |
+
self.post(context)
|
| 107 |
+
except KeyboardInterrupt:
|
| 108 |
+
cprint("\nInterrupted.", color="red")
|
| 109 |
+
raise SystemExit(1)
|
| 110 |
+
|
| 111 |
+
@staticmethod
|
| 112 |
+
def instruct(msg):
|
| 113 |
+
"""Instruction."""
|
| 114 |
+
cprint(msg, color="green")
|
| 115 |
+
|
| 116 |
+
def print_run(self, msg):
|
| 117 |
+
"""Print run step."""
|
| 118 |
+
cprint("Run:", color="cyan", style="bright")
|
| 119 |
+
self.print_cmd(msg)
|
| 120 |
+
|
| 121 |
+
@staticmethod
|
| 122 |
+
def print_cmd(msg):
|
| 123 |
+
"""Print cmd step."""
|
| 124 |
+
cprint("\t" + msg, color="cyan", style="bright")
|
| 125 |
+
|
| 126 |
+
@staticmethod
|
| 127 |
+
def do_cmd(cmd):
|
| 128 |
+
"""Wait for confirmation."""
|
| 129 |
+
cprint(f"Going to run: {cmd}", color="magenta", style="bright")
|
| 130 |
+
wait_for_enter()
|
| 131 |
+
os.system(cmd)
|
| 132 |
+
|
| 133 |
+
def action(self, context):
|
| 134 |
+
"""Carry out action."""
|
| 135 |
+
raise NotImplementedError("abstract method")
|
| 136 |
+
|
| 137 |
+
|
| 138 |
+
class ConfirmGitStatus(Step):
|
| 139 |
+
"""Confirm git status."""
|
| 140 |
+
|
| 141 |
+
def __init__(self, branch):
|
| 142 |
+
self.branch = branch
|
| 143 |
+
|
| 144 |
+
def action(self, context):
|
| 145 |
+
"""Carry out action."""
|
| 146 |
+
self.instruct(
|
| 147 |
+
f"Make sure you're on: {self.branch}, you're local "
|
| 148 |
+
f"branch is up-to-date, and all new changes are merged "
|
| 149 |
+
f"in."
|
| 150 |
+
)
|
| 151 |
+
self.do_cmd(f"git checkout {self.branch}")
|
| 152 |
+
self.do_cmd("git pull")
|
| 153 |
+
|
| 154 |
+
|
| 155 |
+
class UpdateChangelog(Step):
|
| 156 |
+
"""Update the changelog."""
|
| 157 |
+
|
| 158 |
+
def action(self, context):
|
| 159 |
+
"""Carry out action."""
|
| 160 |
+
self.instruct(f"Update CHANGELOG for version: {context['version']}")
|
| 161 |
+
|
| 162 |
+
|
| 163 |
+
class UpdateReadme(Step):
|
| 164 |
+
"""Update the readme."""
|
| 165 |
+
|
| 166 |
+
def action(self, context):
|
| 167 |
+
"""Carry out action."""
|
| 168 |
+
self.instruct(f"Update README for version: {context['version']}")
|
| 169 |
+
|
| 170 |
+
|
| 171 |
+
class UpdateVersion(Step):
|
| 172 |
+
"""Update sktime version."""
|
| 173 |
+
|
| 174 |
+
def action(self, context):
|
| 175 |
+
"""Carry out action."""
|
| 176 |
+
self.instruct("Update __init__.py with new version")
|
| 177 |
+
|
| 178 |
+
def post(self, context):
|
| 179 |
+
"""Post-action step."""
|
| 180 |
+
wait_for_enter()
|
| 181 |
+
context["version"] = find_version(context["package_name"], "__init__.py")
|
| 182 |
+
|
| 183 |
+
|
| 184 |
+
class MakeClean(Step):
|
| 185 |
+
"""Make clean."""
|
| 186 |
+
|
| 187 |
+
def action(self, context):
|
| 188 |
+
"""Carry out action."""
|
| 189 |
+
self.do_cmd("make clean")
|
| 190 |
+
|
| 191 |
+
|
| 192 |
+
class MakeDocs(Step):
|
| 193 |
+
"""Make docs."""
|
| 194 |
+
|
| 195 |
+
def action(self, context):
|
| 196 |
+
"""Carry out action."""
|
| 197 |
+
self.do_cmd("make docs")
|
| 198 |
+
|
| 199 |
+
|
| 200 |
+
class MakeDist(Step):
|
| 201 |
+
"""Make dist."""
|
| 202 |
+
|
| 203 |
+
def action(self, context):
|
| 204 |
+
"""Carry out action."""
|
| 205 |
+
self.do_cmd("make dist")
|
| 206 |
+
|
| 207 |
+
|
| 208 |
+
class UploadToTestPyPI(Step):
|
| 209 |
+
"""Upload to test pypi."""
|
| 210 |
+
|
| 211 |
+
def action(self, context):
|
| 212 |
+
"""Carry out action."""
|
| 213 |
+
self.instruct("Upload to TestPyPI")
|
| 214 |
+
cmd = "twine upload --repository-url https://test.pypi.org/legacy/ dist/*"
|
| 215 |
+
self.do_cmd(cmd)
|
| 216 |
+
|
| 217 |
+
|
| 218 |
+
class InstallFromTestPyPI(Step):
|
| 219 |
+
"""Install from test pypi."""
|
| 220 |
+
|
| 221 |
+
def action(self, context):
|
| 222 |
+
"""Carry out action."""
|
| 223 |
+
self.instruct("Check installation from TestPyPI")
|
| 224 |
+
self.do_cmd(
|
| 225 |
+
f"sh build_tools/check_install_from_test_pypi.sh {context['version']}"
|
| 226 |
+
)
|
| 227 |
+
|
| 228 |
+
|
| 229 |
+
class CheckVersionNumber(Step):
|
| 230 |
+
"""Check version number."""
|
| 231 |
+
|
| 232 |
+
def action(self, context):
|
| 233 |
+
"""Carry out action."""
|
| 234 |
+
self.instruct(
|
| 235 |
+
f"Ensure that the following command gives version: {context['version']}"
|
| 236 |
+
)
|
| 237 |
+
self.do_cmd(
|
| 238 |
+
f"python -c 'import {context['package_name']}; print("
|
| 239 |
+
f"{context['package_name']}.__version__)'"
|
| 240 |
+
)
|
| 241 |
+
|
| 242 |
+
|
| 243 |
+
class GitTagRelease(Step):
|
| 244 |
+
"""Git tag release."""
|
| 245 |
+
|
| 246 |
+
def action(self, context):
|
| 247 |
+
"""Carry out action."""
|
| 248 |
+
self.instruct("Tag version as a release")
|
| 249 |
+
self.do_cmd(f"git tag v{context['version']}")
|
| 250 |
+
|
| 251 |
+
|
| 252 |
+
class GitTagPreRelease(Step):
|
| 253 |
+
"""Git tag prerelease."""
|
| 254 |
+
|
| 255 |
+
def action(self, context):
|
| 256 |
+
"""Carry out action."""
|
| 257 |
+
self.instruct("Tag version as a pre-release (increment as needed)")
|
| 258 |
+
self.print_run(f"git tag v{context['version']}-rc.1")
|
| 259 |
+
|
| 260 |
+
|
| 261 |
+
class PushToGitHub(Step):
|
| 262 |
+
"""Push to GitHub."""
|
| 263 |
+
|
| 264 |
+
def action(self, context):
|
| 265 |
+
"""Carry out action."""
|
| 266 |
+
self.instruct("Add and commit to git, then push to GitHub")
|
| 267 |
+
|
| 268 |
+
|
| 269 |
+
class CheckCIStatus(Step):
|
| 270 |
+
"""Check CI status."""
|
| 271 |
+
|
| 272 |
+
def action(self, context):
|
| 273 |
+
"""Carry out action."""
|
| 274 |
+
self.instruct("Wait for CI to complete and check status")
|
| 275 |
+
|
| 276 |
+
|
| 277 |
+
class CheckOnlineDocs(Step):
|
| 278 |
+
"""Check online docs."""
|
| 279 |
+
|
| 280 |
+
def action(self, context):
|
| 281 |
+
"""Carry out action."""
|
| 282 |
+
self.instruct("Check online docs")
|
| 283 |
+
open_website(URLs.DOCS_ONLINE)
|
| 284 |
+
|
| 285 |
+
|
| 286 |
+
class CheckLocalDocs(Step):
|
| 287 |
+
"""Check local docs."""
|
| 288 |
+
|
| 289 |
+
def action(self, context):
|
| 290 |
+
"""Carry out action."""
|
| 291 |
+
self.instruct("Check local docs")
|
| 292 |
+
open_website(URLs.DOCS_LOCAL)
|
| 293 |
+
|
| 294 |
+
|
| 295 |
+
class CheckPyPIFiles(Step):
|
| 296 |
+
"""Check pypi files."""
|
| 297 |
+
|
| 298 |
+
def action(self, context):
|
| 299 |
+
"""Carry out action."""
|
| 300 |
+
self.instruct("Check PyPI files")
|
| 301 |
+
open_website(URLs.PYPI)
|
| 302 |
+
|
| 303 |
+
|
| 304 |
+
class PushTagToGitHub(Step):
|
| 305 |
+
"""Push tag to GitHub."""
|
| 306 |
+
|
| 307 |
+
def action(self, context):
|
| 308 |
+
"""Carry out action."""
|
| 309 |
+
self.do_cmd(f"git push origin v{context['version']}")
|
| 310 |
+
|
| 311 |
+
|
| 312 |
+
def main():
|
| 313 |
+
"""Run release, main script."""
|
| 314 |
+
colorama.init()
|
| 315 |
+
steps = [
|
| 316 |
+
# prepare and run final checks
|
| 317 |
+
ConfirmGitStatus(branch="main"),
|
| 318 |
+
MakeClean(),
|
| 319 |
+
UpdateVersion(),
|
| 320 |
+
CheckVersionNumber(),
|
| 321 |
+
UpdateReadme(),
|
| 322 |
+
UpdateChangelog(),
|
| 323 |
+
MakeDocs(),
|
| 324 |
+
CheckLocalDocs(),
|
| 325 |
+
MakeDist(),
|
| 326 |
+
UploadToTestPyPI(),
|
| 327 |
+
InstallFromTestPyPI(),
|
| 328 |
+
PushToGitHub(),
|
| 329 |
+
CheckCIStatus(),
|
| 330 |
+
# check pre-release online
|
| 331 |
+
# GitTagPreRelease(),
|
| 332 |
+
# PushTagToGitHub(),
|
| 333 |
+
# make release
|
| 334 |
+
GitTagRelease(),
|
| 335 |
+
PushTagToGitHub(),
|
| 336 |
+
CheckCIStatus(),
|
| 337 |
+
CheckOnlineDocs(),
|
| 338 |
+
CheckPyPIFiles(),
|
| 339 |
+
]
|
| 340 |
+
context = dict()
|
| 341 |
+
context["package_name"] = PACKAGE_NAME
|
| 342 |
+
context["version"] = find_version(context["package_name"], "__init__.py")
|
| 343 |
+
context["testdir"] = "temp/"
|
| 344 |
+
for step in steps:
|
| 345 |
+
step.run(context)
|
| 346 |
+
cprint("\nDone!", color="yellow", style="bright")
|
| 347 |
+
|
| 348 |
+
|
| 349 |
+
if __name__ == "__main__":
|
| 350 |
+
main()
|
sktime/source/build_tools/nb_json_formatter.py
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Notebook formatter.
|
| 2 |
+
|
| 3 |
+
Formats jupyter notebooks as follows:
|
| 4 |
+
|
| 5 |
+
* changes execution count to consecutive numbers, starting with 1
|
| 6 |
+
* sets json indent to 1 space
|
| 7 |
+
* adds a newline at the end, if not present
|
| 8 |
+
|
| 9 |
+
Does not change cell content or output.
|
| 10 |
+
"""
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
def format_nb_json(notebook_path, indent=1):
|
| 14 |
+
"""Format a jupyter notebook.
|
| 15 |
+
|
| 16 |
+
Changes notebook at ``notebook_path`` in place, as follows:
|
| 17 |
+
|
| 18 |
+
Formats jupyter notebooks as follows:
|
| 19 |
+
|
| 20 |
+
* changes execution count to consecutive numbers, starting with 1
|
| 21 |
+
* sets json indent to 1 space
|
| 22 |
+
* adds a newline at the end, if not present
|
| 23 |
+
|
| 24 |
+
Does not change cell content or output.
|
| 25 |
+
|
| 26 |
+
Parameters
|
| 27 |
+
----------
|
| 28 |
+
notebook_path : str
|
| 29 |
+
Path to the notebook file. Accessed via ``open``.
|
| 30 |
+
indent: int, optional, default=1
|
| 31 |
+
Indentation to use for json output. Used in ``json.dump``.
|
| 32 |
+
"""
|
| 33 |
+
import json
|
| 34 |
+
|
| 35 |
+
# Read the notebook
|
| 36 |
+
with open(notebook_path, encoding="utf-8") as f:
|
| 37 |
+
notebook = json.load(f)
|
| 38 |
+
|
| 39 |
+
# Update execution counts
|
| 40 |
+
execution_count = 1
|
| 41 |
+
for cell in notebook["cells"]:
|
| 42 |
+
if cell["cell_type"] == "code":
|
| 43 |
+
cell["execution_count"] = execution_count
|
| 44 |
+
execution_count += 1
|
| 45 |
+
for output in cell.get("outputs", []):
|
| 46 |
+
if "execution_count" in output:
|
| 47 |
+
output["execution_count"] = cell["execution_count"]
|
| 48 |
+
|
| 49 |
+
# Write the updated notebook back
|
| 50 |
+
with open(notebook_path, "w", encoding="utf-8") as f:
|
| 51 |
+
json.dump(notebook, f, indent=indent, ensure_ascii=False)
|
| 52 |
+
f.write("\n") # Add a newline at the end of the file
|
sktime/source/build_tools/run_blogposts.sh
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/bin/bash
|
| 2 |
+
|
| 3 |
+
# Script to run all blog post notebooks.
|
| 4 |
+
set -euxo pipefail
|
| 5 |
+
|
| 6 |
+
CMD="jupyter nbconvert --to notebook --inplace --execute --ExecutePreprocessor.timeout=600"
|
| 7 |
+
|
| 8 |
+
for notebook in examples/blog_posts/*.ipynb; do
|
| 9 |
+
echo "Running: $notebook"
|
| 10 |
+
$CMD "$notebook"
|
| 11 |
+
done
|
sktime/source/build_tools/run_examples.sh
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/bin/bash
|
| 2 |
+
|
| 3 |
+
# Script to run all example notebooks.
|
| 4 |
+
set -euxo pipefail
|
| 5 |
+
|
| 6 |
+
CMD="jupyter nbconvert --to notebook --inplace --execute --ExecutePreprocessor.timeout=600"
|
| 7 |
+
|
| 8 |
+
for notebook in examples/*.ipynb; do
|
| 9 |
+
echo "Running: $notebook"
|
| 10 |
+
$CMD "$notebook"
|
| 11 |
+
done
|
sktime/source/conftest.py
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Main configuration file for pytest.
|
| 2 |
+
|
| 3 |
+
Contents:
|
| 4 |
+
adds the following options to pytest
|
| 5 |
+
--matrixdesign : bool, default False
|
| 6 |
+
allows to turn on/off the sub-sampling in the tests (for shorter runtime)
|
| 7 |
+
"on" condition is partition/block design to ensure each estimator full tests are run
|
| 8 |
+
on each operating system at least once, and on each python version at least once,
|
| 9 |
+
but not necessarily on each operating system / python version combination
|
| 10 |
+
--only_changed_modules : bool, default False
|
| 11 |
+
turns on/off differential testing (for shorter runtime)
|
| 12 |
+
"on" condition ensures that only estimators are tested that have changed,
|
| 13 |
+
more precisely, only estimators whose class is in a module
|
| 14 |
+
that has changed compared to the main branch
|
| 15 |
+
"off" = runs tests for all estimators
|
| 16 |
+
|
| 17 |
+
by default, all options are off, including for default local runs of pytest
|
| 18 |
+
if multiple options are turned on, they are combined with AND,
|
| 19 |
+
i.e., intersection of estimators satisfying the conditions
|
| 20 |
+
"""
|
| 21 |
+
|
| 22 |
+
# copyright: sktime developers, BSD-3-Clause License (see LICENSE file)
|
| 23 |
+
|
| 24 |
+
__author__ = ["fkiraly"]
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
def pytest_addoption(parser):
|
| 28 |
+
"""Pytest command line parser options adder."""
|
| 29 |
+
parser.addoption(
|
| 30 |
+
"--matrixdesign",
|
| 31 |
+
default=False,
|
| 32 |
+
help="sub-sample estimators in tests by os/version matrix partition design",
|
| 33 |
+
)
|
| 34 |
+
parser.addoption(
|
| 35 |
+
"--only_changed_modules",
|
| 36 |
+
default=False,
|
| 37 |
+
help="test only estimators from modules that have changed compared to main",
|
| 38 |
+
)
|
| 39 |
+
|
| 40 |
+
|
| 41 |
+
def pytest_configure(config):
|
| 42 |
+
"""Pytest configuration preamble."""
|
| 43 |
+
from sktime.tests import _config
|
| 44 |
+
|
| 45 |
+
if config.getoption("--matrixdesign") in [True, "True"]:
|
| 46 |
+
_config.MATRIXDESIGN = True
|
| 47 |
+
if config.getoption("--only_changed_modules") in [True, "True"]:
|
| 48 |
+
_config.ONLY_CHANGED_MODULES = True
|