Initial commit: Lunar calendar converter project
- Add lunar calendar astronomical calculation engine (lunar_calendar.py) - Add converter utilities for solar/lunar date conversion - Add historical era name conversions (chrono_converter.py, converter_with_eras.py) - Add FastAPI REST API for date conversion services - Add age calculator using lunar calendar - Add batch generation script for lunar calendar JSON data - Add project documentation (CLAUDE.md, pyproject.toml) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
26
.gitignore
vendored
Normal file
26
.gitignore
vendored
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
# Local editor/credentials files
|
||||||
|
.vscode/sftp.json
|
||||||
|
|
||||||
|
# Python caches
|
||||||
|
__pycache__/
|
||||||
|
*.pyc
|
||||||
|
.pytest_cache/
|
||||||
|
.ruff_cache/
|
||||||
|
.mypy_cache/
|
||||||
|
|
||||||
|
# Build outputs
|
||||||
|
build/
|
||||||
|
dist/
|
||||||
|
|
||||||
|
# Virtual environment
|
||||||
|
.venv/
|
||||||
|
venv/
|
||||||
|
|
||||||
|
# Generated lunar calendar data
|
||||||
|
lunar_json/
|
||||||
|
|
||||||
|
# JPL ephemeris files (large binary files, download separately)
|
||||||
|
*.bsp
|
||||||
|
|
||||||
|
# tar archives
|
||||||
|
*.tar.gz
|
||||||
7
.tarignore
Normal file
7
.tarignore
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
__pycache__
|
||||||
|
.pytest_cache
|
||||||
|
.git
|
||||||
|
.venv
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
|
uv.lock
|
||||||
10
.vscode/extensions.json
vendored
Normal file
10
.vscode/extensions.json
vendored
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
// 推薦安裝的擴充(可於側邊欄 Extensions 接受建議安裝)
|
||||||
|
"recommendations": [
|
||||||
|
"charliermarsh.ruff",
|
||||||
|
"ms-python.python",
|
||||||
|
"ms-python.vscode-pylance",
|
||||||
|
"ms-toolsai.jupyter",
|
||||||
|
"Natizyskunk.sftp"
|
||||||
|
]
|
||||||
|
}
|
||||||
94
.vscode/settings.json
vendored
Normal file
94
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
{
|
||||||
|
// ——— 工作區 VS Code 設定 ———
|
||||||
|
// 需安裝擴充(建議):
|
||||||
|
// 1) charliermarsh.ruff → Python 格式化 + 匯入排序 + Lint/修復
|
||||||
|
// 2) ms-python.python → Python 語言支援、測試、偵錯、終端環境
|
||||||
|
// 3) ms-python.vscode-pylance → 型別分析/智慧提示(使用 Pylance)
|
||||||
|
// 4) ms-toolsai.jupyter →(可選)Notebook 支援
|
||||||
|
// 也可直接接受工作區推薦(.vscode/extensions.json)
|
||||||
|
|
||||||
|
// 檔案總管把雜物藏起來,乾淨一點
|
||||||
|
"files.exclude": {
|
||||||
|
"**/.git": true,
|
||||||
|
"**/.svn": true,
|
||||||
|
"**/.hg": true,
|
||||||
|
"**/CVS": true,
|
||||||
|
"**/__pycache__": true,
|
||||||
|
"**/.DS_Store": true
|
||||||
|
},
|
||||||
|
|
||||||
|
// 不愛被一直彈參數提示,關掉就清爽
|
||||||
|
"editor.parameterHints.enabled": false,
|
||||||
|
|
||||||
|
// 字型&連字:看起來順眼一點
|
||||||
|
"editor.fontFamily": "JetBrainsMono Nerd Font Mono",
|
||||||
|
"editor.fontLigatures": true,
|
||||||
|
|
||||||
|
// 介面縮放:0 就是原尺寸,自己再調
|
||||||
|
"window.zoomLevel": 0,
|
||||||
|
|
||||||
|
// 存檔只格式化實際修改的區塊(減少整檔 diff)
|
||||||
|
"editor.formatOnSaveMode": "modificationsIfAvailable",
|
||||||
|
|
||||||
|
// 若未安裝 Code Runner,避免未知設定警告:先移除相關設定
|
||||||
|
|
||||||
|
// 版面微調:全域用空白縮排,預設 2 格;換行一律 LF
|
||||||
|
"editor.insertSpaces": true,
|
||||||
|
"editor.tabSize": 2,
|
||||||
|
"files.eol": "\n",
|
||||||
|
"files.trimTrailingWhitespace": true,
|
||||||
|
"files.insertFinalNewline": true,
|
||||||
|
// 專案行寬 100 欄(與 Ruff 設定一致)
|
||||||
|
"editor.rulers": [100],
|
||||||
|
|
||||||
|
// 使用 Ruff:Lint + 匯入排序 + 格式化(見 ruff.toml)
|
||||||
|
|
||||||
|
// Python 語言專屬設定
|
||||||
|
"[python]": {
|
||||||
|
// 以 Ruff 當預設格式器
|
||||||
|
"editor.defaultFormatter": "charliermarsh.ruff",
|
||||||
|
// 存檔:格式化 + 自動修復 + 匯入排序
|
||||||
|
"editor.formatOnSave": true,
|
||||||
|
// 交給 Ruff 做自動修復與匯入排序(避免與 isort 重疊)
|
||||||
|
"editor.codeActionsOnSave": {
|
||||||
|
"source.fixAll.ruff": "explicit",
|
||||||
|
"source.organizeImports.ruff": "explicit"
|
||||||
|
},
|
||||||
|
// Python 習慣 4 空白縮排
|
||||||
|
"editor.tabSize": 4
|
||||||
|
},
|
||||||
|
|
||||||
|
// Pylance/分析:全專案診斷(型別等級改由 pyrightconfig.json 管理)
|
||||||
|
"python.analysis.diagnosticMode": "workspace",
|
||||||
|
"python.terminal.activateEnvironment": true,
|
||||||
|
// 指定預設的工作區 Interpreter(本機虛擬環境)
|
||||||
|
"python.defaultInterpreterPath": "${workspaceFolder}/.venv/bin/python",
|
||||||
|
// 若需調整 Pylance 型別檢查或診斷嚴重度,請至 pyrightconfig.json
|
||||||
|
|
||||||
|
// 測試(若使用 pytest):VS Code 直接偵測測試並執行
|
||||||
|
"python.testing.pytestEnabled": true,
|
||||||
|
"python.testing.unittestEnabled": false,
|
||||||
|
"python.testing.pytestArgs": ["tests"],
|
||||||
|
|
||||||
|
// 搜尋/監控忽略更多常見產物與虛擬環境
|
||||||
|
"search.exclude": {
|
||||||
|
"**/node_modules": true,
|
||||||
|
"**/bower_components": true,
|
||||||
|
"**/.venv": true,
|
||||||
|
"**/venv": true,
|
||||||
|
"**/.tox": true,
|
||||||
|
"**/.mypy_cache": true,
|
||||||
|
"**/.pytest_cache": true,
|
||||||
|
"**/.ruff_cache": true,
|
||||||
|
"**/dist": true,
|
||||||
|
"**/build": true
|
||||||
|
},
|
||||||
|
"search.useIgnoreFiles": true,
|
||||||
|
"files.watcherExclude": {
|
||||||
|
"**/node_modules/**": true,
|
||||||
|
"**/.venv/**": true,
|
||||||
|
"**/venv/**": true,
|
||||||
|
"**/.tox/**": true,
|
||||||
|
"**/.git/**": true
|
||||||
|
}
|
||||||
|
}
|
||||||
57
.vscode/sftp.example.jsonc
vendored
Normal file
57
.vscode/sftp.example.jsonc
vendored
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
{
|
||||||
|
// 提示:將本檔複製為 .vscode/sftp.json(純 JSON,勿含註解)後再編輯。
|
||||||
|
|
||||||
|
// 顯示用名稱(任意字串)
|
||||||
|
"name": "My Server",
|
||||||
|
|
||||||
|
// 伺服器位址(IP 或 ~/.ssh/config 的 Host 別名)
|
||||||
|
"host": "192.168.42.108",
|
||||||
|
|
||||||
|
// 傳輸協定:sftp(SSH 上的檔案傳輸)
|
||||||
|
"protocol": "sftp",
|
||||||
|
|
||||||
|
// SSH 連線埠,預設 22
|
||||||
|
"port": 22,
|
||||||
|
|
||||||
|
// 登入使用者(例:root)
|
||||||
|
"username": "root",
|
||||||
|
|
||||||
|
// ——— 擇一方式(請只保留其中一種)———
|
||||||
|
// A) 使用系統環境中的 ssh-agent(SSH_AUTH_SOCK)
|
||||||
|
// "agent": "env",
|
||||||
|
// B) 直接指定私鑰路徑(例如 ECDSA)
|
||||||
|
"privateKeyPath": "~/.ssh/id_ecdsa",
|
||||||
|
// 若金鑰有通關詞,請移除此欄並讓 agent 代為解鎖
|
||||||
|
// "passphrase": "不建議填在設定檔",
|
||||||
|
// 參考本機 SSH 設定(可選)
|
||||||
|
"sshConfigPath": "~/.ssh/config",
|
||||||
|
// 不回退互動式密碼驗證
|
||||||
|
"interactiveAuth": false,
|
||||||
|
|
||||||
|
// ——— 可選:改用 OpenSSH 設定 ——
|
||||||
|
// 若想完全沿用 ~/.ssh/config 與 multiplex,可改為:
|
||||||
|
// "openSsh": true, 並刪除上方 agent/privateKeyPath 等欄位
|
||||||
|
|
||||||
|
// 遠端根目錄(所有上下載相對於此路徑)
|
||||||
|
"remotePath": "/opt/lunar-converter",
|
||||||
|
|
||||||
|
// 存檔即自動上傳:true 開啟;若不想每次存檔都上傳,改為 false
|
||||||
|
"uploadOnSave": true,
|
||||||
|
|
||||||
|
// 上傳時先用暫存檔再改名:false 直接覆寫;若遠端需要原子寫入可設 true
|
||||||
|
"useTempFile": false,
|
||||||
|
|
||||||
|
// 忽略不需上傳的檔案/資料夾
|
||||||
|
"ignore": [
|
||||||
|
"**/.git/**",
|
||||||
|
"**/.DS_Store",
|
||||||
|
"**/node_modules/**",
|
||||||
|
"**/.venv/**",
|
||||||
|
"**/venv/**",
|
||||||
|
"**/.mypy_cache/**",
|
||||||
|
"**/.pytest_cache/**",
|
||||||
|
"**/.ruff_cache/**",
|
||||||
|
"**/dist/**",
|
||||||
|
"**/build/**"
|
||||||
|
]
|
||||||
|
}
|
||||||
112
CLAUDE.md
Normal file
112
CLAUDE.md
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
# CLAUDE.md
|
||||||
|
|
||||||
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||||
|
|
||||||
|
## Project Overview
|
||||||
|
|
||||||
|
This is a lunar calendar converter (lunar-converter) that provides:
|
||||||
|
- Western (Gregorian) calendar ↔ Chinese lunar calendar conversion
|
||||||
|
- Historical era name conversions (Ming/Qing dynasties, Taiping Heavenly Kingdom, Japanese eras, Republic of China era)
|
||||||
|
- Age calculation (real age and East Asian nominal age)
|
||||||
|
- REST API for date conversion services
|
||||||
|
|
||||||
|
## Core Architecture
|
||||||
|
|
||||||
|
### Data Generation Pipeline
|
||||||
|
|
||||||
|
1. **`lunar_calendar.py`** - Astronomical calculation engine using Skyfield
|
||||||
|
- Computes lunar calendar data from first principles using JPL ephemeris
|
||||||
|
- Uses `de421.bsp` / `de422.bsp` / `de440s.bsp` ephemeris files (must exist in working directory)
|
||||||
|
- Calculates new moons, solar terms (24 jieqi), and determines leap months
|
||||||
|
- Generates ganzhi (sexagenary cycle) and zodiac animals
|
||||||
|
- Output: yearly JSON files with complete lunar calendar mapping
|
||||||
|
|
||||||
|
2. **`generate_lunar_calendar_json.py`** - Batch generation script
|
||||||
|
- Generates JSON files for multiple years in parallel using multiprocessing
|
||||||
|
- Outputs to `lunar_json/{year}.json` directory
|
||||||
|
- Usage: `python generate_lunar_calendar_json.py`
|
||||||
|
|
||||||
|
### Conversion Layer
|
||||||
|
|
||||||
|
3. **`converter.py`** - Primary conversion class using JSON data
|
||||||
|
- `Converter.solar_to_lunar(date_str)` - Convert "YYYY-MM-DD" to lunar date info
|
||||||
|
- `Converter.lunar_to_solar(year, month, day, leap=False)` - Reverse conversion
|
||||||
|
- `Converter.get_leap_month(year)` - Return leap month number or None
|
||||||
|
- Depends on `lunar_json/` directory containing pre-generated JSON files
|
||||||
|
|
||||||
|
### Historical Era Conversion
|
||||||
|
|
||||||
|
4. **`chrono_converter.py`** - Historical era name conversions
|
||||||
|
- Converts Western dates to era names (Ming/Qing dynasties, Taiping, Minguo)
|
||||||
|
- Contains era date ranges as class constants
|
||||||
|
|
||||||
|
5. **`converter_with_eras.py`** - Combined converter (CLI tool)
|
||||||
|
- Merges lunar conversion with era name conversion
|
||||||
|
- CLI usage: `python converter_with_eras.py solar2lunar YYYY-MM-DD`
|
||||||
|
- CLI usage: `python converter_with_eras.py lunar2solar YYYY-MM-DD [--leap]`
|
||||||
|
- CLI usage: `python converter_with_eras.py era YYYY-MM-DD`
|
||||||
|
|
||||||
|
### Applications
|
||||||
|
|
||||||
|
6. **`api.py`** - FastAPI REST API server
|
||||||
|
- `GET /solar2lunar?date=YYYY-MM-DD` - Solar to lunar conversion
|
||||||
|
- `GET /lunar2solar?date=YYYY-MM-DD` - Lunar to solar (handles leap months)
|
||||||
|
- `GET /leap-info?year=YYYY` - Leap month info for a year
|
||||||
|
- Runs on a dynamically-assigned free port
|
||||||
|
|
||||||
|
7. **`age_calculator.py`** - Age calculator using lunar calendar
|
||||||
|
- Calculates "real age" (足歲) and "East Asian age" (虛歲)
|
||||||
|
- Uses dependency injection pattern with `Converter`
|
||||||
|
- Accurately handles leap month birthdays
|
||||||
|
|
||||||
|
## Common Commands
|
||||||
|
|
||||||
|
### Generate lunar calendar data (required before conversions work)
|
||||||
|
```bash
|
||||||
|
# Generate all years (1-2149, parallel processing)
|
||||||
|
python generate_lunar_calendar_json.py
|
||||||
|
|
||||||
|
# Generate single year
|
||||||
|
python lunar_calendar.py 2025
|
||||||
|
```
|
||||||
|
|
||||||
|
### Run conversions
|
||||||
|
```bash
|
||||||
|
# Solar to lunar
|
||||||
|
python -c "from converter import Converter; print(Converter().solar_to_lunar('2025-01-01'))"
|
||||||
|
|
||||||
|
# Lunar to solar
|
||||||
|
python -c "from converter import Converter; print(Converter().lunar_to_solar(2025, 1, 1))"
|
||||||
|
|
||||||
|
# Era conversion
|
||||||
|
python converter_with_eras.py era 1900-01-01
|
||||||
|
```
|
||||||
|
|
||||||
|
### Run API server
|
||||||
|
```bash
|
||||||
|
python api.py
|
||||||
|
```
|
||||||
|
|
||||||
|
### Run tests
|
||||||
|
```bash
|
||||||
|
pytest
|
||||||
|
```
|
||||||
|
|
||||||
|
## Important Notes
|
||||||
|
|
||||||
|
- **Ephemeris files**: The JPL ephemeris files (`de421.bsp`, `de422.bsp`, or `de440s.bsp`) are required for astronomical calculations. These must be present in the working directory. `lunar_calendar.py:92` selects which ephemeris to use.
|
||||||
|
|
||||||
|
- **Data dependency**: `converter.py` and dependent modules require pre-generated JSON files in `lunar_json/` directory. Generate these first using `generate_lunar_calendar_json.py` or `lunar_calendar.py`.
|
||||||
|
|
||||||
|
- **Calendar systems**: The code handles multiple calendar systems:
|
||||||
|
- Gregorian (Western) calendar
|
||||||
|
- Chinese lunar calendar (with leap months)
|
||||||
|
- Historical era names (Chinese dynasties, Japanese eras)
|
||||||
|
- Republic of China (Minguo) calendar
|
||||||
|
|
||||||
|
- **Timezone**: All calculations use UTC+8 (Taipei timezone) as defined in `LunarCalendar.TZ_OFFSET`.
|
||||||
|
|
||||||
|
- **Date ranges**:
|
||||||
|
- Chinese eras defined in `converter_with_eras.py:15-31` (CHINESE_ERAS_SOLAR)
|
||||||
|
- Japanese eras defined in `converter_with_eras.py:91-98` (JAPANESE_ERAS)
|
||||||
|
- Taiping Heavenly Kingdom: 1851-02-01 to 1872-07-05
|
||||||
123
Lunar_Calendar_Converter_README
Normal file
123
Lunar_Calendar_Converter_README
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
Lunar Calendar Converter 農曆轉換工具
|
||||||
|
|
||||||
|
一套使用 Python 3.13+ 與 Skyfield 天文資料庫實作的農曆轉換工具,支援西曆↔農曆、閏月查詢,並提供 CLI 與 API(FastAPI)。
|
||||||
|
|
||||||
|
需求
|
||||||
|
|
||||||
|
- Python >= 3.13(可用 uv 安裝)
|
||||||
|
- 套件:
|
||||||
|
- skyfield
|
||||||
|
- jplephem
|
||||||
|
- numpy
|
||||||
|
- fastapi、uvicorn(僅在使用 API 時)
|
||||||
|
- Skyfield 天文資料檔(本庫已附):
|
||||||
|
- de422.bsp(程式目前預設使用)
|
||||||
|
- de440s.bsp、de421.bsp(可替代)
|
||||||
|
|
||||||
|
安裝與環境(使用 uv)
|
||||||
|
|
||||||
|
初始化與安裝依賴(如已存在可略過 init)
|
||||||
|
uv init lunar-converter
|
||||||
|
cd lunar-converter
|
||||||
|
uv add skyfield jplephem numpy flask
|
||||||
|
uv lock
|
||||||
|
uv sync
|
||||||
|
|
||||||
|
uv 會自動建立 .venv/ 虛擬環境,無需手動啟動。
|
||||||
|
|
||||||
|
專案結構(重點檔案)
|
||||||
|
|
||||||
|
.
|
||||||
|
├── converter.py # 西曆↔農曆轉換核心與閏月查詢(供程式/API 使用)
|
||||||
|
├── converter_with_eras.py # 指令列工具:solar2lunar / lunar2solar / era
|
||||||
|
├── api.py # FastAPI 服務
|
||||||
|
├── generate_lunar_calendar_json.py # 批次產生 JSON(可自訂年份範圍)
|
||||||
|
├── lunar_calendar.py # 天文計算與 JSON 產生
|
||||||
|
├── lunar_json/ # 每年一檔的農曆 JSON(執行產生器後)
|
||||||
|
|
||||||
|
產生農曆資料(JSON)
|
||||||
|
|
||||||
|
預設腳本為 `generate_lunar_calendar_json.py`,內含可調整的年份範圍。
|
||||||
|
|
||||||
|
uv run python generate_lunar_calendar_json.py
|
||||||
|
|
||||||
|
會輸出到 `lunar_json/`,例如:`lunar_json/2025.json`。
|
||||||
|
|
||||||
|
若只想產生 1900–2100,可修改腳本內的 years 範圍:
|
||||||
|
|
||||||
|
# generate_lunar_calendar_json.py
|
||||||
|
# years = range(1900, 2101)
|
||||||
|
|
||||||
|
指令列(CLI)使用
|
||||||
|
|
||||||
|
CLI 功能位於 `converter_with_eras.py`:
|
||||||
|
|
||||||
|
uv run python converter_with_eras.py solar2lunar 2025-10-12
|
||||||
|
uv run python converter_with_eras.py lunar2solar 1977-08-30 --leap # 閏月請加上 --leap
|
||||||
|
uv run python converter_with_eras.py era 1906-02-07 # 歷代年號 / 日本元號查詢
|
||||||
|
|
||||||
|
範例輸出(solar2lunar)
|
||||||
|
|
||||||
|
{
|
||||||
|
"西曆": "2025-10-12",
|
||||||
|
"農曆": "8月21日",
|
||||||
|
"干支": "乙巳",
|
||||||
|
"生肖": "蛇",
|
||||||
|
"節氣": ""
|
||||||
|
}
|
||||||
|
|
||||||
|
啟用 API(FastAPI)
|
||||||
|
|
||||||
|
uv run python api.py
|
||||||
|
|
||||||
|
程式會自動尋找可用埠(預設從 5000 開始)。可瀏覽 `/docs` 或 `/redoc` 查看互動式文件。
|
||||||
|
或直接用 Uvicorn 啟動:
|
||||||
|
|
||||||
|
uv run uvicorn api:app --host 0.0.0.0 --port 5000
|
||||||
|
|
||||||
|
API 範例
|
||||||
|
|
||||||
|
# 查詢一個存在的日期
|
||||||
|
curl "http://127.0.0.1:5001/solar2lunar?date=2025-10-06" | jq
|
||||||
|
|
||||||
|
# 不提供 date 參數
|
||||||
|
curl "http://127.0.0.1:5001/solar2lunar" | jq
|
||||||
|
|
||||||
|
# 查詢一個沒有閏月的日期
|
||||||
|
curl "http://127.0.0.1:5001/lunar2solar?date=1977-08-30" | jq
|
||||||
|
|
||||||
|
# 查詢一個有閏月的日期
|
||||||
|
curl "http://127.0.0.1:5001/lunar2solar?date=1976-08-25" | jq
|
||||||
|
|
||||||
|
# 查詢一個不存在的日期(會得到 404)
|
||||||
|
curl -i "http://127.0.0.1:5001/lunar2solar?date=2025-08-30"
|
||||||
|
|
||||||
|
# 查詢 2023 年(該年有閏二月)
|
||||||
|
curl "http://127.0.0.1:5001/leap-info?year=2023" | jq
|
||||||
|
|
||||||
|
# 查詢 1977 年
|
||||||
|
curl "http://127.0.0.1:5001/leap-info?year=1977" | jq
|
||||||
|
|
||||||
|
# 提供一個非數字的年份
|
||||||
|
curl "http://127.0.0.1:5001/leap-info?year=abc" | jq
|
||||||
|
|
||||||
|
備註
|
||||||
|
|
||||||
|
- 干支與生肖依據「農曆年」切換。
|
||||||
|
- 使用 Skyfield 計算節氣與朔望月,精度高於傳統對照表。
|
||||||
|
- 目前 `lunar_calendar.py` 預設載入 `de422.bsp`。欲改用 `de440s.bsp` 或 `de421.bsp`,請修改:
|
||||||
|
self.eph = load('de422.bsp')
|
||||||
|
- 若缺少某年 JSON 檔,查詢會提示錯誤,請先執行產生器產生對應年份。
|
||||||
|
|
||||||
|
作者
|
||||||
|
|
||||||
|
由 Timmy(羅楊竣)開發。
|
||||||
|
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
開發小工具(直接使用 uv 指令)
|
||||||
|
|
||||||
|
- `uv run --group dev black .`:使用 Black 格式化專案
|
||||||
|
- `uv run --group dev ruff format .`:使用 Ruff 內建 formatter 格式化
|
||||||
|
- `uv run --group dev ruff check .`:Ruff 檢查
|
||||||
|
- `uv run --group dev ruff check --fix .`:Ruff 自動修正
|
||||||
99
age_calculator.py
Normal file
99
age_calculator.py
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
# age_calculator.py
|
||||||
|
import datetime
|
||||||
|
from collections import namedtuple
|
||||||
|
from loguru import logger # type: ignore[reportMissingImports]
|
||||||
|
|
||||||
|
# 從 converter.py 這個檔案,匯入 Converter 這個 class
|
||||||
|
from converter import Converter
|
||||||
|
|
||||||
|
# --- 類型定義 ---
|
||||||
|
AgeResult = namedtuple("AgeResult", ["real_age", "east_asian_age"])
|
||||||
|
|
||||||
|
# ======================================================================
|
||||||
|
# 主要類別:AgeCalculator
|
||||||
|
# ======================================================================
|
||||||
|
class AgeCalculator:
|
||||||
|
"""
|
||||||
|
提供精準的年齡計算功能 (實歲與虛歲)。
|
||||||
|
初始化時需要傳入一個 Converter 物件。
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, converter: Converter):
|
||||||
|
"""
|
||||||
|
初始化年齡計算機。
|
||||||
|
這個設計模式稱為「依賴注入 (Dependency Injection)」,
|
||||||
|
AgeCalculator 本身不建立 Converter,而是由外部提供,讓架構更靈活。
|
||||||
|
|
||||||
|
:param converter: 一個 Converter 的實體物件。
|
||||||
|
"""
|
||||||
|
if not isinstance(converter, Converter):
|
||||||
|
raise TypeError("初始化 AgeCalculator 時,必須提供一個有效的 Converter 物件")
|
||||||
|
self.converter = converter
|
||||||
|
|
||||||
|
def calculate(
|
||||||
|
self,
|
||||||
|
solar_birth_date: datetime.date,
|
||||||
|
lunar_birth_info: dict,
|
||||||
|
today: datetime.date
|
||||||
|
) -> AgeResult:
|
||||||
|
"""
|
||||||
|
根據生日資訊,使用農曆轉換器精準計算實歲和虛歲。
|
||||||
|
"""
|
||||||
|
# 虛歲計算 (邏輯不變)
|
||||||
|
east_asian_age = today.year - solar_birth_date.year + 1
|
||||||
|
|
||||||
|
# 實歲計算 (使用 self.converter)
|
||||||
|
try:
|
||||||
|
# 用 converter 找出「今年的農曆生日」對應的西曆日期
|
||||||
|
this_year_lunar_bday_solar_str = self.converter.lunar_to_solar(
|
||||||
|
lunar_year=today.year,
|
||||||
|
lunar_month=lunar_birth_info['month'],
|
||||||
|
lunar_day=lunar_birth_info['day'],
|
||||||
|
leap=lunar_birth_info['leap']
|
||||||
|
)
|
||||||
|
this_year_lunar_bday_date = datetime.datetime.strptime(this_year_lunar_bday_solar_str, '%Y-%m-%d').date()
|
||||||
|
except KeyError:
|
||||||
|
# Edge case: 若今年沒有該農曆日期(如閏月),則認定生日已過,讓邏輯更強健
|
||||||
|
this_year_lunar_bday_date = today - datetime.timedelta(days=1)
|
||||||
|
|
||||||
|
real_age = today.year - solar_birth_date.year
|
||||||
|
# 核心判斷:如果今天還沒到「今年的農曆生日(的西曆日期)」,那實歲就 -1
|
||||||
|
if today < this_year_lunar_bday_date:
|
||||||
|
real_age -= 1
|
||||||
|
|
||||||
|
return AgeResult(real_age=real_age, east_asian_age=east_asian_age)
|
||||||
|
|
||||||
|
|
||||||
|
# ======================================================================
|
||||||
|
# 主程式區塊:作為使用範例
|
||||||
|
# ======================================================================
|
||||||
|
if __name__ == "__main__":
|
||||||
|
# --- 作為範例的資料 ---
|
||||||
|
TODAY_OVERRIDE = datetime.date(2025, 7, 30)
|
||||||
|
SOLAR_BIRTH_DATE_STR = "1977-10-12"
|
||||||
|
LUNAR_BIRTH_INFO = {"month": 8, "day": 30, "leap": False}
|
||||||
|
|
||||||
|
try:
|
||||||
|
# --- 步驟 1: 建立依賴物件 (工具人) ---
|
||||||
|
converter = Converter()
|
||||||
|
|
||||||
|
# --- 步驟 2: 建立主物件,並注入依賴 (主角登場,並把工具人交給他) ---
|
||||||
|
age_calculator = AgeCalculator(converter=converter)
|
||||||
|
|
||||||
|
# --- 步驟 3: 執行計算 (叫主角開始幹活) ---
|
||||||
|
solar_birth_date = datetime.datetime.strptime(SOLAR_BIRTH_DATE_STR, "%Y-%m-%d").date()
|
||||||
|
age_result = age_calculator.calculate(
|
||||||
|
solar_birth_date=solar_birth_date,
|
||||||
|
lunar_birth_info=LUNAR_BIRTH_INFO,
|
||||||
|
today=TODAY_OVERRIDE,
|
||||||
|
)
|
||||||
|
|
||||||
|
# --- 步驟 4: 使用 loguru 輸出結果 ---
|
||||||
|
logger.remove()
|
||||||
|
logger.add(lambda msg: print(msg, end=""), format="{message}")
|
||||||
|
|
||||||
|
logger.info(f"實歲 (足歲):{age_result.real_age} 歲。")
|
||||||
|
logger.info(f"虛歲:{age_result.east_asian_age} 歲。")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"執行時發生錯誤: {e}")
|
||||||
110
api.py
Normal file
110
api.py
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# 提供農曆-西曆轉換的 API 服務(FastAPI 版本)
|
||||||
|
# 依賴: fastapi, uvicorn, converter.py
|
||||||
|
|
||||||
|
# /// script
|
||||||
|
# requires-python = ">=3.12"
|
||||||
|
# dependencies = [
|
||||||
|
# "fastapi",
|
||||||
|
# "uvicorn",
|
||||||
|
# ]
|
||||||
|
# ///
|
||||||
|
|
||||||
|
import socket
|
||||||
|
from contextlib import closing
|
||||||
|
from typing import Any, Dict, List
|
||||||
|
|
||||||
|
from fastapi import FastAPI, Query # type: ignore[reportMissingImports]
|
||||||
|
from fastapi.responses import JSONResponse # type: ignore[reportMissingImports]
|
||||||
|
import uvicorn # type: ignore[reportMissingImports]
|
||||||
|
|
||||||
|
from converter import Converter
|
||||||
|
|
||||||
|
|
||||||
|
def find_free_port() -> int:
|
||||||
|
"""使用臨時 socket 綁定到 0 取得可用埠號"""
|
||||||
|
with closing(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as s:
|
||||||
|
s.bind(("", 0))
|
||||||
|
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||||
|
return s.getsockname()[1]
|
||||||
|
|
||||||
|
|
||||||
|
app = FastAPI(title="Lunar Calendar Converter API")
|
||||||
|
conv = Converter()
|
||||||
|
|
||||||
|
|
||||||
|
@app.get("/solar2lunar")
|
||||||
|
def solar2lunar_endpoint(date: str = Query(None, description="YYYY-MM-DD")):
|
||||||
|
"""西曆轉農曆"""
|
||||||
|
if not date:
|
||||||
|
return JSONResponse({"error": "缺少參數 date,格式 YYYY-MM-DD"}, status_code=400)
|
||||||
|
try:
|
||||||
|
info_raw = conv.solar_to_lunar(date)
|
||||||
|
info = {
|
||||||
|
"gregorian": info_raw.get("西曆"),
|
||||||
|
"lunar": info_raw.get("農曆"),
|
||||||
|
"ganzhi": info_raw.get("干支"),
|
||||||
|
"zodiac": info_raw.get("生肖"),
|
||||||
|
"solar_term": info_raw.get("節氣"),
|
||||||
|
}
|
||||||
|
return info
|
||||||
|
except Exception as e:
|
||||||
|
return JSONResponse({"error": str(e)}, status_code=400)
|
||||||
|
|
||||||
|
|
||||||
|
@app.get("/lunar2solar")
|
||||||
|
def lunar2solar_endpoint(date: str = Query(None, description="YYYY-MM-DD")):
|
||||||
|
"""農曆轉西曆(自動處理閏月,回傳所有可能性)"""
|
||||||
|
if not date:
|
||||||
|
return JSONResponse({"error": "缺少參數 date,格式 YYYY-MM-DD"}, status_code=400)
|
||||||
|
|
||||||
|
try:
|
||||||
|
y_str, m_str, d_str = date.split("-", 2)
|
||||||
|
y, m, d = int(y_str), int(m_str), int(d_str)
|
||||||
|
except Exception:
|
||||||
|
return JSONResponse({"error": "農曆日期格式應為 YYYY-MM-DD"}, status_code=400)
|
||||||
|
|
||||||
|
possible_solar_dates: List[str] = conv.lunar_to_solar_all(y, m, d)
|
||||||
|
if not possible_solar_dates:
|
||||||
|
error_msg = f"找不到任何對應農曆 {y}年{m}月{d}日 的西曆日期"
|
||||||
|
return JSONResponse({"error": error_msg}, status_code=404)
|
||||||
|
|
||||||
|
results_list: List[Dict[str, Any]] = []
|
||||||
|
for solar_date in possible_solar_dates:
|
||||||
|
try:
|
||||||
|
info_raw = conv.solar_to_lunar(solar_date)
|
||||||
|
results_list.append({
|
||||||
|
"gregorian": info_raw.get("西曆"),
|
||||||
|
"lunar": info_raw.get("農曆"),
|
||||||
|
"ganzhi": info_raw.get("干支"),
|
||||||
|
"zodiac": info_raw.get("生肖"),
|
||||||
|
"solar_term": info_raw.get("節氣"),
|
||||||
|
})
|
||||||
|
except Exception:
|
||||||
|
continue
|
||||||
|
|
||||||
|
return results_list
|
||||||
|
|
||||||
|
|
||||||
|
@app.get("/leap-info")
|
||||||
|
def leap_info_endpoint(year: str = Query(None, description="西曆年份,數字")):
|
||||||
|
"""查詢指定西曆年份是否有農曆閏月,以及是閏幾月。"""
|
||||||
|
if not year:
|
||||||
|
return JSONResponse({"error": "缺少參數 year"}, status_code=400)
|
||||||
|
try:
|
||||||
|
y = int(year)
|
||||||
|
leap_month = conv.get_leap_month(y)
|
||||||
|
return {"year": y, "leap_month": leap_month}
|
||||||
|
except ValueError:
|
||||||
|
return JSONResponse({"error": "參數 year 必須是有效的整數"}, status_code=400)
|
||||||
|
except Exception as e:
|
||||||
|
return JSONResponse({"error": str(e)}, status_code=500)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
try:
|
||||||
|
free_port = find_free_port()
|
||||||
|
print(f"找到一個可用的 port: {free_port}")
|
||||||
|
uvicorn.run(app, host="0.0.0.0", port=free_port, reload=False)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"啟動服務失敗: {e}")
|
||||||
213
chrono_converter.py
Normal file
213
chrono_converter.py
Normal file
@@ -0,0 +1,213 @@
|
|||||||
|
from datetime import date
|
||||||
|
|
||||||
|
class ChronoConverter:
|
||||||
|
# 太平天國
|
||||||
|
TP_START = (1851, 2, 1)
|
||||||
|
TP_END = (1872, 7, 5)
|
||||||
|
|
||||||
|
# 清朝年號區間(含康熙到宣統)
|
||||||
|
KX_START = date(1662, 2, 18)
|
||||||
|
KX_END = date(1723, 2, 4)
|
||||||
|
|
||||||
|
YZ_START = date(1723, 2, 5)
|
||||||
|
YZ_END = date(1736, 2, 11)
|
||||||
|
|
||||||
|
QL_START = date(1736, 2, 12)
|
||||||
|
QL_END = date(1796, 2, 8)
|
||||||
|
|
||||||
|
JQ_START = date(1796, 2, 9)
|
||||||
|
JQ_END = date(1821, 2, 2)
|
||||||
|
|
||||||
|
DG_START = date(1821, 2, 3)
|
||||||
|
DG_END = date(1851, 1, 31)
|
||||||
|
|
||||||
|
XF_START = date(1851, 2, 1)
|
||||||
|
XF_END = date(1862, 1, 29)
|
||||||
|
|
||||||
|
TZ_START = date(1862, 1, 30)
|
||||||
|
TZ_END = date(1875, 2, 5)
|
||||||
|
|
||||||
|
GX_START = date(1875, 2, 6)
|
||||||
|
GX_END = date(1909, 1, 21)
|
||||||
|
|
||||||
|
XT_START = date(1909, 1, 22)
|
||||||
|
XT_END = date(1912, 2, 17)
|
||||||
|
|
||||||
|
# 清太祖天命 & 順治
|
||||||
|
TN_START = date(1616, 2, 17)
|
||||||
|
TN_END = date(1627, 2, 15)
|
||||||
|
|
||||||
|
SZ_START = date(1644, 2, 8)
|
||||||
|
SZ_END = date(1662, 2, 17)
|
||||||
|
|
||||||
|
# 明朝年號
|
||||||
|
WL_START = date(1573, 1, 30)
|
||||||
|
WL_END = date(1620, 8, 18)
|
||||||
|
|
||||||
|
TQ_START = date(1620, 8, 19)
|
||||||
|
TQ_END = date(1627, 9, 29)
|
||||||
|
|
||||||
|
CZ_START = date(1628, 2, 5)
|
||||||
|
CZ_END = date(1644, 4, 25)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def to_minguo(year: int) -> str:
|
||||||
|
if year < 1912:
|
||||||
|
return f"西元 {year} 年,尚未進入民國"
|
||||||
|
return f"民國 {year - 1911} 年"
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def to_ad_from_minguo(minguo_year: int) -> str:
|
||||||
|
if minguo_year <= 0:
|
||||||
|
return "民國元年從西元 1912 年開始,不能為 0 或負數"
|
||||||
|
return f"西元 {minguo_year + 1911} 年"
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def to_taiping(cls, year: int, month: int = 1, day: int = 1) -> str:
|
||||||
|
if (year, month, day) < cls.TP_START:
|
||||||
|
return f"西元 {year} 年 {month} 月 {day} 日尚未進入太平天國年間"
|
||||||
|
elif (year, month, day) > cls.TP_END:
|
||||||
|
return f"西元 {year} 年 {month} 月 {day} 日已超過太平天國年間"
|
||||||
|
else:
|
||||||
|
tp_year = year - 1850
|
||||||
|
return f"太平天國 {tp_year} 年"
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def to_ad_from_taiping(tp_year: int) -> str:
|
||||||
|
if 1 <= tp_year <= 22:
|
||||||
|
return f"西元 {tp_year + 1850} 年(約太平天國 {tp_year} 年)"
|
||||||
|
else:
|
||||||
|
return f"太平天國 {tp_year} 年超出有效範圍(1~22)"
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def to_tianming(cls, y: int, m: int = 1, d: int = 1) -> str:
|
||||||
|
try:
|
||||||
|
input_date = date(y, m, d)
|
||||||
|
except ValueError:
|
||||||
|
return "無效的日期"
|
||||||
|
|
||||||
|
if input_date < cls.TN_START:
|
||||||
|
return f"西元 {y} 年 {m} 月 {d} 日尚未進入天命年間"
|
||||||
|
elif input_date > cls.TN_END:
|
||||||
|
return f"西元 {y} 年 {m} 月 {d} 日已超過天命年間"
|
||||||
|
else:
|
||||||
|
return f"清太祖天命 {y - 1615} 年"
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def to_ad_from_tianming(tn_year: int) -> str:
|
||||||
|
if 1 <= tn_year <= 12:
|
||||||
|
return f"西元 {tn_year + 1615} 年(約天命 {tn_year} 年)"
|
||||||
|
else:
|
||||||
|
return "天命年間僅有 1~12 年"
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def to_shunzhi(cls, y: int, m: int = 1, d: int = 1) -> str:
|
||||||
|
try:
|
||||||
|
input_date = date(y, m, d)
|
||||||
|
except ValueError:
|
||||||
|
return "無效的日期"
|
||||||
|
|
||||||
|
if input_date < cls.SZ_START:
|
||||||
|
return f"西元 {y} 年 {m} 月 {d} 日尚未進入順治年間"
|
||||||
|
elif input_date > cls.SZ_END:
|
||||||
|
return f"西元 {y} 年 {m} 月 {d} 日已超過順治年間"
|
||||||
|
else:
|
||||||
|
return f"清世祖順治 {y - 1643} 年"
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def to_ad_from_shunzhi(sz_year: int) -> str:
|
||||||
|
if 1 <= sz_year <= 18:
|
||||||
|
return f"西元 {sz_year + 1643} 年(約順治 {sz_year} 年)"
|
||||||
|
else:
|
||||||
|
return "順治年間僅有 1~18 年"
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def to_qing_dynasty(cls, y: int, m: int = 1, d: int = 1) -> str:
|
||||||
|
try:
|
||||||
|
input_date = date(y, m, d)
|
||||||
|
except ValueError:
|
||||||
|
return "無效的日期"
|
||||||
|
|
||||||
|
ranges = [
|
||||||
|
(cls.KX_START, cls.KX_END, 1661, "清聖祖康熙", 1),
|
||||||
|
(cls.YZ_START, cls.YZ_END, 1722, "清世宗雍正", 1),
|
||||||
|
(cls.QL_START, cls.QL_END, 1735, "清高宗乾隆", 1),
|
||||||
|
(cls.JQ_START, cls.JQ_END, 1795, "清仁宗嘉慶", 1),
|
||||||
|
(cls.DG_START, cls.DG_END, 1820, "清宣宗道光", 1),
|
||||||
|
(cls.XF_START, cls.XF_END, 1850, "清文宗咸豐", 1),
|
||||||
|
(cls.TZ_START, cls.TZ_END, 1861, "清穆宗同治", 1),
|
||||||
|
(cls.GX_START, cls.GX_END, 1874, "清德宗光緒", 1),
|
||||||
|
(cls.XT_START, cls.XT_END, 1908, "清遜帝宣統", 1),
|
||||||
|
]
|
||||||
|
|
||||||
|
for start, end, base_year, label, base_era in ranges:
|
||||||
|
if start <= input_date <= end:
|
||||||
|
return f"{label} {y - base_year + base_era} 年"
|
||||||
|
|
||||||
|
return f"西元 {y} 年 {m} 月 {d} 日不在清代指定年號範圍內"
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def to_ming_dynasty(cls, y: int, m: int = 1, d: int = 1) -> str:
|
||||||
|
try:
|
||||||
|
input_date = date(y, m, d)
|
||||||
|
except ValueError:
|
||||||
|
return "無效的日期"
|
||||||
|
|
||||||
|
ranges = [
|
||||||
|
(cls.WL_START, cls.WL_END, 1572, "明神宗萬曆", 1),
|
||||||
|
(cls.TQ_START, cls.TQ_END, 1619, "明熹宗天啟", 1),
|
||||||
|
(cls.CZ_START, cls.CZ_END, 1627, "明思宗崇禎", 1),
|
||||||
|
]
|
||||||
|
|
||||||
|
for start, end, base_year, label, base_era in ranges:
|
||||||
|
if start <= input_date <= end:
|
||||||
|
return f"{label} {y - base_year + base_era} 年"
|
||||||
|
|
||||||
|
return f"西元 {y} 年 {m} 月 {d} 日不在明代指定年號範圍內"
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def weekday_str(y: int, m: int, d: int) -> str:
|
||||||
|
try:
|
||||||
|
dt = date(y, m, d)
|
||||||
|
return dt.strftime("%A")
|
||||||
|
except ValueError:
|
||||||
|
return "無效日期"
|
||||||
|
|
||||||
|
|
||||||
|
# 檢查當前程式是否被作為主程式執行
|
||||||
|
if __name__ == "__main__":
|
||||||
|
|
||||||
|
|
||||||
|
def convert_date(y: int, m: int, d: int) -> dict:
|
||||||
|
cc = ChronoConverter()
|
||||||
|
raw = {
|
||||||
|
"民國": cc.to_minguo(y),
|
||||||
|
"太平天國": cc.to_taiping(y, m, d),
|
||||||
|
"清太祖天命": cc.to_tianming(y, m, d),
|
||||||
|
"清世祖順治": cc.to_shunzhi(y, m, d),
|
||||||
|
"清朝其他年號": cc.to_qing_dynasty(y, m, d),
|
||||||
|
"明朝晚期年號": cc.to_ming_dynasty(y, m, d),
|
||||||
|
"星期": cc.weekday_str(y, m, d),
|
||||||
|
}
|
||||||
|
|
||||||
|
# 過濾掉無效的年號資訊
|
||||||
|
filtered = {
|
||||||
|
k: v for k, v in raw.items()
|
||||||
|
if not (
|
||||||
|
"尚未進入" in v or
|
||||||
|
"已超過" in v or
|
||||||
|
"不在" in v or
|
||||||
|
"無效" in v
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return filtered
|
||||||
|
|
||||||
|
|
||||||
|
# result = convert_date(1851, 2, 1)
|
||||||
|
# result = convert_date(1977, 10, 12)
|
||||||
|
result = convert_date(1906, 2, 7)
|
||||||
|
# result = convert_date(1967, 10, 17)
|
||||||
|
print(result)
|
||||||
|
for key, val in result.items():
|
||||||
|
print(f"{key}:{val}")
|
||||||
107
converter.py
Normal file
107
converter.py
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
# converter.py
|
||||||
|
import os
|
||||||
|
import json
|
||||||
|
from datetime import datetime
|
||||||
|
from typing import List, Optional
|
||||||
|
|
||||||
|
class Converter:
|
||||||
|
"""
|
||||||
|
提供西曆與農曆互轉功能,並能判斷特定年份的閏月。
|
||||||
|
"""
|
||||||
|
LUNAR_JSON_DIR = 'lunar_json'
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
"""初始化時,建立一個空的快取來存放已查詢過的年份閏月資訊。"""
|
||||||
|
self._leap_month_cache = {}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def load_solar_to_lunar(cls, year: int) -> dict:
|
||||||
|
"""這是一個類別方法,用來載入指定年份的資料檔。"""
|
||||||
|
path = os.path.join(cls.LUNAR_JSON_DIR, f"{year}.json")
|
||||||
|
if not os.path.exists(path):
|
||||||
|
raise FileNotFoundError(f"找不到農曆資料檔: {path}")
|
||||||
|
with open(path, encoding='utf-8') as f:
|
||||||
|
return json.load(f)
|
||||||
|
|
||||||
|
def solar_to_lunar(self, solar_date_str: str) -> dict:
|
||||||
|
try:
|
||||||
|
dt = datetime.strptime(solar_date_str, '%Y-%m-%d').date()
|
||||||
|
except ValueError:
|
||||||
|
raise ValueError("西曆日期格式應為 YYYY-MM-DD")
|
||||||
|
# 【修正點】從 self. 呼叫改為 Converter. 呼叫
|
||||||
|
data = Converter.load_solar_to_lunar(dt.year)
|
||||||
|
if solar_date_str not in data:
|
||||||
|
raise KeyError(f"沒有找到對應 {solar_date_str} 的農曆資料")
|
||||||
|
return data[solar_date_str]
|
||||||
|
|
||||||
|
def lunar_to_solar(self, lunar_year: int, lunar_month: int, lunar_day: int, leap: bool=False) -> str:
|
||||||
|
years_to_check = {lunar_year, lunar_year + 1}
|
||||||
|
for year in sorted(list(years_to_check)):
|
||||||
|
try:
|
||||||
|
# 【修正點】從 self. 呼叫改為 Converter. 呼叫
|
||||||
|
data = Converter.load_solar_to_lunar(year)
|
||||||
|
for solar_date, info in data.items():
|
||||||
|
lstr = info.get('農曆', '')
|
||||||
|
is_leap = lstr.startswith('閏')
|
||||||
|
core = lstr[1:] if is_leap else lstr
|
||||||
|
if not all(c in core for c in ['月', '日']): continue
|
||||||
|
m_str, d_str = core.replace('月','-').replace('日','').split('-')
|
||||||
|
if int(m_str) == lunar_month and int(d_str) == lunar_day and is_leap == leap:
|
||||||
|
return info.get("西曆")
|
||||||
|
except FileNotFoundError:
|
||||||
|
continue
|
||||||
|
raise KeyError(f"找不到對應農曆 {lunar_year}{'閏' if leap else ''}{lunar_month}月{lunar_day}日 的西曆")
|
||||||
|
|
||||||
|
def lunar_to_solar_all(self, lunar_year: int, lunar_month: int, lunar_day: int) -> List[str]:
|
||||||
|
results = []
|
||||||
|
try:
|
||||||
|
solar_date = self.lunar_to_solar(lunar_year, lunar_month, lunar_day, leap=False)
|
||||||
|
results.append(solar_date)
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
try:
|
||||||
|
solar_date = self.lunar_to_solar(lunar_year, lunar_month, lunar_day, leap=True)
|
||||||
|
results.append(solar_date)
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
return results
|
||||||
|
|
||||||
|
def get_leap_month(self, year: int) -> Optional[int]:
|
||||||
|
if year in self._leap_month_cache:
|
||||||
|
return self._leap_month_cache[year]
|
||||||
|
try:
|
||||||
|
# 【修正點】從 self. 呼叫改為 Converter. 呼叫
|
||||||
|
data = Converter.load_solar_to_lunar(year)
|
||||||
|
for info in data.values():
|
||||||
|
lstr = info.get('農曆', '')
|
||||||
|
if lstr.startswith('閏'):
|
||||||
|
core = lstr[1:]
|
||||||
|
if '月' in core:
|
||||||
|
month_str = core.split('月')[0]
|
||||||
|
leap_month = int(month_str)
|
||||||
|
self._leap_month_cache[year] = leap_month
|
||||||
|
return leap_month
|
||||||
|
self._leap_month_cache[year] = None
|
||||||
|
return None
|
||||||
|
except FileNotFoundError:
|
||||||
|
self._leap_month_cache[year] = None
|
||||||
|
return None
|
||||||
|
|
||||||
|
# ... (main 函式不變) ...
|
||||||
|
def main():
|
||||||
|
"""展示 Converter 的新功能:查詢閏月"""
|
||||||
|
print("=== Converter 閏月判斷功能展示 ===")
|
||||||
|
try:
|
||||||
|
converter = Converter()
|
||||||
|
years_to_test = [1976, 1977, 2023, 2024, 2025]
|
||||||
|
for year in years_to_test:
|
||||||
|
leap_month = converter.get_leap_month(year)
|
||||||
|
if leap_month:
|
||||||
|
print(f"西曆 {year} 年,有閏月,是閏 {leap_month} 月。")
|
||||||
|
else:
|
||||||
|
print(f"西曆 {year} 年,沒有閏月。")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"\n發生錯誤: {e}")
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
174
converter_with_eras.py
Normal file
174
converter_with_eras.py
Normal file
@@ -0,0 +1,174 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# converter_with_eras.py
|
||||||
|
#
|
||||||
|
# 結合「西曆↔農曆轉換」與「歷代年號 ↔ 西曆」功能
|
||||||
|
# 支援:太平天國、民國、中國明清諸年號(農曆基準)、日本各元號(西曆基準)
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import json
|
||||||
|
import argparse
|
||||||
|
from datetime import datetime, date
|
||||||
|
from typing import Dict
|
||||||
|
|
||||||
|
# 中國明清年號對應的西曆範圍及基準年 (起始日, 結束日, 基年)
|
||||||
|
CHINESE_ERAS_SOLAR = {
|
||||||
|
# 明朝
|
||||||
|
"萬曆": (date(1573, 1, 1), date(1620, 12, 31), 1572),
|
||||||
|
"天啟": (date(1621, 1, 1), date(1627, 12, 31), 1620),
|
||||||
|
"崇禎": (date(1628, 1, 1), date(1644, 4, 25), 1627), # 崇禎最後一天 1644-04-25
|
||||||
|
# 清朝
|
||||||
|
"順治": (date(1644, 2, 8), date(1662, 2, 17), 1643), # 順治 1年 1644-02-08 至 1662-02-17
|
||||||
|
"康熙": (date(1662, 2, 18), date(1723, 2, 8), 1661), # 康熙 1年 1662-02-18 至 1723-02-08
|
||||||
|
"雍正": (date(1723, 2, 9), date(1736, 1, 28), 1722), # 雍正 1年 1723-02-09 至 1736-01-28
|
||||||
|
"乾隆": (date(1736, 1, 29), date(1796, 2, 17), 1735), # 乾隆 1年 1736-01-29 至 1796-02-17
|
||||||
|
"嘉慶": (date(1796, 2, 18), date(1821, 2, 6), 1795), # 嘉慶 1年 1796-02-18 至 1821-02-06
|
||||||
|
"道光": (date(1821, 2, 7), date(1851, 1, 27), 1820), # 道光 1年 1821-02-07 至 1851-01-27
|
||||||
|
"咸豐": (date(1851, 1, 28), date(1862, 1, 16), 1850), # 咸豐 1年 1851-01-28 至 1862-01-16
|
||||||
|
"同治": (date(1862, 1, 17), date(1875, 2, 5), 1861), # 同治 1年 1862-01-17 至 1875-02-05
|
||||||
|
"光緒": (date(1875, 2, 6), date(1909, 1, 22), 1874), # 光緒 1年 1875-02-06 至 1909-01-22
|
||||||
|
"宣統": (date(1909, 1, 23), date(1912, 2, 18), 1908), # 宣統 1年 1909-01-23 至 1912-02-18
|
||||||
|
}
|
||||||
|
|
||||||
|
class Converter:
|
||||||
|
"""
|
||||||
|
提供西曆與農曆互轉功能:
|
||||||
|
- solar_to_lunar(date_str: str) -> dict
|
||||||
|
- lunar_to_solar(year: int, month: int, day: int, leap: bool=False) -> str
|
||||||
|
"""
|
||||||
|
LUNAR_JSON_DIR = 'lunar_json'
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def load_solar_to_lunar(cls, year: int) -> Dict:
|
||||||
|
path = os.path.join(cls.LUNAR_JSON_DIR, f"{year}.json")
|
||||||
|
if not os.path.exists(path):
|
||||||
|
raise FileNotFoundError(f"找不到 {path}")
|
||||||
|
with open(path, encoding='utf-8') as f:
|
||||||
|
return json.load(f)
|
||||||
|
|
||||||
|
def solar_to_lunar(self, solar_date_str: str) -> Dict:
|
||||||
|
# 允許輸入 "YYYY-M-D",並自動標準化為 ISO 格式 "YYYY-MM-DD"
|
||||||
|
parts = solar_date_str.split('-')
|
||||||
|
if len(parts) != 3:
|
||||||
|
raise ValueError(f"日期格式錯誤,請使用 YYYY-MM-DD 或類似格式:{solar_date_str}")
|
||||||
|
y, m, d = map(int, parts)
|
||||||
|
dt = date(y, m, d)
|
||||||
|
key = dt.isoformat()
|
||||||
|
try:
|
||||||
|
data = self.load_solar_to_lunar(dt.year)
|
||||||
|
except FileNotFoundError:
|
||||||
|
raise FileNotFoundError(f"無法取得 {dt.year} 年的農曆資料,請先生成對應的 lunar_json/{dt.year}.json 檔案")
|
||||||
|
if key not in data:
|
||||||
|
raise KeyError(f"沒有找到對應 {key} 的農曆資料")
|
||||||
|
return data[key]
|
||||||
|
|
||||||
|
def lunar_to_solar(self, lunar_year: int, lunar_month: int, lunar_day: int, leap: bool=False) -> str:
|
||||||
|
solar_year = lunar_year + 1 if lunar_month in (11, 12) else lunar_year
|
||||||
|
data = self.load_solar_to_lunar(solar_year)
|
||||||
|
# 精確匹配
|
||||||
|
for solar, info in data.items():
|
||||||
|
lstr = info.get('農曆','')
|
||||||
|
is_leap = lstr.startswith('閏')
|
||||||
|
core = lstr[1:] if is_leap else lstr
|
||||||
|
m_str, d_str = core.replace('月','-').replace('日','').split('-')
|
||||||
|
if int(m_str)==lunar_month and int(d_str)==lunar_day and is_leap==leap:
|
||||||
|
return solar
|
||||||
|
# 回退匹配非閏月
|
||||||
|
for solar, info in data.items():
|
||||||
|
lstr = info.get('農曆','')
|
||||||
|
is_leap = lstr.startswith('閏')
|
||||||
|
core = lstr[1:] if is_leap else lstr
|
||||||
|
m_str, d_str = core.replace('月','-').replace('日','').split('-')
|
||||||
|
if int(m_str)==lunar_month and int(d_str)==lunar_day and not is_leap:
|
||||||
|
return solar
|
||||||
|
raise KeyError(f"找不到對應農曆 {lunar_year}{'閏' if leap else ''}{lunar_month}月{lunar_day}日 的西曆")
|
||||||
|
|
||||||
|
class ChronoConverter:
|
||||||
|
"""
|
||||||
|
統一各種紀年 ↔ 西曆 的轉換
|
||||||
|
"""
|
||||||
|
# 日本元號對應的西曆範圍及基準年 (起始日, 結束日, 基年)
|
||||||
|
JAPANESE_ERAS = {
|
||||||
|
"慶應": (date(1865,3,18), date(1868,10,22), 1864),
|
||||||
|
"明治": (date(1868,10,23), date(1912,7,30), 1867),
|
||||||
|
"大正": (date(1912,7,30), date(1926,12,24), 1911),
|
||||||
|
"昭和": (date(1926,12,25), date(1989,1,7), 1925),
|
||||||
|
"平成": (date(1989,1,8), date(2019,4,30), 1988),
|
||||||
|
"令和": (date(2019,5,1), None, 2018),
|
||||||
|
}
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _lunar_year(y: int, m: int, d: int) -> int:
|
||||||
|
conv = Converter()
|
||||||
|
dt = date(y, m, d)
|
||||||
|
for ly in (y, y-1):
|
||||||
|
try:
|
||||||
|
start = conv.lunar_to_solar(ly, 1, 1)
|
||||||
|
nxt = conv.lunar_to_solar(ly+1, 1, 1)
|
||||||
|
except Exception:
|
||||||
|
continue
|
||||||
|
d0, d1 = date.fromisoformat(start), date.fromisoformat(nxt)
|
||||||
|
if d0 <= dt < d1:
|
||||||
|
return ly
|
||||||
|
return y
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def to_era(cls, y: int, m: int, d: int) -> Dict:
|
||||||
|
dt = date(y, m, d)
|
||||||
|
ly = cls._lunar_year(y, m, d)
|
||||||
|
res: Dict[str, str] = {}
|
||||||
|
|
||||||
|
if date(1851,2,1) <= dt <= date(1872,7,5):
|
||||||
|
res["太平天國"] = f"太平天國 {y-1850} 年"
|
||||||
|
if y >= 1912:
|
||||||
|
res["民國"] = f"民國 {y-1911} 年"
|
||||||
|
for era, (st, ed, base) in CHINESE_ERAS_SOLAR.items():
|
||||||
|
if st <= dt <= ed:
|
||||||
|
res[era] = f"{era} {dt.year - base} 年"
|
||||||
|
for era, (st, ed, base) in cls.JAPANESE_ERAS.items():
|
||||||
|
if dt >= st and (ed is None or dt <= ed):
|
||||||
|
res[era] = f"{era} {dt.year-base} 年"
|
||||||
|
res["星期"] = dt.strftime("%A")
|
||||||
|
return res
|
||||||
|
|
||||||
|
|
||||||
|
def convert_date(y: int, m: int, d: int) -> Dict:
|
||||||
|
return ChronoConverter.to_era(y, m, d)
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = argparse.ArgumentParser(description="西曆↔農曆+歷代年號+日本元號 轉換工具")
|
||||||
|
sub = parser.add_subparsers(dest='cmd', required=True)
|
||||||
|
|
||||||
|
p1 = sub.add_parser('solar2lunar', help='西曆轉農曆')
|
||||||
|
p1.add_argument('date', help='YYYY-MM-DD 或 YYYY-M-D')
|
||||||
|
|
||||||
|
p2 = sub.add_parser('lunar2solar', help='農曆轉西曆')
|
||||||
|
p2.add_argument('date', help='YYYY-MM-DD')
|
||||||
|
p2.add_argument('--leap', action='store_true', help='閏月')
|
||||||
|
|
||||||
|
p3 = sub.add_parser('era', help='西曆轉歷代年號+日本元號')
|
||||||
|
p3.add_argument('date', help='YYYY-MM-DD')
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
if args.cmd == 'solar2lunar':
|
||||||
|
try:
|
||||||
|
result = Converter().solar_to_lunar(args.date)
|
||||||
|
print(json.dumps(result, ensure_ascii=False, indent=2))
|
||||||
|
except (FileNotFoundError, KeyError, ValueError) as e:
|
||||||
|
print(e)
|
||||||
|
sys.exit(1)
|
||||||
|
elif args.cmd == 'lunar2solar':
|
||||||
|
try:
|
||||||
|
y, m, d = map(int, args.date.split('-',2))
|
||||||
|
solar = Converter().lunar_to_solar(y, m, d, args.leap)
|
||||||
|
print(json.dumps(Converter().solar_to_lunar(solar), ensure_ascii=False, indent=2))
|
||||||
|
except Exception as e:
|
||||||
|
print(e)
|
||||||
|
sys.exit(1)
|
||||||
|
elif args.cmd == 'era':
|
||||||
|
y, m, d = map(int, args.date.split('-',2))
|
||||||
|
print(json.dumps(convert_date(y, m, d), ensure_ascii=False, indent=2))
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
29
generate_lunar_calendar_json.py
Normal file
29
generate_lunar_calendar_json.py
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
import os
|
||||||
|
from multiprocessing import Pool
|
||||||
|
from pathlib import Path
|
||||||
|
from lunar_calendar import LunarCalendar
|
||||||
|
|
||||||
|
def process_year(year, output_dir):
|
||||||
|
try:
|
||||||
|
cal = LunarCalendar(year)
|
||||||
|
out_file = output_dir / f"{year}.json"
|
||||||
|
# 如果不想覆寫,再加個 exists() 檢查
|
||||||
|
if not out_file.exists():
|
||||||
|
cal.save_json(str(out_file))
|
||||||
|
print(f"完成,已輸出:{out_file}")
|
||||||
|
else:
|
||||||
|
print(f"跳過,檔案已存在:{out_file}")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"處理 {year} 時出錯:{e}")
|
||||||
|
|
||||||
|
def main():
|
||||||
|
output_dir = Path('lunar_json')
|
||||||
|
output_dir.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
|
# years = range(1851, 2149)
|
||||||
|
years = range(1, 2149)
|
||||||
|
with Pool() as pool:
|
||||||
|
pool.starmap(process_year, [(y, output_dir) for y in years])
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
225
lunar_calendar.py
Normal file
225
lunar_calendar.py
Normal file
@@ -0,0 +1,225 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# /// script
|
||||||
|
# requires-python = ">=3.13"
|
||||||
|
# dependencies = [
|
||||||
|
# "skyfield",
|
||||||
|
# "jplephem",
|
||||||
|
# "numpy",
|
||||||
|
# ]
|
||||||
|
# ///
|
||||||
|
|
||||||
|
import json
|
||||||
|
from datetime import date, timedelta
|
||||||
|
from typing import Any, cast
|
||||||
|
|
||||||
|
from skyfield.almanac import find_discrete, moon_phases
|
||||||
|
from skyfield.api import load
|
||||||
|
from skyfield.framelib import ecliptic_frame
|
||||||
|
|
||||||
|
|
||||||
|
class LunarCalendar:
|
||||||
|
"""利用 Skyfield 計算農曆、干支、生肖、節氣並輸出 JSON。"""
|
||||||
|
|
||||||
|
TZ_OFFSET = timedelta(hours=8) # 台北時區
|
||||||
|
|
||||||
|
HEAVENLY_STEMS = ["甲", "乙", "丙", "丁", "戊", "己", "庚", "辛", "壬", "癸"]
|
||||||
|
EARTHLY_BRANCHES = [
|
||||||
|
"子",
|
||||||
|
"丑",
|
||||||
|
"寅",
|
||||||
|
"卯",
|
||||||
|
"辰",
|
||||||
|
"巳",
|
||||||
|
"午",
|
||||||
|
"未",
|
||||||
|
"申",
|
||||||
|
"酉",
|
||||||
|
"戌",
|
||||||
|
"亥",
|
||||||
|
]
|
||||||
|
ZODIAC = {
|
||||||
|
"子": "鼠",
|
||||||
|
"丑": "牛",
|
||||||
|
"寅": "虎",
|
||||||
|
"卯": "兔",
|
||||||
|
"辰": "龍",
|
||||||
|
"巳": "蛇",
|
||||||
|
"午": "馬",
|
||||||
|
"未": "羊",
|
||||||
|
"申": "猴",
|
||||||
|
"酉": "雞",
|
||||||
|
"戌": "狗",
|
||||||
|
"亥": "豬",
|
||||||
|
}
|
||||||
|
SOLAR_TERMS_24 = {
|
||||||
|
315: "立春",
|
||||||
|
330: "雨水",
|
||||||
|
345: "驚蟄",
|
||||||
|
0: "春分",
|
||||||
|
15: "清明",
|
||||||
|
30: "穀雨",
|
||||||
|
45: "立夏",
|
||||||
|
60: "小滿",
|
||||||
|
75: "芒種",
|
||||||
|
90: "夏至",
|
||||||
|
105: "小暑",
|
||||||
|
120: "大暑",
|
||||||
|
135: "立秋",
|
||||||
|
150: "處暑",
|
||||||
|
165: "白露",
|
||||||
|
180: "秋分",
|
||||||
|
195: "寒露",
|
||||||
|
210: "霜降",
|
||||||
|
225: "立冬",
|
||||||
|
240: "小雪",
|
||||||
|
255: "大雪",
|
||||||
|
270: "冬至",
|
||||||
|
285: "小寒",
|
||||||
|
300: "大寒",
|
||||||
|
}
|
||||||
|
|
||||||
|
def __init__(self, year: int):
|
||||||
|
self.year = year
|
||||||
|
self.ts = load.timescale()
|
||||||
|
# Ephemeris kernel options:
|
||||||
|
# - de422.bsp: default here as it is bundled in this repo.
|
||||||
|
# - de440s.bsp: newer, compact; suitable for 1900–2150 use-cases.
|
||||||
|
# - de421.bsp: older but still usable for compatibility.
|
||||||
|
# Switch by uncommenting one of the lines below and ensure the file
|
||||||
|
# exists in the working directory (or provide an absolute path).
|
||||||
|
# self.eph = load('de421.bsp')
|
||||||
|
# self.eph = load('de440s.bsp')
|
||||||
|
self.eph = load("de422.bsp")
|
||||||
|
# Pylance sometimes mis-infers types.
|
||||||
|
# Cast to Any to avoid false positives.
|
||||||
|
self.earth = cast(Any, self.eph["earth"]) # has method .at(t)
|
||||||
|
self.sun = cast(Any, self.eph["sun"]) # used with .observe()
|
||||||
|
|
||||||
|
def _compute_astronomy(self):
|
||||||
|
"""抓新朔與 24 節氣時間點"""
|
||||||
|
t0 = self.ts.utc(self.year - 1, 11, 1)
|
||||||
|
t1 = self.ts.utc(self.year + 1, 3, 1)
|
||||||
|
|
||||||
|
# 每月朔
|
||||||
|
times, phases = find_discrete(t0, t1, moon_phases(self.eph))
|
||||||
|
new_moons = [t for t, p in zip(times, phases, strict=False) if p == 0]
|
||||||
|
|
||||||
|
# 每 15° 的節氣
|
||||||
|
def term_index(t):
|
||||||
|
lat, lon, _ = (
|
||||||
|
self.earth.at(t)
|
||||||
|
.observe(self.sun)
|
||||||
|
.apparent()
|
||||||
|
.frame_latlon(ecliptic_frame)
|
||||||
|
)
|
||||||
|
return (lon.degrees // 15).astype(int)
|
||||||
|
|
||||||
|
term_index.step_days = 1
|
||||||
|
|
||||||
|
st_times, st_idxs = find_discrete(t0, t1, term_index)
|
||||||
|
zhongqi = [
|
||||||
|
(t, (idx * 15) % 360) for t, idx in zip(st_times, st_idxs, strict=False)
|
||||||
|
]
|
||||||
|
|
||||||
|
return new_moons, zhongqi
|
||||||
|
|
||||||
|
def _label_months(self, new_moons, zhongqi):
|
||||||
|
"""根據冬至、中氣規則標記每段朔月的月號與閏月屬性"""
|
||||||
|
cutoff = date(self.year, 1, 1)
|
||||||
|
sols = [
|
||||||
|
t
|
||||||
|
for t, deg in zhongqi
|
||||||
|
if deg == 270 and (t.utc_datetime() + self.TZ_OFFSET).date() < cutoff
|
||||||
|
]
|
||||||
|
solstice = max(sols)
|
||||||
|
i0 = max(
|
||||||
|
i
|
||||||
|
for i, t in enumerate(new_moons)
|
||||||
|
if t.utc_datetime() < solstice.utc_datetime()
|
||||||
|
)
|
||||||
|
|
||||||
|
labels = []
|
||||||
|
month_no = 11
|
||||||
|
leap_used = False
|
||||||
|
|
||||||
|
for j in range(i0, len(new_moons) - 1):
|
||||||
|
start, end = new_moons[j], new_moons[j + 1]
|
||||||
|
cnt = sum(1 for t, deg in zhongqi if start < t < end and deg % 30 == 0)
|
||||||
|
|
||||||
|
if j == i0:
|
||||||
|
labels.append((start, end, 11, False))
|
||||||
|
else:
|
||||||
|
if cnt == 0 and not leap_used:
|
||||||
|
labels.append((start, end, month_no, True))
|
||||||
|
leap_used = True
|
||||||
|
else:
|
||||||
|
month_no = month_no % 12 + 1
|
||||||
|
labels.append((start, end, month_no, False))
|
||||||
|
|
||||||
|
return labels
|
||||||
|
|
||||||
|
def _ganzhi_year(self, y):
|
||||||
|
"""計算指定年之干支"""
|
||||||
|
s = self.HEAVENLY_STEMS[(y - 4) % 10]
|
||||||
|
b = self.EARTHLY_BRANCHES[(y - 4) % 12]
|
||||||
|
return s + b
|
||||||
|
|
||||||
|
def build_calendar(self):
|
||||||
|
"""產生從 YYYY-01-01 至 YYYY-12-31 的完整農曆對照表"""
|
||||||
|
new_moons, zhongqi = self._compute_astronomy()
|
||||||
|
month_labels = self._label_months(new_moons, zhongqi)
|
||||||
|
|
||||||
|
# 節氣快查
|
||||||
|
solar_terms = {}
|
||||||
|
for t, deg in zhongqi:
|
||||||
|
d = (t.utc_datetime() + self.TZ_OFFSET).date().isoformat()
|
||||||
|
name = self.SOLAR_TERMS_24.get(deg)
|
||||||
|
if name:
|
||||||
|
solar_terms[d] = name
|
||||||
|
|
||||||
|
result = {}
|
||||||
|
day = date(self.year, 1, 1)
|
||||||
|
end = date(self.year, 12, 31)
|
||||||
|
|
||||||
|
while day <= end:
|
||||||
|
for ts, te, m, is_leap in month_labels:
|
||||||
|
ds = (ts.utc_datetime() + self.TZ_OFFSET).date()
|
||||||
|
de = (te.utc_datetime() + self.TZ_OFFSET).date()
|
||||||
|
if ds <= day < de:
|
||||||
|
# 農曆年:11–12 月屬上一農曆年,其它屬當年
|
||||||
|
lunar_year = self.year if 1 <= m <= 10 else self.year - 1
|
||||||
|
gz_year = self._ganzhi_year(lunar_year)
|
||||||
|
zodiac = self.ZODIAC[self.EARTHLY_BRANCHES[(lunar_year - 4) % 12]]
|
||||||
|
|
||||||
|
offset = (day - ds).days + 1
|
||||||
|
lunar_str = f"{'閏' if is_leap else ''}{m}月{offset}日"
|
||||||
|
result[day.isoformat()] = {
|
||||||
|
"西曆": day.isoformat(),
|
||||||
|
"農曆": lunar_str,
|
||||||
|
"干支": gz_year,
|
||||||
|
"生肖": zodiac,
|
||||||
|
"節氣": solar_terms.get(day.isoformat(), ""),
|
||||||
|
}
|
||||||
|
break
|
||||||
|
day += timedelta(days=1)
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
def save_json(self, filename: str | None = None):
|
||||||
|
"""將該年日曆輸出為 JSON 檔"""
|
||||||
|
data = self.build_calendar()
|
||||||
|
fname = filename or f"{self.year}.json"
|
||||||
|
with open(fname, "w", encoding="utf-8") as f:
|
||||||
|
json.dump(data, f, ensure_ascii=False, indent=2)
|
||||||
|
print(f"完成!已輸出:{fname}")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
import sys
|
||||||
|
|
||||||
|
if len(sys.argv) != 2 or not sys.argv[1].isdigit():
|
||||||
|
print("用法:python3 lunar_calendar.py <年份>")
|
||||||
|
sys.exit(1)
|
||||||
|
year = int(sys.argv[1])
|
||||||
|
cal = LunarCalendar(year)
|
||||||
|
cal.save_json()
|
||||||
16
pyproject.toml
Normal file
16
pyproject.toml
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
[project]
|
||||||
|
name = "lunar-converter"
|
||||||
|
version = "0.1.0"
|
||||||
|
requires-python = ">=3.10"
|
||||||
|
dependencies = [
|
||||||
|
"skyfield",
|
||||||
|
"jplephem",
|
||||||
|
"numpy",
|
||||||
|
"fastapi",
|
||||||
|
"uvicorn",
|
||||||
|
"loguru",
|
||||||
|
]
|
||||||
|
|
||||||
|
[tool.pytest.ini_options]
|
||||||
|
addopts = "-q"
|
||||||
|
testpaths = ["tests"]
|
||||||
14
pyrightconfig.json
Normal file
14
pyrightconfig.json
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
// Pylance/Pyright 設定:用來指定 Python 語言等級與檢查行為
|
||||||
|
// 注意:這是正確的位置,VS Code 設定中沒有 `python.analysis.pythonVersion` 此鍵
|
||||||
|
"pythonVersion": "3.11",
|
||||||
|
"typeCheckingMode": "basic",
|
||||||
|
"diagnosticSeverityOverrides": {
|
||||||
|
// 若已在 .vscode/settings.json 關閉這兩者,可移除以下兩行
|
||||||
|
"reportMissingImports": "none",
|
||||||
|
"reportMissingModuleSource": "none"
|
||||||
|
},
|
||||||
|
"executionEnvironments": [
|
||||||
|
{ "root": ".", "pythonVersion": "3.11" }
|
||||||
|
]
|
||||||
|
}
|
||||||
33
ruff.toml
Normal file
33
ruff.toml
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
line-length = 100
|
||||||
|
target-version = "py310"
|
||||||
|
|
||||||
|
# 忽略常見產物與虛擬環境資料夾
|
||||||
|
extend-exclude = [
|
||||||
|
".venv",
|
||||||
|
"venv",
|
||||||
|
".tox",
|
||||||
|
".mypy_cache",
|
||||||
|
".pytest_cache",
|
||||||
|
".ruff_cache",
|
||||||
|
"build",
|
||||||
|
"dist",
|
||||||
|
"node_modules",
|
||||||
|
]
|
||||||
|
|
||||||
|
[lint]
|
||||||
|
# 基本錯誤/風格 + 匯入排序 + pyupgrade + bugbear
|
||||||
|
select = ["E", "F", "I", "UP", "B"]
|
||||||
|
# 允許自動修復所有可修復項目(VS Code 會透過 Code Action 觸發)
|
||||||
|
fixable = ["ALL"]
|
||||||
|
|
||||||
|
[lint.isort]
|
||||||
|
# 預設與 Black 兼容的行為已良好,一般無需額外調整
|
||||||
|
|
||||||
|
[format]
|
||||||
|
# 格式器偏好(VS Code 也設定了 LF 與 ruler 88)
|
||||||
|
quote-style = "double" # 可選:"single" | "double" | "preserve"
|
||||||
|
indent-style = "space" # 可選:"space" | "tab"
|
||||||
|
line-ending = "lf" # 可選:"lf" | "cr-lf" | "auto"
|
||||||
|
# 若文件含有 docstring 內嵌程式碼,可一併格式化
|
||||||
|
docstring-code-format = true
|
||||||
|
docstring-code-line-length = 100
|
||||||
4
run_uvicorn.sh
Normal file
4
run_uvicorn.sh
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# uv run uvicorn api:app --host 0.0.0.0 --port 0
|
||||||
|
# uv run uvicorn api:app --host 0.0.0.0 --port 5001
|
||||||
|
uv run uvicorn api:app --host 0.0.0.0 --port 53511
|
||||||
524
uv.lock
generated
Normal file
524
uv.lock
generated
Normal file
@@ -0,0 +1,524 @@
|
|||||||
|
version = 1
|
||||||
|
revision = 2
|
||||||
|
requires-python = ">=3.10"
|
||||||
|
resolution-markers = [
|
||||||
|
"python_full_version >= '3.11'",
|
||||||
|
"python_full_version < '3.11'",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "annotated-types"
|
||||||
|
version = "0.7.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/ee/67/531ea369ba64dcff5ec9c3402f9f51bf748cec26dde048a2f973a4eea7f5/annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89", size = 16081, upload-time = "2024-05-20T21:33:25.928Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", size = 13643, upload-time = "2024-05-20T21:33:24.1Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anyio"
|
||||||
|
version = "4.10.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "exceptiongroup", marker = "python_full_version < '3.11'" },
|
||||||
|
{ name = "idna" },
|
||||||
|
{ name = "sniffio" },
|
||||||
|
{ name = "typing-extensions", marker = "python_full_version < '3.13'" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/f1/b4/636b3b65173d3ce9a38ef5f0522789614e590dab6a8d505340a4efe4c567/anyio-4.10.0.tar.gz", hash = "sha256:3f3fae35c96039744587aa5b8371e7e8e603c0702999535961dd336026973ba6", size = 213252, upload-time = "2025-08-04T08:54:26.451Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/6f/12/e5e0282d673bb9746bacfb6e2dba8719989d3660cdb2ea79aee9a9651afb/anyio-4.10.0-py3-none-any.whl", hash = "sha256:60e474ac86736bbfd6f210f7a61218939c318f43f9972497381f1c5e930ed3d1", size = 107213, upload-time = "2025-08-04T08:54:24.882Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "certifi"
|
||||||
|
version = "2025.8.3"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/dc/67/960ebe6bf230a96cda2e0abcf73af550ec4f090005363542f0765df162e0/certifi-2025.8.3.tar.gz", hash = "sha256:e564105f78ded564e3ae7c923924435e1daa7463faeab5bb932bc53ffae63407", size = 162386, upload-time = "2025-08-03T03:07:47.08Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/e5/48/1549795ba7742c948d2ad169c1c8cdbae65bc450d6cd753d124b17c8cd32/certifi-2025.8.3-py3-none-any.whl", hash = "sha256:f6c12493cfb1b06ba2ff328595af9350c65d6644968e5d3a2ffd78699af217a5", size = 161216, upload-time = "2025-08-03T03:07:45.777Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "click"
|
||||||
|
version = "8.2.1"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "colorama", marker = "sys_platform == 'win32'" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/60/6c/8ca2efa64cf75a977a0d7fac081354553ebe483345c734fb6b6515d96bbc/click-8.2.1.tar.gz", hash = "sha256:27c491cc05d968d271d5a1db13e3b5a184636d9d930f148c50b038f0d0646202", size = 286342, upload-time = "2025-05-20T23:19:49.832Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/85/32/10bb5764d90a8eee674e9dc6f4db6a0ab47c8c4d0d83c27f7c39ac415a4d/click-8.2.1-py3-none-any.whl", hash = "sha256:61a3265b914e850b85317d0b3109c7f8cd35a670f963866005d6ef1d5175a12b", size = 102215, upload-time = "2025-05-20T23:19:47.796Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "colorama"
|
||||||
|
version = "0.4.6"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "exceptiongroup"
|
||||||
|
version = "1.3.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "typing-extensions", marker = "python_full_version < '3.11'" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/0b/9f/a65090624ecf468cdca03533906e7c69ed7588582240cfe7cc9e770b50eb/exceptiongroup-1.3.0.tar.gz", hash = "sha256:b241f5885f560bc56a59ee63ca4c6a8bfa46ae4ad651af316d4e81817bb9fd88", size = 29749, upload-time = "2025-05-10T17:42:51.123Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/36/f4/c6e662dade71f56cd2f3735141b265c3c79293c109549c1e6933b0651ffc/exceptiongroup-1.3.0-py3-none-any.whl", hash = "sha256:4d111e6e0c13d0644cad6ddaa7ed0261a0b36971f6d23e7ec9b4b9097da78a10", size = 16674, upload-time = "2025-05-10T17:42:49.33Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fastapi"
|
||||||
|
version = "0.116.1"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "pydantic" },
|
||||||
|
{ name = "starlette" },
|
||||||
|
{ name = "typing-extensions" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/78/d7/6c8b3bfe33eeffa208183ec037fee0cce9f7f024089ab1c5d12ef04bd27c/fastapi-0.116.1.tar.gz", hash = "sha256:ed52cbf946abfd70c5a0dccb24673f0670deeb517a88b3544d03c2a6bf283143", size = 296485, upload-time = "2025-07-11T16:22:32.057Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/e5/47/d63c60f59a59467fda0f93f46335c9d18526d7071f025cb5b89d5353ea42/fastapi-0.116.1-py3-none-any.whl", hash = "sha256:c46ac7c312df840f0c9e220f7964bada936781bc4e2e6eb71f1c4d7553786565", size = 95631, upload-time = "2025-07-11T16:22:30.485Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "h11"
|
||||||
|
version = "0.16.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/01/ee/02a2c011bdab74c6fb3c75474d40b3052059d95df7e73351460c8588d963/h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1", size = 101250, upload-time = "2025-04-24T03:35:25.427Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86", size = 37515, upload-time = "2025-04-24T03:35:24.344Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "idna"
|
||||||
|
version = "3.10"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/f1/70/7703c29685631f5a7590aa73f1f1d3fa9a380e654b86af429e0934a32f7d/idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9", size = 190490, upload-time = "2024-09-15T18:07:39.745Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442, upload-time = "2024-09-15T18:07:37.964Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jplephem"
|
||||||
|
version = "2.23"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" },
|
||||||
|
{ name = "numpy", version = "2.3.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/3c/42/0545c37e070e5f940eb52987fb25a351ab3c9327b40bab6ad3dd6125b2e1/jplephem-2.23.tar.gz", hash = "sha256:d3fb9477e4bf4c39d10497d4ff15e5271b7ac03fa101e1821aac527d646eccf9", size = 44989, upload-time = "2025-06-22T18:42:28.813Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/da/e0/b215df7cae3be61a0a293346723f5b068e359a3430dcadb32ef90ae3398c/jplephem-2.23-py3-none-any.whl", hash = "sha256:66110814810b0b30213bdd058a85a41bedbc030bb8a365c85088674fe02546cf", size = 49368, upload-time = "2025-06-22T18:42:27.642Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "loguru"
|
||||||
|
version = "0.7.3"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "colorama", marker = "sys_platform == 'win32'" },
|
||||||
|
{ name = "win32-setctime", marker = "sys_platform == 'win32'" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/3a/05/a1dae3dffd1116099471c643b8924f5aa6524411dc6c63fdae648c4f1aca/loguru-0.7.3.tar.gz", hash = "sha256:19480589e77d47b8d85b2c827ad95d49bf31b0dcde16593892eb51dd18706eb6", size = 63559, upload-time = "2024-12-06T11:20:56.608Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/0c/29/0348de65b8cc732daa3e33e67806420b2ae89bdce2b04af740289c5c6c8c/loguru-0.7.3-py3-none-any.whl", hash = "sha256:31a33c10c8e1e10422bfd431aeb5d351c7cf7fa671e3c4df004162264b28220c", size = 61595, upload-time = "2024-12-06T11:20:54.538Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lunar-converter"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = { virtual = "." }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "fastapi" },
|
||||||
|
{ name = "jplephem" },
|
||||||
|
{ name = "loguru" },
|
||||||
|
{ name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" },
|
||||||
|
{ name = "numpy", version = "2.3.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" },
|
||||||
|
{ name = "skyfield" },
|
||||||
|
{ name = "uvicorn" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.metadata]
|
||||||
|
requires-dist = [
|
||||||
|
{ name = "fastapi" },
|
||||||
|
{ name = "jplephem" },
|
||||||
|
{ name = "loguru" },
|
||||||
|
{ name = "numpy" },
|
||||||
|
{ name = "skyfield" },
|
||||||
|
{ name = "uvicorn" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "numpy"
|
||||||
|
version = "2.2.6"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
resolution-markers = [
|
||||||
|
"python_full_version < '3.11'",
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/76/21/7d2a95e4bba9dc13d043ee156a356c0a8f0c6309dff6b21b4d71a073b8a8/numpy-2.2.6.tar.gz", hash = "sha256:e29554e2bef54a90aa5cc07da6ce955accb83f21ab5de01a62c8478897b264fd", size = 20276440, upload-time = "2025-05-17T22:38:04.611Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/9a/3e/ed6db5be21ce87955c0cbd3009f2803f59fa08df21b5df06862e2d8e2bdd/numpy-2.2.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b412caa66f72040e6d268491a59f2c43bf03eb6c96dd8f0307829feb7fa2b6fb", size = 21165245, upload-time = "2025-05-17T21:27:58.555Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/22/c2/4b9221495b2a132cc9d2eb862e21d42a009f5a60e45fc44b00118c174bff/numpy-2.2.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8e41fd67c52b86603a91c1a505ebaef50b3314de0213461c7a6e99c9a3beff90", size = 14360048, upload-time = "2025-05-17T21:28:21.406Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/fd/77/dc2fcfc66943c6410e2bf598062f5959372735ffda175b39906d54f02349/numpy-2.2.6-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:37e990a01ae6ec7fe7fa1c26c55ecb672dd98b19c3d0e1d1f326fa13cb38d163", size = 5340542, upload-time = "2025-05-17T21:28:30.931Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/7a/4f/1cb5fdc353a5f5cc7feb692db9b8ec2c3d6405453f982435efc52561df58/numpy-2.2.6-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:5a6429d4be8ca66d889b7cf70f536a397dc45ba6faeb5f8c5427935d9592e9cf", size = 6878301, upload-time = "2025-05-17T21:28:41.613Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/eb/17/96a3acd228cec142fcb8723bd3cc39c2a474f7dcf0a5d16731980bcafa95/numpy-2.2.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:efd28d4e9cd7d7a8d39074a4d44c63eda73401580c5c76acda2ce969e0a38e83", size = 14297320, upload-time = "2025-05-17T21:29:02.78Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/b4/63/3de6a34ad7ad6646ac7d2f55ebc6ad439dbbf9c4370017c50cf403fb19b5/numpy-2.2.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc7b73d02efb0e18c000e9ad8b83480dfcd5dfd11065997ed4c6747470ae8915", size = 16801050, upload-time = "2025-05-17T21:29:27.675Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/07/b6/89d837eddef52b3d0cec5c6ba0456c1bf1b9ef6a6672fc2b7873c3ec4e2e/numpy-2.2.6-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:74d4531beb257d2c3f4b261bfb0fc09e0f9ebb8842d82a7b4209415896adc680", size = 15807034, upload-time = "2025-05-17T21:29:51.102Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/01/c8/dc6ae86e3c61cfec1f178e5c9f7858584049b6093f843bca541f94120920/numpy-2.2.6-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8fc377d995680230e83241d8a96def29f204b5782f371c532579b4f20607a289", size = 18614185, upload-time = "2025-05-17T21:30:18.703Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/5b/c5/0064b1b7e7c89137b471ccec1fd2282fceaae0ab3a9550f2568782d80357/numpy-2.2.6-cp310-cp310-win32.whl", hash = "sha256:b093dd74e50a8cba3e873868d9e93a85b78e0daf2e98c6797566ad8044e8363d", size = 6527149, upload-time = "2025-05-17T21:30:29.788Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/a3/dd/4b822569d6b96c39d1215dbae0582fd99954dcbcf0c1a13c61783feaca3f/numpy-2.2.6-cp310-cp310-win_amd64.whl", hash = "sha256:f0fd6321b839904e15c46e0d257fdd101dd7f530fe03fd6359c1ea63738703f3", size = 12904620, upload-time = "2025-05-17T21:30:48.994Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/da/a8/4f83e2aa666a9fbf56d6118faaaf5f1974d456b1823fda0a176eff722839/numpy-2.2.6-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f9f1adb22318e121c5c69a09142811a201ef17ab257a1e66ca3025065b7f53ae", size = 21176963, upload-time = "2025-05-17T21:31:19.36Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/b3/2b/64e1affc7972decb74c9e29e5649fac940514910960ba25cd9af4488b66c/numpy-2.2.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c820a93b0255bc360f53eca31a0e676fd1101f673dda8da93454a12e23fc5f7a", size = 14406743, upload-time = "2025-05-17T21:31:41.087Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/4a/9f/0121e375000b5e50ffdd8b25bf78d8e1a5aa4cca3f185d41265198c7b834/numpy-2.2.6-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:3d70692235e759f260c3d837193090014aebdf026dfd167834bcba43e30c2a42", size = 5352616, upload-time = "2025-05-17T21:31:50.072Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/31/0d/b48c405c91693635fbe2dcd7bc84a33a602add5f63286e024d3b6741411c/numpy-2.2.6-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:481b49095335f8eed42e39e8041327c05b0f6f4780488f61286ed3c01368d491", size = 6889579, upload-time = "2025-05-17T21:32:01.712Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/52/b8/7f0554d49b565d0171eab6e99001846882000883998e7b7d9f0d98b1f934/numpy-2.2.6-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b64d8d4d17135e00c8e346e0a738deb17e754230d7e0810ac5012750bbd85a5a", size = 14312005, upload-time = "2025-05-17T21:32:23.332Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/b3/dd/2238b898e51bd6d389b7389ffb20d7f4c10066d80351187ec8e303a5a475/numpy-2.2.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba10f8411898fc418a521833e014a77d3ca01c15b0c6cdcce6a0d2897e6dbbdf", size = 16821570, upload-time = "2025-05-17T21:32:47.991Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/83/6c/44d0325722cf644f191042bf47eedad61c1e6df2432ed65cbe28509d404e/numpy-2.2.6-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:bd48227a919f1bafbdda0583705e547892342c26fb127219d60a5c36882609d1", size = 15818548, upload-time = "2025-05-17T21:33:11.728Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/ae/9d/81e8216030ce66be25279098789b665d49ff19eef08bfa8cb96d4957f422/numpy-2.2.6-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9551a499bf125c1d4f9e250377c1ee2eddd02e01eac6644c080162c0c51778ab", size = 18620521, upload-time = "2025-05-17T21:33:39.139Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/6a/fd/e19617b9530b031db51b0926eed5345ce8ddc669bb3bc0044b23e275ebe8/numpy-2.2.6-cp311-cp311-win32.whl", hash = "sha256:0678000bb9ac1475cd454c6b8c799206af8107e310843532b04d49649c717a47", size = 6525866, upload-time = "2025-05-17T21:33:50.273Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/31/0a/f354fb7176b81747d870f7991dc763e157a934c717b67b58456bc63da3df/numpy-2.2.6-cp311-cp311-win_amd64.whl", hash = "sha256:e8213002e427c69c45a52bbd94163084025f533a55a59d6f9c5b820774ef3303", size = 12907455, upload-time = "2025-05-17T21:34:09.135Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/82/5d/c00588b6cf18e1da539b45d3598d3557084990dcc4331960c15ee776ee41/numpy-2.2.6-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:41c5a21f4a04fa86436124d388f6ed60a9343a6f767fced1a8a71c3fbca038ff", size = 20875348, upload-time = "2025-05-17T21:34:39.648Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/66/ee/560deadcdde6c2f90200450d5938f63a34b37e27ebff162810f716f6a230/numpy-2.2.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:de749064336d37e340f640b05f24e9e3dd678c57318c7289d222a8a2f543e90c", size = 14119362, upload-time = "2025-05-17T21:35:01.241Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/3c/65/4baa99f1c53b30adf0acd9a5519078871ddde8d2339dc5a7fde80d9d87da/numpy-2.2.6-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:894b3a42502226a1cac872f840030665f33326fc3dac8e57c607905773cdcde3", size = 5084103, upload-time = "2025-05-17T21:35:10.622Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/cc/89/e5a34c071a0570cc40c9a54eb472d113eea6d002e9ae12bb3a8407fb912e/numpy-2.2.6-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:71594f7c51a18e728451bb50cc60a3ce4e6538822731b2933209a1f3614e9282", size = 6625382, upload-time = "2025-05-17T21:35:21.414Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/f8/35/8c80729f1ff76b3921d5c9487c7ac3de9b2a103b1cd05e905b3090513510/numpy-2.2.6-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f2618db89be1b4e05f7a1a847a9c1c0abd63e63a1607d892dd54668dd92faf87", size = 14018462, upload-time = "2025-05-17T21:35:42.174Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/8c/3d/1e1db36cfd41f895d266b103df00ca5b3cbe965184df824dec5c08c6b803/numpy-2.2.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd83c01228a688733f1ded5201c678f0c53ecc1006ffbc404db9f7a899ac6249", size = 16527618, upload-time = "2025-05-17T21:36:06.711Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/61/c6/03ed30992602c85aa3cd95b9070a514f8b3c33e31124694438d88809ae36/numpy-2.2.6-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:37c0ca431f82cd5fa716eca9506aefcabc247fb27ba69c5062a6d3ade8cf8f49", size = 15505511, upload-time = "2025-05-17T21:36:29.965Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/b7/25/5761d832a81df431e260719ec45de696414266613c9ee268394dd5ad8236/numpy-2.2.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fe27749d33bb772c80dcd84ae7e8df2adc920ae8297400dabec45f0dedb3f6de", size = 18313783, upload-time = "2025-05-17T21:36:56.883Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/57/0a/72d5a3527c5ebffcd47bde9162c39fae1f90138c961e5296491ce778e682/numpy-2.2.6-cp312-cp312-win32.whl", hash = "sha256:4eeaae00d789f66c7a25ac5f34b71a7035bb474e679f410e5e1a94deb24cf2d4", size = 6246506, upload-time = "2025-05-17T21:37:07.368Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/36/fa/8c9210162ca1b88529ab76b41ba02d433fd54fecaf6feb70ef9f124683f1/numpy-2.2.6-cp312-cp312-win_amd64.whl", hash = "sha256:c1f9540be57940698ed329904db803cf7a402f3fc200bfe599334c9bd84a40b2", size = 12614190, upload-time = "2025-05-17T21:37:26.213Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/f9/5c/6657823f4f594f72b5471f1db1ab12e26e890bb2e41897522d134d2a3e81/numpy-2.2.6-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0811bb762109d9708cca4d0b13c4f67146e3c3b7cf8d34018c722adb2d957c84", size = 20867828, upload-time = "2025-05-17T21:37:56.699Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/dc/9e/14520dc3dadf3c803473bd07e9b2bd1b69bc583cb2497b47000fed2fa92f/numpy-2.2.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:287cc3162b6f01463ccd86be154f284d0893d2b3ed7292439ea97eafa8170e0b", size = 14143006, upload-time = "2025-05-17T21:38:18.291Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/4f/06/7e96c57d90bebdce9918412087fc22ca9851cceaf5567a45c1f404480e9e/numpy-2.2.6-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:f1372f041402e37e5e633e586f62aa53de2eac8d98cbfb822806ce4bbefcb74d", size = 5076765, upload-time = "2025-05-17T21:38:27.319Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/73/ed/63d920c23b4289fdac96ddbdd6132e9427790977d5457cd132f18e76eae0/numpy-2.2.6-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:55a4d33fa519660d69614a9fad433be87e5252f4b03850642f88993f7b2ca566", size = 6617736, upload-time = "2025-05-17T21:38:38.141Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/85/c5/e19c8f99d83fd377ec8c7e0cf627a8049746da54afc24ef0a0cb73d5dfb5/numpy-2.2.6-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f92729c95468a2f4f15e9bb94c432a9229d0d50de67304399627a943201baa2f", size = 14010719, upload-time = "2025-05-17T21:38:58.433Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/19/49/4df9123aafa7b539317bf6d342cb6d227e49f7a35b99c287a6109b13dd93/numpy-2.2.6-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1bc23a79bfabc5d056d106f9befb8d50c31ced2fbc70eedb8155aec74a45798f", size = 16526072, upload-time = "2025-05-17T21:39:22.638Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/b2/6c/04b5f47f4f32f7c2b0e7260442a8cbcf8168b0e1a41ff1495da42f42a14f/numpy-2.2.6-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:e3143e4451880bed956e706a3220b4e5cf6172ef05fcc397f6f36a550b1dd868", size = 15503213, upload-time = "2025-05-17T21:39:45.865Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/17/0a/5cd92e352c1307640d5b6fec1b2ffb06cd0dabe7d7b8227f97933d378422/numpy-2.2.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b4f13750ce79751586ae2eb824ba7e1e8dba64784086c98cdbbcc6a42112ce0d", size = 18316632, upload-time = "2025-05-17T21:40:13.331Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/f0/3b/5cba2b1d88760ef86596ad0f3d484b1cbff7c115ae2429678465057c5155/numpy-2.2.6-cp313-cp313-win32.whl", hash = "sha256:5beb72339d9d4fa36522fc63802f469b13cdbe4fdab4a288f0c441b74272ebfd", size = 6244532, upload-time = "2025-05-17T21:43:46.099Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/cb/3b/d58c12eafcb298d4e6d0d40216866ab15f59e55d148a5658bb3132311fcf/numpy-2.2.6-cp313-cp313-win_amd64.whl", hash = "sha256:b0544343a702fa80c95ad5d3d608ea3599dd54d4632df855e4c8d24eb6ecfa1c", size = 12610885, upload-time = "2025-05-17T21:44:05.145Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/6b/9e/4bf918b818e516322db999ac25d00c75788ddfd2d2ade4fa66f1f38097e1/numpy-2.2.6-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:0bca768cd85ae743b2affdc762d617eddf3bcf8724435498a1e80132d04879e6", size = 20963467, upload-time = "2025-05-17T21:40:44Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/61/66/d2de6b291507517ff2e438e13ff7b1e2cdbdb7cb40b3ed475377aece69f9/numpy-2.2.6-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:fc0c5673685c508a142ca65209b4e79ed6740a4ed6b2267dbba90f34b0b3cfda", size = 14225144, upload-time = "2025-05-17T21:41:05.695Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/e4/25/480387655407ead912e28ba3a820bc69af9adf13bcbe40b299d454ec011f/numpy-2.2.6-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:5bd4fc3ac8926b3819797a7c0e2631eb889b4118a9898c84f585a54d475b7e40", size = 5200217, upload-time = "2025-05-17T21:41:15.903Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/aa/4a/6e313b5108f53dcbf3aca0c0f3e9c92f4c10ce57a0a721851f9785872895/numpy-2.2.6-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:fee4236c876c4e8369388054d02d0e9bb84821feb1a64dd59e137e6511a551f8", size = 6712014, upload-time = "2025-05-17T21:41:27.321Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/b7/30/172c2d5c4be71fdf476e9de553443cf8e25feddbe185e0bd88b096915bcc/numpy-2.2.6-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e1dda9c7e08dc141e0247a5b8f49cf05984955246a327d4c48bda16821947b2f", size = 14077935, upload-time = "2025-05-17T21:41:49.738Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/12/fb/9e743f8d4e4d3c710902cf87af3512082ae3d43b945d5d16563f26ec251d/numpy-2.2.6-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f447e6acb680fd307f40d3da4852208af94afdfab89cf850986c3ca00562f4fa", size = 16600122, upload-time = "2025-05-17T21:42:14.046Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/12/75/ee20da0e58d3a66f204f38916757e01e33a9737d0b22373b3eb5a27358f9/numpy-2.2.6-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:389d771b1623ec92636b0786bc4ae56abafad4a4c513d36a55dce14bd9ce8571", size = 15586143, upload-time = "2025-05-17T21:42:37.464Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/76/95/bef5b37f29fc5e739947e9ce5179ad402875633308504a52d188302319c8/numpy-2.2.6-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:8e9ace4a37db23421249ed236fdcdd457d671e25146786dfc96835cd951aa7c1", size = 18385260, upload-time = "2025-05-17T21:43:05.189Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/09/04/f2f83279d287407cf36a7a8053a5abe7be3622a4363337338f2585e4afda/numpy-2.2.6-cp313-cp313t-win32.whl", hash = "sha256:038613e9fb8c72b0a41f025a7e4c3f0b7a1b5d768ece4796b674c8f3fe13efff", size = 6377225, upload-time = "2025-05-17T21:43:16.254Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/67/0e/35082d13c09c02c011cf21570543d202ad929d961c02a147493cb0c2bdf5/numpy-2.2.6-cp313-cp313t-win_amd64.whl", hash = "sha256:6031dd6dfecc0cf9f668681a37648373bddd6421fff6c66ec1624eed0180ee06", size = 12771374, upload-time = "2025-05-17T21:43:35.479Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/9e/3b/d94a75f4dbf1ef5d321523ecac21ef23a3cd2ac8b78ae2aac40873590229/numpy-2.2.6-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:0b605b275d7bd0c640cad4e5d30fa701a8d59302e127e5f79138ad62762c3e3d", size = 21040391, upload-time = "2025-05-17T21:44:35.948Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/17/f4/09b2fa1b58f0fb4f7c7963a1649c64c4d315752240377ed74d9cd878f7b5/numpy-2.2.6-pp310-pypy310_pp73-macosx_14_0_x86_64.whl", hash = "sha256:7befc596a7dc9da8a337f79802ee8adb30a552a94f792b9c9d18c840055907db", size = 6786754, upload-time = "2025-05-17T21:44:47.446Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/af/30/feba75f143bdc868a1cc3f44ccfa6c4b9ec522b36458e738cd00f67b573f/numpy-2.2.6-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce47521a4754c8f4593837384bd3424880629f718d87c5d44f8ed763edd63543", size = 16643476, upload-time = "2025-05-17T21:45:11.871Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/37/48/ac2a9584402fb6c0cd5b5d1a91dcf176b15760130dd386bbafdbfe3640bf/numpy-2.2.6-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:d042d24c90c41b54fd506da306759e06e568864df8ec17ccc17e9e884634fd00", size = 12812666, upload-time = "2025-05-17T21:45:31.426Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "numpy"
|
||||||
|
version = "2.3.3"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
resolution-markers = [
|
||||||
|
"python_full_version >= '3.11'",
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/d0/19/95b3d357407220ed24c139018d2518fab0a61a948e68286a25f1a4d049ff/numpy-2.3.3.tar.gz", hash = "sha256:ddc7c39727ba62b80dfdbedf400d1c10ddfa8eefbd7ec8dcb118be8b56d31029", size = 20576648, upload-time = "2025-09-09T16:54:12.543Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/7a/45/e80d203ef6b267aa29b22714fb558930b27960a0c5ce3c19c999232bb3eb/numpy-2.3.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0ffc4f5caba7dfcbe944ed674b7eef683c7e94874046454bb79ed7ee0236f59d", size = 21259253, upload-time = "2025-09-09T15:56:02.094Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/52/18/cf2c648fccf339e59302e00e5f2bc87725a3ce1992f30f3f78c9044d7c43/numpy-2.3.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e7e946c7170858a0295f79a60214424caac2ffdb0063d4d79cb681f9aa0aa569", size = 14450980, upload-time = "2025-09-09T15:56:05.926Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/93/fb/9af1082bec870188c42a1c239839915b74a5099c392389ff04215dcee812/numpy-2.3.3-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:cd4260f64bc794c3390a63bf0728220dd1a68170c169088a1e0dfa2fde1be12f", size = 5379709, upload-time = "2025-09-09T15:56:07.95Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/75/0f/bfd7abca52bcbf9a4a65abc83fe18ef01ccdeb37bfb28bbd6ad613447c79/numpy-2.3.3-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:f0ddb4b96a87b6728df9362135e764eac3cfa674499943ebc44ce96c478ab125", size = 6913923, upload-time = "2025-09-09T15:56:09.443Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/79/55/d69adad255e87ab7afda1caf93ca997859092afeb697703e2f010f7c2e55/numpy-2.3.3-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:afd07d377f478344ec6ca2b8d4ca08ae8bd44706763d1efb56397de606393f48", size = 14589591, upload-time = "2025-09-09T15:56:11.234Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/10/a2/010b0e27ddeacab7839957d7a8f00e91206e0c2c47abbb5f35a2630e5387/numpy-2.3.3-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bc92a5dedcc53857249ca51ef29f5e5f2f8c513e22cfb90faeb20343b8c6f7a6", size = 16938714, upload-time = "2025-09-09T15:56:14.637Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/1c/6b/12ce8ede632c7126eb2762b9e15e18e204b81725b81f35176eac14dc5b82/numpy-2.3.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:7af05ed4dc19f308e1d9fc759f36f21921eb7bbfc82843eeec6b2a2863a0aefa", size = 16370592, upload-time = "2025-09-09T15:56:17.285Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/b4/35/aba8568b2593067bb6a8fe4c52babb23b4c3b9c80e1b49dff03a09925e4a/numpy-2.3.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:433bf137e338677cebdd5beac0199ac84712ad9d630b74eceeb759eaa45ddf30", size = 18884474, upload-time = "2025-09-09T15:56:20.943Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/45/fa/7f43ba10c77575e8be7b0138d107e4f44ca4a1ef322cd16980ea3e8b8222/numpy-2.3.3-cp311-cp311-win32.whl", hash = "sha256:eb63d443d7b4ffd1e873f8155260d7f58e7e4b095961b01c91062935c2491e57", size = 6599794, upload-time = "2025-09-09T15:56:23.258Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/0a/a2/a4f78cb2241fe5664a22a10332f2be886dcdea8784c9f6a01c272da9b426/numpy-2.3.3-cp311-cp311-win_amd64.whl", hash = "sha256:ec9d249840f6a565f58d8f913bccac2444235025bbb13e9a4681783572ee3caa", size = 13088104, upload-time = "2025-09-09T15:56:25.476Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/79/64/e424e975adbd38282ebcd4891661965b78783de893b381cbc4832fb9beb2/numpy-2.3.3-cp311-cp311-win_arm64.whl", hash = "sha256:74c2a948d02f88c11a3c075d9733f1ae67d97c6bdb97f2bb542f980458b257e7", size = 10460772, upload-time = "2025-09-09T15:56:27.679Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/51/5d/bb7fc075b762c96329147799e1bcc9176ab07ca6375ea976c475482ad5b3/numpy-2.3.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:cfdd09f9c84a1a934cde1eec2267f0a43a7cd44b2cca4ff95b7c0d14d144b0bf", size = 20957014, upload-time = "2025-09-09T15:56:29.966Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/6b/0e/c6211bb92af26517acd52125a237a92afe9c3124c6a68d3b9f81b62a0568/numpy-2.3.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:cb32e3cf0f762aee47ad1ddc6672988f7f27045b0783c887190545baba73aa25", size = 14185220, upload-time = "2025-09-09T15:56:32.175Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/22/f2/07bb754eb2ede9073f4054f7c0286b0d9d2e23982e090a80d478b26d35ca/numpy-2.3.3-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:396b254daeb0a57b1fe0ecb5e3cff6fa79a380fa97c8f7781a6d08cd429418fe", size = 5113918, upload-time = "2025-09-09T15:56:34.175Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/81/0a/afa51697e9fb74642f231ea36aca80fa17c8fb89f7a82abd5174023c3960/numpy-2.3.3-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:067e3d7159a5d8f8a0b46ee11148fc35ca9b21f61e3c49fbd0a027450e65a33b", size = 6647922, upload-time = "2025-09-09T15:56:36.149Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/5d/f5/122d9cdb3f51c520d150fef6e87df9279e33d19a9611a87c0d2cf78a89f4/numpy-2.3.3-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1c02d0629d25d426585fb2e45a66154081b9fa677bc92a881ff1d216bc9919a8", size = 14281991, upload-time = "2025-09-09T15:56:40.548Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/51/64/7de3c91e821a2debf77c92962ea3fe6ac2bc45d0778c1cbe15d4fce2fd94/numpy-2.3.3-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d9192da52b9745f7f0766531dcfa978b7763916f158bb63bdb8a1eca0068ab20", size = 16641643, upload-time = "2025-09-09T15:56:43.343Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/30/e4/961a5fa681502cd0d68907818b69f67542695b74e3ceaa513918103b7e80/numpy-2.3.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:cd7de500a5b66319db419dc3c345244404a164beae0d0937283b907d8152e6ea", size = 16056787, upload-time = "2025-09-09T15:56:46.141Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/99/26/92c912b966e47fbbdf2ad556cb17e3a3088e2e1292b9833be1dfa5361a1a/numpy-2.3.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:93d4962d8f82af58f0b2eb85daaf1b3ca23fe0a85d0be8f1f2b7bb46034e56d7", size = 18579598, upload-time = "2025-09-09T15:56:49.844Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/17/b6/fc8f82cb3520768718834f310c37d96380d9dc61bfdaf05fe5c0b7653e01/numpy-2.3.3-cp312-cp312-win32.whl", hash = "sha256:5534ed6b92f9b7dca6c0a19d6df12d41c68b991cef051d108f6dbff3babc4ebf", size = 6320800, upload-time = "2025-09-09T15:56:52.499Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/32/ee/de999f2625b80d043d6d2d628c07d0d5555a677a3cf78fdf868d409b8766/numpy-2.3.3-cp312-cp312-win_amd64.whl", hash = "sha256:497d7cad08e7092dba36e3d296fe4c97708c93daf26643a1ae4b03f6294d30eb", size = 12786615, upload-time = "2025-09-09T15:56:54.422Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/49/6e/b479032f8a43559c383acb20816644f5f91c88f633d9271ee84f3b3a996c/numpy-2.3.3-cp312-cp312-win_arm64.whl", hash = "sha256:ca0309a18d4dfea6fc6262a66d06c26cfe4640c3926ceec90e57791a82b6eee5", size = 10195936, upload-time = "2025-09-09T15:56:56.541Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/7d/b9/984c2b1ee61a8b803bf63582b4ac4242cf76e2dbd663efeafcb620cc0ccb/numpy-2.3.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f5415fb78995644253370985342cd03572ef8620b934da27d77377a2285955bf", size = 20949588, upload-time = "2025-09-09T15:56:59.087Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/a6/e4/07970e3bed0b1384d22af1e9912527ecbeb47d3b26e9b6a3bced068b3bea/numpy-2.3.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d00de139a3324e26ed5b95870ce63be7ec7352171bc69a4cf1f157a48e3eb6b7", size = 14177802, upload-time = "2025-09-09T15:57:01.73Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/35/c7/477a83887f9de61f1203bad89cf208b7c19cc9fef0cebef65d5a1a0619f2/numpy-2.3.3-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:9dc13c6a5829610cc07422bc74d3ac083bd8323f14e2827d992f9e52e22cd6a6", size = 5106537, upload-time = "2025-09-09T15:57:03.765Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/52/47/93b953bd5866a6f6986344d045a207d3f1cfbad99db29f534ea9cee5108c/numpy-2.3.3-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:d79715d95f1894771eb4e60fb23f065663b2298f7d22945d66877aadf33d00c7", size = 6640743, upload-time = "2025-09-09T15:57:07.921Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/23/83/377f84aaeb800b64c0ef4de58b08769e782edcefa4fea712910b6f0afd3c/numpy-2.3.3-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:952cfd0748514ea7c3afc729a0fc639e61655ce4c55ab9acfab14bda4f402b4c", size = 14278881, upload-time = "2025-09-09T15:57:11.349Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/9a/a5/bf3db6e66c4b160d6ea10b534c381a1955dfab34cb1017ea93aa33c70ed3/numpy-2.3.3-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5b83648633d46f77039c29078751f80da65aa64d5622a3cd62aaef9d835b6c93", size = 16636301, upload-time = "2025-09-09T15:57:14.245Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/a2/59/1287924242eb4fa3f9b3a2c30400f2e17eb2707020d1c5e3086fe7330717/numpy-2.3.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:b001bae8cea1c7dfdb2ae2b017ed0a6f2102d7a70059df1e338e307a4c78a8ae", size = 16053645, upload-time = "2025-09-09T15:57:16.534Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/e6/93/b3d47ed882027c35e94ac2320c37e452a549f582a5e801f2d34b56973c97/numpy-2.3.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8e9aced64054739037d42fb84c54dd38b81ee238816c948c8f3ed134665dcd86", size = 18578179, upload-time = "2025-09-09T15:57:18.883Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/20/d9/487a2bccbf7cc9d4bfc5f0f197761a5ef27ba870f1e3bbb9afc4bbe3fcc2/numpy-2.3.3-cp313-cp313-win32.whl", hash = "sha256:9591e1221db3f37751e6442850429b3aabf7026d3b05542d102944ca7f00c8a8", size = 6312250, upload-time = "2025-09-09T15:57:21.296Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/1b/b5/263ebbbbcede85028f30047eab3d58028d7ebe389d6493fc95ae66c636ab/numpy-2.3.3-cp313-cp313-win_amd64.whl", hash = "sha256:f0dadeb302887f07431910f67a14d57209ed91130be0adea2f9793f1a4f817cf", size = 12783269, upload-time = "2025-09-09T15:57:23.034Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/fa/75/67b8ca554bbeaaeb3fac2e8bce46967a5a06544c9108ec0cf5cece559b6c/numpy-2.3.3-cp313-cp313-win_arm64.whl", hash = "sha256:3c7cf302ac6e0b76a64c4aecf1a09e51abd9b01fc7feee80f6c43e3ab1b1dbc5", size = 10195314, upload-time = "2025-09-09T15:57:25.045Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/11/d0/0d1ddec56b162042ddfafeeb293bac672de9b0cfd688383590090963720a/numpy-2.3.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:eda59e44957d272846bb407aad19f89dc6f58fecf3504bd144f4c5cf81a7eacc", size = 21048025, upload-time = "2025-09-09T15:57:27.257Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/36/9e/1996ca6b6d00415b6acbdd3c42f7f03ea256e2c3f158f80bd7436a8a19f3/numpy-2.3.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:823d04112bc85ef5c4fda73ba24e6096c8f869931405a80aa8b0e604510a26bc", size = 14301053, upload-time = "2025-09-09T15:57:30.077Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/05/24/43da09aa764c68694b76e84b3d3f0c44cb7c18cdc1ba80e48b0ac1d2cd39/numpy-2.3.3-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:40051003e03db4041aa325da2a0971ba41cf65714e65d296397cc0e32de6018b", size = 5229444, upload-time = "2025-09-09T15:57:32.733Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/bc/14/50ffb0f22f7218ef8af28dd089f79f68289a7a05a208db9a2c5dcbe123c1/numpy-2.3.3-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:6ee9086235dd6ab7ae75aba5662f582a81ced49f0f1c6de4260a78d8f2d91a19", size = 6738039, upload-time = "2025-09-09T15:57:34.328Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/55/52/af46ac0795e09657d45a7f4db961917314377edecf66db0e39fa7ab5c3d3/numpy-2.3.3-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:94fcaa68757c3e2e668ddadeaa86ab05499a70725811e582b6a9858dd472fb30", size = 14352314, upload-time = "2025-09-09T15:57:36.255Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/a7/b1/dc226b4c90eb9f07a3fff95c2f0db3268e2e54e5cce97c4ac91518aee71b/numpy-2.3.3-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:da1a74b90e7483d6ce5244053399a614b1d6b7bc30a60d2f570e5071f8959d3e", size = 16701722, upload-time = "2025-09-09T15:57:38.622Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/9d/9d/9d8d358f2eb5eced14dba99f110d83b5cd9a4460895230f3b396ad19a323/numpy-2.3.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:2990adf06d1ecee3b3dcbb4977dfab6e9f09807598d647f04d385d29e7a3c3d3", size = 16132755, upload-time = "2025-09-09T15:57:41.16Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/b6/27/b3922660c45513f9377b3fb42240bec63f203c71416093476ec9aa0719dc/numpy-2.3.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:ed635ff692483b8e3f0fcaa8e7eb8a75ee71aa6d975388224f70821421800cea", size = 18651560, upload-time = "2025-09-09T15:57:43.459Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/5b/8e/3ab61a730bdbbc201bb245a71102aa609f0008b9ed15255500a99cd7f780/numpy-2.3.3-cp313-cp313t-win32.whl", hash = "sha256:a333b4ed33d8dc2b373cc955ca57babc00cd6f9009991d9edc5ddbc1bac36bcd", size = 6442776, upload-time = "2025-09-09T15:57:45.793Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/1c/3a/e22b766b11f6030dc2decdeff5c2fb1610768055603f9f3be88b6d192fb2/numpy-2.3.3-cp313-cp313t-win_amd64.whl", hash = "sha256:4384a169c4d8f97195980815d6fcad04933a7e1ab3b530921c3fef7a1c63426d", size = 12927281, upload-time = "2025-09-09T15:57:47.492Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/7b/42/c2e2bc48c5e9b2a83423f99733950fbefd86f165b468a3d85d52b30bf782/numpy-2.3.3-cp313-cp313t-win_arm64.whl", hash = "sha256:75370986cc0bc66f4ce5110ad35aae6d182cc4ce6433c40ad151f53690130bf1", size = 10265275, upload-time = "2025-09-09T15:57:49.647Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/6b/01/342ad585ad82419b99bcf7cebe99e61da6bedb89e213c5fd71acc467faee/numpy-2.3.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:cd052f1fa6a78dee696b58a914b7229ecfa41f0a6d96dc663c1220a55e137593", size = 20951527, upload-time = "2025-09-09T15:57:52.006Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/ef/d8/204e0d73fc1b7a9ee80ab1fe1983dd33a4d64a4e30a05364b0208e9a241a/numpy-2.3.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:414a97499480067d305fcac9716c29cf4d0d76db6ebf0bf3cbce666677f12652", size = 14186159, upload-time = "2025-09-09T15:57:54.407Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/22/af/f11c916d08f3a18fb8ba81ab72b5b74a6e42ead4c2846d270eb19845bf74/numpy-2.3.3-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:50a5fe69f135f88a2be9b6ca0481a68a136f6febe1916e4920e12f1a34e708a7", size = 5114624, upload-time = "2025-09-09T15:57:56.5Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/fb/11/0ed919c8381ac9d2ffacd63fd1f0c34d27e99cab650f0eb6f110e6ae4858/numpy-2.3.3-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:b912f2ed2b67a129e6a601e9d93d4fa37bef67e54cac442a2f588a54afe5c67a", size = 6642627, upload-time = "2025-09-09T15:57:58.206Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/ee/83/deb5f77cb0f7ba6cb52b91ed388b47f8f3c2e9930d4665c600408d9b90b9/numpy-2.3.3-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9e318ee0596d76d4cb3d78535dc005fa60e5ea348cd131a51e99d0bdbe0b54fe", size = 14296926, upload-time = "2025-09-09T15:58:00.035Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/77/cc/70e59dcb84f2b005d4f306310ff0a892518cc0c8000a33d0e6faf7ca8d80/numpy-2.3.3-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ce020080e4a52426202bdb6f7691c65bb55e49f261f31a8f506c9f6bc7450421", size = 16638958, upload-time = "2025-09-09T15:58:02.738Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/b6/5a/b2ab6c18b4257e099587d5b7f903317bd7115333ad8d4ec4874278eafa61/numpy-2.3.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:e6687dc183aa55dae4a705b35f9c0f8cb178bcaa2f029b241ac5356221d5c021", size = 16071920, upload-time = "2025-09-09T15:58:05.029Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/b8/f1/8b3fdc44324a259298520dd82147ff648979bed085feeacc1250ef1656c0/numpy-2.3.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:d8f3b1080782469fdc1718c4ed1d22549b5fb12af0d57d35e992158a772a37cf", size = 18577076, upload-time = "2025-09-09T15:58:07.745Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/f0/a1/b87a284fb15a42e9274e7fcea0dad259d12ddbf07c1595b26883151ca3b4/numpy-2.3.3-cp314-cp314-win32.whl", hash = "sha256:cb248499b0bc3be66ebd6578b83e5acacf1d6cb2a77f2248ce0e40fbec5a76d0", size = 6366952, upload-time = "2025-09-09T15:58:10.096Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/70/5f/1816f4d08f3b8f66576d8433a66f8fa35a5acfb3bbd0bf6c31183b003f3d/numpy-2.3.3-cp314-cp314-win_amd64.whl", hash = "sha256:691808c2b26b0f002a032c73255d0bd89751425f379f7bcd22d140db593a96e8", size = 12919322, upload-time = "2025-09-09T15:58:12.138Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/8c/de/072420342e46a8ea41c324a555fa90fcc11637583fb8df722936aed1736d/numpy-2.3.3-cp314-cp314-win_arm64.whl", hash = "sha256:9ad12e976ca7b10f1774b03615a2a4bab8addce37ecc77394d8e986927dc0dfe", size = 10478630, upload-time = "2025-09-09T15:58:14.64Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/d5/df/ee2f1c0a9de7347f14da5dd3cd3c3b034d1b8607ccb6883d7dd5c035d631/numpy-2.3.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:9cc48e09feb11e1db00b320e9d30a4151f7369afb96bd0e48d942d09da3a0d00", size = 21047987, upload-time = "2025-09-09T15:58:16.889Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/d6/92/9453bdc5a4e9e69cf4358463f25e8260e2ffc126d52e10038b9077815989/numpy-2.3.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:901bf6123879b7f251d3631967fd574690734236075082078e0571977c6a8e6a", size = 14301076, upload-time = "2025-09-09T15:58:20.343Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/13/77/1447b9eb500f028bb44253105bd67534af60499588a5149a94f18f2ca917/numpy-2.3.3-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:7f025652034199c301049296b59fa7d52c7e625017cae4c75d8662e377bf487d", size = 5229491, upload-time = "2025-09-09T15:58:22.481Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/3d/f9/d72221b6ca205f9736cb4b2ce3b002f6e45cd67cd6a6d1c8af11a2f0b649/numpy-2.3.3-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:533ca5f6d325c80b6007d4d7fb1984c303553534191024ec6a524a4c92a5935a", size = 6737913, upload-time = "2025-09-09T15:58:24.569Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/3c/5f/d12834711962ad9c46af72f79bb31e73e416ee49d17f4c797f72c96b6ca5/numpy-2.3.3-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0edd58682a399824633b66885d699d7de982800053acf20be1eaa46d92009c54", size = 14352811, upload-time = "2025-09-09T15:58:26.416Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/a1/0d/fdbec6629d97fd1bebed56cd742884e4eead593611bbe1abc3eb40d304b2/numpy-2.3.3-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:367ad5d8fbec5d9296d18478804a530f1191e24ab4d75ab408346ae88045d25e", size = 16702689, upload-time = "2025-09-09T15:58:28.831Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/9b/09/0a35196dc5575adde1eb97ddfbc3e1687a814f905377621d18ca9bc2b7dd/numpy-2.3.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8f6ac61a217437946a1fa48d24c47c91a0c4f725237871117dea264982128097", size = 16133855, upload-time = "2025-09-09T15:58:31.349Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/7a/ca/c9de3ea397d576f1b6753eaa906d4cdef1bf97589a6d9825a349b4729cc2/numpy-2.3.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:179a42101b845a816d464b6fe9a845dfaf308fdfc7925387195570789bb2c970", size = 18652520, upload-time = "2025-09-09T15:58:33.762Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/fd/c2/e5ed830e08cd0196351db55db82f65bc0ab05da6ef2b72a836dcf1936d2f/numpy-2.3.3-cp314-cp314t-win32.whl", hash = "sha256:1250c5d3d2562ec4174bce2e3a1523041595f9b651065e4a4473f5f48a6bc8a5", size = 6515371, upload-time = "2025-09-09T15:58:36.04Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/47/c7/b0f6b5b67f6788a0725f744496badbb604d226bf233ba716683ebb47b570/numpy-2.3.3-cp314-cp314t-win_amd64.whl", hash = "sha256:b37a0b2e5935409daebe82c1e42274d30d9dd355852529eab91dab8dcca7419f", size = 13112576, upload-time = "2025-09-09T15:58:37.927Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/06/b9/33bba5ff6fb679aa0b1f8a07e853f002a6b04b9394db3069a1270a7784ca/numpy-2.3.3-cp314-cp314t-win_arm64.whl", hash = "sha256:78c9f6560dc7e6b3990e32df7ea1a50bbd0e2a111e05209963f5ddcab7073b0b", size = 10545953, upload-time = "2025-09-09T15:58:40.576Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/b8/f2/7e0a37cfced2644c9563c529f29fa28acbd0960dde32ece683aafa6f4949/numpy-2.3.3-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:1e02c7159791cd481e1e6d5ddd766b62a4d5acf8df4d4d1afe35ee9c5c33a41e", size = 21131019, upload-time = "2025-09-09T15:58:42.838Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/1a/7e/3291f505297ed63831135a6cc0f474da0c868a1f31b0dd9a9f03a7a0d2ed/numpy-2.3.3-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:dca2d0fc80b3893ae72197b39f69d55a3cd8b17ea1b50aa4c62de82419936150", size = 14376288, upload-time = "2025-09-09T15:58:45.425Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/bf/4b/ae02e985bdeee73d7b5abdefeb98aef1207e96d4c0621ee0cf228ddfac3c/numpy-2.3.3-pp311-pypy311_pp73-macosx_14_0_arm64.whl", hash = "sha256:99683cbe0658f8271b333a1b1b4bb3173750ad59c0c61f5bbdc5b318918fffe3", size = 5305425, upload-time = "2025-09-09T15:58:48.6Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/8b/eb/9df215d6d7250db32007941500dc51c48190be25f2401d5b2b564e467247/numpy-2.3.3-pp311-pypy311_pp73-macosx_14_0_x86_64.whl", hash = "sha256:d9d537a39cc9de668e5cd0e25affb17aec17b577c6b3ae8a3d866b479fbe88d0", size = 6819053, upload-time = "2025-09-09T15:58:50.401Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/57/62/208293d7d6b2a8998a4a1f23ac758648c3c32182d4ce4346062018362e29/numpy-2.3.3-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8596ba2f8af5f93b01d97563832686d20206d303024777f6dfc2e7c7c3f1850e", size = 14420354, upload-time = "2025-09-09T15:58:52.704Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/ed/0c/8e86e0ff7072e14a71b4c6af63175e40d1e7e933ce9b9e9f765a95b4e0c3/numpy-2.3.3-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e1ec5615b05369925bd1125f27df33f3b6c8bc10d788d5999ecd8769a1fa04db", size = 16760413, upload-time = "2025-09-09T15:58:55.027Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/af/11/0cc63f9f321ccf63886ac203336777140011fb669e739da36d8db3c53b98/numpy-2.3.3-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:2e267c7da5bf7309670523896df97f93f6e469fb931161f483cd6882b3b1a5dc", size = 12971844, upload-time = "2025-09-09T15:58:57.359Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pydantic"
|
||||||
|
version = "2.11.7"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "annotated-types" },
|
||||||
|
{ name = "pydantic-core" },
|
||||||
|
{ name = "typing-extensions" },
|
||||||
|
{ name = "typing-inspection" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/00/dd/4325abf92c39ba8623b5af936ddb36ffcfe0beae70405d456ab1fb2f5b8c/pydantic-2.11.7.tar.gz", hash = "sha256:d989c3c6cb79469287b1569f7447a17848c998458d49ebe294e975b9baf0f0db", size = 788350, upload-time = "2025-06-14T08:33:17.137Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/6a/c0/ec2b1c8712ca690e5d61979dee872603e92b8a32f94cc1b72d53beab008a/pydantic-2.11.7-py3-none-any.whl", hash = "sha256:dde5df002701f6de26248661f6835bbe296a47bf73990135c7d07ce741b9623b", size = 444782, upload-time = "2025-06-14T08:33:14.905Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pydantic-core"
|
||||||
|
version = "2.33.2"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "typing-extensions" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/ad/88/5f2260bdfae97aabf98f1778d43f69574390ad787afb646292a638c923d4/pydantic_core-2.33.2.tar.gz", hash = "sha256:7cb8bc3605c29176e1b105350d2e6474142d7c1bd1d9327c4a9bdb46bf827acc", size = 435195, upload-time = "2025-04-23T18:33:52.104Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/e5/92/b31726561b5dae176c2d2c2dc43a9c5bfba5d32f96f8b4c0a600dd492447/pydantic_core-2.33.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:2b3d326aaef0c0399d9afffeb6367d5e26ddc24d351dbc9c636840ac355dc5d8", size = 2028817, upload-time = "2025-04-23T18:30:43.919Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/a3/44/3f0b95fafdaca04a483c4e685fe437c6891001bf3ce8b2fded82b9ea3aa1/pydantic_core-2.33.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0e5b2671f05ba48b94cb90ce55d8bdcaaedb8ba00cc5359f6810fc918713983d", size = 1861357, upload-time = "2025-04-23T18:30:46.372Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/30/97/e8f13b55766234caae05372826e8e4b3b96e7b248be3157f53237682e43c/pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0069c9acc3f3981b9ff4cdfaf088e98d83440a4c7ea1bc07460af3d4dc22e72d", size = 1898011, upload-time = "2025-04-23T18:30:47.591Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/9b/a3/99c48cf7bafc991cc3ee66fd544c0aae8dc907b752f1dad2d79b1b5a471f/pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d53b22f2032c42eaaf025f7c40c2e3b94568ae077a606f006d206a463bc69572", size = 1982730, upload-time = "2025-04-23T18:30:49.328Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/de/8e/a5b882ec4307010a840fb8b58bd9bf65d1840c92eae7534c7441709bf54b/pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0405262705a123b7ce9f0b92f123334d67b70fd1f20a9372b907ce1080c7ba02", size = 2136178, upload-time = "2025-04-23T18:30:50.907Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/e4/bb/71e35fc3ed05af6834e890edb75968e2802fe98778971ab5cba20a162315/pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4b25d91e288e2c4e0662b8038a28c6a07eaac3e196cfc4ff69de4ea3db992a1b", size = 2736462, upload-time = "2025-04-23T18:30:52.083Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/31/0d/c8f7593e6bc7066289bbc366f2235701dcbebcd1ff0ef8e64f6f239fb47d/pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6bdfe4b3789761f3bcb4b1ddf33355a71079858958e3a552f16d5af19768fef2", size = 2005652, upload-time = "2025-04-23T18:30:53.389Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/d2/7a/996d8bd75f3eda405e3dd219ff5ff0a283cd8e34add39d8ef9157e722867/pydantic_core-2.33.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:efec8db3266b76ef9607c2c4c419bdb06bf335ae433b80816089ea7585816f6a", size = 2113306, upload-time = "2025-04-23T18:30:54.661Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/ff/84/daf2a6fb2db40ffda6578a7e8c5a6e9c8affb251a05c233ae37098118788/pydantic_core-2.33.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:031c57d67ca86902726e0fae2214ce6770bbe2f710dc33063187a68744a5ecac", size = 2073720, upload-time = "2025-04-23T18:30:56.11Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/77/fb/2258da019f4825128445ae79456a5499c032b55849dbd5bed78c95ccf163/pydantic_core-2.33.2-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:f8de619080e944347f5f20de29a975c2d815d9ddd8be9b9b7268e2e3ef68605a", size = 2244915, upload-time = "2025-04-23T18:30:57.501Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/d8/7a/925ff73756031289468326e355b6fa8316960d0d65f8b5d6b3a3e7866de7/pydantic_core-2.33.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:73662edf539e72a9440129f231ed3757faab89630d291b784ca99237fb94db2b", size = 2241884, upload-time = "2025-04-23T18:30:58.867Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/0b/b0/249ee6d2646f1cdadcb813805fe76265745c4010cf20a8eba7b0e639d9b2/pydantic_core-2.33.2-cp310-cp310-win32.whl", hash = "sha256:0a39979dcbb70998b0e505fb1556a1d550a0781463ce84ebf915ba293ccb7e22", size = 1910496, upload-time = "2025-04-23T18:31:00.078Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/66/ff/172ba8f12a42d4b552917aa65d1f2328990d3ccfc01d5b7c943ec084299f/pydantic_core-2.33.2-cp310-cp310-win_amd64.whl", hash = "sha256:b0379a2b24882fef529ec3b4987cb5d003b9cda32256024e6fe1586ac45fc640", size = 1955019, upload-time = "2025-04-23T18:31:01.335Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/3f/8d/71db63483d518cbbf290261a1fc2839d17ff89fce7089e08cad07ccfce67/pydantic_core-2.33.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:4c5b0a576fb381edd6d27f0a85915c6daf2f8138dc5c267a57c08a62900758c7", size = 2028584, upload-time = "2025-04-23T18:31:03.106Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/24/2f/3cfa7244ae292dd850989f328722d2aef313f74ffc471184dc509e1e4e5a/pydantic_core-2.33.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e799c050df38a639db758c617ec771fd8fb7a5f8eaaa4b27b101f266b216a246", size = 1855071, upload-time = "2025-04-23T18:31:04.621Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/b3/d3/4ae42d33f5e3f50dd467761304be2fa0a9417fbf09735bc2cce003480f2a/pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dc46a01bf8d62f227d5ecee74178ffc448ff4e5197c756331f71efcc66dc980f", size = 1897823, upload-time = "2025-04-23T18:31:06.377Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/f4/f3/aa5976e8352b7695ff808599794b1fba2a9ae2ee954a3426855935799488/pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a144d4f717285c6d9234a66778059f33a89096dfb9b39117663fd8413d582dcc", size = 1983792, upload-time = "2025-04-23T18:31:07.93Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/d5/7a/cda9b5a23c552037717f2b2a5257e9b2bfe45e687386df9591eff7b46d28/pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:73cf6373c21bc80b2e0dc88444f41ae60b2f070ed02095754eb5a01df12256de", size = 2136338, upload-time = "2025-04-23T18:31:09.283Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/2b/9f/b8f9ec8dd1417eb9da784e91e1667d58a2a4a7b7b34cf4af765ef663a7e5/pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3dc625f4aa79713512d1976fe9f0bc99f706a9dee21dfd1810b4bbbf228d0e8a", size = 2730998, upload-time = "2025-04-23T18:31:11.7Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/47/bc/cd720e078576bdb8255d5032c5d63ee5c0bf4b7173dd955185a1d658c456/pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:881b21b5549499972441da4758d662aeea93f1923f953e9cbaff14b8b9565aef", size = 2003200, upload-time = "2025-04-23T18:31:13.536Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/ca/22/3602b895ee2cd29d11a2b349372446ae9727c32e78a94b3d588a40fdf187/pydantic_core-2.33.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bdc25f3681f7b78572699569514036afe3c243bc3059d3942624e936ec93450e", size = 2113890, upload-time = "2025-04-23T18:31:15.011Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/ff/e6/e3c5908c03cf00d629eb38393a98fccc38ee0ce8ecce32f69fc7d7b558a7/pydantic_core-2.33.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:fe5b32187cbc0c862ee201ad66c30cf218e5ed468ec8dc1cf49dec66e160cc4d", size = 2073359, upload-time = "2025-04-23T18:31:16.393Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/12/e7/6a36a07c59ebefc8777d1ffdaf5ae71b06b21952582e4b07eba88a421c79/pydantic_core-2.33.2-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:bc7aee6f634a6f4a95676fcb5d6559a2c2a390330098dba5e5a5f28a2e4ada30", size = 2245883, upload-time = "2025-04-23T18:31:17.892Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/16/3f/59b3187aaa6cc0c1e6616e8045b284de2b6a87b027cce2ffcea073adf1d2/pydantic_core-2.33.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:235f45e5dbcccf6bd99f9f472858849f73d11120d76ea8707115415f8e5ebebf", size = 2241074, upload-time = "2025-04-23T18:31:19.205Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/e0/ed/55532bb88f674d5d8f67ab121a2a13c385df382de2a1677f30ad385f7438/pydantic_core-2.33.2-cp311-cp311-win32.whl", hash = "sha256:6368900c2d3ef09b69cb0b913f9f8263b03786e5b2a387706c5afb66800efd51", size = 1910538, upload-time = "2025-04-23T18:31:20.541Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/fe/1b/25b7cccd4519c0b23c2dd636ad39d381abf113085ce4f7bec2b0dc755eb1/pydantic_core-2.33.2-cp311-cp311-win_amd64.whl", hash = "sha256:1e063337ef9e9820c77acc768546325ebe04ee38b08703244c1309cccc4f1bab", size = 1952909, upload-time = "2025-04-23T18:31:22.371Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/49/a9/d809358e49126438055884c4366a1f6227f0f84f635a9014e2deb9b9de54/pydantic_core-2.33.2-cp311-cp311-win_arm64.whl", hash = "sha256:6b99022f1d19bc32a4c2a0d544fc9a76e3be90f0b3f4af413f87d38749300e65", size = 1897786, upload-time = "2025-04-23T18:31:24.161Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/18/8a/2b41c97f554ec8c71f2a8a5f85cb56a8b0956addfe8b0efb5b3d77e8bdc3/pydantic_core-2.33.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:a7ec89dc587667f22b6a0b6579c249fca9026ce7c333fc142ba42411fa243cdc", size = 2009000, upload-time = "2025-04-23T18:31:25.863Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/a1/02/6224312aacb3c8ecbaa959897af57181fb6cf3a3d7917fd44d0f2917e6f2/pydantic_core-2.33.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3c6db6e52c6d70aa0d00d45cdb9b40f0433b96380071ea80b09277dba021ddf7", size = 1847996, upload-time = "2025-04-23T18:31:27.341Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/d6/46/6dcdf084a523dbe0a0be59d054734b86a981726f221f4562aed313dbcb49/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e61206137cbc65e6d5256e1166f88331d3b6238e082d9f74613b9b765fb9025", size = 1880957, upload-time = "2025-04-23T18:31:28.956Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/ec/6b/1ec2c03837ac00886ba8160ce041ce4e325b41d06a034adbef11339ae422/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eb8c529b2819c37140eb51b914153063d27ed88e3bdc31b71198a198e921e011", size = 1964199, upload-time = "2025-04-23T18:31:31.025Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/2d/1d/6bf34d6adb9debd9136bd197ca72642203ce9aaaa85cfcbfcf20f9696e83/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c52b02ad8b4e2cf14ca7b3d918f3eb0ee91e63b3167c32591e57c4317e134f8f", size = 2120296, upload-time = "2025-04-23T18:31:32.514Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/e0/94/2bd0aaf5a591e974b32a9f7123f16637776c304471a0ab33cf263cf5591a/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:96081f1605125ba0855dfda83f6f3df5ec90c61195421ba72223de35ccfb2f88", size = 2676109, upload-time = "2025-04-23T18:31:33.958Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/f9/41/4b043778cf9c4285d59742281a769eac371b9e47e35f98ad321349cc5d61/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f57a69461af2a5fa6e6bbd7a5f60d3b7e6cebb687f55106933188e79ad155c1", size = 2002028, upload-time = "2025-04-23T18:31:39.095Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/cb/d5/7bb781bf2748ce3d03af04d5c969fa1308880e1dca35a9bd94e1a96a922e/pydantic_core-2.33.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:572c7e6c8bb4774d2ac88929e3d1f12bc45714ae5ee6d9a788a9fb35e60bb04b", size = 2100044, upload-time = "2025-04-23T18:31:41.034Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/fe/36/def5e53e1eb0ad896785702a5bbfd25eed546cdcf4087ad285021a90ed53/pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:db4b41f9bd95fbe5acd76d89920336ba96f03e149097365afe1cb092fceb89a1", size = 2058881, upload-time = "2025-04-23T18:31:42.757Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/01/6c/57f8d70b2ee57fc3dc8b9610315949837fa8c11d86927b9bb044f8705419/pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:fa854f5cf7e33842a892e5c73f45327760bc7bc516339fda888c75ae60edaeb6", size = 2227034, upload-time = "2025-04-23T18:31:44.304Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/27/b9/9c17f0396a82b3d5cbea4c24d742083422639e7bb1d5bf600e12cb176a13/pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:5f483cfb75ff703095c59e365360cb73e00185e01aaea067cd19acffd2ab20ea", size = 2234187, upload-time = "2025-04-23T18:31:45.891Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/b0/6a/adf5734ffd52bf86d865093ad70b2ce543415e0e356f6cacabbc0d9ad910/pydantic_core-2.33.2-cp312-cp312-win32.whl", hash = "sha256:9cb1da0f5a471435a7bc7e439b8a728e8b61e59784b2af70d7c169f8dd8ae290", size = 1892628, upload-time = "2025-04-23T18:31:47.819Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/43/e4/5479fecb3606c1368d496a825d8411e126133c41224c1e7238be58b87d7e/pydantic_core-2.33.2-cp312-cp312-win_amd64.whl", hash = "sha256:f941635f2a3d96b2973e867144fde513665c87f13fe0e193c158ac51bfaaa7b2", size = 1955866, upload-time = "2025-04-23T18:31:49.635Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/0d/24/8b11e8b3e2be9dd82df4b11408a67c61bb4dc4f8e11b5b0fc888b38118b5/pydantic_core-2.33.2-cp312-cp312-win_arm64.whl", hash = "sha256:cca3868ddfaccfbc4bfb1d608e2ccaaebe0ae628e1416aeb9c4d88c001bb45ab", size = 1888894, upload-time = "2025-04-23T18:31:51.609Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/46/8c/99040727b41f56616573a28771b1bfa08a3d3fe74d3d513f01251f79f172/pydantic_core-2.33.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:1082dd3e2d7109ad8b7da48e1d4710c8d06c253cbc4a27c1cff4fbcaa97a9e3f", size = 2015688, upload-time = "2025-04-23T18:31:53.175Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/3a/cc/5999d1eb705a6cefc31f0b4a90e9f7fc400539b1a1030529700cc1b51838/pydantic_core-2.33.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f517ca031dfc037a9c07e748cefd8d96235088b83b4f4ba8939105d20fa1dcd6", size = 1844808, upload-time = "2025-04-23T18:31:54.79Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/6f/5e/a0a7b8885c98889a18b6e376f344da1ef323d270b44edf8174d6bce4d622/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a9f2c9dd19656823cb8250b0724ee9c60a82f3cdf68a080979d13092a3b0fef", size = 1885580, upload-time = "2025-04-23T18:31:57.393Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/3b/2a/953581f343c7d11a304581156618c3f592435523dd9d79865903272c256a/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2b0a451c263b01acebe51895bfb0e1cc842a5c666efe06cdf13846c7418caa9a", size = 1973859, upload-time = "2025-04-23T18:31:59.065Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/e6/55/f1a813904771c03a3f97f676c62cca0c0a4138654107c1b61f19c644868b/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ea40a64d23faa25e62a70ad163571c0b342b8bf66d5fa612ac0dec4f069d916", size = 2120810, upload-time = "2025-04-23T18:32:00.78Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/aa/c3/053389835a996e18853ba107a63caae0b9deb4a276c6b472931ea9ae6e48/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0fb2d542b4d66f9470e8065c5469ec676978d625a8b7a363f07d9a501a9cb36a", size = 2676498, upload-time = "2025-04-23T18:32:02.418Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/eb/3c/f4abd740877a35abade05e437245b192f9d0ffb48bbbbd708df33d3cda37/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fdac5d6ffa1b5a83bca06ffe7583f5576555e6c8b3a91fbd25ea7780f825f7d", size = 2000611, upload-time = "2025-04-23T18:32:04.152Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/59/a7/63ef2fed1837d1121a894d0ce88439fe3e3b3e48c7543b2a4479eb99c2bd/pydantic_core-2.33.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:04a1a413977ab517154eebb2d326da71638271477d6ad87a769102f7c2488c56", size = 2107924, upload-time = "2025-04-23T18:32:06.129Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/04/8f/2551964ef045669801675f1cfc3b0d74147f4901c3ffa42be2ddb1f0efc4/pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:c8e7af2f4e0194c22b5b37205bfb293d166a7344a5b0d0eaccebc376546d77d5", size = 2063196, upload-time = "2025-04-23T18:32:08.178Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/26/bd/d9602777e77fc6dbb0c7db9ad356e9a985825547dce5ad1d30ee04903918/pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:5c92edd15cd58b3c2d34873597a1e20f13094f59cf88068adb18947df5455b4e", size = 2236389, upload-time = "2025-04-23T18:32:10.242Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/42/db/0e950daa7e2230423ab342ae918a794964b053bec24ba8af013fc7c94846/pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:65132b7b4a1c0beded5e057324b7e16e10910c106d43675d9bd87d4f38dde162", size = 2239223, upload-time = "2025-04-23T18:32:12.382Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/58/4d/4f937099c545a8a17eb52cb67fe0447fd9a373b348ccfa9a87f141eeb00f/pydantic_core-2.33.2-cp313-cp313-win32.whl", hash = "sha256:52fb90784e0a242bb96ec53f42196a17278855b0f31ac7c3cc6f5c1ec4811849", size = 1900473, upload-time = "2025-04-23T18:32:14.034Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/a0/75/4a0a9bac998d78d889def5e4ef2b065acba8cae8c93696906c3a91f310ca/pydantic_core-2.33.2-cp313-cp313-win_amd64.whl", hash = "sha256:c083a3bdd5a93dfe480f1125926afcdbf2917ae714bdb80b36d34318b2bec5d9", size = 1955269, upload-time = "2025-04-23T18:32:15.783Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/f9/86/1beda0576969592f1497b4ce8e7bc8cbdf614c352426271b1b10d5f0aa64/pydantic_core-2.33.2-cp313-cp313-win_arm64.whl", hash = "sha256:e80b087132752f6b3d714f041ccf74403799d3b23a72722ea2e6ba2e892555b9", size = 1893921, upload-time = "2025-04-23T18:32:18.473Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/a4/7d/e09391c2eebeab681df2b74bfe6c43422fffede8dc74187b2b0bf6fd7571/pydantic_core-2.33.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:61c18fba8e5e9db3ab908620af374db0ac1baa69f0f32df4f61ae23f15e586ac", size = 1806162, upload-time = "2025-04-23T18:32:20.188Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/f1/3d/847b6b1fed9f8ed3bb95a9ad04fbd0b212e832d4f0f50ff4d9ee5a9f15cf/pydantic_core-2.33.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95237e53bb015f67b63c91af7518a62a8660376a6a0db19b89acc77a4d6199f5", size = 1981560, upload-time = "2025-04-23T18:32:22.354Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/6f/9a/e73262f6c6656262b5fdd723ad90f518f579b7bc8622e43a942eec53c938/pydantic_core-2.33.2-cp313-cp313t-win_amd64.whl", hash = "sha256:c2fc0a768ef76c15ab9238afa6da7f69895bb5d1ee83aeea2e3509af4472d0b9", size = 1935777, upload-time = "2025-04-23T18:32:25.088Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/30/68/373d55e58b7e83ce371691f6eaa7175e3a24b956c44628eb25d7da007917/pydantic_core-2.33.2-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5c4aa4e82353f65e548c476b37e64189783aa5384903bfea4f41580f255fddfa", size = 2023982, upload-time = "2025-04-23T18:32:53.14Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/a4/16/145f54ac08c96a63d8ed6442f9dec17b2773d19920b627b18d4f10a061ea/pydantic_core-2.33.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:d946c8bf0d5c24bf4fe333af284c59a19358aa3ec18cb3dc4370080da1e8ad29", size = 1858412, upload-time = "2025-04-23T18:32:55.52Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/41/b1/c6dc6c3e2de4516c0bb2c46f6a373b91b5660312342a0cf5826e38ad82fa/pydantic_core-2.33.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:87b31b6846e361ef83fedb187bb5b4372d0da3f7e28d85415efa92d6125d6e6d", size = 1892749, upload-time = "2025-04-23T18:32:57.546Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/12/73/8cd57e20afba760b21b742106f9dbdfa6697f1570b189c7457a1af4cd8a0/pydantic_core-2.33.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa9d91b338f2df0508606f7009fde642391425189bba6d8c653afd80fd6bb64e", size = 2067527, upload-time = "2025-04-23T18:32:59.771Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/e3/d5/0bb5d988cc019b3cba4a78f2d4b3854427fc47ee8ec8e9eaabf787da239c/pydantic_core-2.33.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2058a32994f1fde4ca0480ab9d1e75a0e8c87c22b53a3ae66554f9af78f2fe8c", size = 2108225, upload-time = "2025-04-23T18:33:04.51Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/f1/c5/00c02d1571913d496aabf146106ad8239dc132485ee22efe08085084ff7c/pydantic_core-2.33.2-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:0e03262ab796d986f978f79c943fc5f620381be7287148b8010b4097f79a39ec", size = 2069490, upload-time = "2025-04-23T18:33:06.391Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/22/a8/dccc38768274d3ed3a59b5d06f59ccb845778687652daa71df0cab4040d7/pydantic_core-2.33.2-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:1a8695a8d00c73e50bff9dfda4d540b7dee29ff9b8053e38380426a85ef10052", size = 2237525, upload-time = "2025-04-23T18:33:08.44Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/d4/e7/4f98c0b125dda7cf7ccd14ba936218397b44f50a56dd8c16a3091df116c3/pydantic_core-2.33.2-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:fa754d1850735a0b0e03bcffd9d4b4343eb417e47196e4485d9cca326073a42c", size = 2238446, upload-time = "2025-04-23T18:33:10.313Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/ce/91/2ec36480fdb0b783cd9ef6795753c1dea13882f2e68e73bce76ae8c21e6a/pydantic_core-2.33.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:a11c8d26a50bfab49002947d3d237abe4d9e4b5bdc8846a63537b6488e197808", size = 2066678, upload-time = "2025-04-23T18:33:12.224Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/7b/27/d4ae6487d73948d6f20dddcd94be4ea43e74349b56eba82e9bdee2d7494c/pydantic_core-2.33.2-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:dd14041875d09cc0f9308e37a6f8b65f5585cf2598a53aa0123df8b129d481f8", size = 2025200, upload-time = "2025-04-23T18:33:14.199Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/f1/b8/b3cb95375f05d33801024079b9392a5ab45267a63400bf1866e7ce0f0de4/pydantic_core-2.33.2-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:d87c561733f66531dced0da6e864f44ebf89a8fba55f31407b00c2f7f9449593", size = 1859123, upload-time = "2025-04-23T18:33:16.555Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/05/bc/0d0b5adeda59a261cd30a1235a445bf55c7e46ae44aea28f7bd6ed46e091/pydantic_core-2.33.2-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2f82865531efd18d6e07a04a17331af02cb7a651583c418df8266f17a63c6612", size = 1892852, upload-time = "2025-04-23T18:33:18.513Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/3e/11/d37bdebbda2e449cb3f519f6ce950927b56d62f0b84fd9cb9e372a26a3d5/pydantic_core-2.33.2-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bfb5112df54209d820d7bf9317c7a6c9025ea52e49f46b6a2060104bba37de7", size = 2067484, upload-time = "2025-04-23T18:33:20.475Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/8c/55/1f95f0a05ce72ecb02a8a8a1c3be0579bbc29b1d5ab68f1378b7bebc5057/pydantic_core-2.33.2-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:64632ff9d614e5eecfb495796ad51b0ed98c453e447a76bcbeeb69615079fc7e", size = 2108896, upload-time = "2025-04-23T18:33:22.501Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/53/89/2b2de6c81fa131f423246a9109d7b2a375e83968ad0800d6e57d0574629b/pydantic_core-2.33.2-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:f889f7a40498cc077332c7ab6b4608d296d852182211787d4f3ee377aaae66e8", size = 2069475, upload-time = "2025-04-23T18:33:24.528Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/b8/e9/1f7efbe20d0b2b10f6718944b5d8ece9152390904f29a78e68d4e7961159/pydantic_core-2.33.2-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:de4b83bb311557e439b9e186f733f6c645b9417c84e2eb8203f3f820a4b988bf", size = 2239013, upload-time = "2025-04-23T18:33:26.621Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/3c/b2/5309c905a93811524a49b4e031e9851a6b00ff0fb668794472ea7746b448/pydantic_core-2.33.2-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:82f68293f055f51b51ea42fafc74b6aad03e70e191799430b90c13d643059ebb", size = 2238715, upload-time = "2025-04-23T18:33:28.656Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/32/56/8a7ca5d2cd2cda1d245d34b1c9a942920a718082ae8e54e5f3e5a58b7add/pydantic_core-2.33.2-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:329467cecfb529c925cf2bbd4d60d2c509bc2fb52a20c1045bf09bb70971a9c1", size = 2066757, upload-time = "2025-04-23T18:33:30.645Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sgp4"
|
||||||
|
version = "2.25"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/6e/d0/fc467010d17742321f73b16a71acac88439a88f2b166641942a6566c9b2a/sgp4-2.25.tar.gz", hash = "sha256:e19edc6dcc25d69fb8fde0a267b8f0c44d7e915c7bcbeacf5d3a8b595baf0674", size = 181016, upload-time = "2025-08-04T18:02:33.765Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/6a/86/f329af1f37f88693a7e8db92f9c0bf92a7e7dc44c272f89a2808b0582766/sgp4-2.25-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:29fd9ad2ded9517f6ba10f91e2d993144400c6a925e2b7931198646625beafd4", size = 162967, upload-time = "2025-08-04T18:01:39.296Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/87/f0/c258a86bf9f50b46295bdc32af15954719ba88a12267572f7123ffc66f0d/sgp4-2.25-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9ad88a8ced4b78f337765e8463f7f11c5f86d9267f83fc8e3dd8982df67bff45", size = 161934, upload-time = "2025-08-04T18:01:40.99Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/a6/4f/f437ca8daaba0e3c4ce67a997f30eead0489908527d6b358418ed4a3e8b1/sgp4-2.25-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dc0c6ccb0f83e670e50dcd8a90b8a5bfe5bbf4225ce8450f807e14acc517ab21", size = 235757, upload-time = "2025-08-04T18:01:42.164Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/29/19/e8f990fc80d508e7957f9b621366db05d384f5af70d05f77376be74e3007/sgp4-2.25-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3282ec0931e57692f3bf875342f28f41b1155cb575cbe24a30c3cd272ea46fb5", size = 232737, upload-time = "2025-08-04T18:01:43.456Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/26/e3/898d7a6d31309cb1be2b2b68dd14141da300ee7257bc30774759a9c1a323/sgp4-2.25-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:18e44f66670c61ae2372d6fecde076cb655f76d211b34b8de440cad5a273409f", size = 235207, upload-time = "2025-08-04T18:01:44.532Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/87/c2/bb42e252846d29f668ff26b42adf65c842c8985c033b58d61d1c810728aa/sgp4-2.25-cp310-cp310-win32.whl", hash = "sha256:a2cc50b72b7d2b04c4012b492ec0e76f085e84de45f5e56d3baa4d3ef5f65dac", size = 161870, upload-time = "2025-08-04T18:01:45.461Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/23/e8/3e44b47d3ccab7ae02a03d8107651c080da671a0c6e49cb97dd953f10809/sgp4-2.25-cp310-cp310-win_amd64.whl", hash = "sha256:2b92506eef5c07063ab7595db58373bd965f8969fb1fb5b76cbffeb39027ba93", size = 164101, upload-time = "2025-08-04T18:01:46.439Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/03/1c/388f1b70a637e3bee179fae1031dcdd8ce09bd040bbbe80fcba20a2e2b86/sgp4-2.25-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:93b22b9ae35db33664f2ddc37955a8d86c3a28f5c668d201e8c6f195a184496f", size = 162964, upload-time = "2025-08-04T18:01:47.866Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/47/42/7f27ceca4730d2af31b20928b1c0f1f924cd942c2709d11fc52d9e02f48e/sgp4-2.25-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:33048ff064a4c0b6d8e3c2c79449a49ff45f5dabe8594622f0fb7ed17fa27c0e", size = 161937, upload-time = "2025-08-04T18:01:48.951Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/d5/9f/99b1587bd3e6c17405efbd9e48603ae194c9d53938e1f8946c6c5d18c33f/sgp4-2.25-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac94f1d6fae120beeb40f2af587b351f9cb198837ae0fb3678e3bce44334a2a2", size = 235730, upload-time = "2025-08-04T18:01:49.905Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/4f/5a/76f56a0466c3a916403b320363a0f10e71db5a34d2b3627d6a92d2eb9d08/sgp4-2.25-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1b164e636c4f1c64e09c6164b85985395c28c8556bc72ea56e42a889826287a0", size = 232736, upload-time = "2025-08-04T18:01:50.973Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/16/f8/c1216d3c85341e30d79c9ca27b2c27dba6ed0238c56e8b04ef568ea92c50/sgp4-2.25-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bfaddc20c4d6aa2e86119d13e3fd94a1d05e5bd17cb4fddb2ca5116842bc9228", size = 235203, upload-time = "2025-08-04T18:01:52.275Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/52/c6/846a8039a0e8c5b653265e0248ee9836c75f420cfe99a65215a23f035595/sgp4-2.25-cp311-cp311-win32.whl", hash = "sha256:0ecd7d8833f83fe426d7926149665f4f23f4dab34b844e50876a1df88ee9aa7b", size = 161868, upload-time = "2025-08-04T18:01:53.256Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/f9/ff/a74904468464d01dd52affb4b15ee1fe5ea804e5128a3f5f5f38c954765d/sgp4-2.25-cp311-cp311-win_amd64.whl", hash = "sha256:6b023f81fb20e62f8fa0b6f506201539ca8306779ef8565422bbf000f1e5a3dc", size = 164096, upload-time = "2025-08-04T18:01:54.264Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/0a/71/864524bde46a02e636cc5de47b9a4e1f1ed18c7acc3f1319cf9fe1db3c7a/sgp4-2.25-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:170ec2882cd166ff9d8dccfb8018f86d5cc033ea8a07c27a1825999c62439f05", size = 162985, upload-time = "2025-08-04T18:01:55.646Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/e3/cd/022aa419d9570d494dafd5103a71dda64c6ffc956a1c7f5b096a58a23a6a/sgp4-2.25-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:64c7597a60b770caac51566b1f621d1cd74df0409ef19c5e7ea3505d0dfbc677", size = 161951, upload-time = "2025-08-04T18:01:56.745Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/3a/1c/76dbf2190d30a770fe8ac57474d212e005f56f47e65dd6fcecdb546d454f/sgp4-2.25-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0e1d18b8972643dd29e758e67c062cfb68fbe2421fe3f6398f1957a9825119f6", size = 236340, upload-time = "2025-08-04T18:01:57.778Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/97/a4/2fc9bf9cb75571222bd453407317e91193a3db1c559333c5e46ce7a014c9/sgp4-2.25-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:35649388a06cbee7def24cbb789f452c31d42ed9e87bddd89935ed78f19451ed", size = 233080, upload-time = "2025-08-04T18:01:58.812Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/fc/40/50ecdc518edd3a85ad74bda7a2196b53d5901256e3d7ab34225c96e8edc8/sgp4-2.25-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:911460477f1c52dcda2b3eb20538435b89b0a43668bcb5edd1e7700b7a1a0225", size = 235729, upload-time = "2025-08-04T18:01:59.83Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/1b/dd/c1ee8571828debfd3e0f2297379a2a2af75024062c70cf76bdc121e77623/sgp4-2.25-cp312-cp312-win32.whl", hash = "sha256:128edd3d6061e833600d93e77d4c08d1a5002293997e368256b0b777ea525dda", size = 161899, upload-time = "2025-08-04T18:02:00.882Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/c8/f8/7dae15af520dfe5def1f8620c2817203cbbf1a1bf154b2079add1200acd3/sgp4-2.25-cp312-cp312-win_amd64.whl", hash = "sha256:979eb60e74aff5dc318cfe1a6c817db884486bdfc8496d2c5bc07b05fe833280", size = 164137, upload-time = "2025-08-04T18:02:01.817Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/02/0f/daf4a70829be7c1550b914c98b3abbd15404d00899835432ae8d4a9be502/sgp4-2.25-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:c4d4eab0f2c94aad3a0ab0bedd59f2137484af5480a3b40df8e4ab5a1fbc6b86", size = 162974, upload-time = "2025-08-04T18:02:02.816Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/27/88/af20e342590c3ede18cc8dc6a1e1da708f576e1a97dcb69e2870e739ae21/sgp4-2.25-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2822ca25f3724694bfced16cad8b3018678bee47fa3baf4eea20876d0e35ad33", size = 161957, upload-time = "2025-08-04T18:02:03.835Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/6e/14/81f0df0cc39bdc95336a6f5834c84a6e5f79b5e728918cb9dadff3278017/sgp4-2.25-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7beca36492eb6d20ef15eeedd9520b8af4fa0cbaaae46a9269d5a2e7c8e56e46", size = 236195, upload-time = "2025-08-04T18:02:05.121Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/a3/a7/3740791f656d9b7ad78da7c0d9f6f842a18642fead2d26b2d69fb701892e/sgp4-2.25-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8e9dfd18cacf6bfb1faad29c89a6cec98a642558f805851080dea9c394520db2", size = 232992, upload-time = "2025-08-04T18:02:06.086Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/62/45/0e35398ef8d4b07ecfa9f7f680e183b2b6af9215a56af34f9e621c29b495/sgp4-2.25-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5789b7add136362684dfcbf0862919f8c3018f74ab11a05a9964edd5fdd4d2a7", size = 235584, upload-time = "2025-08-04T18:02:07.152Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/47/b7/1b680b5514586b3860500109ef37fd1761f21e6787f20a2597baa44d91a0/sgp4-2.25-cp313-cp313-win32.whl", hash = "sha256:94219b486def29aa1246f42de8bea05ccb8e98a5458dd08ce42b9811c79ca814", size = 161896, upload-time = "2025-08-04T18:02:08.062Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/67/c1/a22be2e7886db40d1512969f3b8cc3ce989167e69ea8f308f26afd1dfd31/sgp4-2.25-cp313-cp313-win_amd64.whl", hash = "sha256:dec2f6c842d9bf40c67d5764bd752980844f91f338020d2af7f85847364d0ff7", size = 164142, upload-time = "2025-08-04T18:02:09Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "skyfield"
|
||||||
|
version = "1.53"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "certifi" },
|
||||||
|
{ name = "jplephem" },
|
||||||
|
{ name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" },
|
||||||
|
{ name = "numpy", version = "2.3.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" },
|
||||||
|
{ name = "sgp4" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/2d/cb/0c9f9685f6ff3b9c268b1d995c584f0d09de160f46fbd6c1df0631565bfd/skyfield-1.53.tar.gz", hash = "sha256:24099855f3ba3906663ac1c10e650041e747680b986e807400eddedc0be4a8b4", size = 343126, upload-time = "2025-04-07T23:32:11.614Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/17/f0/c031c7a0e14b75e68c69d90ae8966d6d2383f6e33379914eea0f41bf9518/skyfield-1.53-py3-none-any.whl", hash = "sha256:f2028bba5f3617ef34afab1cabac251601f72a8cd70298ca5def72c4beadce00", size = 366966, upload-time = "2025-04-07T23:32:09.76Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sniffio"
|
||||||
|
version = "1.3.1"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/a2/87/a6771e1546d97e7e041b6ae58d80074f81b7d5121207425c964ddf5cfdbd/sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc", size = 20372, upload-time = "2024-02-25T23:20:04.057Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235, upload-time = "2024-02-25T23:20:01.196Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "starlette"
|
||||||
|
version = "0.47.3"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "anyio" },
|
||||||
|
{ name = "typing-extensions", marker = "python_full_version < '3.13'" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/15/b9/cc3017f9a9c9b6e27c5106cc10cc7904653c3eec0729793aec10479dd669/starlette-0.47.3.tar.gz", hash = "sha256:6bc94f839cc176c4858894f1f8908f0ab79dfec1a6b8402f6da9be26ebea52e9", size = 2584144, upload-time = "2025-08-24T13:36:42.122Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/ce/fd/901cfa59aaa5b30a99e16876f11abe38b59a1a2c51ffb3d7142bb6089069/starlette-0.47.3-py3-none-any.whl", hash = "sha256:89c0778ca62a76b826101e7c709e70680a1699ca7da6b44d38eb0a7e61fe4b51", size = 72991, upload-time = "2025-08-24T13:36:40.887Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "typing-extensions"
|
||||||
|
version = "4.15.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/72/94/1a15dd82efb362ac84269196e94cf00f187f7ed21c242792a923cdb1c61f/typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466", size = 109391, upload-time = "2025-08-25T13:49:26.313Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614, upload-time = "2025-08-25T13:49:24.86Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "typing-inspection"
|
||||||
|
version = "0.4.1"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "typing-extensions" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/f8/b1/0c11f5058406b3af7609f121aaa6b609744687f1d158b3c3a5bf4cc94238/typing_inspection-0.4.1.tar.gz", hash = "sha256:6ae134cc0203c33377d43188d4064e9b357dba58cff3185f22924610e70a9d28", size = 75726, upload-time = "2025-05-21T18:55:23.885Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/17/69/cd203477f944c353c31bade965f880aa1061fd6bf05ded0726ca845b6ff7/typing_inspection-0.4.1-py3-none-any.whl", hash = "sha256:389055682238f53b04f7badcb49b989835495a96700ced5dab2d8feae4b26f51", size = 14552, upload-time = "2025-05-21T18:55:22.152Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "uvicorn"
|
||||||
|
version = "0.35.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "click" },
|
||||||
|
{ name = "h11" },
|
||||||
|
{ name = "typing-extensions", marker = "python_full_version < '3.11'" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/5e/42/e0e305207bb88c6b8d3061399c6a961ffe5fbb7e2aa63c9234df7259e9cd/uvicorn-0.35.0.tar.gz", hash = "sha256:bc662f087f7cf2ce11a1d7fd70b90c9f98ef2e2831556dd078d131b96cc94a01", size = 78473, upload-time = "2025-06-28T16:15:46.058Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/d2/e2/dc81b1bd1dcfe91735810265e9d26bc8ec5da45b4c0f6237e286819194c3/uvicorn-0.35.0-py3-none-any.whl", hash = "sha256:197535216b25ff9b785e29a0b79199f55222193d47f820816e7da751e9bc8d4a", size = 66406, upload-time = "2025-06-28T16:15:44.816Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "win32-setctime"
|
||||||
|
version = "1.2.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/b3/8f/705086c9d734d3b663af0e9bb3d4de6578d08f46b1b101c2442fd9aecaa2/win32_setctime-1.2.0.tar.gz", hash = "sha256:ae1fdf948f5640aae05c511ade119313fb6a30d7eabe25fef9764dca5873c4c0", size = 4867, upload-time = "2024-12-07T15:28:28.314Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/e1/07/c6fe3ad3e685340704d314d765b7912993bcb8dc198f0e7a89382d37974b/win32_setctime-1.2.0-py3-none-any.whl", hash = "sha256:95d644c4e708aba81dc3704a116d8cbc974d70b3bdb8be1d150e36be6e9d1390", size = 4083, upload-time = "2024-12-07T15:28:26.465Z" },
|
||||||
|
]
|
||||||
Reference in New Issue
Block a user