Alerting to unused module globals, instance attributes, etc?
If I write a standalong script/program, it looks just like a module to the outside world (as long as I name it correctly), though it might have a #! line at the top. Otherwise, to a static analyzer, it still looks like a module, which means anything it defines might be visible from the outside. Consequently, if I happen not to use module globals or instance attributes, tools like pylint won't complain. I think it would be nice if I could tell such tools either: 1. The thing I'm feeding you is a standalone program. Nobody else might reference this stuff, so complain about unused names. 2. This particular thing I'm defining is either public or private. So, if I have this block of "constants": ONE_SECOND = 1000 # ms ONE_MINUTE = 60 * ONE_SECOND ONE_HOUR = 60 * ONE_MINUTE ONE_SECOND_DELTA = datetime.timedelta(seconds=1) ONE_MINUTE_DELTA = datetime.timedelta(minutes=1) ONE_DAY_DELTA = datetime.timedelta(days=1) ONE_YEAR_DELTA = 365 * ONE_DAY_DELTA EPSILON = 1e-10 it would be nice if I was told if any were unused. Similarly, if an attribute of a class is defined but not used elsewhere within the class (or perhaps within the defining module), I'd like to know if it's unused. At a minimum, if I've defined an instance method with a leading underscore in its name, it would be real nice if I was told about lack of use within the class. For classes where most of the API is public, it might be nice to mark the class as public then explicitly mark any private attributes: # <marker> public class Point: def __init__(self): self.x = self.y = 0.0 # <marker> private self.r = self.theta = 0.0 # <marker> private def convert_to_polar(self): self.r = math.sqrt(self.x**2 + self.y**2) self.theta = math.atan2(self.y, self.x) Do any existing static analysis tools support anything like this? I'm certainly not married to the notion of annotating attributes. Also, I should note that I am still using Python 2.7. If there are any features of Python 3 that facilitate this, I'd love to hear about it. Thx, Skip
On 04/23/2014 09:44 AM, Skip Montanaro wrote:
[...] So, if I have this block of "constants":
ONE_SECOND = 1000 # ms ONE_MINUTE = 60 * ONE_SECOND
it would be nice if I was told if any were unused.
[...] it might be nice to mark the class as public then explicitly mark any private attributes: [...] Do any existing static analysis tools support anything like this?
pyflakes does exactly this first thing: tells you if any names are unused. It does this the same way whether you are writing a module or a stand-alone program. It requires modules which wish to expose constants and such to declare them explicitly in __all__. It does not have any mechanism for "private" versus "public" class or instance attributes, because it is difficult to tell if they are used or not by anything short of running the program. Reflect: __metaclass__ = OhNoes class Foo: bar = 1 def __init__(self): self.baz = 2 def frob(self): if moon_phase() > 0.5: self = 15 print self.baz Rather than make guesses that are right 90% of the time and yield 10% false positives, pyflakes takes the PEP 20 approach: """ In the face of ambiguity, refuse the temptation to guess. """ It is the opinion of pyflakes that determining the correctness of your program in such complex situations is better served by unit tests.
On Wed, Apr 23, 2014 at 9:28 AM, Phil Frost <indigo@bitglue.com> wrote:
Rather than make guesses that are right 90% of the time and yield 10% false positives, pyflakes takes the PEP 20 approach: ... It is the opinion of pyflakes that determining the correctness of your program in such complex situations is better served by unit tests.
Thanks for the response. How would a unit test tell me a particular method or data attribute is unused within the module? And if the attribute used to be used, but no longer is (and should be deleted to ease maintenance), does a unit test keep it alive? The main Python code base I work with is now more than 10 years old, and was not designed at the outset to easily support the creation of unit tests. (Numbers-wise, it's nearly 50kloc in over 200 Python files.) It also grew organically as requirements and focus of the code changed. I'm sure there's now a ton of unused code in there I could just discard. Finding it can be a challenge. Just because an attribute isn't used within a module doesn't mean it's dead, but in certain situations it would be nice if a checker could at least warn me, "hey, I see that you assigned to 'self.foo', but I don't see any obvious uses of that attribute within the class or module." I would be more than happy with a 90% hit rate on such stuff. I don't care about perfection here. I don't care about the craziness of assigning something bizarre to "self" or use of getattr and its cousins. I also would be happy if I needed to set a config variable or add a command line flag to enable such behavior. And if we are using the Zen of Python as our guide: Special cases aren't special enough to break the rules. Although practicality beats purity. I'm looking for practicality here, not purity. Skip
participants (2)
-
Phil Frost
-
Skip Montanaro