{
"info": {
"author": "Jonathan Reichelt Gjertsen",
"author_email": "jonath.re@gmail.com",
"bugtrack_url": null,
"classifiers": [
"Development Status :: 4 - Beta",
"Intended Audience :: Developers",
"License :: OSI Approved :: MIT License",
"Natural Language :: English",
"Programming Language :: Python",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.5",
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: Implementation :: CPython"
],
"description": "# jchord - Python toolkit for working with chord progressions\n\n[](https://travis-ci.com/jonathangjertsen/jchord)\n[](https://codecov.io/gh/jonathangjertsen/jchord)\n\n```\n>>> from jchord.progressions import ChordProgression\n>>> prog = ChordProgression.from_string(\"C -- Fm7 -- C -- G7 -- C -- E7 Am F Bm7b5 E7 Am9 F Bo C69 --\")\n>>> print(prog.to_string())\nC -- Fm7 --\nC -- G7 --\nC -- E7 Am\nF Bm7b5 E7 Am9\nF Bo C69 --\n>>> prog.to_midi(\"example.midi\", tempo=100, beats_per_chord=2, instrument=4)\n```\n\n* Chord progressions can be imported from:\n - string (`prog = ChordProgression.from_string(string)`)\n - text file (`prog = ChordProgression.from_txt(filename)`)\n - XLSX file (`prog = ChordProgression.from_xlsx(filename)`)\n* Chord progressions can be exported to:\n - string (`print(prog.to_string(...optional))`)\n - text file (`prog.to_txt(filename, ..optional)`)\n - XLSX file (`prog.to_xlsx(filename, ...optional)`)\n - MIDI file (`prog.to_midi(filename, ...optional)`)\n\n# Install\n\n* `pip install jchord`\n* If you want to use the MIDI and XLSX functionality, also `pip install mido openpyxl`\n\n# Development\n\nClone the repo, and in the folder run `pip install -r requirements_dev.txt`\n\n## Testing\n\nTo run the tests:\n\n```\npytest --cov-report term-missing --cov jchord -vvv\n```\n\nMake sure all tests pass and that the code has 100% test coverage.\n\n## Formatting\n\nThe code is formatted with black. In the root of the repo, run:\n\n```\nblack .\n```\n\n## Documenting\n\nTo generate documentation, run the documentation generation script:\n\n```\npython doc_gen/generate_doc.py -o README.md\n```\n\nThe script appends documentation from each source module to `doc_gen/index.md`. If the script ran successfully, README.md should contain a section called \"Documentation\" below.\n\nTo decide which parts should be present in the documentation, go and edit `doc_gen/pydocmd.yml`. The reason for the format is that I originally wanted to use `pydocmd` (but found it too limiting).\n\n---\n\n# Documentation\n\n## Table of contents\n* `jchord.core`\n * Class `Note`\n * Method `Note.__init__(self, name: str, octave: int)`\n * Method `Note.pitch(self) -> float`\n * Method `Note.transpose(self: 'Note', shift: int) -> 'Note'`\n * Method `Note.transpose_degree(self: 'Note', shift: str) -> 'Note'`\n * Class `CompositeObject`\n * Method `CompositeObject._keys(self) -> Hashable`\n * Function `split_to_base_and_shift(name_or_degree: str, name_before_accidental: bool) -> (, )`\n * Function `degree_to_semitone(degree: str) -> int`\n * Function `semitone_to_degree_options(semitone: int, max_accidentals: int = 1) -> List[str]`\n * Function `note_diff(name_low: str, name_high: str) -> int`\n * Exception `InvalidDegree`\n* `jchord.midi`\n * Class `PlayedNote`\n * Method `PlayedNote.time(self)`\n * Method `PlayedNote.note(self)`\n * Method `PlayedNote.duration(self)`\n * Function `note_to_midi(note: jchord.core.Note) -> int`\n * Function `midi_to_note(midi: int) -> jchord.core.Note`\n * Function `midi_to_pitch(midi: int) -> float`\n * Function `read_midi_file(filename: str) -> List[jchord.midi.PlayedNote]`\n * Function `group_notes_to_chords(notes: List[jchord.midi.PlayedNote]) -> Dict[float, jchord.midi.PlayedNote]`\n * Exception `InvalidNote`\n* `jchord.knowledge`\n* `jchord.chords`\n * Class `Chord`\n * Method `Chord.__init__(self, name: str, semitones: List[int])`\n * Method `Chord.from_semitones(name: Union[str, NoneType], semitones: List[int]) -> 'Chord'`\n * Method `Chord.from_degrees(name: str, degrees: List[str]) -> 'Chord'`\n * Method `Chord.from_name(name: str) -> 'Chord'`\n * Method `Chord.intervals(self) -> List[int]`\n * Method `Chord.with_root(self, root: jchord.core.Note) -> 'ChordWithRoot'`\n * Method `Chord.add_semitone(self, semitone: int)`\n * Class `ChordWithRoot`\n * Method `ChordWithRoot.__init__(self, name: str, root: jchord.core.Note, chord: jchord.chords.Chord)`\n * Method `ChordWithRoot.from_root_and_semitones(root: jchord.core.Note, semitones: List[int]) -> 'ChordWithRoot'`\n * Method `ChordWithRoot.from_midi(midi: Set[int]) -> 'ChordWithRoot'`\n * Method `ChordWithRoot.from_name(name: str, octave: int = 4) -> 'ChordWithRoot'`\n * Method `ChordWithRoot.semitones(self)`\n * Method `ChordWithRoot.intervals(self) -> List[int]`\n * Method `ChordWithRoot.midi(self) -> List[int]`\n * Method `ChordWithRoot.transpose(self, shift: int) -> 'ChordWithRoot'`\n * Function `semitones_to_chord_name_options(semitones: Set[int], _rec=5) -> List[str]`\n * Exception `InvalidChord`\n* `jchord.progressions`\n * Class `ChordProgression`\n * Method `ChordProgression.__init__(self, progression: List[jchord.chords.ChordWithRoot])`\n * Method `ChordProgression.from_string(string: str) -> 'ChordProgression'`\n * Method `ChordProgression.from_txt(filename: str) -> 'ChordProgression'`\n * Method `ChordProgression.from_xlsx(filename: str) -> 'ChordProgression'`\n * Method `ChordProgression.from_midi_file(filename: str) -> 'ChordProgression'`\n * Method `ChordProgression.chords(self) -> Set[jchord.chords.ChordWithRoot]`\n * Method `ChordProgression.midi(self) -> List[List[int]]`\n * Method `ChordProgression.to_string(self, chords_per_row: int = 4, column_spacing: int = 2, newline: str = '\\n') -> str`\n * Method `ChordProgression.to_txt(self, filename: str, chords_per_row: int = 4, column_spacing: int = 2, newline: str = '\\n')`\n * Method `ChordProgression.to_xlsx(self, filename: str, chords_per_row: int = 4)`\n * Method `ChordProgression.to_midi(self, filename: str, instrument: int = 1, tempo: int = 120, beats_per_chord: int = 2, velocity: int = 100)`\n * Class `SongSection`\n * Method `SongSection.name(self)`\n * Method `SongSection.progression(self)`\n * Class `Song`\n * Method `Song.__init__(self, sections: List[jchord.progressions.SongSection])`\n * Method `Song.to_string(self, chords_per_row: int = 4, column_spacing: int = 2, newline: str = '\\n')`\n * Exception `InvalidProgression`\n\n## `jchord.core`\n\n\nBasic utilities for working with notes, base classes for objects etc.\n\n### Classes\n\n#### `Note`\n\nRepresents an absolute note with a name and an octave.\n\nTwo `Note`s are equal if they have the same name and octave,\nor if they have the same octave and their names are enharmonic\n(so `Note('A#', 4) == Note('Gb', 4)`)\n\n\n##### Methods\n\n###### `__init__(self, name: str, octave: int)`\n\n\n\n\n###### `pitch(self) -> float`\n\nReturns the absolute pitch of the note in Hz.\n\nExamples (equalities are approximate):\n\n* `Note(\"A\", 4).pitch() == 440.0`\n* `Note(\"A\", 0).pitch() == 27.5`\n* `Note(\"C\", 4).pitch() == 261.62556`\n\n\n\n###### `transpose(self: 'Note', shift: int) -> 'Note'`\n\nTransposes the note by the given number of semitones.\n\nExamples:\n\n* `Note(\"C\", 0).transpose(1) == Note(\"C#\", 0)`\n* `Note(\"C\", 4).transpose(19) == Note(\"G\", 5)`\n\n\n\n###### `transpose_degree(self: 'Note', shift: str) -> 'Note'`\n\nTransposes the given note by the given scale degree\n\nExamples:\n\n* `Note(\"C\", 0).transpose_degree(\"b2\") == Note(\"C#\", 0)`\n* `Note(\"C\", 4).transpose_degree(\"12\") == Note(\"G\", 5)`\n\n\n\n---\n\n\n\n#### `CompositeObject`\n\n\nBase class for objects which can be represented by a few attributes.\n\nSubclasses must implement a `_keys()` function which returns a hashable\nrepresentation of these attributes (e.g. returns them as a tuple).\n\nA CompositeObject is considered equal to another if the return value of their \n`_keys()` function is equal.\n\nIterating over a CompositeObject is like iterating over the return value of its\n`_keys()` function.\n\n\n##### Methods\n\n###### `_keys(self) -> Hashable`\n\nReturns a hashable representation of the attributes that the object wraps.\n\n\n---\n\n\n### Functions\n\n#### `split_to_base_and_shift(name_or_degree: str, name_before_accidental: bool) -> (, )`\n\nTakes a string representation of a note name or a degree. Returns a \ntuple where the first element is the string representation of the degree\nwith accidentals removed, and the second element is the number of semitones\nneeded to account fo accidentals.\n\nExamples:\n\n* `split_to_base_and_shift(\"A#\", name_before_accidental=True) == (\"A\", 1)`\n* `split_to_base_and_shift(\"Ab\", name_before_accidental=True) == (\"A\", -1)`\n* `split_to_base_and_shift(\"A\", name_before_accidental=True) == (\"A\", 0)`\n* `split_to_base_and_shift(\"Abbbb\", name_before_accidental=True) == (\"A\", -4)`\n* `split_to_base_and_shift(\"b9\", name_before_accidental=False) == (\"9\", -1)`\n* `split_to_base_and_shift(\"#9\", name_before_accidental=False) == (\"9\", 1)`\n\n\n\n#### `degree_to_semitone(degree: str) -> int`\n\nConverts a string representation of a scale degree to the number of semitones between the root and that scale degree.\n\nExamples:\n\n* `degree_to_semitone(\"b9\") == 13`\n* `degree_to_semitone(\"5\") == 7`\n\n\n\n#### `semitone_to_degree_options(semitone: int, max_accidentals: int = 1) -> List[str]`\n\nConverts the number of semitones between the root and the wanted scale degree to\na list of possible names for that scale degree.\n\nThe list of options is sorted by \"reasonableness\":\n\n* If option A has fewer accidentals than option B, option A comes first.\n* If option A has the same number of accidentals as option B, then the option with a \"b\" comes before the option with a \"#\".\n\nExamples:\n\n* `semitone_to_degree_options(semitone=3, max_accidentals=1) = [\"b3\", \"#2\"]`\n* `semitone_to_degree_options(semitone=3, max_accidentals=0) = []`\n* `semitone_to_degree_options(semitone=17, max_accidentals=1) = [\"11\", \"#10\"]`\n\n\n\n#### `note_diff(name_low: str, name_high: str) -> int`\n\nReturns the number of semitones between the first note and the second note.\nThe first note is assumed to be the lower of the two notes.\n\nExamples:\n\n* `note_diff(\"G\", \"A\") == 2`\n* `note_diff(\"A\", \"Bb\") == 1`\n* `note_diff(\"A\", \"G\") == 10`\n* `note_diff(\"A\", \"A\") == 0`\n\n\n### Exceptions\n\n#### `InvalidDegree`\n\nRaised if the string one attempts to interpret is not a valid scale degree\n\n\n\n---\n\n\n\n## `jchord.midi`\n\n\nTools for working with MIDI.\n\n### Classes\n\n#### `PlayedNote`\n\nnamedtuple which represents a (MIDI) note played at a given time for a given duration.\n\n##### Methods\n\n###### `time(self)`\n\nAlias for field number 0\n\n\n###### `note(self)`\n\nAlias for field number 1\n\n\n###### `duration(self)`\n\nAlias for field number 2\n\n\n---\n\n\n### Functions\n\n#### `note_to_midi(note: jchord.core.Note) -> int`\n\nReturns the midi value corresponding to the given `Note`.\n\n\n#### `midi_to_note(midi: int) -> jchord.core.Note`\n\nReturns the `Note` corresponding to the given MIDI note value.\n\n\n#### `midi_to_pitch(midi: int) -> float`\n\nReturns the absolute pitch in Hz for the given MIDI note value.\n\n\n#### `read_midi_file(filename: str) -> List[jchord.midi.PlayedNote]`\n\nReads the MIDI file for the given filename and returns the corresponding list of `PlayedNote`s.\n\n\n#### `group_notes_to_chords(notes: List[jchord.midi.PlayedNote]) -> Dict[float, jchord.midi.PlayedNote]`\n\nGroups the list of `PlayedNote`s by time.\n\nThe return value maps time to a list of `PlayedNote`s for that time.\n\nThere is no attempt at quantization at this time, so the notes must be played\nat the exact same time to be grouped together.\n\n\n### Exceptions\n\n#### `InvalidNote`\n\nRaised when trying to get the MIDI value of a note that doesn't seem valid.\n\n\n\n---\n\n\n\n## `jchord.knowledge`\n\n\nContains various literals that are used for computations throughout the library.\n\n* `REPETITION_SYMBOL` (`str`): The symbol that's used to indicate repetition in textual representations of chord progressions.\n* `MAJOR_SCALE_OFFSETS` (`Dict[int, int]`): Maps the scale degrees of the major scale to number of semitones from the root.\n* `ACCIDENTALS` (`Set[str]`): The set of accidentals.\n* `MAJOR_FROM_C` (`List[str]`): A list of the 7 note names in the C major scale.\n* `CHROMATIC` (`List[str]`): A list of the 12 chromatic notes starting from C. Only sharp notes are included here.\n* `ENHARMONIC` (`List[Tuple[str, str]])`): A list of the 5 pairs of enharmonic note names.\n* `CHORD_NAMES` (`Dict[str, List[str]]`): Maps chord names to the list of scale degrees in the chord, not including the root.\n* `CHORD_ALIASES`: (`Dict[str, str]`): Maps alternative chord names to the canonical chord name in `CHORD_NAMES`.\n* `DYADS`: (`Dict[int, str]`): A collection of two-note chords with names. Maps the number of semitones between the root and the other note to the chord name.\n* `TRIADS_WITH_FIFTH` (`Dict[int, str]`): A collection of three-note chords with names. All of these triads include a fifth. Maps the semitone that is not the root or the fifth to the chord name.\n\n\n\n---\n\n\n\n## `jchord.chords`\n\n\nTools for working with chords.\n\n### Classes\n\n#### `Chord`\n\nRepresents a chord quality (no root).\n\n##### Methods\n\n###### `__init__(self, name: str, semitones: List[int])`\n\n\n\n\n###### `from_semitones(name: Union[str, NoneType], semitones: List[int]) -> 'Chord'`\n\nCreates a Chord from a list of semitones from the root.\n\nIf `name` is `None`, `semitones_to_chord_name_options` is used to guess a good name for the chord.\n\n\n\n###### `from_degrees(name: str, degrees: List[str]) -> 'Chord'`\n\nCreates a Chord from a list of scale degrees.\n\nIf `name` is `None`, `semitones_to_chord_name_options` is used to guess a good name for the chord.\n\n\n\n###### `from_name(name: str) -> 'Chord'`\n\nCreates a Chord from a name.\nThe `CHORD_NAMES` and `CHORD_ALIASES` dictionaries in `jchord.knowledge` are used to find the semitones in the chord.\n\nRaises `InvalidChord` if no chord is found.\n\n\n\n###### `intervals(self) -> List[int]`\n\nReturns the list of internal intervals in the chord.\n\nExamples:\n\n* `Chord.from_name(\"minor\").intervals() == [3, 4]`\n* `Chord.from_name(\"major7\").intervals() == [4, 3, 4]`\n\n\n\n###### `with_root(self, root: jchord.core.Note) -> 'ChordWithRoot'`\n\nReturns a `ChordWithRoot` based on the chord and the provided root.\n\n\n###### `add_semitone(self, semitone: int)`\n\nAdds the given semitone (as a difference from the root degree) to the chord.\n\nThe name of the chord does not get re-calculated, so use with care.\n\n\n\n---\n\n\n\n#### `ChordWithRoot`\n\nRepresents a chord with a chord quality and a root note.\n\n##### Methods\n\n###### `__init__(self, name: str, root: jchord.core.Note, chord: jchord.chords.Chord)`\n\n\n\n\n###### `from_root_and_semitones(root: jchord.core.Note, semitones: List[int]) -> 'ChordWithRoot'`\n\nCreates a ChordWithRoot from a root `Note` and a list of semitones from the root.\n\n`semitones_to_chord_name_options` is used to guess a good name for the chord.\n\n\n\n###### `from_midi(midi: Set[int]) -> 'ChordWithRoot'`\n\nCreates a ChordWithRoot from a set of MIDI note values.\n\n`semitones_to_chord_name_options` is used to guess a good name for the chord.\n\n\n\n###### `from_name(name: str, octave: int = 4) -> 'ChordWithRoot'`\n\nCreates a ChordWithRoot from a name.\n\n`semitones_to_chord_name_options` is used to guess a good name for the chord.\n\n\n\n###### `semitones(self)`\n\nReturns the semitones in the chord.\n\n\n###### `intervals(self) -> List[int]`\n\nReturns the semitones in the chord.\n\n\n###### `midi(self) -> List[int]`\n\nReturns the list of MIDI note values in the chord.\n\n\n###### `transpose(self, shift: int) -> 'ChordWithRoot'`\n\nTransposes the chord by the given shift (in semitones).\n\n\n---\n\n\n### Functions\n\n#### `semitones_to_chord_name_options(semitones: Set[int], _rec=5) -> List[str]`\n\nReturns a set of chord names corresponding to the given set of semitones.\n\nThe function tries to put the most reasonable chord names first and the more dubious ones last.\n\nThe `_rec` argument is for internal use only; in some cases, it prevents infinite recursion while computing the chord name.\n\n\n### Exceptions\n\n#### `InvalidChord`\n\nRaised if trying to construct a chord from an invalid chord name.\n\n\n\n---\n\n\n\n## `jchord.progressions`\n\n\nTools for working with chord progressions.\n\n### Classes\n\n#### `ChordProgression`\n\nRepresents a chord progression.\n\n##### Methods\n\n###### `__init__(self, progression: List[jchord.chords.ChordWithRoot])`\n\n\n\n\n###### `from_string(string: str) -> 'ChordProgression'`\n\nCreates a `ChordProgression` from its string representation.\n\n\n###### `from_txt(filename: str) -> 'ChordProgression'`\n\nCreates a `ChordProgression` from a text file with its string representation.\n\n\n###### `from_xlsx(filename: str) -> 'ChordProgression'`\n\nCreates a `ChordProgression` from an Excel file.\n\n\n###### `from_midi_file(filename: str) -> 'ChordProgression'`\n\nCreates a `ChordProgression` from an MIDI file.\n\nThere is no attempt at quantization at this time, so the notes must be played\nat the exact same time to be grouped together as chords.\n\n\n\n###### `chords(self) -> Set[jchord.chords.ChordWithRoot]`\n\nReturns the set of chords in the progression.\n\n\n###### `midi(self) -> List[List[int]]`\n\nReturns the MIDI values for each chord in the progression.\n\n\n###### `to_string(self, chords_per_row: int = 4, column_spacing: int = 2, newline: str = '\\n') -> str`\n\nReturns the string representation of the chord progression.\n\n\n###### `to_txt(self, filename: str, chords_per_row: int = 4, column_spacing: int = 2, newline: str = '\\n')`\n\nSaves the string representation of the chord progression to a text file.\n\n\n###### `to_xlsx(self, filename: str, chords_per_row: int = 4)`\n\nSaves the chord progression to an Excel file.\n\n\n###### `to_midi(self, filename: str, instrument: int = 1, tempo: int = 120, beats_per_chord: int = 2, velocity: int = 100)`\n\nSaves the chord progression to a MIDI file.\n\n\n---\n\n\n\n#### `SongSection`\n\nRepresents a section in a Song.\n\n##### Methods\n\n###### `name(self)`\n\nAlias for field number 0\n\n\n###### `progression(self)`\n\nAlias for field number 1\n\n\n---\n\n\n\n#### `Song`\n\nRepresents a song (a series of sections).\n\n##### Methods\n\n###### `__init__(self, sections: List[jchord.progressions.SongSection])`\n\n\n\n\n###### `to_string(self, chords_per_row: int = 4, column_spacing: int = 2, newline: str = '\\n')`\n\nReturns the string representation of the song.\n\n\n---\n\n\n### Exceptions\n\n#### `InvalidProgression`\n\nRaised when encountering what seems like an invalid chord progression.\n\n\n\n---\n\n\n\n\n",
"description_content_type": "text/markdown",
"docs_url": null,
"download_url": "",
"downloads": {
"last_day": -1,
"last_month": -1,
"last_week": -1
},
"home_page": "https://github.com/jonathangjertsen/jchord",
"keywords": "",
"license": "MIT",
"maintainer": "",
"maintainer_email": "",
"name": "jchord",
"package_url": "https://pypi.org/project/jchord/",
"platform": "",
"project_url": "https://pypi.org/project/jchord/",
"project_urls": {
"Documentation": "https://github.com/jonathangjertsen/jchord",
"Homepage": "https://github.com/jonathangjertsen/jchord",
"Source": "https://github.com/jonathangjertsen/jchord"
},
"release_url": "https://pypi.org/project/jchord/0.1.5/",
"requires_dist": null,
"requires_python": "",
"summary": "Python toolkit for working with chord progressions",
"version": "0.1.5"
},
"last_serial": 5881554,
"releases": {
"0.1.0": [
{
"comment_text": "",
"digests": {
"md5": "fed42d8af856c129e4958744f389fa55",
"sha256": "ba2da2b07a4835740f8bb93b347112fff9d6b2fac9fb2d3a01922e76f8ef987e"
},
"downloads": -1,
"filename": "jchord-0.1.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "fed42d8af856c129e4958744f389fa55",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": null,
"size": 19821,
"upload_time": "2019-09-22T20:09:07",
"url": "https://files.pythonhosted.org/packages/53/43/9498f825648696121a61701f0e4e959d11d6a391803b9a05815583216d54/jchord-0.1.0-py3-none-any.whl"
},
{
"comment_text": "",
"digests": {
"md5": "dd2351d1cd20ab7f91c20856826deb2b",
"sha256": "664a3b6b52a49b47363f09d57bcfcd9480fe1e1f35a444707b790b22b3692375"
},
"downloads": -1,
"filename": "jchord-0.1.0.tar.gz",
"has_sig": false,
"md5_digest": "dd2351d1cd20ab7f91c20856826deb2b",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 25993,
"upload_time": "2019-09-22T20:09:09",
"url": "https://files.pythonhosted.org/packages/fd/5e/21a08309a7a01854400436d0418bcccb980ed99f713633cae22ce875b9a3/jchord-0.1.0.tar.gz"
}
],
"0.1.1": [
{
"comment_text": "",
"digests": {
"md5": "89c7e6dcf545577e1ee21a1789bf3ad2",
"sha256": "6127e1149bb147fc775cea1bb60f7cf3baee51698f5f0d12fe6f02feb1c17e2f"
},
"downloads": -1,
"filename": "jchord-0.1.1-py3-none-any.whl",
"has_sig": false,
"md5_digest": "89c7e6dcf545577e1ee21a1789bf3ad2",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": null,
"size": 19819,
"upload_time": "2019-09-22T20:45:15",
"url": "https://files.pythonhosted.org/packages/16/0d/17f962bd7d981bb4e7c5c7a92126414300a641820f7d4d0393e60ace158e/jchord-0.1.1-py3-none-any.whl"
},
{
"comment_text": "",
"digests": {
"md5": "45b6b0f4945516584dc34048af0b2b4c",
"sha256": "9e76255b6ba8031cb1529d9257ef3dcf447a37700b8e690faca2cfbb568a2ed6"
},
"downloads": -1,
"filename": "jchord-0.1.1.tar.gz",
"has_sig": false,
"md5_digest": "45b6b0f4945516584dc34048af0b2b4c",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 26037,
"upload_time": "2019-09-22T20:45:18",
"url": "https://files.pythonhosted.org/packages/35/3b/2f316bb3633e2388b0e69b801910ff6ab3bfa7f7c0aa0e6336329c36b8aa/jchord-0.1.1.tar.gz"
}
],
"0.1.2": [
{
"comment_text": "",
"digests": {
"md5": "ffda6c0ae8b37af77b651fe18e8f9af8",
"sha256": "fcf8f39dcbb2f14dbc1eac5351f9e3b97c9bb876e26c75fc9d8d5576a263591d"
},
"downloads": -1,
"filename": "jchord-0.1.2-py3-none-any.whl",
"has_sig": false,
"md5_digest": "ffda6c0ae8b37af77b651fe18e8f9af8",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": null,
"size": 19819,
"upload_time": "2019-09-22T20:45:16",
"url": "https://files.pythonhosted.org/packages/88/06/629fa38a5b569fb242f44fa874e320c97932c22a3cf2a2059d25cb241a61/jchord-0.1.2-py3-none-any.whl"
},
{
"comment_text": "",
"digests": {
"md5": "0fc4c2b7d5dc85f652dceb17c6cb583f",
"sha256": "52fd7954840a6b8db920aab0858c494eec8170d5622f37a8081f9ec940da1532"
},
"downloads": -1,
"filename": "jchord-0.1.2.tar.gz",
"has_sig": false,
"md5_digest": "0fc4c2b7d5dc85f652dceb17c6cb583f",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 26033,
"upload_time": "2019-09-22T20:45:19",
"url": "https://files.pythonhosted.org/packages/d8/40/82ede0385f58b2762256895c0e605b1cf25df12b22a166a248c27f9db8b5/jchord-0.1.2.tar.gz"
}
],
"0.1.3": [
{
"comment_text": "",
"digests": {
"md5": "4a4c2a6feb98db1fac177ebd073e07d1",
"sha256": "c6803e2c6898f0e9af86d98f9e5413852d2199b5a00622c340da698f13a67c74"
},
"downloads": -1,
"filename": "jchord-0.1.3-py3-none-any.whl",
"has_sig": false,
"md5_digest": "4a4c2a6feb98db1fac177ebd073e07d1",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": null,
"size": 19821,
"upload_time": "2019-09-22T21:12:11",
"url": "https://files.pythonhosted.org/packages/6a/9d/200dd6652f8174c5f824122df69b0521aa294d9adecc5fc5b33bc1da99d7/jchord-0.1.3-py3-none-any.whl"
},
{
"comment_text": "",
"digests": {
"md5": "4a8bcb3cbf4a476fb35895c4f8c14813",
"sha256": "a79c2d97ae36f0c8d393b724a041cab9c4f6bbff7141c40b734e3c5ac0d5dbdb"
},
"downloads": -1,
"filename": "jchord-0.1.3.tar.gz",
"has_sig": false,
"md5_digest": "4a8bcb3cbf4a476fb35895c4f8c14813",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 26031,
"upload_time": "2019-09-22T21:12:15",
"url": "https://files.pythonhosted.org/packages/6a/7d/ef9e44184cc883a6efc9a9dc7cec200a11ff13b4f656f5b46995daa578fe/jchord-0.1.3.tar.gz"
}
],
"0.1.4": [
{
"comment_text": "",
"digests": {
"md5": "aca33380d5c4ccf5f05024f53f83944d",
"sha256": "26cdf7178226739cea01938c0521aaf539cf42386bc5a8a5cae2f3447626c5dd"
},
"downloads": -1,
"filename": "jchord-0.1.4-py3-none-any.whl",
"has_sig": false,
"md5_digest": "aca33380d5c4ccf5f05024f53f83944d",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": null,
"size": 19822,
"upload_time": "2019-09-22T21:12:13",
"url": "https://files.pythonhosted.org/packages/af/fc/4e0ef40467fbffb033f9eadc202a61bdb1ef3ee18d051095a19022842466/jchord-0.1.4-py3-none-any.whl"
},
{
"comment_text": "",
"digests": {
"md5": "b5442d0892962a851c5988423c74ce39",
"sha256": "62bfd4ec4f103a518305756b4c621e9064427f11424672e4e0b14abe1ccac4cb"
},
"downloads": -1,
"filename": "jchord-0.1.4.tar.gz",
"has_sig": false,
"md5_digest": "b5442d0892962a851c5988423c74ce39",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 26032,
"upload_time": "2019-09-22T21:12:17",
"url": "https://files.pythonhosted.org/packages/07/2c/ea6883cd2740b596ea44060179680e4dc2d068550fd4e6bb29165b9ede1d/jchord-0.1.4.tar.gz"
}
],
"0.1.5": [
{
"comment_text": "",
"digests": {
"md5": "e0b32d6e4b59ec9c3058d485787c78f1",
"sha256": "8c3cf1a635903f3d993f626099de6fdb147af7c30b7aa9c894cead92a5db6414"
},
"downloads": -1,
"filename": "jchord-0.1.5-py3-none-any.whl",
"has_sig": false,
"md5_digest": "e0b32d6e4b59ec9c3058d485787c78f1",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": null,
"size": 19809,
"upload_time": "2019-09-24T19:40:51",
"url": "https://files.pythonhosted.org/packages/71/53/80e4032b377937547584cdfe08cbed373bc2046c59e654623f333a8acfce/jchord-0.1.5-py3-none-any.whl"
},
{
"comment_text": "",
"digests": {
"md5": "ed4cf7a2e175ef1e9012ecadca1d76c6",
"sha256": "aed08645ae9ee7ed8459704c9cb0ff01587b159d2810045be874164d33be3382"
},
"downloads": -1,
"filename": "jchord-0.1.5.tar.gz",
"has_sig": false,
"md5_digest": "ed4cf7a2e175ef1e9012ecadca1d76c6",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 26015,
"upload_time": "2019-09-24T19:40:53",
"url": "https://files.pythonhosted.org/packages/5b/50/c38e2bb7887e81ecb17e095f3d234288626757a954111c64018211387574/jchord-0.1.5.tar.gz"
}
]
},
"urls": [
{
"comment_text": "",
"digests": {
"md5": "e0b32d6e4b59ec9c3058d485787c78f1",
"sha256": "8c3cf1a635903f3d993f626099de6fdb147af7c30b7aa9c894cead92a5db6414"
},
"downloads": -1,
"filename": "jchord-0.1.5-py3-none-any.whl",
"has_sig": false,
"md5_digest": "e0b32d6e4b59ec9c3058d485787c78f1",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": null,
"size": 19809,
"upload_time": "2019-09-24T19:40:51",
"url": "https://files.pythonhosted.org/packages/71/53/80e4032b377937547584cdfe08cbed373bc2046c59e654623f333a8acfce/jchord-0.1.5-py3-none-any.whl"
},
{
"comment_text": "",
"digests": {
"md5": "ed4cf7a2e175ef1e9012ecadca1d76c6",
"sha256": "aed08645ae9ee7ed8459704c9cb0ff01587b159d2810045be874164d33be3382"
},
"downloads": -1,
"filename": "jchord-0.1.5.tar.gz",
"has_sig": false,
"md5_digest": "ed4cf7a2e175ef1e9012ecadca1d76c6",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 26015,
"upload_time": "2019-09-24T19:40:53",
"url": "https://files.pythonhosted.org/packages/5b/50/c38e2bb7887e81ecb17e095f3d234288626757a954111c64018211387574/jchord-0.1.5.tar.gz"
}
]
}