Skip to content

Commit 087b196

Browse files
Merge pull request #17 from splendidtoad/dev
Separate chords and spaces with commas
2 parents dd6222e + 186b8dd commit 087b196

5 files changed

Lines changed: 42 additions & 33 deletions

File tree

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
0.2.0 - The Measure __str__() method now adds a comma between all chords
2+
and spaces in the measure; this prevents iRealPro from choking on
3+
run-on chord names if a measure has a different chord for every
4+
beat; for example, "EbG-Bb-C7" is now "Eb,G-,Bb-,C7"
5+
and "C " is now "C, , , "
16
0.1.3 - Fix Song.ur() for Songs with no measures
27
- Fix package/module namespacing
38

doc/pyrealpro.html

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@
111111
<td colspan=2><tt><a href="#Song">Song</a>(**kwargs)<br>
112112
&nbsp;<br>
113113
A&nbsp;class&nbsp;for&nbsp;building&nbsp;fake-book&nbsp;style&nbsp;chord&nbsp;charts&nbsp;that&nbsp;can&nbsp;be&nbsp;imported&nbsp;into&nbsp;iRealPro.&nbsp;Implements&nbsp;the&nbsp;iRealPro<br>
114-
data&nbsp;format&nbsp;as&nbsp;described&nbsp;at&nbsp;https://irealpro.com/ireal-pro-file-format/.<br>&nbsp;</tt></td></tr>
114+
data&nbsp;format&nbsp;as&nbsp;described&nbsp;at&nbsp;<a href="https://irealpro.com/ireal-pro-file-format/">https://irealpro.com/ireal-pro-file-format/</a>.<br>&nbsp;</tt></td></tr>
115115
<tr><td>&nbsp;</td>
116116
<td width="100%">Methods defined here:<br>
117117
<dl><dt><a name="Song-__init__"><strong>__init__</strong></a>(self, **kwargs)</dt><dd><tt>Initializes&nbsp;a&nbsp;new&nbsp;<a href="#Song">Song</a>&nbsp;<a href="builtins.html#object">object</a>.<br>
@@ -131,6 +131,11 @@
131131
:param&nbsp;urlencode:&nbsp;(bool),&nbsp;optional<br>
132132
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Indicates&nbsp;whether&nbsp;or&nbsp;not&nbsp;the&nbsp;result&nbsp;should&nbsp;be&nbsp;URL-encoded.</tt></dd></dl>
133133

134+
<hr>
135+
Readonly properties defined here:<br>
136+
<dl><dt><strong>composer_name</strong></dt>
137+
<dd><tt>:return:&nbsp;(str)&nbsp;The&nbsp;composer's&nbsp;full&nbsp;name&nbsp;in&nbsp;"Last&nbsp;First"&nbsp;format.</tt></dd>
138+
</dl>
134139
<hr>
135140
Data descriptors defined here:<br>
136141
<dl><dt><strong>__dict__</strong></dt>
@@ -139,9 +144,6 @@
139144
<dl><dt><strong>__weakref__</strong></dt>
140145
<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
141146
</dl>
142-
<dl><dt><strong>composer_name</strong></dt>
143-
<dd><tt>:return:&nbsp;(str)&nbsp;The&nbsp;composer's&nbsp;full&nbsp;name&nbsp;in&nbsp;"Last&nbsp;First"&nbsp;format.</tt></dd>
144-
</dl>
145147
<hr>
146148
Data and other attributes defined here:<br>
147149
<dl><dt><strong>measures</strong> = None</dl>

pyrealpro.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,10 @@ def __init__(self, chords, time_sig=None, rehearsal_marks=[], barline_open="", b
279279
raise ValueError("Found one or more unrecognized rehearsal marks.")
280280

281281
def __str__(self):
282-
chords_str = "".join(self.chords)
282+
chords_sep = ""
283+
if len(self.chords) > 1:
284+
chords_sep = ","
285+
chords_str = chords_sep.join(self.chords)
283286
if self.render_ts:
284287
ts = self.time_sig
285288
else:

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
setuptools.setup(
77
name="pyrealpro",
8-
version="0.1.3",
8+
version="0.2.0",
99
author="Andy Chase",
1010
author_email="andychase@gmail.com",
1111
description="Tools for building iRealPro songs.",

test/test_pyrealpro.py

Lines changed: 26 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -55,21 +55,21 @@ def test_barline_and_ts_behavior(self):
5555
m2 = Measure(chords='G')
5656
s = Song(title=TITLE, composer_name_first=COMPOSER_NAME_FIRST, composer_name_last=COMPOSER_NAME_LAST, measures=[m1, m2])
5757
self.assertEqual(s.url(urlencode=False),
58-
'irealbook://A Test Song=Jackson Arthur "Two-Sheds"=Medium Swing=C=n=[T44C |G Z')
58+
'irealbook://A Test Song=Jackson Arthur "Two-Sheds"=Medium Swing=C=n=[T44C, , , |G, , , Z')
5959
m3 = Measure(chords='A', barline_open='{', time_sig=TimeSignature(3, 4))
6060
m4 = Measure(chords='D', barline_close='}', time_sig=TimeSignature(3, 4))
6161
s2 = Song(title=TITLE, composer_name_first=COMPOSER_NAME_FIRST, composer_name_last=COMPOSER_NAME_LAST, measures=[m3, m4])
6262

6363
self.assertEqual(s2.url(urlencode=False),
64-
'irealbook://A Test Song=Jackson Arthur "Two-Sheds"=Medium Swing=C=n={T34A |D }')
64+
'irealbook://A Test Song=Jackson Arthur "Two-Sheds"=Medium Swing=C=n={T34A, , |D, , }')
6565

6666
def test_empty_measures(self):
6767
"""
6868
Tests expected output of a Song object with no measures
6969
"""
7070
s = Song(title=TITLE, composer_name_first=COMPOSER_NAME_FIRST, composer_name_last=COMPOSER_NAME_LAST)
71-
self.assertEqual(s.url(), "irealbook://A%20Test%20Song=Jackson%20Arthur%20%22Two-Sheds%22=Medium%20Swing=C=n=%5BT44%20%20%20%20Z")
72-
self.assertEqual(s.url(urlencode=False), "irealbook://A Test Song=Jackson Arthur \"Two-Sheds\"=Medium Swing=C=n=[T44 Z")
71+
self.assertEqual(s.url(), "irealbook://A%20Test%20Song=Jackson%20Arthur%20%22Two-Sheds%22=Medium%20Swing=C=n=%5BT44%20%2C%20%2C%20%2C%20Z")
72+
self.assertEqual(s.url(urlencode=False), 'irealbook://A Test Song=Jackson Arthur "Two-Sheds"=Medium Swing=C=n=[T44 , , , Z')
7373

7474

7575
class TestMeasures(unittest.TestCase):
@@ -106,15 +106,15 @@ def test_measure_string_from_chords_string(self):
106106
"""
107107
# TODO test multiple time signatures
108108
m = Measure(chords='C', time_sig=TimeSignature(5, 4))
109-
expected_measure_string = 'C |'
109+
expected_measure_string = 'C, , , , |'
110110
self.assertEqual(m.__str__(), expected_measure_string)
111111

112112
def test_measure_string_from_chords_list(self):
113113
"""
114114
Test that Measure.__str__() returns the expected value when chords are provided as a list.
115115
"""
116116
m = Measure(chords=['C', None, 'G7', None], time_sig=TimeSignature(4, 4))
117-
expected_measure_string = 'C G7 |'
117+
expected_measure_string = 'C, ,G7, |'
118118
self.assertEqual(m.__str__(), expected_measure_string)
119119

120120
def test_modulo_chord_padding(self):
@@ -124,68 +124,68 @@ def test_modulo_chord_padding(self):
124124
"""
125125
chords = ['C', 'F']
126126
m = Measure(chords=chords, time_sig=TimeSignature(4, 4))
127-
self.assertEqual(m.__str__(), 'C F |')
127+
self.assertEqual(m.__str__(), 'C, ,F, |')
128128
m = Measure(chords=chords, time_sig=TimeSignature(6, 4))
129-
self.assertEqual(m.__str__(), 'C F |')
129+
self.assertEqual(m.__str__(), 'C, , ,F, , |')
130130
m = Measure(chords=['C', 'F', 'G'], time_sig=TimeSignature(6, 4))
131-
self.assertEqual(m.__str__(), 'C F G |')
131+
self.assertEqual(m.__str__(), 'C, ,F, ,G, |')
132132

133133
def test_staff_text(self):
134134
"""
135135
Test that staff text is formatted correctly and in the expected position
136136
"""
137137
m = Measure(chords='C', time_sig=TimeSignature(4, 4), staff_text="Test")
138-
self.assertEqual(m.__str__(), '<Test>C |')
138+
self.assertEqual(m.__str__(), '<Test>C, , , |')
139139
m = Measure(chords=['C', 'F'], time_sig=TimeSignature(4, 4), staff_text='Test',
140140
barline_open='{', barline_close='}')
141-
self.assertEqual(m.__str__(), '{<Test>C F }')
141+
self.assertEqual(m.__str__(), '{<Test>C, ,F, }')
142142
m.render_ts = True
143-
self.assertEqual(m.__str__(), '{T44<Test>C F }')
143+
self.assertEqual(m.__str__(), '{T44<Test>C, ,F, }')
144144

145145
def test_barline_open(self):
146146
"""
147147
Test opening barline options
148148
"""
149149
m = Measure(chords='C', barline_open="")
150-
self.assertEqual(m.__str__(), 'C |')
150+
self.assertEqual(m.__str__(), 'C, , , |')
151151
m2 = Measure(chords='C', barline_open='[')
152-
self.assertEqual(m2.__str__(), '[C |')
152+
self.assertEqual(m2.__str__(), '[C, , , |')
153153
m3 = Measure(chords='C', barline_open='{')
154154
m3.render_ts = True
155-
self.assertEqual(m3.__str__(), '{T44C |')
155+
self.assertEqual(m3.__str__(), '{T44C, , , |')
156156

157157
def test_barline_close(self):
158158
"""
159159
Test closing barline options
160160
"""
161161
m = Measure(chords='C', barline_close=None)
162-
self.assertEqual(m.__str__(), 'C |')
162+
self.assertEqual(m.__str__(), 'C, , , |')
163163
m = Measure(chords='C', barline_close='')
164-
self.assertEqual(m.__str__(), 'C |')
164+
self.assertEqual(m.__str__(), 'C, , , |')
165165
m2 = Measure(chords='C', barline_close=']')
166-
self.assertEqual(m2.__str__(), 'C ]')
166+
self.assertEqual(m2.__str__(), 'C, , , ]')
167167
m3 = Measure(chords='C', barline_close='}')
168-
self.assertEqual(m3.__str__(), 'C }')
168+
self.assertEqual(m3.__str__(), 'C, , , }')
169169
m4 = Measure(chords='C', barline_close='Z')
170-
self.assertEqual(m4.__str__(), 'C Z')
170+
self.assertEqual(m4.__str__(), 'C, , , Z')
171171

172172
def test_ending(self):
173173
"""
174174
Test output of `ending` property
175175
"""
176176
m = Measure(chords='C', ending='N1', barline_close='}')
177-
self.assertEqual(m.__str__(), 'N1C }')
177+
self.assertEqual(m.__str__(), 'N1C, , , }')
178178
m1 = Measure(chords=['C', 'G7'], ending="N2", barline_close='}', render_ts=True)
179-
self.assertEqual(m1.__str__(), 'T44N2C G7 }')
179+
self.assertEqual(m1.__str__(), 'T44N2C, ,G7, }')
180180

181181
def test_rehearsal_marks(self):
182182
"""
183183
Test behavior of the rehearsal_marks property
184184
"""
185185
m = Measure(chords='C', rehearsal_marks="*A", barline_open="[", render_ts=True)
186-
self.assertEqual(m.__str__(), '*A[T44C |')
186+
self.assertEqual(m.__str__(), '*A[T44C, , , |')
187187
m1 = Measure(chords=['G', 'C7'], rehearsal_marks=['*B', 'Q'])
188-
self.assertEqual(m1.__str__(), '*BG C7 Q|')
188+
self.assertEqual(m1.__str__(), '*BG, ,C7, Q|')
189189
with self.assertRaises(ValueError):
190190
Measure(chords='G', rehearsal_marks=['M'])
191191

@@ -248,9 +248,8 @@ def test_blues(self):
248248

249249
s.measures.append(Measure(chords='G7', ending='N2'))
250250
s.measures.append(Measure(chords='G7', barline_close='Z'))
251-
252-
self.assertEqual(s.url(), "irealbook://Automation%20Blues=Matonne%20Otto=New%20Orleans%20Swing=G=n=%7BT44%3CGenerated%20by%20pyrealpro%3EG7%20%20%20%7CG7%20%20%20%7CG7%20%20%20%7CG7%20%20%20%5D%5BC7%20%20%20%7CC7%20%20%20%7CG7%20%20%20%7CG7%20%20%20%5D%5BD7%20%20%20%7CC7%20%20%20%7CN1G7%20%20%20%7CD7%20%20%20%7DN2G7%20%20%20%7CG7%20%20%20Z")
253-
self.assertEqual(s.url(urlencode=False), "irealbook://Automation Blues=Matonne Otto=New Orleans Swing=G=n={T44<Generated by pyrealpro>G7 |G7 |G7 |G7 ][C7 |C7 |G7 |G7 ][D7 |C7 |N1G7 |D7 }N2G7 |G7 Z")
251+
self.assertEqual(s.url(), "irealbook://Automation%20Blues=Matonne%20Otto=New%20Orleans%20Swing=G=n=%7BT44%3CGenerated%20by%20pyrealpro%3EG7%2C%20%2C%20%2C%20%7CG7%2C%20%2C%20%2C%20%7CG7%2C%20%2C%20%2C%20%7CG7%2C%20%2C%20%2C%20%5D%5BC7%2C%20%2C%20%2C%20%7CC7%2C%20%2C%20%2C%20%7CG7%2C%20%2C%20%2C%20%7CG7%2C%20%2C%20%2C%20%5D%5BD7%2C%20%2C%20%2C%20%7CC7%2C%20%2C%20%2C%20%7CN1G7%2C%20%2C%20%2C%20%7CD7%2C%20%2C%20%2C%20%7DN2G7%2C%20%2C%20%2C%20%7CG7%2C%20%2C%20%2C%20Z")
252+
self.assertEqual(s.url(urlencode=False), "irealbook://Automation Blues=Matonne Otto=New Orleans Swing=G=n={T44<Generated by pyrealpro>G7, , , |G7, , , |G7, , , |G7, , , ][C7, , , |C7, , , |G7, , , |G7, , , ][D7, , , |C7, , , |N1G7, , , |D7, , , }N2G7, , , |G7, , , Z")
254253

255254

256255
if __name__ == '__main__':

0 commit comments

Comments
 (0)