Mailing List Archive

"Compiling" scripts before execution ?
One concern I've been mulling over lately is the potential problem
maintaining Python scripts over time. For example:

1) It's easy to never create (or to sever) a link to a imported symbol
defined in another module, and you may never know it until python
tries to execute the referencing line of script code.

2) If the signature of an imported method changes, and all
references to it in all scripts aren't updated, you may never know
it until Python tries to execute one of these "broken" line of
script code.

I realize with batch scripts, if you're diligent you can write and maintain
exhaustive test code and include it in the modules (Re: Tim's doctest
thread) -- a good idea IMO.

However, I primarily have Python GUI code in mind, where it's not so simple
to automate testing.

What are folks doing to keep this class of errors from being a problem?

Is there a way to "lint" or compile Python code such that it forces symbols
to resolve when seen (possibly disallowing some dynamic symbol definition
available in the language (e.g. adding methods to classes after class
definition).

To take a few examples:

$ python >>> class C: $ python
>>> def F(): ... def M(): >>> class C:
... return G() ... print self ... def M(self):
... ... ... self.RemovedMethod()
>>> >>> ...
>>>

Is there a "Python lint" tool or hidden option (e.g. "-Dstrict_python") that
can turn these into build-time errors of some sort?

Any tips appreciated.

Thanks,

Randall
"Compiling" scripts before execution ? [ In reply to ]
[Randall Hopper]
> One concern I've been mulling over lately is the potential problem
> maintaining Python scripts over time. For example:
>
> 1) It's easy to never create (or to sever) a link to a
> imported symbol defined in another module, and you may never
> know it until python tries to execute the referencing line of
> script code.
>
> 2) If the signature of an imported method changes, and all
> references to it in all scripts aren't updated, you may never know
> it until Python tries to execute one of these "broken" line of
> script code.
> ...
> What are folks doing to keep this class of errors from being a problem?

I use a text editor with extremely fast file-based search-and-replace <0.5
module's advertised contract, and a module has no right to change its
contract unilaterally in an incompatible way. This isn't as flippant as it
sounds (*almost*, but not quite ...). Python argument lists are exceedingly
flexible beasts, and it's almost always possible to maintain backwards
compatibility when changing a signature.

> Is there a way to "lint" or compile Python code such that it
> forces symbols to resolve when seen (possibly disallowing some dynamic
> symbol definition available in the language (e.g. adding methods to
> classes after class definition).

Nope, you'll have to deal with it. The best stab at a Python "lint" is
Aaron Watters's kjpylint, available from

http://www.chordate.com/kwParsing/index.html

It's not trying to do cross-module analysis, though.

Python2 may or may not introduce some notion of optional static typing,
which could catch this stuff for those motivated enough to use it. That's a
Types-SIG topic.

the-downside-of-a-dynamic-language-is-its-dynamicism-ly y'rs - tim
"Compiling" scripts before execution ? [ In reply to ]
Tim Peters:
|[Randall Hopper]
|> One concern I've been mulling over lately is the potential problem
|> maintaining Python scripts over time. For example:
|>
|> 1) It's easy to never create (or to sever) a link to a
|> imported symbol defined in another module, and you may never
|> know it until python tries to execute the referencing line of
|> script code.
|>
|> 2) If the signature of an imported method changes, and all
|> references to it in all scripts aren't updated, you may never know
|> it until Python tries to execute one of these "broken" line of
|> script code.
|> ...
|> What are folks doing to keep this class of errors from being a problem?
|
|I use a text editor with extremely fast file-based search-and-replace
|<0.5 wink>. Short of that, signatures and exported symbols are part of a
|module's advertised contract, and a module has no right to change its
|contract unilaterally in an incompatible way.

During the course of maintenance and enhancement (not to mention
prototyping), class or module signatures will change, and possibly change
frequently. This is especially true for a multi-developer project. A
method, function, or constant may be removed for example, and though the
developer making a change shouldn't "get up from his chair" until he
impacts all references to it in the software tree, we all make mistakes or
get distracted occasionally. So we'd like to know that as soon as
reasonably possible that some piece of code isn't quite right and is
destined to blow up.

I see your point for the case where function warguments change. However,
going to the trouble to ensure a past interface works implies a significant
penalty for just "changing it" (such as, a past version of your module was
released and is being used by other folks). But for prototyping or an
application, this isn't (shouldn't be) the case. Just change it; keep it
simple, understandable, and cut out the dead wood.

One of Python's big strengths is that it lends itself to fast prototyping.
If Joe User is prototyping an interface, he shouldn't have to insure that
any version of it he tentatively defines is always available. If it
doesn't work, get out the eraser, chalk-in something different, and try
that.

|This isn't as flippant as it sounds (*almost*, but not quite ...).
|Python argument lists are exceedingly flexible beasts, and it's almost
|always possible to maintain backwards compatibility when changing a
|signature.

For Python functions this is certainly true. But one area I'm thinking of
is interfaces in wrapped C libraries (using SWIG).

I'm searching for the best way to implement a "build-time error" (as you'd
get with C) when a Python or wrapped C API, which is referenced in a Python
script, changes or is removed.

If one could just invoke the Python script and have it try to "link" all
its symbol references ("python -l"?), reporting failure if it couldn't,
that would be a big step toward the goal. Though this doesn't cover type
and argument signature changes.

I'm toyifng with having copies of C header files checked-in with the Python
source, and "diffing" those to generate build errors. But this really is
an ugly hack.

|> Is there a way to "lint" or compile Python code such that it
...
|
|Nope, you'll have to deal with it. The best stab at a Python "lint" is
|Aaron Watters's kjpylint, available from
|
| http://www.chordate.com/kwParsing/index.html
|
|It's not trying to do cross-module analysis, though.

Thanks for the tip. I'll check into it.

|Python2 may or may not introduce some notion of optional static typing,
|which could catch this stuff for those motivated enough to use it. That's a
|Types-SIG topic.

That sounds promising. Some syntactic sugar where a module could declare
assumptions about what it is importing would go a long way.

Thanks,

Randall