Puzzle sources
Links and payloads from SudokuPad, f-puzzles, Penpa and Logic Masters, read into puzzles. Generated from the docstrings by tools/gen_reference_md.py; public names only.
pencilmark.sources
src/pencilmark/sources/init.py
Puzzle sources: links / payloads from SudokuPad, f-puzzles, penpa-edit and Logic Masters -> puzzle JSON.
from pencilmark import sources
pj = sources.load("https://sudokupad.app/wjgxgaji9a") # -> puzzle JSON dict (pencilmark.puzzle_json)
p = pencilmark.puzzle_json.from_json(pj)
load() recognises
SudokuPad sudokupad.app/... , app.crackingthecryptic.com/... (short ids are fetched: one API request),
bare 'scl...' / 'ctc...' / 'fpuzzles...' payloads, 'sudokupad:<shortid>'
f-puzzles f-puzzles.com/?load=... (offline), ?id=<alias> (one TinyURL HEAD request)
penpa any .../penpa-edit/?m=..&p=... (penpa-edit, penpa+, mirrors; offline), 'penpa:<p value>'
LMD logic-masters.de/Raetselportal/Raetsel/zeigen.php?id=XXXXXX or 'lmd:XXXXXX' (page fetch, robots.txt
obeyed, >= 2.5 s between requests), converting the first linked puzzle that translates
shorteners tinyurl / bit.ly / git.io / is.gd links are resolved (one HEAD request) and dispatched
puzzle JSON a dict / JSON text already in pencilmark.puzzle_json format is returned as is
Modules: sudokupad, fpuzzles, penpa, lmd (each with decode / to_puzzle; see their docstrings for coverage).
Errors: SourceError > DecodeError (unrecognised / undecodable), FetchError (network, robots.txt), UnsupportedPuzzle
(.elements = what could not be mapped exactly; nothing is silently dropped), VerificationError (verify=True).
| Name | What it does |
|---|---|
class VerificationError | verify=True: the translated puzzle is not unique, or contradicts its embedded solution. |
def detect | -> 'puzzle_json' | 'sudokupad' | 'fpuzzles' | 'penpa' | 'lmd' | 'short' | None. |
def load | Link / payload / decoded dict -> puzzle JSON dict. |
def check | Unique solution (and equal to pj['solution'] when present) or VerificationError. |
class VerificationError(SourceError)
verify=True: the translated puzzle is not unique, or contradicts its embedded solution.
def detect(x)
-> 'puzzle_json' | 'sudokupad' | 'fpuzzles' | 'penpa' | 'lmd' | 'short' | None.
def load(x, rules_text=None, infer=False, fetch=True, verify=False, time_limit=30.0)
Link / payload / decoded dict -> puzzle JSON dict. rules_text: the rules from the page that links the puzzle (used where the puzzle file has none, and for penpa's rule screening). infer=True lets SudokuPad / f-puzzles search line readings with the solver (slow). fetch=False refuses anything that needs a network request. verify=True checks uniqueness (and the embedded solution) with CP-SAT and raises VerificationError otherwise.
def check(pj, time_limit=30.0)
Unique solution (and equal to pj['solution'] when present) or VerificationError. Returns the solution string.
pencilmark.sources._common
src/pencilmark/sources/_common.py
Shared pieces of pencilmark.sources: exception types, a polite HTTP client, Puzzle -> puzzle JSON.
| Name | What it does |
|---|---|
class SourceError | Base class for every error raised by pencilmark.sources. |
class DecodeError | The link / payload could not be recognised or decoded. |
def reads | decorator for a reader: a crash on malformed data (a missing key, a value of the wrong type, a short list)… |
class FetchError | A network request failed (or robots.txt forbids it). |
class UnsupportedPuzzle | The puzzle decoded, but it uses elements / rules the translation cannot model exactly. |
def unsupported_from_reason | Translator failure reason ('unsupported: a, b' or a plain reason) -> UnsupportedPuzzle. |
class Http | Sequential, polite HTTP: identifying User-Agent, timeouts, a minimum gap between requests to the same host,… |
def to_puzzle_json | engine Puzzle (finalized or not) -> puzzle JSON dict (pencilmark.puzzle_json.to_json); a solution string /… |
class SourceError(Exception)
Base class for every error raised by pencilmark.sources.
class DecodeError(SourceError)
The link / payload could not be recognised or decoded.
def reads(source)
decorator for a reader: a crash on malformed data (a missing key, a value of the wrong type, a short list) becomes a DecodeError naming the source and the problem
class FetchError(SourceError)
A network request failed (or robots.txt forbids it).
class UnsupportedPuzzle(SourceError)
The puzzle decoded, but it uses elements / rules the translation cannot model exactly. .elements lists them (nothing is silently dropped).
def unsupported_from_reason(reason, source='')
Translator failure reason ('unsupported: a, b' or a plain reason) -> UnsupportedPuzzle.
class Http
Sequential, polite HTTP: identifying User-Agent, timeouts, a minimum gap between requests to the same host, optional robots.txt checks, at most one retry (after a pause) on 429 / 5xx / network errors.
def allowed(self, url)
No docstring.
def get_text(self, url)
No docstring.