← Back to team overview

quickly-talk team mailing list archive

Re: Scope of upgrade command

 

Hi Michael,

I haven't made significant contributions to quickly and shouldn't have a
say in policy. I hope you don't mind my sharing some comments related to
your proposal.

I feel that updates will be much easier to handle for quickly developers
if as much code as possible that quickly generates and edits be moved to
a separate folder so that it may be assumed that the user (of quickly
not of a quickly application), who is writing a project `foo` using
quickly, has not changed the files. For example, if the bin/foo file
were to contain minimal code, most of which was imported from a folder
containing abstract code, for all ubuntu-template applications, that the
user does not touch, then we could make major changes to that abstract
code without having to worry about changes that the user might have made
to the files. Similarly for files in foo/ like fooconfig.py and
helpers.py could be moved into a folder that does is not to be changed
by the user. Also, setup.py could be split so that properties can be
stored in one file and the remaining setup logic in setup.py. This will
allow us to replace the whole setup.py file in an update if we need to
rewrite the whole setup.py logic. Such changes could allow us to include
more unessential changes in the update than we require.

I also have a small suggestion about updates. I believe updates in the
ubuntu-application template (I haven't really worked with the code for
any other template) currently checks the version of quickly that the
project was last run with, if there have been any changes since check
whether the changes have already been applied and apply them if they
have not. Here are examples of lines of code I am referring to:

Line 55 onwards:
##### 0.4 update
if project_version < '0.4':
    ## new licensing format

Line 158 onwards:
if project_version < '0.4.3':
    ## update dependencies format
    if 'dependencies' in configurationhandler.project_config \

Further, there are if statements that exist outside blocks that check
the project_version (i.e. they are checked every time).

I think it would make sense for every small update we'd like to make on
a quickly project (not every version of quickly) to give every update a
number (e.g. #123 to fix a dependency, #124 to fix bug 606285, #125 to
perform the next update, and so on...) and each update can be performed
inside a function. Then update.py will check what the last update
performed was and run the next update. This way, there will be no need
to check for "symptoms" of old code--we will be able to update a project
based solely on which update was last performed. This will also bring an
addition advantage of being able to track exactly which update crashed
should an update crash. This can easily be done by making an array of
update functions, loop through the required functions (if we are at
update 5 we have to loop through updates[6:]) and  revise the update
version after performing each update.

To respond to your proposal, like you pointed out, there is a trade off
between including as many and as few changes in updates as possible.

We could include as many changes/refactors as possible in updates so
that in all quickly code, it may be assumed that the current quickly
project has the new code. Otherwise, if you write a new quickly command
`bar` that concerns a part of the code that was changed by an upgrade,
you will have to check which version of quickly the project was created
with and maintain multiple versions of the command bar that behaves
differently for different quickly projects depending on which version of
quickly it was created with.

At the same time, trying to guess the possible changes that users could
make to their quickly projects is not easy. Developers of quickly
templates should not be spending their time trying to find the numerous
possible situations that an update will take place in and trying to
accommodate each one of them. So in your example, updates #2 and #3b are
not worth including. However, we will have to ensure that there is
absolutely no code in quickly that assumes that changes like #2 and #3b
have been updated. E.g. in a future update or in a quickly command you
cannot assume that code has been moved into a BaseProjectWindow class
because that would be a false assumption.

So I think it makes sense to go with your proposal and only include
updates that fit your criteria. Also, like I explained, if updates could
be made simpler to include, the trade-off would reduce. Finally, I think
that eventually we will be forced to sunset old quickly projects and
stop supporting projects created before XYZ. For that reason, I suggest
that we begin to track with version of quickly a project was created
with in order to end their life with sufficient warning. Before quickly
eventually sunsets old code, we should examine every style of doing
things in quickly and use the opportunity of not needing to care about
old versions to change anything we may feel can be changed to make
quickly more efficient.

Umang


On 12/20/2010 09:33 AM, Michael Terry wrote:
> Hello!  I'd like to talk about the intended scope of the upgrade
> command.  Specifically, what sort of promises the Quickly project makes
> about it.
> 
> The two ends of the spectrum are:
> 1) any change at all needs an upgrade hook
> 2) no changes ever need an upgrade hook; if users want new code, they
> can copy and paste
> 
> Obviously 2 is no good.  But I think 1 is also not very workable and we
> need a middle ground.  Let me give some scenarios I'm considering:
> 
> 1) We add features to project_root.  Like /opt or appindicator support.
> Traditionally, we've added such features upon an upgrade.
> 
> 2) We refactor project_root.  This recently happened when we moved some
> Window code into a BaseProjectWindow class.  Upgrading such a change is
> very difficult because customizations made could have been made on the
> refactored code.  When I did made this change, I chose not to bother
> adding an upgrade hook since no functionality was actually added.
> 
> 3) We fix bugs in project_root.  Some sub examples:
>   a) python_name->project_name.  I recently fixed a bug in the /opt
> support where we specified the path as /opt/.../python_name, but it
> should be project_name.
>   b) png->svg.  I have a branch I'm about to propose that reduces the
> three identical, differently-sized project logos in project_root to one
> svg.  This fixes issues with blurry window icons.  So sort of a cross
> between refactoring and bug-fixing.
>   c) a crasher.  Let's say we find a crasher (e.g. attribute error) and
> fix it.
> 
> My proposal for promises from the Quickly project:
> 
>  * Project-level features (like /opt and appindicators) will be added by
> upgrades.
>  * Refactoring will not be guaranteed to be upgradeable.
>  * Severe bugs will be fixed by upgrades.
>  * Upgrades are only guaranteed to work from adjacent stable releases
> (i.e. from 10.09 to 11.04, but not directly from 10.09 to 11.10).
> 
> So #1 will be upgraded, #2 wouldn't, #3a would, #3b wouldn't, #3c would.
> 
> (all bugs are subject to whether they were present in the latest stable
> release -- the example #3a was only introduced in an unstable release,
> so I didn't write a hook for it)
> 
> The reason I'm trying to reduce promises regarding upgrading from any
> release to any other release is to reduce maintainer burden.  Especially
> if we aren't promising to upgrade refactors.  Which would mean that
> unless we can sunset old code, upgrade logic has to be able to handle
> any version of project_root ever.  That's a place I'd rather not go.
> 
> It's an open question in my mind whether we should also follow the LTS
> schedule of Ubuntu and promise working upgrades from Ubuntu LTS to LTS.
> This would tie the project closer to the Ubuntu project and may not suit
> the needs of, say, the Fedora project when and if we get templates for
> them.  But it would be useful for Ubuntu users.
> 
> What do ya'll think of this proposal?
> 



Follow ups

References