Skip to main content

Automate creation of Obsidian markdown files for art collection

Project description

gesso

CI Coverage

Generate Obsidian-ready painting notes from a simple input list. The CLI reads PERPLEXITY_API_KEY from your environment (or .env), enriches each row via Perplexity, and writes markdown files from the bundled template.

Pre-requisites

  • uv for dependency management

Quickstart

  • Install deps: uv sync
  • Export PERPLEXITY_API_KEY (or add to .env)
  • Run: gesso --input data/input.txt --output outputs/
    • Defaults: --input data/input.txt --output outputs/ --cache .cache --template data/example-template.md

Input & Template

  • Input lines: number: Title, Artist
  • Template: Use --template to specify a custom template file (default: data/example-template.md). Output files land in outputs/{title}.md.

Template Field Extraction

The tool automatically extracts YAML frontmatter field names from your template and queries Perplexity for those fields. This allows you to customize which metadata fields you want to collect.

Blacklisted fields (user-defined, not from Perplexity): title, date, created, category, rating, seen, tags, artist. These fields are always excluded from Perplexity queries. Will probably need to modify this to make it configurable as well...oh well, feel free to drop a PR.

Example template:

---
created: {{date}}
title: "{{title}}"
artist: 
year:           # ← Collected from Perplexity
style:          # ← Collected from Perplexity
medium:         # ← Collected from Perplexity
museum:         # ← Collected from Perplexity
image:          # ← Collected from Perplexity
rating:         # ← NOT collected (blacklisted)
tags:           # ← NOT collected (blacklisted)
  - paintings
---

The tool prints which fields it's collecting at startup:

[INFO] Collecting fields from Perplexity: year, style, medium, museum, image

Field name mapping: Template field names are mapped to API field names where needed (e.g., imageimage_url). Most fields use the same name in both template and API.

  • Cache: .cache/{title_artist}.json to avoid duplicate API calls.

[!warning] If you change the template structure, you need to clear out the cache to ensure the code requeries everything. Otherwise, it'll just write an empty field

Flow (per painting)

  1. Extract fields from template YAML frontmatter (excluding blacklisted fields).
  2. Parse input line into {number, title, artist}.
  3. Check cache; otherwise query Perplexity for metadata (only the fields found in template).
  4. Post-process strings into Obsidian-friendly lists/links.
  5. Render template placeholders and frontmatter with collected data.
  6. Write markdown to the output directory.

Module reference

  • parse_input(filepath): read lines into structured dicts; warns on invalid rows.
  • extract_template_fields(template_path): extract YAML frontmatter field names, filtering out blacklisted fields.
  • get_cache_key(title, artist): normalize to cache filename.
  • load_from_cache / save_to_cache: JSON cache helpers under .cache/.
  • query_painting_metadata(title, artist, fields): Perplexity SDK wrapper using PERPLEXITY_API_KEY; accepts optional list of fields to query dynamically.
  • post_process_fields(data, template_fields): convert comma-separated strings to lists and wrap wikilinks; drop "Unknown" values (except for description).
  • render_markdown(template_path, painting_data, today, template_fields): fill template placeholders and YAML lists dynamically based on template fields.
  • write_output(output_dir, filename, content): ensure dirs exist and persist markdown.
  • main(...): CLI orchestrator; accepts --input, --output, --cache, --template arguments.

Usage Examples

# Use default template
gesso --input data/input.txt

# Use custom template
gesso --input data/input.txt --template my-template.md

# Specify all options
gesso --input paintings.txt --output notes/ --cache .cache/ --template templates/custom.md

Error handling

  • Missing env key: fails fast with a clear message.
  • Template errors: fails if template file not found or has no fields to collect.
  • Input parse errors: warn and skip lines.
  • Perplexity failures: log error and skip that painting.
  • Cache/IO issues: log warnings and continue to the next item.

Development

  • Python 3.13+, managed with uv.
  • Style: uv run ruff format --check . and uv run ruff check .
  • Tests: uv run pytest -v --cov --cov-report=xml
  • CI mirrors these steps (.github/workflows/ci.yml).

Contributing

  • Keep README aligned with behavior; update TODOs when adding features.
  • Add tests for new parsing, templating, or API edge cases.
  • Run lint/format/tests before sending changes.

Tasks

lint

uv run ruff check . --fix --unsafe-fixes
uv run ruff format .

test

pytest

sync

uv sync

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

gesso-0.2.0.tar.gz (14.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

gesso-0.2.0-py3-none-any.whl (9.9 kB view details)

Uploaded Python 3

File details

Details for the file gesso-0.2.0.tar.gz.

File metadata

  • Download URL: gesso-0.2.0.tar.gz
  • Upload date:
  • Size: 14.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.9.18 {"installer":{"name":"uv","version":"0.9.18","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for gesso-0.2.0.tar.gz
Algorithm Hash digest
SHA256 c99f73181eabe62e103b0c8c128b90f77ed3bdd956b44d952ea5d66a26fa75fb
MD5 322017c5dd3e15160d2e5d35bea93cc9
BLAKE2b-256 1eeda0f0f9e3bebbe3519a78144140fdd28590a2f109bd965f05208b56b97f30

See more details on using hashes here.

File details

Details for the file gesso-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: gesso-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 9.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.9.18 {"installer":{"name":"uv","version":"0.9.18","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for gesso-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 d34d9bb496e548ee8fc1913cd45cf5bba7788932d14c639da3bc97d516adecf8
MD5 a85af9706309a4ef103c2a19724ac1f4
BLAKE2b-256 42ec59ea196f61b8ed34af815af3e365277f0a2680ef242cbaf0de105ff0fe28

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page