On 19 Oct 2009, at 23:06, Ilona Chodnicka wrote:

Hello

I just downloaded your PyChecker module and used it to check my code - really glad that we have it :) , thank you.

I would like to report a bug against version 0.8.18 - semi-private attributes and __getattr__ are not handled by this version properly.

Here is my code snippet that uses semi-private attributes and __getattr__

class PyHciPerforceServer(object):
   
'''
    This is the class whose instances will start p4d.exe (Perforce server)
     - by default, use temporary directory and first available port
     - or use rootDir and port number as specified by the user
    '''

    def __getattr__(self, attributeName):
       
'''
        Return object's attribute with attributeName
        '''

        # List of valid attribute names for . operation
        if (attributeName == 'port' ):
           
return self.__port
       
if (attributeName == 'hostName' ):
           
return self.__hostName
       
if (attributeName == 'rootDir' ):
           
return self.__rootDir
       
if (attributeName == 'serverProcess'):
           
return self.__serverProcess
       
if (attributeName == 'isRunning'):
           
if self.__serverProcess == None :
               
return False
            else :
               
# Return true if Perforce server process is running
                return self.__serverProcess.poll() == None

        # If we got here, attributeName is invalid
        raise AttributeError(attributeName)

   
def __init__(self, rootDir = None , port = 0 ):
       
'''
        Initialize object attributes and start the server on given rootDir
        and port
        '''

        # Initialize all of object's attributes
        self.__port          = None
        self.__hostName      = None
        self.__rootDir       = None
        self.__serverProcess = None

        # Start Perforce server using given rootDir and port number
        # Using default parameters will start the server in a temp root dir
        # and on the first available port
        self.start(rootDir, port)
[ SNIP ]

Here's what PyChecker reports for this class:

Warnings...

PyHciPerforceServer_Test.py:71: Object (server) has no attribute (isRunning)
PyHciPerforceServer_Test.py:72: Object (server) has no attribute (port)
PyHciPerforceServer_Test.py:73: Object (server) has no attribute (rootDir)
PyHciPerforceServer_Test.py:74: Object (server) has no attribute (serverProcess)
PyHciPerforceServer_Test.py:75: Object (server) has no attribute (hostName)
PyHciPerforceServer_Test.py:93: Object (server) has no attribute (isRunning)
PyHciPerforceServer_Test.py:105: Object (server) has no attribute (port)
PyHciPerforceServer_Test.py:106: Object (server) has no attribute (rootDir)
PyHciPerforceServer_Test.py:107: Object (server) has no attribute (serverProcess)
PyHciPerforceServer_Test.py:108: Object (server) has no attribute (hostName)
PyHciPerforceServer_Test.py:109: Object (server) has no attribute (isRunning)
PyHciPerforceServer_Test.py:132: Object (server) has no attribute (port)
PyHciPerforceServer_Test.py:133: Object (server) has no attribute (rootDir)
PyHciPerforceServer_Test.py:134: Object (server) has no attribute (serverProcess)
PyHciPerforceServer_Test.py:135: Object (server) has no attribute (hostName)
PyHciPerforceServer_Test.py:136: Object (server) has no attribute (isRunning)
PyHciPerforceServer_Test.py:167: Object (server) has no attribute (port)
PyHciPerforceServer_Test.py:168: Object (server) has no attribute (rootDir)
PyHciPerforceServer_Test.py:169: Object (server) has no attribute (serverProcess)
PyHciPerforceServer_Test.py:170: Object (server) has no attribute (hostName)
PyHciPerforceServer_Test.py:171: Object (server) has no attribute (isRunning)
PyHciPerforceServer_Test.py:204: Object (server) has no attribute (isRunning)
PyHciPerforceServer_Test.py:212: Object (server) has no attribute (port)
PyHciPerforceServer_Test.py:213: Object (server) has no attribute (rootDir)


You are asking a lot for an analyser to understand the sematics of __getattr__ given
if can be implemented with arbitarily complex and ``clever'' code.

What I do is add a something like this to the class so that pychecker knows about variables:

def __pychecker__( self ):
self.isRunning = None
self.port = None
# etc...

This also works for mixin classes.

Barry