Problem--Extending the behavior of an upstream package
pavlovevidence at gmail.com
Thu Feb 19 06:40:24 CET 2009
Ok, I think I know I want to do this, but I thought I'd run it by yins
I have a fairly large and complex application with two top-level
packages, which we'll call upstream and mine. The "upstream" package
isn't really upstream. I own both packages, but I think of the
upstream package as a third-party library relative to the mine
package. The mine package contains code specific to the application.
Anyway, the upstream modules provide lots of classes and other
functionality, but I want to extend their behavior in various ways.
Say for instance I have a class called Box defined in the module
upstream.packaging. In this particular application, it makes sense
for all boxes to have a certain behavior, such as a certain way of
being drawn. So I define a module called mine.custom_packaging which
defines a subclass of upstream.packaging.Box. That's straightforward
The problem comes when a different part of the upstream package also
subclasses or creates a Box. When an upstream function creates a box,
it creates an upstream.packaging.Box instead of a
mine.custom_packaging.Box, but I'd want it to do the latter.
If this were something that happened only once or twice, it'd be no
big deal, I'd just work around it. However, it's very common. The
upstream package is almost a complete application unto itself; it only
needs data and a small amount of top-level code to run. The sort of
tight internal coupling that exists within the upstream package makes
it a logistical problem to extend it. And the thing is, I can't think
of a convenient way to do it that's tolerably magical, and I am quite
tolerant of homebrew magic in my code. A particularly troublesome
situation is when a base class and subclass are defined in the same
module, and I want to customize both. Even things like disambiguating
nomenclature trip me up.
It isn't just classes, BTW. Sometimes I want to override functions,
or modify permanent data.
So, how would you approach something like this?
(After a little discussion--or not--I'll post some things I've
considered, including a few approaches I've actually implemented. But
I don't want to taint everyone's ideas just yet.)
More information about the Python-list