Skip to content

Commit

Permalink
ci: use nimble python
Browse files Browse the repository at this point in the history
  • Loading branch information
MartinBernstorff committed Oct 25, 2023
1 parent ae437cf commit bc7ef5f
Show file tree
Hide file tree
Showing 17 changed files with 56 additions and 489 deletions.
24 changes: 13 additions & 11 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
# Use an official Python runtime as a parent image
FROM python:3.11-bookworm
FROM python:3.11-bullseye

# Set the working directory to /app
WORKDIR /app

# Install deps
COPY pyproject.toml ./
RUN pip install .[dev]
RUN pip install .[tests]
# Dev experience
COPY makefile ./

COPY dev-requirements.txt ./
RUN make install-dev

# Ensure pyright builds correctly.
# If run in make validate, it is run in parallel, which breaks its installation.
RUN pyright .
COPY requirements.txt ./
RUN make install-deps

COPY pyproject.toml ./
RUN make type-check

# Install the entire app
# Install the app
COPY . /app
RUN pip install -e .
RUN pip install .
2 changes: 1 addition & 1 deletion dev-requirements.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
cruft==2.15.0
pytest==7.1.3
pytest-xdist==3.3.1
ruff==0.1.0
ruff==0.1.2
pyright==1.1.328
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ select = [
"SIM",
"W",
]
ignore = ["ANN101", "ANN401", "E402", "E501", "F401", "F841", "UP006", "RET504"]
ignore = ["ANN101", "ANN401", "E402", "E501", "F401", "F841", "RET504", "COM812", "COM819", "Q000", "Q001", "Q002", "Q003", "W191"]
# Allow autofix for all enabled rules (when `--fix`) is provided.
unfixable = ["ERA"]
# Exclude a variety of commonly ignored directories.
Expand Down
5 changes: 2 additions & 3 deletions src/personal_mnemonic_medium/card_pipeline.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
from collections.abc import Sequence
from pathlib import Path
from typing import List

from personal_mnemonic_medium.exporters.anki.card_types.base import AnkiCard
from personal_mnemonic_medium.exporters.base import CardExporter
Expand All @@ -24,8 +23,8 @@ def __init__(
def run(
self,
input_path: Path,
) -> List[AnkiCard]:
notes: List[Document] = []
) -> list[AnkiCard]:
notes: list[Document] = []
if input_path.is_dir():
notes += list(self.document_factory.get_notes_from_dir(dir_path=input_path))

Expand Down
18 changes: 9 additions & 9 deletions src/personal_mnemonic_medium/exporters/anki/card_types/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@
import os
import re
from abc import ABC, abstractmethod
from collections.abc import Callable
from pathlib import Path
from typing import Any, Callable, List, Optional, Tuple
from typing import Any, Optional

import genanki
from personal_mnemonic_medium.exporters.anki.globals import CONFIG
Expand All @@ -22,9 +23,9 @@ class AnkiCard(ABC):

def __init__(
self,
fields: List[str],
fields: list[str],
source_prompt: Prompt,
url_generator: Callable[[Path, Optional[int]], str] = get_obsidian_url,
url_generator: Callable[[Path, int | None], str] = get_obsidian_url,
html_compiler: Callable[[str], str] = compile_field,
):
self.markdown_fields = fields
Expand All @@ -38,11 +39,11 @@ def source_markdown(self) -> str:
return self.source_doc.content

@property
def html_fields(self) -> List[str]:
def html_fields(self) -> list[str]:
return list(map(self.html_compiler, self.markdown_fields))

@property
def tags(self) -> List[str]:
def tags(self) -> list[str]:
return self.source_doc.tags

@property
Expand Down Expand Up @@ -132,9 +133,9 @@ def to_genanki_note(self) -> genanki.Note:
tags=self.tags,
)

def make_ref_pair(self, filename: str) -> Tuple[Path, str]:
def make_ref_pair(self, filename: str) -> tuple[Path, str]:
"""Take a filename relative to the card, and make it absolute."""
newname = "%".join(filename.split(os.sep))
newname = "%".join(filename.split(os.sep)) # noqa: PTH206

if os.path.isabs(filename): # noqa
abspath = Path(filename)
Expand Down Expand Up @@ -163,8 +164,7 @@ def process_match(m) -> str: # noqa

current_stage = re.sub(regex, process_match, current_stage)

for r in results:
yield r
yield from results

# Anki seems to hate alt tags :(
self.html_fields[i] = re.sub(r'alt="[^"]*?"', "", current_stage)
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import re
from collections.abc import Callable
from pathlib import Path
from typing import Callable, List, Optional

import genanki
from personal_mnemonic_medium.exporters.anki.card_types.base import AnkiCard
Expand All @@ -18,9 +18,9 @@
class AnkiCloze(AnkiCard):
def __init__(
self,
fields: List[str],
fields: list[str],
source_prompt: Prompt,
url_generator: Callable[[Path, Optional[int]], str] = get_obsidian_url,
url_generator: Callable[[Path, int | None], str] = get_obsidian_url,
html_compiler: Callable[[str], str] = compile_field,
):
super().__init__(
Expand Down
6 changes: 3 additions & 3 deletions src/personal_mnemonic_medium/exporters/anki/card_types/qa.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from collections.abc import Callable
from pathlib import Path
from typing import Callable, List, Optional

import genanki
from personal_mnemonic_medium.exporters.anki.card_types.base import AnkiCard
Expand All @@ -17,9 +17,9 @@
class AnkiQA(AnkiCard):
def __init__(
self,
fields: List[str],
fields: list[str],
source_prompt: Prompt,
url_generator: Callable[[Path, Optional[int]], str] = get_obsidian_url,
url_generator: Callable[[Path, int | None], str] = get_obsidian_url,
html_compiler: Callable[[str], str] = compile_field,
):
super().__init__(
Expand Down
4 changes: 2 additions & 2 deletions src/personal_mnemonic_medium/exporters/anki/globals.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Anki 2.1 has mathjax built in, but ankidroid and other clients don't.
import textwrap
from typing import Any, Dict
from typing import Any

from personal_mnemonic_medium.exporters.anki.anki_css import CARD_MODEL_CSS

Expand Down Expand Up @@ -84,7 +84,7 @@
"card_model_template_cloze": CLOZE_MODEL_TEMPLATE,
}

VERSION_LOG: Dict[Any, Any] = {}
VERSION_LOG: dict[Any, Any] = {}
Q_TYPE_TAG = {
"G": "med/type/1_GP",
"A": "med/type/2_Acute_care",
Expand Down
11 changes: 5 additions & 6 deletions src/personal_mnemonic_medium/exporters/anki/package_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,9 @@
from dataclasses import dataclass
from pathlib import Path
from shutil import copyfile
from typing import Any, List, Set
from typing import Any

import genanki

from personal_mnemonic_medium.exporters.anki.card_types.base import AnkiCard
from personal_mnemonic_medium.exporters.anki.card_types.cloze import AnkiCloze
from personal_mnemonic_medium.exporters.anki.card_types.qa import AnkiQA
Expand Down Expand Up @@ -43,7 +42,7 @@ def __getitem__(self, deckname: str) -> Any:
@dataclass(frozen=True)
class DeckBundle:
deck: genanki.Deck
media: Set[str]
media: set[str]

def get_package(self) -> genanki.Package:
return genanki.Package(deck_or_decks=self.deck, media_files=list(self.media))
Expand All @@ -61,7 +60,7 @@ def __init__(self) -> None:
pass

@staticmethod
def cards_to_deck_bundle(cards: List[AnkiCard]) -> DeckBundle:
def cards_to_deck_bundle(cards: list[AnkiCard]) -> DeckBundle:
"""Take an iterable prompts, output an .apkg in a file called output_name.
NOTE: We _must_ be in a temp directory.
"""
Expand All @@ -75,7 +74,7 @@ def cards_to_deck_bundle(cards: List[AnkiCard]) -> DeckBundle:
@staticmethod
def cards_to_deck(
cards: Sequence[AnkiCard],
) -> tuple[genanki.Deck, Set[str]]:
) -> tuple[genanki.Deck, set[str]]:
media = set()

deck_name = cards[0].deckname
Expand Down Expand Up @@ -103,7 +102,7 @@ def cards_to_deck(
def prompts_to_cards(
self,
prompts: Sequence[Prompt],
) -> List[AnkiCard]:
) -> list[AnkiCard]:
"""Takes an iterable of prompts and turns them into AnkiCards"""

cards: list[AnkiCard] = []
Expand Down
13 changes: 6 additions & 7 deletions src/personal_mnemonic_medium/exporters/anki/sync.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,18 @@
import urllib.request
from pathlib import Path
from time import sleep
from typing import Any, Dict, List
from typing import Any

from genanki import Model, Note
from wasabi import Printer

from personal_mnemonic_medium.exporters.anki.globals import ANKICONNECT_URL
from personal_mnemonic_medium.exporters.anki.package_generator import DeckBundle
from wasabi import Printer

msg = Printer(timestamp=True)


# helper for creating anki connect requests
def request(action: Any, **params: Any) -> Dict[str, Any]:
def request(action: Any, **params: Any) -> dict[str, Any]:
return {"action": action, "params": params, "version": 6}


Expand Down Expand Up @@ -139,19 +138,19 @@ def sync_deck(


def get_md_note_infos(deck_bundle: DeckBundle) -> set[str]:
md_notes: List[Note] = deck_bundle.deck.notes
md_notes: list[Note] = deck_bundle.deck.notes
md_note_guids = {str(n.guid) for n in md_notes}
return md_note_guids


def get_anki_note_infos(deck_bundle: DeckBundle) -> tuple[dict[str, Any], set[str]]:
anki_card_ids: List[int] = invoke(
anki_card_ids: list[int] = invoke(
"findCards",
query=f'"deck:{deck_bundle.deck.name}"',
)

# get a list of anki notes in the deck
anki_note_ids: List[int] = invoke("cardsToNotes", cards=anki_card_ids)
anki_note_ids: list[int] = invoke("cardsToNotes", cards=anki_card_ids)

# get the note info for the notes in the deck
anki_notes_info = invoke("notesInfo", notes=anki_note_ids)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from typing import Optional


def get_obsidian_url(source_path: Path, line_nr: Optional[int] = None) -> str:
def get_obsidian_url(source_path: Path, line_nr: int | None = None) -> str:
"""Get the obsidian URI for the source document."""
vault: str = urllib.parse.quote(source_path.parent.name) # type: ignore
file: str = urllib.parse.quote(source_path.name) # type: ignore
Expand Down
5 changes: 2 additions & 3 deletions src/personal_mnemonic_medium/note_factories/markdown.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,9 @@
from pathlib import Path
from typing import Optional

from tqdm import tqdm

from personal_mnemonic_medium.note_factories.base import DocumentFactory
from personal_mnemonic_medium.note_factories.note import Document
from tqdm import tqdm


class MarkdownNoteFactory(DocumentFactory):
Expand All @@ -31,7 +30,7 @@ def get_and_append_new_uuid(self, file_path: Path) -> str:
def get_note_id(self, file_string: str) -> str:
return re.findall(r"<!-- {BearID:.+", file_string)[0]

def get_note_from_file(self, file_path: Path) -> Optional[Document]:
def get_note_from_file(self, file_path: Path) -> Document | None:
with file_path.open(encoding="utf8") as f:
file_contents = f.read()

Expand Down
3 changes: 1 addition & 2 deletions src/personal_mnemonic_medium/note_factories/note.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import datetime
import re
from pathlib import Path
from typing import List


class Document:
Expand Down Expand Up @@ -43,7 +42,7 @@ def _replace_alias_wiki_links(text: str) -> str:

return text

def get_tags(self, input_str: str, import_time: str) -> List[str]:
def get_tags(self, input_str: str, import_time: str) -> list[str]:
file_tags = [import_time]

if self.has_supplementary_tags(input_str):
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import hashlib
import re
from collections.abc import Sequence
from typing import Any, List, Optional
from typing import Any

from personal_mnemonic_medium.note_factories.note import Document
from personal_mnemonic_medium.prompt_extractors.base import PromptExtractor
Expand All @@ -19,7 +19,7 @@ def __init__(self) -> None:
pass

@staticmethod
def _break_string_by_two_or_more_newlines(string: str) -> List[str]:
def _break_string_by_two_or_more_newlines(string: str) -> list[str]:
"""Break string into a list by 2+ newlines in a row."""
return re.split(r"(\n\n)+", string)

Expand All @@ -39,7 +39,7 @@ def _has_cloze(string: str) -> bool:
@staticmethod
def _replace_cloze_id_with_unique(
string: str,
selected_cloze: Optional[str] = None,
selected_cloze: str | None = None,
) -> str:
"""Each cloze deletion in a note is numbered sequentially.
Expand Down
6 changes: 2 additions & 4 deletions src/personal_mnemonic_medium/prompt_extractors/prompt.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
from typing import List, Optional

from personal_mnemonic_medium.note_factories.note import Document


Expand All @@ -8,8 +6,8 @@ def __init__(
self,
note_uuid: str,
source_note: Document,
tags: Optional[List[str]] = None,
line_nr: Optional[int] = None,
tags: list[str] | None = None,
line_nr: int | None = None,
):
self.tags = tags
self.note_uuid = note_uuid
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import logging
import re
from collections.abc import Sequence
from typing import Any, List
from typing import Any

from personal_mnemonic_medium.note_factories.note import Document
from personal_mnemonic_medium.prompt_extractors.base import PromptExtractor
Expand Down Expand Up @@ -50,7 +50,7 @@ def _get_first_answer(self, string: str) -> str:
return answer[len(self.answer_prefix) + 2 :].rstrip()

@staticmethod
def _break_string_by_two_or_more_newlines(string: str) -> List[str]:
def _break_string_by_two_or_more_newlines(string: str) -> list[str]:
"""Break string into a list by 2+ newlines in a row."""
return re.split(r"(\n\n)+", string)

Expand Down
Loading

0 comments on commit bc7ef5f

Please sign in to comment.