songleaf.tools¶
The single source of truth for every surface: plain functions, flat arguments, JSON-ready results.
The CLI (python -m songleaf) is cw over TOOLS. Nothing here
knows about any surface. sources, store and renderer are the seams:
library callers pass them, the CLI hides them. Code that wants objects rather
than dicts uses songleaf.sources, songleaf.store and
songleaf.render directly.
Module Attributes
Every operation, in the order the CLI lists them. |
Functions
|
Build the search index of the Kaggle corpus, once, where the corpus zip is. |
|
Export a song as ChordPro ( |
|
Remove a song from the stored songs, from every list it was in, and from every Viewed list. |
|
Read pasted song text from a file ( |
|
Store a song pasted from anywhere: Ultimate Guitar markup, ChordPro, OpenSong or plain chords over lyrics. |
|
Fetch one community Ultimate Guitar chord page and store its chart as |
|
Link the song's recording: a YouTube video and/or a Spotify track, by id or link. |
|
Find songs with one query: in your lists' names, then titles, artists and lyrics. |
|
Make a one-page song sheet (PDF) for the best match of |
|
Put a score snippet over one line of a song; the |
|
The song itself as JSON: lyrics text, chords and sections, and every key it can move to. |
|
Render a list (group) of songs as one PDF: a table of contents, then every song at its fitted size. |
|
The keys of the stored songs. |
|
Time the song's lines from an LRC, so the page can scroll with the recording. |
|
Take a song out of |
|
Put a stored song at the top of |
|
The songs |
- songleaf.tools.TOOLS = (<function search>, <function sheet>, <function songbook>, <function song>, <function export>, <function songs>, <function import_file>, <function import_url>, <function viewed>, <function view>, <function unview>, <function forget>, <function build_index>, <function sync>, <function media>, <function snippet>)¶
Every operation, in the order the CLI lists them.
- songleaf.tools.build_index(*, path='')[source]¶
Build the search index of the Kaggle corpus, once, where the corpus zip is.
Searching then reads the index instead of loading the whole corpus into memory (tens of MB instead of over a GB per process). Run it again after replacing the zip.
pathdefaults to beside the zip under the data root.- Return type:
- songleaf.tools.export(query, *, format='chordpro', transpose=0, output='', pick=1, refresh=False, sources=None, store=None)[source]¶
Export a song as ChordPro (
chordpro) or plain text with chords over lyrics (text).queryis a song key or a search, as forsheet.transposemoves every chord by that many semitones (the stored song keeps its chords). The result has thetext; withoutputset it is also written to that file, andpathsays where. ChordPro is the fleet’s interchange (Songbook Pro, OnSong and the ChordPro app read it); chords that sound before their syllable travel in thex_songleaf_beforedirective.- Return type:
- songleaf.tools.forget(key, *, store=None, library_root=None)[source]¶
Remove a song from the stored songs, from every list it was in, and from every Viewed list.
It can be found and stored again by searching. Returns
{"key", "deleted"};deletedis False when it was not stored.- Return type:
- songleaf.tools.import_file(path='-', *, title='', artist='', url='', format='', store=None)[source]¶
Read pasted song text from a file (
-: standard input) and store it; seeimport_text.- Return type:
- songleaf.tools.import_text(text, *, title='', artist='', url='', key='', capo='', format='', store=None)[source]¶
Store a song pasted from anywhere: Ultimate Guitar markup, ChordPro, OpenSong or plain chords over lyrics.
The format is detected (
formatforces one ofultimate-guitar,chordpro,opensong,chords-over-lyrics).urlis only recorded as provenance: songleaf never contacts it (an official or Pro Ultimate Guitar URL is refused). The song is stored underpaste:<hash>(the same text, the same key), orug:<id>for an Ultimate Guitar URL, and is then usable like any other:sheet <key>,song <key>.- Return type:
- songleaf.tools.import_url(url, *, refresh=False, store=None, source=None)[source]¶
Fetch one community Ultimate Guitar chord page and store its chart as
ug:<id>.Local command line only, and off unless
SONGLEAF_UG_URL=1is set: prefer pasting, or the bookmarklet run on the page you opened (seesongleaf.ultimate_guitar). Official and Pro pages are refused. A chart already stored is not fetched again unlessrefresh.- Return type:
- songleaf.tools.media(query, *, youtube='', spotify='', pick=1, store=None, sources=None)[source]¶
Link the song’s recording: a YouTube video and/or a Spotify track, by id or link.
An id given as
""is left as it is;"-"removes it. Returns{"key", "media"}.- Return type:
- songleaf.tools.search(query='', *, title='', artist='', lyrics='', limit=10, list_songs=3, sources=None, store=None, library_root=None)[source]¶
Find songs with one query: in your lists’ names, then titles, artists and lyrics.
With only
query, every song comes once, tagged with where it matched (match):"list"(the firstlist_songsstored songs of each list whose name the query names;listandlist_namesay which, and the list’s other songs are found in the later kinds as usual), then"title","artist"and"lyrics", in that order, at mostlimitof each, best first within each. A song that matches its title and its lyrics is a title match only.highlightholds the matched words of the title and artist (and oflist_name) as[start, end]spans; a lyrics match carriessnippet, the line that matched, with its spans.With
title,artistorlyrics, it is a narrower search instead: songs that match every field given (andquery, fuzzily over title and artist),match: "".
- songleaf.tools.sheet(query, *, output='', pick=1, refresh=False, layout='dense', transpose=0, scale=1.0, sources=None, store=None, renderer=None)[source]¶
Make a one-page song sheet (PDF) for the best match of
query.querymay also be a song key, assearchandsongsshow them (kaggle_chords:1234): a stored song renders without searching, and the key of a known source is fetched from it directly.pickchooses the n-th best match instead of the best. The song is saved to the store;refreshfetches it from its source again, replacing the stored copy. The PDF goes tooutput, by default thesheetsdata directory.layoutisdense(the default), or options joined with+:overlap(chords over the words themselves),inline(chords in the line, before their syllable),packed(rows break where the lyrics do),two-column,shaded(sections, repeated lines and chord functions); for exampleinline+packed+two-column. Arendererdecides the layout itself, so it does not go withlayoutorscale.transposemoves every chord by that many semitones (spelled for the new key); the stored song keeps its chords.scalemultiplies the font size that fills the page:0.8for smaller type,1.2for larger type over more pages.- Return type:
- songleaf.tools.snippet(query, notation, *, line=0, format='abc', pick=1, store=None, sources=None)[source]¶
Put a score snippet over one line of a song; the
scorelayout draws it on the sheet.notationis a few bars of ABC ("G2 AB c2 | d4"; the unit is an eighth note).lineis the 1-based lyric line it goes with;0lets the rule choose (the first line of the chorus, else the most repeated line, else the first).formatmay also bemusicxmlormei(drawn with thescoreextra only). Returns{"key", "start", "end", "rule"}.- Return type:
- songleaf.tools.song(query, *, pick=1, refresh=False, transpositions=6, sources=None, store=None)[source]¶
The song itself as JSON: lyrics text, chords and sections, and every key it can move to.
queryis a song key or a search, as forsheet; the song is stored the same way. Besides the song’s own fields (text,annotations,meta,provenance), the result haschords(the distinct chords, in order of first appearance),sections({"start", "end", "label", "family"}, the family as the printed sheet shades it:"chorus","bridge"or""),song_key(the estimated key,""with no chords) andtranspositions: one table per shift from-transpositions + 1totranspositionssemitones, each{"semitones", "key", "chords": {original: transposed}}.- Return type:
- songleaf.tools.songbook(group, *, output='', title='', layout='dense', scale=1.0, library_root=None, sources=None, store=None, renderer=None)[source]¶
Render a list (group) of songs as one PDF: a table of contents, then every song at its fitted size.
groupis a list’s id or its name (the best match of the name). The songs come in the order they were filed in the list, nested lists included, so the list order is the set list. Page numbers are stamped on every page and each song is a PDF bookmark.titledefaults to the list’s name.layoutandscaleare as forsheet. The PDF goes tooutput, by default thesheetsdata directory.- Return type:
- songleaf.tools.sync(query, *, lrc='', lrclib=False, pick=1, store=None, sources=None, get_json=None)[source]¶
Time the song’s lines from an LRC, so the page can scroll with the recording.
lrcis the LRC text (an.lrcfile’s content); withlrcliband nolrc, LRCLIB is asked for the song’s synced lyrics. Only the times are stored ("time"annotations), never the LRC’s text. Returns{"key", "timed", "lines"}: how many lyric lines got a time, of how many.- Return type:
- songleaf.tools.unview(key, *, user='', library_root=None)[source]¶
Take a song out of
user’s Viewed list. It stays stored, and in its lists.Returns
{"key", "removed", "viewed_at"}: when it had been viewed, so the same time can be given back toview()to undo.- Return type:
- songleaf.tools.view(key, *, user='', at=0.0, store=None, library_root=None)[source]¶
Put a stored song at the top of
user’s Viewed list: they just opened it.at(seconds since the epoch) records that time instead, which is how an undo puts a song it took out back where it was. Returns{"key", "viewed_at"}.- Return type:
- songleaf.tools.viewed(*, user='', store=None, library_root=None)[source]¶
The songs
useropened, the most recent first:key,title,artist,viewed_at.useris who the host says is asking (no one: the list everyone shares). Songs no longer stored are left out.viewed_atis in seconds since the epoch.