We've discussed this a little before. We currently are deprecating a
lot of things, which I personally see as a good thing, because it
means that we are cleaning up some old cruft. I would like to start
some discussion about it, though, particularly about the length of
deprecation cycles. I'd like to hear both from developers and from
users.
- First off, I think we can all agree that it's a good thing to set
deprecation cycles specifically, so that users will know exactly when
they can expect the old feature to be removed. My questions below
rely on this assumption.
- Do you think we should have a set deprecation cycle length, or
should we decide each on a per-case basis? We could also set
different lengths for different situations, e.g., if the feature
change would likely cause severe problems in many people's code, we
could make the cycle longer. On the other hand, if some now feature is
blocked on removing deprecated behavior, we could make it shorter.
Even if you think the answer to the above question is "per-case", the
rest of these are still worth discussing. But if you think they
should be set, what should they be set to?
- Should deprecation cycles be time based or version based? On the
one hand, our release cycle is irregular, and will remain so for the
foreseeable future. We went over a year between 0.6.7 and 0.7.0.
Then we went just over a month to release 0.7.1. So there may be
something to be said for having time based cycles instead of release
based ones ("the next release after February 1, 2013" or something
like that). On the other hand, there's no telling how SymPy itself
will advance in a given period of time (I guess the same can be true
about releases themselves, but there's at least some guarantee of a
certain amount of changes for every 0.0.1 or 0.1 release).
I think no release will be under a month, unless we find some minor
problem with a release immediately after it goes out. In that case, I
think we should do a 0.0.0.1 release (like 0.7.2.1 for example).
So I think that if we do release based deprecations, we should set a
specific release, not "+2 releases" or something like that, to handle
potential 0.0.0.1 releases. The question here is what should we do
about 0.1 releases? I don't think these should happen very often,
only when we have a very significant change in the codebase, (e.g.,
for 0.7.0 we had the new polys). But if we say "this feature will be
removed by 0.7.4" and the next release after 0.7.3 is 0.8.0, then that
could cause confusion. We could be precise and say "the next two
0.0.1 or 0.1 releases", but that starts to get confusing fast.
- I discussed the implementation of this in another thread, and I
don't think there were any disagreements. The idea was to add flags
to SymPyDeprecationWarning (and to @deprecated, which would pass them
through), which would build up a deprecation string with the relevant
information. We would also do necessary tracking in the issues to
make sure old features are removed when they should be.
Here are two examples of things we deprecated or plan to deprecate, so
you can get an idea of the sorts of things I'm talking about:
- In 0.7.0, we renamed Real to Float. We kept Real and .is_Real as
deprecated shortcuts to Float and .is_Float, respectively. This is a
good example of a fairly harmless deprecation. Keeping the old names
around indefinitely would not harm anything, other than that they
clutter things up. Furthermore, if they were removed, it would be
trivial for users to fix their code, and, perhaps more importantly, it
would be easy for them to tell that they would need to do that,
because they would get ImportError or AttributeError, which would
clearly tell them that Real was not defined any more. A simple Google
search or question here would reveal that it's been renamed to Float.
- In https://github.com/sympy/sympy/pull/1009, we are changing the
syntax for Piecewise. The current syntax is Piecewise((expr1, cond1),
(expr2, cond2), ..., (exprn, condn), (otherwise, True)). For example,
Piecewise((1, x < 0), (2, x > 0), (0, True)) means 1 if x is negative,
2 if x is positive, and 0 otherwise.
However, the use of True to signify the otherwise condition is
problematic, because a user may enter, either manually or
programmatically, a condition that automatically evaluated to True.
So something like Piecewise((1, x < 0), (2, 1 > 0)) would evaluate to
a Piecewise, not 2 as would be expected.
The solution is to change the syntax to Piecewise((expr1, cond1), ...,
(exprn, condn), otherwise), where the otherwise condition is optional.
With the new syntax, if any condition is True, the piecewise will
automatically return the corresponding expression. The above would
become simply Piecewise((1, x < 0), (2, x > 0), 0)
For now, we are supporting both syntaxes in the following way: if a
condition that is not the last condition it True, or if otherwise is
given using the new syntax and any condition is True, the
corresponding expression is returned. If the last condition is True,
and no otherwise is given (i.e., the old syntax), the corresponding
expression is set to the otherwise condition and a deprecation warning
is raised.
This deprecation is a whole different animal. On the one hand, as
long as we support both the old syntax and the new syntax
simultaneously, it is very confusing, inconsistant, and essentially
wrong. On the other, changing it permanently, so that Piecewise((1, x
< 0), (2, x > 0), (0, True)) returns 0 instead of a Piecewise with an
otherwise condition, would be much harder on users. It could
potentially go unnoticed, especially if the Piecewise in question
would have evaluated to the otherwise condition anyway, and would
either raise no error and just return a wrong result, or would raise
some cryptic error (e.g., "IndexError: tuple index out of range" if
they tried to call .args).
Finally, I want to point out that users can avoid ambiguity during the
deprecation cycle by manually passing nan as the otherwise condition
(like Piecewise((1, x < 0), (2, x > 0), (0, True), nan)). nan is the
default otherwise condition, so this effectively does nothing but
force the new syntax and silence the deprecation warning.
Aaron Meurer
It would be best if new stuff can be added without removing deprecated
stuff.
If it's really incompatible, make things live in different modules (but
still make sure that they interoperate).
I know this isn't always possible, but one can design for it.
E.g. by having pluggable instead of hardcoded heuristics, for example.
Removing features, even deprecated ones, is always bad.
> Even if you think the answer to the above question is "per-case", the
> rest of these are still worth discussing. But if you think they
> should be set, what should they be set to?
If things are designed so that deprecated stuff can live in parallel
with new stuff, the deprecation cycle could be "infinite".
Deprecation would then be just a warning to people that other, better
implementations are available elsewhere.
(Deprecation markers should also contain or point to clear instructions
how to get rid of calls to old cruft.)
> - Should deprecation cycles be time based or version based?
Since deprecation is a service to SymPy users, and users don't know what
the development speed and version timing will be, they'll want a
time-based deprecation.
If you mean "period from deprecation warning to feature removal", then
it should definitely be time-based. Imagine somebody writing a PhD
thesis, using a feature, finding it deprecated, and not knowing whether
it will go away a day before he finishes or a day after, since he
doesn't know when the release will come.
Of course, people can still stick with an old version of SymPy, but not
everybody can do that (campus policy may ban old software versions, for
example, and then it's too bad if your thesis gets derailed...)
> On the
> one hand, our release cycle is irregular, and will remain so for the
> foreseeable future. We went over a year between 0.6.7 and 0.7.0.
> Then we went just over a month to release 0.7.1. So there may be
> something to be said for having time based cycles instead of release
> based ones ("the next release after February 1, 2013" or something
> like that). On the other hand, there's no telling how SymPy itself
> will advance in a given period of time (I guess the same can be true
> about releases themselves, but there's at least some guarantee of a
> certain amount of changes for every 0.0.1 or 0.1 release).
It's essentially impossible to give a date.
> I think no release will be under a month, unless we find some minor
> problem with a release immediately after it goes out. In that case, I
> think we should do a 0.0.0.1 release (like 0.7.2.1 for example).
I think bug fixes should always be possible.
> Here are two examples of things we deprecated or plan to deprecate, so
> you can get an idea of the sorts of things I'm talking about:
>
> - In 0.7.0, we renamed Real to Float. We kept Real and .is_Real as
> deprecated shortcuts to Float and .is_Float, respectively. This is a
> good example of a fairly harmless deprecation. Keeping the old names
> around indefinitely would not harm anything, other than that they
> clutter things up. Furthermore, if they were removed, it would be
> trivial for users to fix their code, and, perhaps more importantly, it
> would be easy for them to tell that they would need to do that,
> because they would get ImportError or AttributeError, which would
> clearly tell them that Real was not defined any more. A simple Google
> search or question here would reveal that it's been renamed to Float.
A better migration path would be to keep Real and .is_Real around, but
let them throw exceptions.
That way, people can be given exact instructions what they need to change.
An ImportError or AttributeError tells you what's wrong, but it does not
tell you how to fix it.
Alternatively, we could make a "deprecated SymPy" package that has all
the old clutter in it, with deprecation warnings and docs and stuff
helping people migrate.
Variant 1: Name the new Piecewise something different, say, Piecewise2.
Variant 2: Put the different Piecewise classes in different, mutually
incompatible modules and instruct people to import one or the other, but
not both.
E.g. the module structure could look like this:
sympy. - current API
sympy.api1 - API 1 (deprecated)
sympy.api2 - API 2 (deprecated, too)
...
sympy.api10 - API 10 (last API we deprecated)
sympy.api11 - API 11 (current)
Modules in sympy will just load modules from api11.
People who need long-term stability import their modules from sympy.apiNN.
People who want to just hack something up import their modules from sympy.
(I hope this is understandable.)
> Finally, I want to point out that users can avoid ambiguity during the
> deprecation cycle by manually passing nan as the otherwise condition
> (like Piecewise((1, x< 0), (2, x> 0), (0, True), nan)). nan is the
> default otherwise condition, so this effectively does nothing but
> force the new syntax and silence the deprecation warning.
That's not a systematic way to invoke an old API.
It would work for the Piecewise use case I guess, but it wouldn't work
in general.
Just my 2c.
Regards,
Jo
> - Should deprecation cycles be time based or version based? On the
Version-based deprecations are more convenient for users and developers,
I think, but we'd need to set a release policy - define the difference
between major and minor versions, and find a more constraining answer to
"When do we release?" than "Whenever we feel like it."
> - In https://github.com/sympy/sympy/pull/1009, we are changing the
> syntax for Piecewise.
In this case, it would be better to create a new object with a new name,
considering that Piecewise isn't a good name (it's supposed to be
piecewise-what, exactly?) and that the object is actually a
case-expression. It would also allow to put its args in the right order,
with the results after the corresponding tests.
> > Even if you think the answer to the above question is "per-case", the
> > rest of these are still worth discussing. But if you think they
> > should be set, what should they be set to?
>
> If things are designed so that deprecated stuff can live in parallel
> with new stuff, the deprecation cycle could be "infinite".
>
> Deprecation would then be just a warning to people that other, better
> implementations are available elsewhere.
> (Deprecation markers should also contain or point to clear instructions
> how to get rid of calls to old cruft.)
If we don't want to eventually remove some feature, we shouldn't
deprecate it in the first place.
Keeping old stuff has a significant cost in maintenance and in
development agility. As long as we keep it, it must stay in working
condition and there are some changes that are simply impossible (for
instance, creating a new object with the same name as some deprecated
thing).
>
> > - Should deprecation cycles be time based or version based?
>
> Since deprecation is a service to SymPy users, and users don't know what
> the development speed and version timing will be, they'll want a
> time-based deprecation.
>
> If you mean "period from deprecation warning to feature removal", then
> it should definitely be time-based. Imagine somebody writing a PhD
> thesis, using a feature, finding it deprecated, and not knowing whether
> it will go away a day before he finishes or a day after, since he
> doesn't know when the release will come.
>
Your user doesn't know anything either if deprecation is time-based.
Since we aren't going to release a time-bomb inside the library, the
deprecation means that it'll be removed in the next version after the
cut-off date, but it can land on the user's computer anywhere between 3
months and 5 years after said date...
> Of course, people can still stick with an old version of SymPy, but not
> everybody can do that (campus policy may ban old software versions, for
> example, and then it's too bad if your thesis gets derailed...)
> > - In https://github.com/sympy/sympy/pull/1009, we are changing the
Urgh!! That would mean we'd have to maintain 11 different APIs instead
of only one. That would be a nightmare.
Deprecation still serves as notice to users:
- If there's a problem, there won't be fixes
- There's a newer and better API available
> Keeping old stuff has a significant cost in maintenance and in
> development agility.
I know. Sometimes stuff simply has to go.
Removing stuff should be avoided though.
Consider Linux. The userspace interface has been extremely stable -
stuff was added, but never removed, unless it was really impossible or
didn't make sense.
That's what enables people to use 10-year-old Linux software, with no
changes. (Compare that with Windows - trying to run decade-old
applications is an exercise in frustration.)
*Internal* interfaces in Linux, however, are ruthlessly restructured at
the drop of a hat.
That's how Linux stays agile despite being highly compatible.
> As long as we keep it, it must stay in working
> condition and there are some changes that are simply impossible (for
> instance, creating a new object with the same name as some deprecated
> thing).
>>
>>> - Should deprecation cycles be time based or version based?
>>
>> Since deprecation is a service to SymPy users, and users don't know what
>> the development speed and version timing will be, they'll want a
>> time-based deprecation.
>>
>> If you mean "period from deprecation warning to feature removal", then
>> it should definitely be time-based. Imagine somebody writing a PhD
>> thesis, using a feature, finding it deprecated, and not knowing whether
>> it will go away a day before he finishes or a day after, since he
>> doesn't know when the release will come.
>>
> Your user doesn't know anything either if deprecation is time-based.
> Since we aren't going to release a time-bomb inside the library, the
> deprecation means that it'll be removed in the next version after the
> cut-off date, but it can land on the user's computer anywhere between 3
> months and 5 years after said date...
Yes, but they can plan ahead. In the sense that "I'll need a year to
complete this, but feature Foo may be unavailable in five months from
now, so I better restructure my code now to use the other feature".
If removal is release-based, a feature could get deprecated tomorrow and
removed four weeks after that (assuming a minimum distance of four weeks).
Essentially, the question is:
"What minimum guarantees do we give SymPy users about the long-term
stability?"
Release-based deprecation would mean: features are guaranteed to stay
available for the next four weeks.
Time-based deprecation would mean: features are guaranteed to stay for
whatever perdiod we define.
>> Variant 2: Put the different Piecewise classes in different, mutually
>> incompatible modules and instruct people to import one or the other, but
>> not both.
>> E.g. the module structure could look like this:
>> sympy. - current API
>> sympy.api1 - API 1 (deprecated)
>> sympy.api2 - API 2 (deprecated, too)
>> ...
>> sympy.api10 - API 10 (last API we deprecated)
>> sympy.api11 - API 11 (current)
>>
>> Modules in sympy will just load modules from api11.
>>
>> People who need long-term stability import their modules from sympy.apiNN.
>> People who want to just hack something up import their modules from sympy.
>
> Urgh!! That would mean we'd have to maintain 11 different APIs instead
> of only one. That would be a nightmare.
Old APIs don't need much maintenance. They don't even need to
interoperate with the newer APIs (unless we want to make them do that).
Think of them as old versions of SymPy, packaged as part of the whole
system.
The alternative might be keeping old versions of SymPy around for download.
Cheers,
Brian
> --
> You received this message because you are subscribed to the Google Groups "sympy" group.
> To post to this group, send email to sy...@googlegroups.com.
> To unsubscribe from this group, send email to sympy+un...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/sympy?hl=en.
>
--
Brian E. Granger
Cal Poly State University, San Luis Obispo
bgra...@calpoly.edu and elli...@gmail.com
Yes, of course. But in some cases, deprecation simply can't be
avoided. The alternative is just changing it entirely, which isn't
ideal for the user. I'm talking specifically about these cases.
>
> I know this isn't always possible, but one can design for it.
> E.g. by having pluggable instead of hardcoded heuristics, for example.
Right. We want to always try to get the best API the first time
around, so we don't ever have to change it. But unfortunately, the
APIs the currently exist don't always follow this, and some of them
really need to be changed (like Piecewise).
>
> Removing features, even deprecated ones, is always bad.
>
>
>> Even if you think the answer to the above question is "per-case", the
>> rest of these are still worth discussing. But if you think they
>> should be set, what should they be set to?
>
>
> If things are designed so that deprecated stuff can live in parallel with
> new stuff, the deprecation cycle could be "infinite".
I agree with Ronan. It isn't really a deprecation if we do that.
Interesting idea. So you would have something like this (up to a
change in version numbers or dates):
0.7.0: Real, is_Real deprecated. Use of them works but raises a
deprecation warning telling the user to use Float.
0.7.2: Real, is_Real are made to raise something like ValueError("Use
Float instead.") or AttributeError("Use is_Float instead").
0.7.3: Real, is_Real are removed completely.
>
> An ImportError or AttributeError tells you what's wrong, but it does not
> tell you how to fix it.
>
> Alternatively, we could make a "deprecated SymPy" package that has all the
> old clutter in it, with deprecation warnings and docs and stuff helping
> people migrate.
We already have such a thing. It's called the old versions of SymPy.
They are not actively maintained (except in the form of the newest
version of SymPy).
This sort of thing is unnecessary in this case, because we can
actually reasonably support both syntaxes at the same time. In some
cases, such as with the new plotting module, this is not possible, so
we are splitting the module.
>
> Variant 2: Put the different Piecewise classes in different, mutually
> incompatible modules and instruct people to import one or the other, but not
> both.
> E.g. the module structure could look like this:
> sympy. - current API
> sympy.api1 - API 1 (deprecated)
> sympy.api2 - API 2 (deprecated, too)
> ...
> sympy.api10 - API 10 (last API we deprecated)
> sympy.api11 - API 11 (current)
>
> Modules in sympy will just load modules from api11.
>
> People who need long-term stability import their modules from sympy.apiNN.
> People who want to just hack something up import their modules from sympy.
I don't like this idea at all. If you want an old API, use an old
version. If wer did this, we would not be able to support the old
APIs, nor would we want to (that would defeat the whole purpose of why
we deprecated the old API in the first place). So this is essentially
the same as having old versions, except we don't pretend that we
support them by shipping them with the current version.
>
> (I hope this is understandable.)
>
>
>> Finally, I want to point out that users can avoid ambiguity during the
>> deprecation cycle by manually passing nan as the otherwise condition
>> (like Piecewise((1, x< 0), (2, x> 0), (0, True), nan)). nan is the
>> default otherwise condition, so this effectively does nothing but
>> force the new syntax and silence the deprecation warning.
>
>
> That's not a systematic way to invoke an old API.
> It would work for the Piecewise use case I guess, but it wouldn't work in
> general.
Right, these were just concrete examples. The new plotting module
could be a third example, where the new API is completely
incompatibile with the old API. For that, we are going to split it
into a new module, which will eventually replace the old module (I
forgot the exact sequence we agreed one; maybe someone could remind
me).
Aaron Meurer
>
> Just my 2c.
>
> Regards,
> Jo
>
Exactly. The whole original purpose of me writing this email was so
that we could start to agree on such a policy. But I see that it's
already started to diverge into other discussions.
>
>> - In https://github.com/sympy/sympy/pull/1009, we are changing the
>> syntax for Piecewise.
>
> In this case, it would be better to create a new object with a new name,
> considering that Piecewise isn't a good name (it's supposed to be
> piecewise-what, exactly?) and that the object is actually a
> case-expression. It would also allow to put its args in the right order,
> with the results after the corresponding tests.
Piecewise is the name used by Maple, Mathematica, and Sage (modulo a
capital letter). And to me, the args are in the right order now.
Maple does it the other way around, but this is just confusing to me.
The args are printed in the order that they are given in our syntax,
so to me this is most logical.
Aaron Meurer
Aaron Meurer
I should perhaps point out that the 0 in front of our version number
says a little about the instability of our API. We do try to
deprecate removed features, where possible, but there is no guarantee
that any feature will not be changed, deprecated or not. This is
because we are still building things up. Modules with limited power
may have a limited API, which may simply not work when the power of
that module is extended. We can try to think of things beforehand,
but we can't rely on our ability to do this.
For example, when we update the polys to support symbolic algebraic
expressions (like QQ<sqrt(x)>), we will have to change the RootOf
syntax to name the variable to take the root of. We might not need to
deprecate in this particular case, as we could differentiate based on
how many args there are, but that's just the first example I could
think of.
Also, I should point out that it's fairly easy to run off of a local
copy of SymPy independent of whatever is installed system-wide, even
if you don't have admin access (you just have to add the directory to
the front of your PYTHONPATH).
A concern with time-based cycles is that they would affect how we
release. We might try to push out a release before the time is up, or
we might wait until the time is up before we release. Given how hard
it is to release, I wouldn't want any timelines to affect it, even
non-formally.
>
>
>>> Variant 2: Put the different Piecewise classes in different, mutually
>>> incompatible modules and instruct people to import one or the other, but
>>> not both.
>>> E.g. the module structure could look like this:
>>> sympy. - current API
>>> sympy.api1 - API 1 (deprecated)
>>> sympy.api2 - API 2 (deprecated, too)
>>> ...
>>> sympy.api10 - API 10 (last API we deprecated)
>>> sympy.api11 - API 11 (current)
>>>
>>> Modules in sympy will just load modules from api11.
>>>
>>> People who need long-term stability import their modules from
>>> sympy.apiNN.
>>> People who want to just hack something up import their modules from
>>> sympy.
>>
>>
>> Urgh!! That would mean we'd have to maintain 11 different APIs instead
>> of only one. That would be a nightmare.
>
>
> Old APIs don't need much maintenance. They don't even need to interoperate
> with the newer APIs (unless we want to make them do that).
>
> Think of them as old versions of SymPy, packaged as part of the whole
> system.
I do think of them as such, which is why I don't think they should be
packaged as part of the whole system.
>
> The alternative might be keeping old versions of SymPy around for download.
The are. You can also access any old version from git (run "git tag").
Aaron Meurer
And the argument that Aaron gave against time based releases convinced me.
About the plotting module example:
next version: using Plot raises a warning that Plot will change and
it's better to use PygletPlot if you want the old behavior.
next +1 : The change is done. No warnings.
It was a bit more complicated in the initial idea, but by using
different namespaces there is now only one thing to be deprecated.
By the way, I would appreciate some help in reviewing it.
Hehe, I can understand :-)
Though I think it's not a bad idea to spend a few thoughts on how things
should roll after 1.0. We'll want to build the necessary infrastructure
before 1.0 after all.
Of course, it need not be right now :-)
> Also, I should point out that it's fairly easy to run off of a local
> copy of SymPy independent of whatever is installed system-wide, even
> if you don't have admin access (you just have to add the directory to
> the front of your PYTHONPATH).
It may be impossible to intall a matching Python interpreter due to
company security concerns (which would be bogus, but that doesn't help
the person who needs Sympy).
Or SymPy is used as part of an ongoing project. Project wants to move to
a newer Python, but does not want to upgrade SymPy at the same time
(e.g. it may have been programming around well-known bugs in SymPy for
years, and correcting all that would be a too large project for the time
budget available).
Just examples of things I have seen in my time.
As a general principle, if you have 20 tools and each introduces some
inflexibility that will bite you only 1% of the time where you do
something, you'll have a probability of 1-0.99**20 = 18% that any change
will fail. In other words, one in five change requests will not be
implementable - not good.
So any project that's supposed to be used for serious work should aim
for 100% backwards compatibility. I know that's not possible in
practice, and probably not worth implementing right here, right now, but
it's something to keep in mind put into the set of (conflicting) goals.
Regards,
Jo
The system level Python should be fine. As long as it is 2.5-3.2 (as
of the next release), it should work. We recently dropped 2.4
support, so I suppose if you need to use a Python that ancient, you
are in trouble. I don't see us dropping 2.5 support any time soon, as
there would be little to gain from it.
>
> Or SymPy is used as part of an ongoing project. Project wants to move to a
> newer Python, but does not want to upgrade SymPy at the same time (e.g. it
> may have been programming around well-known bugs in SymPy for years, and
> correcting all that would be a too large project for the time budget
> available).
Again, these should be independent. If a new Python is released after
SymPy, it is unlikely that it will break an old SymPy. The worst I've
seen is a few minor bugs, and that only happens for major Python
releases. In other words, Python itself is very good at handling the
backwards compatibility issue you mention :)
We can also help this by building the release candidates for new
Python versions and fixing bugs before the new Python is released. But
problems really only occur in major Python releases, and these come
out so infrequently that this is almost a non-issue.
>
> Just examples of things I have seen in my time.
> As a general principle, if you have 20 tools and each introduces some
> inflexibility that will bite you only 1% of the time where you do something,
> you'll have a probability of 1-0.99**20 = 18% that any change will fail. In
> other words, one in five change requests will not be implementable - not
> good.
>
> So any project that's supposed to be used for serious work should aim for
> 100% backwards compatibility. I know that's not possible in practice, and
> probably not worth implementing right here, right now, but it's something to
> keep in mind put into the set of (conflicting) goals.
>
> Regards,
> Jo
>
In my experience with people on the mailing list, the things that
break for people from release to release are things that we didn't
even know about. Sometimes they are regressions, and sometimes they
are a result of something that seemed insignificant, or at least
unrelated, when we changed it. Few people ask about things that were
explicitly mentioned in the release notes. So I think we should try
to be very careful to note any kind of (public) API change in the
release notes.
But this is also just my 2¢. Maybe if we discuss it enough we can get
up to a dollar.
Aaron Meurer
In some cases it is more. In some cases (like Real/Float) it is
possible to keep the older API around and put a dep. warning on it.
For the more mature parts of our code base, I am fine with this
approach - even adding version information like are you are proposing.
In other cases (like Piecewise) that is impossible without going
through horrible contortions. In those cases I don't think we should
make any attempt to deprecate the older API - just document it well in
release notes. Also, for less mature parts of the code base that are
still moving quickly, I don't think there is any need to issue
deprecation warnings. Basically, I feel that we should optimize for
ease of development, not API stability.
On Thu, Jan 26, 2012 at 3:30 PM, Brian Granger <elli...@gmail.com> wrote:
> On Thu, Jan 26, 2012 at 9:38 AM, Aaron Meurer <asme...@gmail.com> wrote:
>> So are you -1 just to setting specific time/version lengths to
>> deprecate things, or is it more?
>
> In some cases it is more. In some cases (like Real/Float) it is
> possible to keep the older API around and put a dep. warning on it.
> For the more mature parts of our code base, I am fine with this
> approach - even adding version information like are you are proposing.
> In other cases (like Piecewise) that is impossible without going
> through horrible contortions. In those cases I don't think we should
> make any attempt to deprecate the older API - just document it well in
> release notes. Also, for less mature parts of the code base that are
> still moving quickly, I don't think there is any need to issue
> deprecation warnings. Basically, I feel that we should optimize for
> ease of development, not API stability.
I agree. Thinking about API leads to good development practices,
though, such as trying to make the API a good one from the start.
So while ease of development should indeed be the first priority,
users appreciate API stability, so when there's little difficulty on
our part to make it so, we should do that.
Stable APIs also help facilitate ease of development, as the different
parts of SymPy use each other, and every time an API changes, we have
to change all the code base as well as any open pull requests.
Aaron Meurer