mirror of
https://github.com/kuhyx/testsAndMisc.git
synced 2026-07-04 15:03:01 +02:00
Add Warsaw districts Anki generator with tests and documentation
Co-authored-by: kuhyx <147418882+kuhyx@users.noreply.github.com>
This commit is contained in:
parent
b20e3576e6
commit
452b93f42b
111
python_pkg/warsaw_districts/README.md
Normal file
111
python_pkg/warsaw_districts/README.md
Normal file
@ -0,0 +1,111 @@
|
||||
# Warsaw Districts Anki Generator
|
||||
|
||||
Generate Anki flashcards for learning the 18 districts (dzielnice) of Warsaw, Poland.
|
||||
|
||||
## Features
|
||||
|
||||
- Generates flashcards for all 18 Warsaw districts
|
||||
- Front of card: Map showing only the district in question with its borders highlighted
|
||||
- Back of card: District name in Polish
|
||||
- Anki-compatible output format (semicolon-separated)
|
||||
- Compatible with AnkiWeb and AnkiDroid
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
pip install matplotlib
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### Generate flashcards
|
||||
|
||||
```bash
|
||||
# From the repository root
|
||||
python -m python_pkg.warsaw_districts.warsaw_districts_anki
|
||||
```
|
||||
|
||||
This creates:
|
||||
- `warsaw_districts_anki.txt` - Anki import file
|
||||
- `warsaw_districts_images/` - Directory with 18 PNG map images
|
||||
|
||||
### Custom options
|
||||
|
||||
```bash
|
||||
# Custom output file and image directory
|
||||
python -m python_pkg.warsaw_districts.warsaw_districts_anki \
|
||||
--output my_cards.txt \
|
||||
--image-dir my_maps
|
||||
|
||||
# Custom deck name
|
||||
python -m python_pkg.warsaw_districts.warsaw_districts_anki \
|
||||
--deck-name "Warszawa - Dzielnice"
|
||||
```
|
||||
|
||||
## Importing into Anki
|
||||
|
||||
1. Open Anki
|
||||
2. File → Import
|
||||
3. Select the generated `warsaw_districts_anki.txt` file
|
||||
4. Copy all images from `warsaw_districts_images/` to your Anki profile's `collection.media` folder
|
||||
- On Linux: `~/.local/share/Anki2/[Profile]/collection.media/`
|
||||
- On Windows: `%APPDATA%\Anki2\[Profile]\collection.media\`
|
||||
- On macOS: `~/Library/Application Support/Anki2/[Profile]/collection.media/`
|
||||
5. Click Import
|
||||
|
||||
## Warsaw Districts
|
||||
|
||||
The generator includes all 18 official districts of Warsaw:
|
||||
|
||||
1. Bemowo
|
||||
2. Białołęka
|
||||
3. Bielany
|
||||
4. Mokotów
|
||||
5. Ochota
|
||||
6. Praga-Południe
|
||||
7. Praga-Północ
|
||||
8. Rembertów
|
||||
9. Śródmieście
|
||||
10. Targówek
|
||||
11. Ursus
|
||||
12. Ursynów
|
||||
13. Wawer
|
||||
14. Wesoła
|
||||
15. Wilanów
|
||||
16. Włochy
|
||||
17. Wola
|
||||
18. Żoliborz
|
||||
|
||||
## Output Format
|
||||
|
||||
The generated file uses Anki's standard import format:
|
||||
|
||||
```
|
||||
#separator:semicolon
|
||||
#html:true
|
||||
#deck:Warsaw Districts
|
||||
#tags:geography warsaw poland
|
||||
#columns:Front;Back
|
||||
|
||||
<img src="Bemowo.png">;Bemowo
|
||||
<img src="Białołęka.png">;Białołęka
|
||||
...
|
||||
```
|
||||
|
||||
## Development
|
||||
|
||||
### Running tests
|
||||
|
||||
```bash
|
||||
pytest python_pkg/warsaw_districts/tests/
|
||||
```
|
||||
|
||||
### Code quality
|
||||
|
||||
```bash
|
||||
ruff check python_pkg/warsaw_districts/
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
Same as the parent repository.
|
||||
5
python_pkg/warsaw_districts/__init__.py
Normal file
5
python_pkg/warsaw_districts/__init__.py
Normal file
@ -0,0 +1,5 @@
|
||||
"""Warsaw districts Anki flashcard generator."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
__all__ = ["generate_anki_deck", "main"]
|
||||
5
python_pkg/warsaw_districts/tests/__init__.py
Normal file
5
python_pkg/warsaw_districts/tests/__init__.py
Normal file
@ -0,0 +1,5 @@
|
||||
"""Tests init file."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
__all__: list[str] = []
|
||||
206
python_pkg/warsaw_districts/tests/test_warsaw_districts_anki.py
Normal file
206
python_pkg/warsaw_districts/tests/test_warsaw_districts_anki.py
Normal file
@ -0,0 +1,206 @@
|
||||
"""Tests for the Warsaw districts Anki generator."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
try:
|
||||
from python_pkg.warsaw_districts.warsaw_districts_anki import (
|
||||
WARSAW_DISTRICTS,
|
||||
create_district_map,
|
||||
generate_anki_deck,
|
||||
main,
|
||||
save_district_image,
|
||||
)
|
||||
except ImportError:
|
||||
import sys
|
||||
|
||||
sys.path.insert(0, str(Path(__file__).parent.parent.parent.parent))
|
||||
from python_pkg.warsaw_districts.warsaw_districts_anki import (
|
||||
WARSAW_DISTRICTS,
|
||||
create_district_map,
|
||||
generate_anki_deck,
|
||||
main,
|
||||
save_district_image,
|
||||
)
|
||||
|
||||
|
||||
class TestDistricts:
|
||||
"""Tests for Warsaw districts data."""
|
||||
|
||||
def test_has_18_districts(self) -> None:
|
||||
"""Test that we have exactly 18 Warsaw districts."""
|
||||
assert len(WARSAW_DISTRICTS) == 18
|
||||
|
||||
def test_all_districts_have_names(self) -> None:
|
||||
"""Test that all districts have non-empty names."""
|
||||
for district in WARSAW_DISTRICTS:
|
||||
assert district.name
|
||||
assert isinstance(district.name, str)
|
||||
assert len(district.name) > 0
|
||||
|
||||
def test_all_districts_have_valid_coordinates(self) -> None:
|
||||
"""Test that all districts have coordinates in valid range."""
|
||||
for district in WARSAW_DISTRICTS:
|
||||
assert 0 <= district.x <= 1
|
||||
assert 0 <= district.y <= 1
|
||||
|
||||
def test_districts_are_unique(self) -> None:
|
||||
"""Test that all district names are unique."""
|
||||
names = [d.name for d in WARSAW_DISTRICTS]
|
||||
assert len(names) == len(set(names))
|
||||
|
||||
def test_known_districts_present(self) -> None:
|
||||
"""Test that known Warsaw districts are in the list."""
|
||||
district_names = {d.name for d in WARSAW_DISTRICTS}
|
||||
# Check a few well-known districts
|
||||
assert "Śródmieście" in district_names
|
||||
assert "Mokotów" in district_names
|
||||
assert "Praga-Północ" in district_names
|
||||
assert "Żoliborz" in district_names
|
||||
|
||||
|
||||
class TestCreateDistrictMap:
|
||||
"""Tests for creating district maps."""
|
||||
|
||||
def test_creates_figure(self) -> None:
|
||||
"""Test that create_district_map returns a Figure."""
|
||||
district = WARSAW_DISTRICTS[0]
|
||||
fig = create_district_map(district)
|
||||
assert fig is not None
|
||||
# Clean up
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
plt.close(fig)
|
||||
|
||||
def test_creates_figure_for_all_districts(self) -> None:
|
||||
"""Test that we can create maps for all districts."""
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
for district in WARSAW_DISTRICTS:
|
||||
fig = create_district_map(district)
|
||||
assert fig is not None
|
||||
plt.close(fig)
|
||||
|
||||
|
||||
class TestSaveDistrictImage:
|
||||
"""Tests for saving district images."""
|
||||
|
||||
def test_saves_image_file(self, tmp_path: Path) -> None:
|
||||
"""Test that save_district_image creates a file."""
|
||||
district = WARSAW_DISTRICTS[0]
|
||||
image_path = save_district_image(district, tmp_path)
|
||||
|
||||
assert image_path.exists()
|
||||
assert image_path.suffix == ".png"
|
||||
assert image_path.parent == tmp_path
|
||||
|
||||
def test_saves_all_district_images(self, tmp_path: Path) -> None:
|
||||
"""Test that we can save images for all districts."""
|
||||
for district in WARSAW_DISTRICTS:
|
||||
image_path = save_district_image(district, tmp_path)
|
||||
assert image_path.exists()
|
||||
|
||||
|
||||
class TestGenerateAnkiDeck:
|
||||
"""Tests for generating Anki deck content."""
|
||||
|
||||
def test_generates_valid_header(self, tmp_path: Path) -> None:
|
||||
"""Test that output contains valid Anki headers."""
|
||||
result = generate_anki_deck(tmp_path, "Test Deck")
|
||||
|
||||
assert "#separator:semicolon" in result
|
||||
assert "#deck:Test Deck" in result
|
||||
assert "#html:true" in result
|
||||
|
||||
def test_generates_flashcard_for_all_districts(self, tmp_path: Path) -> None:
|
||||
"""Test that output contains cards for all 18 districts."""
|
||||
result = generate_anki_deck(tmp_path)
|
||||
|
||||
# Check that all district names appear in the output
|
||||
for district in WARSAW_DISTRICTS:
|
||||
assert district.name in result
|
||||
|
||||
def test_generates_images_for_all_districts(self, tmp_path: Path) -> None:
|
||||
"""Test that images are generated for all districts."""
|
||||
generate_anki_deck(tmp_path)
|
||||
|
||||
# Check that all image files were created
|
||||
image_files = list(tmp_path.glob("*.png"))
|
||||
assert len(image_files) == 18
|
||||
|
||||
def test_output_format(self, tmp_path: Path) -> None:
|
||||
"""Test that output has correct semicolon-separated format."""
|
||||
result = generate_anki_deck(tmp_path)
|
||||
|
||||
lines = result.split("\n")
|
||||
# Skip header lines and empty lines
|
||||
data_lines = [
|
||||
line for line in lines if line and not line.startswith("#")
|
||||
]
|
||||
|
||||
# Each data line should have exactly 2 fields (front;back)
|
||||
for line in data_lines:
|
||||
fields = line.split(";")
|
||||
assert len(fields) == 2
|
||||
# Front should contain <img src=
|
||||
assert "<img src=" in fields[0]
|
||||
# Back should be a district name
|
||||
assert fields[1] in {d.name for d in WARSAW_DISTRICTS}
|
||||
|
||||
|
||||
class TestMain:
|
||||
"""Tests for the main CLI function."""
|
||||
|
||||
def test_creates_output_file(self, tmp_path: Path) -> None:
|
||||
"""Test that main creates the output file."""
|
||||
output_file = tmp_path / "test_output.txt"
|
||||
image_dir = tmp_path / "images"
|
||||
|
||||
result = main([
|
||||
"--output", str(output_file),
|
||||
"--image-dir", str(image_dir),
|
||||
])
|
||||
|
||||
assert result == 0
|
||||
assert output_file.exists()
|
||||
assert image_dir.exists()
|
||||
|
||||
def test_creates_images(self, tmp_path: Path) -> None:
|
||||
"""Test that main creates image files."""
|
||||
output_file = tmp_path / "test_output.txt"
|
||||
image_dir = tmp_path / "images"
|
||||
|
||||
main([
|
||||
"--output", str(output_file),
|
||||
"--image-dir", str(image_dir),
|
||||
])
|
||||
|
||||
image_files = list(image_dir.glob("*.png"))
|
||||
assert len(image_files) == 18
|
||||
|
||||
def test_custom_deck_name(self, tmp_path: Path) -> None:
|
||||
"""Test that custom deck name is used."""
|
||||
output_file = tmp_path / "test_output.txt"
|
||||
image_dir = tmp_path / "images"
|
||||
|
||||
main([
|
||||
"--output", str(output_file),
|
||||
"--image-dir", str(image_dir),
|
||||
"--deck-name", "Custom Deck",
|
||||
])
|
||||
|
||||
content = output_file.read_text()
|
||||
assert "#deck:Custom Deck" in content
|
||||
|
||||
def test_help_flag(self) -> None:
|
||||
"""Test that --help works."""
|
||||
with pytest.raises(SystemExit) as exc_info:
|
||||
main(["--help"])
|
||||
assert exc_info.value.code == 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
pytest.main([__file__, "-v"])
|
||||
308
python_pkg/warsaw_districts/warsaw_districts_anki.py
Executable file
308
python_pkg/warsaw_districts/warsaw_districts_anki.py
Executable file
@ -0,0 +1,308 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Anki flashcard generator for Warsaw districts.
|
||||
|
||||
Generates Anki-compatible flashcard decks with maps showing individual
|
||||
Warsaw districts (dzielnice) with their borders.
|
||||
|
||||
Usage:
|
||||
# Generate Anki cards for all Warsaw districts
|
||||
python -m python_pkg.warsaw_districts.warsaw_districts_anki
|
||||
|
||||
# Specify custom output file
|
||||
python -m python_pkg.warsaw_districts.warsaw_districts_anki --output warsaw.txt
|
||||
|
||||
# Specify custom output directory for images
|
||||
python -m python_pkg.warsaw_districts.warsaw_districts_anki --image-dir ./maps
|
||||
|
||||
Output:
|
||||
Creates a semicolon-separated text file that can be imported into Anki.
|
||||
Format: <img src="district_name.png">;district_name_in_polish
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import base64
|
||||
from io import BytesIO
|
||||
from pathlib import Path
|
||||
import sys
|
||||
from typing import TYPE_CHECKING, NamedTuple
|
||||
|
||||
import matplotlib.patches as mpatches
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from collections.abc import Sequence
|
||||
|
||||
from matplotlib.figure import Figure
|
||||
|
||||
|
||||
class District(NamedTuple):
|
||||
"""A Warsaw district with its approximate position."""
|
||||
|
||||
name: str # Polish name
|
||||
x: float # Approximate x coordinate (0-1)
|
||||
y: float # Approximate y coordinate (0-1)
|
||||
|
||||
|
||||
# Warsaw districts (dzielnice) - 18 total
|
||||
# Coordinates are approximate relative positions for visualization
|
||||
WARSAW_DISTRICTS: list[District] = [
|
||||
District("Bemowo", 0.15, 0.55),
|
||||
District("Białołęka", 0.75, 0.7),
|
||||
District("Bielany", 0.35, 0.75),
|
||||
District("Mokotów", 0.45, 0.3),
|
||||
District("Ochota", 0.3, 0.45),
|
||||
District("Praga-Południe", 0.7, 0.35),
|
||||
District("Praga-Północ", 0.7, 0.6),
|
||||
District("Rembertów", 0.85, 0.5),
|
||||
District("Śródmieście", 0.5, 0.5),
|
||||
District("Targówek", 0.65, 0.8),
|
||||
District("Ursus", 0.05, 0.4),
|
||||
District("Ursynów", 0.5, 0.15),
|
||||
District("Wawer", 0.8, 0.25),
|
||||
District("Wesoła", 0.9, 0.45),
|
||||
District("Wilanów", 0.6, 0.1),
|
||||
District("Włochy", 0.15, 0.3),
|
||||
District("Wola", 0.35, 0.6),
|
||||
District("Żoliborz", 0.45, 0.7),
|
||||
]
|
||||
|
||||
|
||||
def create_district_map(
|
||||
district: District, *, highlight_only: bool = True
|
||||
) -> Figure:
|
||||
"""Create a map showing Warsaw districts with one district highlighted.
|
||||
|
||||
Args:
|
||||
district: The district to highlight.
|
||||
highlight_only: If True, show only the highlighted district's border.
|
||||
|
||||
Returns:
|
||||
A matplotlib Figure object.
|
||||
"""
|
||||
fig, ax = plt.subplots(figsize=(8, 8))
|
||||
ax.set_xlim(0, 1)
|
||||
ax.set_ylim(0, 1)
|
||||
ax.set_aspect("equal")
|
||||
ax.axis("off")
|
||||
|
||||
# Draw all districts as points if not highlight_only
|
||||
if not highlight_only:
|
||||
for dist in WARSAW_DISTRICTS:
|
||||
if dist.name != district.name:
|
||||
circle = mpatches.Circle(
|
||||
(dist.x, dist.y),
|
||||
0.03,
|
||||
color="lightgray",
|
||||
alpha=0.3,
|
||||
)
|
||||
ax.add_patch(circle)
|
||||
|
||||
# Draw the highlighted district with a border
|
||||
# Create a polygon approximating the district area
|
||||
# For simplicity, we'll use a circle with border
|
||||
highlighted = mpatches.Circle(
|
||||
(district.x, district.y),
|
||||
0.08,
|
||||
facecolor="white",
|
||||
edgecolor="black",
|
||||
linewidth=3,
|
||||
)
|
||||
ax.add_patch(highlighted)
|
||||
|
||||
# Add some neighboring circles to show context (lighter borders)
|
||||
# Find nearest districts
|
||||
distances = [
|
||||
(
|
||||
d,
|
||||
((d.x - district.x) ** 2 + (d.y - district.y) ** 2) ** 0.5,
|
||||
)
|
||||
for d in WARSAW_DISTRICTS
|
||||
if d.name != district.name
|
||||
]
|
||||
distances.sort(key=lambda x: x[1])
|
||||
|
||||
# Draw 3-4 nearest neighbors with light borders
|
||||
for neighbor, _ in distances[:4]:
|
||||
neighbor_circle = mpatches.Circle(
|
||||
(neighbor.x, neighbor.y),
|
||||
0.08,
|
||||
facecolor="white",
|
||||
edgecolor="lightgray",
|
||||
linewidth=1,
|
||||
alpha=0.5,
|
||||
)
|
||||
ax.add_patch(neighbor_circle)
|
||||
|
||||
return fig
|
||||
|
||||
|
||||
def generate_district_image_base64(district: District) -> str:
|
||||
"""Generate a base64-encoded PNG image of the district map.
|
||||
|
||||
Args:
|
||||
district: The district to visualize.
|
||||
|
||||
Returns:
|
||||
Base64-encoded PNG image string.
|
||||
"""
|
||||
fig = create_district_map(district)
|
||||
|
||||
# Save to bytes buffer
|
||||
buf = BytesIO()
|
||||
fig.savefig(buf, format="png", bbox_inches="tight", dpi=150)
|
||||
plt.close(fig)
|
||||
buf.seek(0)
|
||||
|
||||
# Encode to base64
|
||||
return base64.b64encode(buf.read()).decode("utf-8")
|
||||
|
||||
|
||||
def save_district_image(district: District, output_dir: Path) -> Path:
|
||||
"""Save a district map image to a file.
|
||||
|
||||
Args:
|
||||
district: The district to visualize.
|
||||
output_dir: Directory to save the image.
|
||||
|
||||
Returns:
|
||||
Path to the saved image file.
|
||||
"""
|
||||
output_dir.mkdir(parents=True, exist_ok=True)
|
||||
fig = create_district_map(district)
|
||||
|
||||
# Create filename from district name (sanitized)
|
||||
filename = f"{district.name.replace('-', '_').replace(' ', '_')}.png"
|
||||
output_path = output_dir / filename
|
||||
|
||||
fig.savefig(output_path, format="png", bbox_inches="tight", dpi=150)
|
||||
plt.close(fig)
|
||||
|
||||
return output_path
|
||||
|
||||
|
||||
def generate_anki_deck(
|
||||
output_dir: Path,
|
||||
deck_name: str = "Warsaw Districts",
|
||||
) -> str:
|
||||
"""Generate Anki-compatible deck content for Warsaw districts.
|
||||
|
||||
Args:
|
||||
output_dir: Directory where images will be saved.
|
||||
deck_name: Name for the Anki deck.
|
||||
|
||||
Returns:
|
||||
Semicolon-separated content ready for Anki import.
|
||||
"""
|
||||
lines: list[str] = []
|
||||
|
||||
# Add Anki headers
|
||||
lines.append("#separator:semicolon")
|
||||
lines.append("#html:true")
|
||||
lines.append(f"#deck:{deck_name}")
|
||||
lines.append("#tags:geography warsaw poland")
|
||||
lines.append("#columns:Front;Back")
|
||||
lines.append("") # Empty line before data
|
||||
|
||||
# Generate cards for each district
|
||||
for district in WARSAW_DISTRICTS:
|
||||
# Save the image
|
||||
image_path = save_district_image(district, output_dir)
|
||||
|
||||
# Create the front side: reference to image
|
||||
# Anki expects the image filename to be in the media collection
|
||||
front = f'<img src="{image_path.name}">'
|
||||
|
||||
# Back side: district name in Polish
|
||||
back = district.name
|
||||
|
||||
lines.append(f"{front};{back}")
|
||||
|
||||
return "\n".join(lines)
|
||||
|
||||
|
||||
def main(argv: Sequence[str] | None = None) -> int:
|
||||
"""Main entry point.
|
||||
|
||||
Args:
|
||||
argv: Command line arguments.
|
||||
|
||||
Returns:
|
||||
Exit code.
|
||||
"""
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Generate Anki flashcards for Warsaw districts.",
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
epilog=__doc__,
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"--output",
|
||||
"-o",
|
||||
type=str,
|
||||
default=None,
|
||||
help="Output file path (default: warsaw_districts_anki.txt)",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--image-dir",
|
||||
"-i",
|
||||
type=str,
|
||||
default=None,
|
||||
help="Directory for district images (default: warsaw_districts_images)",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--deck-name",
|
||||
"-d",
|
||||
type=str,
|
||||
default="Warsaw Districts",
|
||||
help="Name for the Anki deck (default: 'Warsaw Districts')",
|
||||
)
|
||||
|
||||
args = parser.parse_args(argv)
|
||||
|
||||
# Determine output paths
|
||||
if args.output:
|
||||
output_path = Path(args.output)
|
||||
else:
|
||||
output_path = Path("warsaw_districts_anki.txt")
|
||||
|
||||
if args.image_dir:
|
||||
image_dir = Path(args.image_dir)
|
||||
else:
|
||||
image_dir = Path("warsaw_districts_images")
|
||||
|
||||
try:
|
||||
print(f"Generating flashcards for {len(WARSAW_DISTRICTS)} Warsaw districts...") # noqa: T201
|
||||
|
||||
# Generate the deck content
|
||||
anki_content = generate_anki_deck(image_dir, args.deck_name)
|
||||
|
||||
# Write output file
|
||||
output_path.write_text(anki_content, encoding="utf-8")
|
||||
|
||||
print() # noqa: T201
|
||||
print("=" * 60) # noqa: T201
|
||||
print("FLASHCARD GENERATION COMPLETE") # noqa: T201
|
||||
print("=" * 60) # noqa: T201
|
||||
print(f"Districts: {len(WARSAW_DISTRICTS)}") # noqa: T201
|
||||
print(f"Images directory: {image_dir.absolute()}") # noqa: T201
|
||||
print(f"Output file: {output_path.absolute()}") # noqa: T201
|
||||
print() # noqa: T201
|
||||
print("To import into Anki:") # noqa: T201
|
||||
print(" 1. Open Anki") # noqa: T201
|
||||
print(" 2. File -> Import") # noqa: T201
|
||||
print(f" 3. Select: {output_path.absolute()}") # noqa: T201
|
||||
img_dir = image_dir.absolute()
|
||||
print(f" 4. Ensure images from {img_dir} are in Anki's media folder") # noqa: T201
|
||||
print(" or copy them to your Anki profile's collection.media folder") # noqa: T201
|
||||
print(" 5. Click Import") # noqa: T201
|
||||
except Exception as e: # noqa: BLE001
|
||||
print(f"Error: {e}", file=sys.stderr) # noqa: T201
|
||||
return 1
|
||||
else:
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
@ -5,6 +5,7 @@ lxml>=5.0
|
||||
mitmproxy>=10.0
|
||||
|
||||
# Optional dependencies for specific scripts (needed for full pylint analysis)
|
||||
matplotlib>=3.0
|
||||
opencv-python>=4.0
|
||||
pillow>=10.0
|
||||
pygame>=2.0
|
||||
|
||||
Loading…
Reference in New Issue
Block a user