pygame / trackmod / module.py

# module trackmod.module

"""Implements a module usage tracker module type"""

import threading


ModuleType = type(threading)
getattribute = ModuleType.__getattribute__
accesses = set()
accesses_lock = threading.RLock()


class Module(ModuleType):
    # A heap subtype of the module type.
    #
    # Allows __class__ to be changed. Otherwise it is just the same.
    # To preserve the module docs this description is a comment.
    
    pass


class TrackerModule(ModuleType):
    # A heap subtype of the module type that tracks attribute gets.
    #
    # Allows __class__ to be changed. Otherwise it is just the same.
    # To preserve the module docs this description is a comment.

    # Attributes to ignore in reporting. The module name is the one
    # attribute guarenteed to not be recorded. The class is used by
    # the reporter. The path is just noise.
    ignored_attributes = set(['__name__', '__class__', '__path__'])
    
    def __getattribute__(self, attr):
        if attr in TrackerModule.ignored_attributes:
            return getattribute(self, attr)
        report(self, attr)
        return getattribute(self, attr)


def report_continuous(module, attr):
    accesses_lock.acquire()
    try:
        # Safe: no recursive call on __name__ attribute.
        accesses.add((module.__name__, attr))
    finally:
        accesses_lock.release()

def report_quit(module, attr):
    module.__class__ = Module

def report_oneshot(module, attr):
    report_continuous(module, attr)
    report_quit(module, attr)

report = report_oneshot


def set_report_mode(mode=None):
    """Set whether access checking is oneshot or continuous

    if mode (default 'oneshot') is 'oneshot' or None then a TrackerModule
    module will stop recording attribute accesses after the first non-trivial
    access. If 'continuous' then all attribute accesses are recorded. If
    'quit' then access recording stops and further calls to this function
    have no effect.

    """
    global report
    
    if report is report_quit:
        return
    if mode is None:
        mode = 'oneshot'
    if mode == 'oneshot':
        report = report_oneshot
    elif mode == 'continuous':
        report = report_continuous
    elif mode == 'quit':
        report = report_quit
    else:
        raise ValueError("Unknown mode %s" % mode)


def get_accesses():
    accesses_lock.acquire()
    try:
        return sorted(accesses)
    finally:
        accesses_lock.release()
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.