Merge lp:~philip-peitsch/quickly/multiple-distros into lp:quickly

Proposed by Philip Peitsch
Status: Rejected
Rejected by: Didier Roche-Tolomelli
Proposed branch: lp:~philip-peitsch/quickly/multiple-distros
Merge into: lp:quickly
Diff against target: 178 lines (+118/-23)
2 files modified
data/templates/ubuntu-application/internal/packaging.py (+47/-23)
test/ubuntu-application/test_packaging.py (+71/-0)
To merge this branch: bzr merge lp:~philip-peitsch/quickly/multiple-distros
Reviewer Review Type Date Requested Status
Didier Roche-Tolomelli Needs Resubmitting
Review via email: mp+19616@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Philip Peitsch (philip-peitsch) wrote :

Design tackles two separate parts:

- Abstraction of version handling to make parsing easier and more consistent
- Finding the LSB distro information required

A --include-distro (yes/no) has been added to release & share. This updates the project's stored value upon calling. If not set, it is assumed false, and this setting is stored.

The behaviour for --include-distro=no is identical to previous definition. With --include-distro=yes, the string "-distroname1" is always appended to the current release or shared value. The number 1 at the end of the distro-name is never incremented (I didn't see a point to doing this at this stage).

Generated file names are as per the bug report. Unit tests have been added to verify the version recognition is behaving correctly.

As every, let me know what I can do to improve this patch :)

428. By Philip Peitsch

Removing unneeded python interpreter message

Revision history for this message
Didier Roche-Tolomelli (didrocks) wrote :

So, I looked at your change and I really like your work there about factoring the versioning scheme :)
Also the testsuite is very great and that motive me to expand it (it just should be in <template_directory>/test/, but that's a detail ;)

Now, about the multi distro thing, I think there is a little misconception, let me explain how it works.

In ubuntu, for instance, let's say you release 0.2-0ubuntu1 in karmic. If you don't change it, 0.2-0ubuntu1 will be rebuild on lucid (and during the dist-upgrade, it will fetch and download it). There is no need for ~<distrib> or other stuff like that which should be used at last resort (for corner case that one developer won't encounter on his/her own, normally).
Now, if a new version is released, we can as well backport to previous version, like 0.2.1-0ubuntu1 for instance.

And I'm sure you will tell me now that "oh, but it's failing in my ppa when I try to reupload the same version, just changing the distro in debian/changelog". Yes, but…

That's because uploading most time the same version is wrong wrong wrong (wrong? ;)). You should just ask for a rebuild against another version of the distribution.

- "Oh sweet, how can I do that?"
- "No pb son, just head to copy, select 'This' as destination ppa and ask for a rebuild against another release".
- "That was quite hidden"
- "Right"
- "So, what about providing a command to do that for the user?"
- "That's an excellent idea, but there is nothing in the API at the moment to due that"
- "So, for Quickly 0.6?"
- "yeah, let's say that"

So, what do you think about that plan? With that, we don't clutter the versionning and it's working better.

But I'm still very very interested in the other part of the patch which refactors and makes a testsuite from the versionning scheme and autobumping. I would just rename "parse_version" to "bump_version" or "parse_and_bump_version" to show that we are returning a new value.

Tell me what do you think about that plan and resubmit this part?

PS: sorry, I'm a little bit ill now and that's why some part are just on the fun side ;)

review: Needs Resubmitting
Revision history for this message
Philip Peitsch (philip-peitsch) wrote :

Ahh! That is exactly the type of explanation I was unable to really find or understand when I did this change :). Thanks very much for laying that out for me... makes a lot more sense now.

So, what I'll do with this patch is eliminate all traces of "include distro" details. Do you want me to remove the handling of that within the parse_version section? I think it might actually be a good idea to leave it in at the moment, because then the user can manually set the distro as a version if required (currently it will refuse to allow it).

Regarding the renaming, I see bumping the version and parsing to be to separate operations because each can potentially get more complex as more styles are supported. Keeping them separate makes unit-testing easier.

With the test directory, are you saying that it should be in /data/templates/ubuntu-application/test rather than /test?

I'll have to think about adding in support for multiple distros some other way then :). I'm hitting the issue where I'm developing in lucid, but want to release in karmic... and manually copying the package all the time is somewhat unattractive :). I'll keep thinking on a better way to do that (it could be as you say, interfacing with the launchpad API).

P.S., I think I quite like your ill patch reviews lol... that was a very entertaining summary to read :D. Thnx!

429. By Philip Peitsch

Merging trunk

430. By Philip Peitsch

Reverting changes to release and share. Include distro option is not required

431. By Philip Peitsch

Removing include distro operation as no longer required

Revision history for this message
Philip Peitsch (philip-peitsch) wrote :

Ok. I've rolled out all the include distro stuff. I'll await your guidance on fixes to the test directory structure and what improvements / changes you want to parse_version.

Hope you get better :)

Revision history for this message
Didier Roche-Tolomelli (didrocks) wrote :

Thanks, I'm getting a little better today. I would be in shape for working next Monday, hopefully for my employer :)

I agree with parsing/replacing thing. I just misunderstood your function the first time as it returned a value. It's better with a clear mind now ;)

I'm quite not comfortable enclosing the user in a shema like -distro and we should free it a little bit… After some reflexion, I think we should:
On quickly release <version provided>, don't check anything (something in release.py like:
if not proposed_version:
    try:
        release_version = packaging.updateversion(proposed_version)
    except (packaging.invalid_versionning_scheme,
        packaging.invalid_version_in_setup), error_message:
        print(error_message)
        sys.exit(1)
else:
    release_version = proposed_version
(or maybe, we can do it in update_version directly, I have no strong opinion about that…

Oh, but it's already present in updateversion() \o/ (see the 5 first lines?). Heh, it seems I'm ok with myself, good! (this is not a joke, but so weird that I don't want to remove it ;)).

So, quickly release foobarversionning will work :)
Going to quickly share, looking at the code this time, I still agree with how it worked previously: it's adding -public1,2,3 whatever the version was in setup.py (either automatically or manually previously added). But it's after the parsing in your version now. So, I would be in favor in making the check in the case we don't share only. The bad part is that now your parse() function should be rewriten as it was used to separate the share version (-publicX) to the core one, maybe 2 functions is needed: one for seperate that and one for checking the "core version"?.
With that, quickly share will whatever the version is, either:
- add -public1 if the previous version wasn't shared
- bump the -public(X+1) part.

So, the "right version checking" will not be done in sharing, only in the "else" part.
The last case is someone tweeting directly the value in setup.py. I would say we should no more support that and change the error message like:
Release version specified in setup.py is not a valid version scheme like 'year.month(.z)' (needed for autobumping version by Quickly). If you want to specify yourself your version, you should use: quickly release %s" % version_string

With that, I think we address all cases, this needs some rewrite for your function and splitting and I can do it if you don't want to, but I think this is the right way to go. What's your thoughts?

Considering the test, I was thinking about /data/templates/ubuntu-application/test/ (each template having their test in their namespace seems logical, isn't it? I have no strong opinion about that to be honest :))

If I'm not clear do not hesitate to shout as well. Thanks for your work again, it's more than appreciated :)

Revision history for this message
Didier Roche-Tolomelli (didrocks) wrote :

I think this MR doesn't apply anymore, cleaning the list :)

Unmerged revisions

431. By Philip Peitsch

Removing include distro operation as no longer required

430. By Philip Peitsch

Reverting changes to release and share. Include distro option is not required

429. By Philip Peitsch

Merging trunk

428. By Philip Peitsch

Removing unneeded python interpreter message

427. By Philip Peitsch

Tidying up changes slightly

426. By Philip Peitsch

Fixing behaviour in how project configuration is persisted

425. By Philip Peitsch

Changing when include distribution setting is stored

424. By Philip Peitsch

Adding support to share for including distribution

423. By Philip Peitsch

Adding support to release for including distribution

422. By Philip Peitsch

Fixing tests to not use relative directories

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'data/templates/ubuntu-application/internal/packaging.py'
2--- data/templates/ubuntu-application/internal/packaging.py 2010-02-19 18:25:08 +0000
3+++ data/templates/ubuntu-application/internal/packaging.py 2010-02-20 02:14:11 +0000
4@@ -208,14 +208,8 @@
5
6 if proposed_version:
7 # check manual versionning is correct
8- try:
9- for number in proposed_version.split('.'):
10- float(number)
11- except ValueError:
12- msg = _("Release version specified in command arguments is not a " \
13- "valid version scheme like 'x(.y)(.z)'.")
14- raise invalid_versionning_scheme(msg)
15- new_version = proposed_version
16+ # parsing will raise an invalid_versionning_scheme if it fails
17+ new_version = parse_version(proposed_version)[0]
18
19 else:
20 # get previous value
21@@ -225,30 +219,22 @@
22 msg = _("No previous version found in setup.py. Put one please")
23 raise invalid_version_in_setup(msg)
24
25+ new_version = parse_version(old_version)
26 # sharing only add -publicX to last release, no other update, no bumping
27 if sharing:
28- splitted_release_version = old_version.split("-public")
29- if len(splitted_release_version) > 1:
30- try:
31- share_version = float(splitted_release_version[1])
32- except ValueError:
33- msg = _("Share version specified after -public in "\
34- "setup.py is not a valid number: %s") \
35- % splitted_release_version[1]
36- raise invalid_versionning_scheme(msg)
37- new_version = splitted_release_version[0] + '-public' + \
38- str(int(share_version + 1))
39+ if new_version[1]:
40+ new_version = new_version[0] + '-public' + \
41+ str(new_version[1]+1)
42 else:
43- new_version = old_version + "-public1"
44+ new_version = new_version[0] + "-public1"
45
46 # automatically version to year.month(.subversion)
47 else:
48 base_version = datetime.datetime.now().strftime("%y.%m")
49- if base_version in old_version:
50+ if base_version in new_version[0]:
51 try:
52 # try to get a minor version, removing -public if one
53- (year, month, minor_version) = old_version.split('.')
54- minor_version = minor_version.split('-public')[0]
55+ (year, month, minor_version) = new_version[0].split('.')
56 try:
57 minor_version = float(minor_version)
58 except ValueError:
59@@ -276,3 +262,41 @@
60 "name", "version", new_version, {})
61
62 return new_version
63+
64+def parse_version(version_string):
65+ '''Parses a version string into it's appropriate components. Supported versions include:
66+ x(.y)(.z)
67+ year.month
68+ year.month-publicX
69+ year.month-publicX-distributionY
70+ year.month-distributionY'''
71+ public_match = None
72+ if version_string:
73+ # attempt to remove publicX and distributionY first
74+ public_match = re.search('-public(\w+)', version_string)
75+ if public_match is not None:
76+ # split the version string at this point as distribution always follows if present
77+ # discard the distribution as it isn't used beyond this point
78+ (version_string, discard_distro) = version_string.split(public_match.group(0), 1)
79+ try:
80+ public_match = int(public_match.group(1)) # first group is the public release number
81+ except ValueError:
82+ msg = _("Share version specified after -public in "\
83+ "setup.py is not a valid number: %s") \
84+ % public_match.group(0)
85+ raise invalid_versionning_scheme(msg)
86+ else:
87+ # assume that any letters followed by numbers is part of the distribution string
88+ distro_match = re.search('-\d*[a-zA-Z]+\d+$', version_string)
89+ if distro_match is not None:
90+ # discard the distribution as it isn't used beyond this point
91+ (version_string, discard_distro) = version_string.split(distro_match.group(0), 1)
92+ try:
93+ # ensure all remaining segments are numeric
94+ for part in version_string.split('.'):
95+ int(part)
96+ except ValueError:
97+ msg = _("Release version specified in command arguments is not a " \
98+ "valid version scheme like 'x(.y)(.z)'.")
99+ raise invalid_versionning_scheme(msg)
100+ return (version_string, public_match)
101
102=== added directory 'test'
103=== added directory 'test/ubuntu-application'
104=== added file 'test/ubuntu-application/test_packaging.py'
105--- test/ubuntu-application/test_packaging.py 1970-01-01 00:00:00 +0000
106+++ test/ubuntu-application/test_packaging.py 2010-02-20 02:14:11 +0000
107@@ -0,0 +1,71 @@
108+import unittest
109+import sys
110+import os
111+
112+# need to set up the paths so the internals will work as expected
113+sys.path.insert(0, os.path.join(os.path.dirname(__file__),"..",".."))
114+sys.path.insert(0, os.path.join(os.path.dirname(__file__),"..","..","data","templates","ubuntu-application"))
115+
116+from internal.packaging import parse_version, get_lsb_release, invalid_versionning_scheme
117+
118+class TestPackaging(unittest.TestCase):
119+ def disabled_test_get_lsb(self):
120+ # can only work on a known distro. Manually verify
121+ self.assertEqual('lucid', get_lsb_release())
122+
123+ def test_parse_none(self):
124+ self._assertVersionEqual((None,None), parse_version(None))
125+
126+ def test_parse_year_month(self):
127+ self._assertVersionEqual(('10.01',None), parse_version('10.01'))
128+
129+ def test_parse_year_month_public(self):
130+ self._assertVersionEqual(('10.01',1), parse_version('10.01-public1'))
131+
132+ def test_parse_year_month_distro(self):
133+ self._assertVersionEqual(('10.01',None), parse_version('10.01-lucid1'))
134+
135+ def test_parse_year_month_public_distro(self):
136+ self._assertVersionEqual(('10.01',10), parse_version('10.01-public10-lucid1'))
137+
138+ def test_parse_custom(self):
139+ self._assertVersionEqual(('10.01.01.09',None), parse_version('10.01.01.09'))
140+
141+ def test_parse_custom_public(self):
142+ self._assertVersionEqual(('10.01.01.09',159), parse_version('10.01.01.09-public159'))
143+
144+ def test_parse_custom_public_distro(self):
145+ self._assertVersionEqual(('10.01.01.09',159), parse_version('10.01.01.09-public159-10lucid93'))
146+
147+ def test_parse_custom_distro(self):
148+ self._assertVersionEqual(('10.01.01.09',None), parse_version('10.01.01.09-lucid93'))
149+
150+ def test_parse_invalid_version_alpha(self):
151+ error_thrown = False
152+ try:
153+ parse_version('10.aa.01')
154+ except invalid_versionning_scheme:
155+ error_thrown = True
156+ self.assertTrue(error_thrown)
157+
158+ def test_parse_invalid_version_distro(self):
159+ error_thrown = False
160+ try:
161+ parse_version('10.01-a10ubuntu10')
162+ except invalid_versionning_scheme:
163+ error_thrown = True
164+ self.assertTrue(error_thrown)
165+
166+ def test_parse_invalid_version_public(self):
167+ error_thrown = False
168+ try:
169+ parse_version('10.01-publica10')
170+ except invalid_versionning_scheme:
171+ error_thrown = True
172+ self.assertTrue(error_thrown)
173+
174+ def _assertVersionEqual(self, first, second):
175+ self.assertEqual(first[0], second[0])
176+ self.assertEqual(first[1], second[1])
177+
178+unittest.main()

Subscribers

People subscribed via source and target branches