#!/usr/bin/env python3 # Copyright (c) 2026 Krzysztof Rudnicki. MIT licence. """Polish artworks, as Wikidata knows them. The category walk in ``commons_api`` answers "what is filed near a Polish category", which is a proxy. Wikidata answers the question actually being asked -- "what was made by somebody with Polish citizenship" -- because it models the artwork, its creator and the creator's citizenship as data rather than as folder membership. One SPARQL query returns about six thousand of them in six seconds. It does not replace the category walk, it adds to it. Wikidata only knows about works somebody has made an item for, which is a fraction of Commons; the categories reach the rest. Used together, the Polish pool means both "by a Pole" and "filed as Polish art". The query service is public and needs no account, unlike Quarry and the Commons Query Service, both of which require an OAuth login. """ from __future__ import annotations import urllib.parse from typing import Any, Final import httpx ENDPOINT: Final = "https://query.wikidata.org/sparql" # Poland; "country of citizenship"; "creator"; "image". # The classes are listed rather than reached through a subclass-of* path, # because that path over every work of art times the service out: measured, # it fails where this returns in six seconds. QUERY: Final = """ SELECT DISTINCT ?image WHERE { VALUES ?class { wd:Q3305213 wd:Q860861 wd:Q93184 wd:Q11060274 wd:Q18761202 wd:Q1473346 } ?work wdt:P31 ?class ; wdt:P18 ?image ; wdt:P170 ?creator . ?creator wdt:P27 wd:Q36 . } """ TIMEOUT: Final = 180.0 def polish_artwork_titles(user_agent: str) -> list[str]: """Commons file titles for artworks by creators of Polish citizenship. Returns: Titles in Commons' own form -- ``File:Something.jpg`` -- ready to be handed to ``commons_api.licensed_titles``. P18 gives a Special:FilePath URL, so the name is percent-decoded and its underscores turned back into spaces here rather than at every use. """ response = httpx.get( ENDPOINT, params={"query": QUERY, "format": "json"}, headers={"User-Agent": user_agent, "Accept": "application/sparql-results+json"}, timeout=TIMEOUT, ) response.raise_for_status() document: dict[str, Any] = response.json() titles: list[str] = [] for row in document["results"]["bindings"]: name = urllib.parse.unquote(str(row["image"]["value"]).rsplit("/", 1)[-1]) titles.append("File:" + name.replace("_", " ")) return titles