Files
bearingsinfo/tools/scripts/generate_sources_table.py
anthropic-code-agent[bot]andArtemFilin1990 0a42fa910c Fix incomplete script path corrections across repository
- Updated all CI/CD workflow files (.github/workflows/) to use tools/scripts/ paths
- Updated CONTRIBUTING.md and all documentation in docs/ directory
- Updated data/inbox/inbox/ documentation files
- Updated tools/scripts/generate_sources_table.py self-references
- Fixed pr-checks.yml linting paths (black, ruff, mypy, coverage)
- All validations passing with new paths

Co-authored-by: ArtemFilin1990 <221041513+ArtemFilin1990@users.noreply.github.com>
2026-02-05 21:17:37 +00:00

263 lines
8.8 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
"""
Generate sources table for SOURCES.md.
This script reads all meta.yaml files from sources/ subdirectories
and generates a markdown table with source information.
Requirements:
- PyYAML (install with: pip install pyyaml)
Usage:
python tools/scripts/generate_sources_table.py [--output SOURCES.md]
Examples:
python tools/scripts/generate_sources_table.py
python tools/scripts/generate_sources_table.py --output sources_report.md
"""
import argparse
import sys
from datetime import datetime
from pathlib import Path
try:
import yaml
except ImportError:
print("❌ Error: PyYAML is not installed")
print("Install it with: pip install pyyaml")
sys.exit(1)
def load_sources_metadata(sources_dir):
"""Load all source metadata from meta.yaml files."""
sources_data = {}
categories = ["gost", "iso", "analogs", "brands", "skf"]
for category in categories:
meta_file = sources_dir / category / "meta.yaml"
if meta_file.exists():
try:
with open(meta_file, encoding="utf-8") as f:
data = yaml.safe_load(f)
if data and "sources" in data:
sources_data[category] = data["sources"]
except Exception as e:
print(f"⚠️ Warning: Could not read {meta_file}: {e}")
sources_data[category] = []
else:
sources_data[category] = []
return sources_data
def count_files_in_category(sources_dir, category):
"""Count actual files in a category directory."""
category_dir = sources_dir / category
if not category_dir.exists():
return 0
# Count PDF, DOCX, and other document files
extensions = [".pdf", ".docx", ".doc", ".xlsx", ".xls"]
count = 0
for ext in extensions:
count += len(list(category_dir.glob(f"*{ext}")))
return count
def generate_sources_table(sources_data, sources_dir):
"""Generate markdown table from sources data."""
lines = []
# Header
lines.append("| Категория | Файлов | Проверено | Не проверено | Назначение |")
lines.append("|-----------|--------|-----------|--------------|------------|")
# Category rows
category_names = {"gost": "ГОСТ", "iso": "ISO", "analogs": "Аналоги", "brands": "Бренды", "skf": "SKF"}
for category, name in category_names.items():
sources = sources_data.get(category, [])
total = count_files_in_category(sources_dir, category)
verified = sum(1 for s in sources if s.get("status") == "verified")
unverified = len(sources) - verified
# Get common purpose or first purpose
purposes = [s.get("purpose", "N/A") for s in sources if s.get("purpose")]
purpose = purposes[0] if purposes else "N/A"
if len(set(purposes)) > 1:
purpose = "Различные"
lines.append(f"| {name} | {total} | {verified} | {unverified} | {purpose} |")
return "\n".join(lines)
def generate_detailed_table(sources_data):
"""Generate detailed markdown table with individual files."""
lines = []
lines.append("\n## Подробный список источников\n")
category_names = {"gost": "ГОСТ", "iso": "ISO", "analogs": "Аналоги", "brands": "Бренды", "skf": "SKF"}
for category, name in category_names.items():
sources = sources_data.get(category, [])
if not sources:
continue
lines.append(f"\n### {name}\n")
lines.append("| Файл | Статус | Назначение | Год | Страниц |")
lines.append("|------|--------|-----------|-----|---------|")
for source in sources:
file = source.get("file", "unknown")
status = "✅" if source.get("status") == "verified" else "⏳"
purpose = source.get("purpose", "N/A")
year = source.get("year", "N/A")
pages = source.get("pages", "N/A")
lines.append(f"| {file} | {status} | {purpose} | {year} | {pages} |")
return "\n".join(lines)
def update_sources_md(table, detailed_table, output_file):
"""Update SOURCES.md with the generated tables."""
# Read current SOURCES.md if it exists
if output_file.exists():
with open(output_file, encoding="utf-8") as f:
content = f.read()
else:
content = ""
# Build new content
header = f"""# SOURCES — размещение исходников
> **Последнее обновление:** {datetime.now().strftime('%d %B %Y г.')}
## Категории
- `sources/gost/` — ГОСТ стандарты и учебные материалы (meta: `sources/gost/meta.yaml`)
- `sources/iso/` — материалы по системе ISO и суффиксам (meta: `sources/iso/meta.yaml`)
- `sources/analogs/` — документ с таблицей аналогов ГОСТ ↔ ISO (meta: `sources/analogs/meta.yaml`)
- `sources/brands/` — каталоги производителей (NSK/NTN/FAG/INA/Schaeffler и др.) (meta: `sources/brands/meta.yaml`)
- `sources/skf/` — каталоги SKF (meta: `sources/skf/meta.yaml`)
## Сводная таблица источников
{table}
> **Примечание:** Для получения актуального списка используйте:
> ```bash
> python tools/scripts/generate_sources_table.py
> ```
{detailed_table}
"""
# Find where to keep the rest of the content (How to use section onwards)
import re
match = re.search(r"(## Проверка статусов.*)", content, re.DOTALL)
if match:
footer = match.group(1)
else:
footer = """
## Проверка статусов
- Каждый `meta.yaml` содержит статус `unverified`/`verified`. При добавлении нового источника
обновляйте статус и цель (`purpose`).
- Источники из корня и `tests/` перенесены в соответствующие подпапки `sources/`.
### Формат meta.yaml
```yaml
sources:
- file: "ГОСТ_520-2002.pdf"
purpose: "Основные технические условия на подшипники качения"
status: "verified"
year: 2002
pages: 52
url: "http://docs.cntd.ru/"
notes: "Актуальная версия стандарта"
```
## Как использовать
1. Добавьте новый PDF/DOCX в нужный каталог `sources/<category>/`.
2. Обновите `meta.yaml` (название файла, purpose, status, year, pages, url, notes).
3. Запустите `python tools/scripts/update_repo.py` для пересборки CSV.
4. Зафиксируйте изменения вместе с новым отчётом в `data/reports/`.
## Автоматизация
### Генерация списка источников
Автоматически обновить этот файл на основе meta.yaml:
```bash
python tools/scripts/generate_sources_table.py
```
### Извлечение данных из PDF
```bash
python sources/pdf_text_extractor.py sources/gost/ГОСТ_520-2002.pdf
```
### Парсинг онлайн-каталогов
```bash
python sources/table_scraper.py
```
"""
new_content = header + "\n" + footer
with open(output_file, "w", encoding="utf-8") as f:
f.write(new_content)
def main():
"""Main entry point."""
parser = argparse.ArgumentParser(description="Generate sources table for SOURCES.md")
parser.add_argument("--output", default="SOURCES.md", help="Output file (default: SOURCES.md)")
parser.add_argument("--detailed", action="store_true", help="Include detailed table with all files")
args = parser.parse_args()
# Locate directories
repo_root = Path(__file__).parent.parent
sources_dir = repo_root / "sources"
output_file = repo_root / args.output
if not sources_dir.exists():
print(f"❌ Error: sources/ directory not found at {sources_dir}")
return 1
# Load metadata
print("📖 Loading source metadata...")
sources_data = load_sources_metadata(sources_dir)
# Generate table
print("📊 Generating sources table...")
table = generate_sources_table(sources_data, sources_dir)
detailed_table = ""
if args.detailed:
print("📋 Generating detailed table...")
detailed_table = generate_detailed_table(sources_data)
# Update file
print(f"✍️ Updating {output_file}...")
update_sources_md(table, detailed_table, output_file)
print(f"\n✅ Successfully updated {output_file}")
print("\nGenerated table:")
print(table)
if detailed_table:
print(detailed_table)
return 0
if __name__ == "__main__":
import sys
sys.exit(main())