Index: /trunk/README.html =================================================================== --- /trunk/README.html (revision 5) +++ /trunk/README.html (revision 5) @@ -0,0 +1,380 @@ + + + + + + +Cheesecake: How tasty is your code? + + + +
+

Cheesecake: How tasty is your code?

+
+

Table of Contents

+ +
+
+

Summary

+

The idea of the Cheesecake project is to rank Python packages based on various +empirical "kwalitee" factors, such as:

+
+
    +
  • whether the package can be downloaded from PyPI given its name
  • +
  • whether the package can be downloaded from a full URL
  • +
  • whether the package can be unpacked
  • +
  • whether the unpack directory is the same as the package name
  • +
  • whether the package can be installed into an alternate directory
  • +
  • existence of certain files such as README, INSTALL, LICENSE, setup.py etc.
  • +
  • existence of certain directories such as doc, test, demo, examples
  • +
  • percentage of modules/functions/classes/methods with docstrings
  • +
  • percentage of functions/methods that are unit tested (not currently +implemented)
  • +
  • average pylint score for all non-test and non-demo modules
  • +
+
+

Currently, the Cheesecake index is computed for invidual packages obtained +through a variety of methods (detailed below). One of the goals of the +Cheesecake project is to automatically compute the Cheesecake index for +all packages uploaded to the PyPI Cheese Shop (possibly at upload time) and +to maintain a collection of Web pages with statistics related to the +various indexes of the packages.

+

Cheesecake currently computes 3 types of indexes:

+
+
    +
  • installability index
  • +
  • documentation index
  • +
  • code kwalitee index
  • +
+
+

The algorithms for computing each index type are detailed below.

+
+
+

Why Cheesecake?

+

The concept of "kwalitee" originated in the Perl community. Here's a relevant +quote:

+
+It looks like quality, it sounds like quality, but it's not quite quality.
+

Kwalitee is an empiric measure of how good a specific body of code is. It +defines quality indicators and measures the code along them. It is currently +used by the CPANTS Testing Service +to evaluate the 'goodness' of CPAN packages.

+

Since the Python package repository (aka PyPI) +is hosted at the Cheese Shop, +it stands to reason that the quality indicator of a PyPI package should be +called the Cheesecake index!

+
+
+

Usage examples

+

To compute the Cheesecake index for a given project, run the cheesecake.py +module from the command line and indicate either:

+
+ +
+

In all cases, the cheesecake module will attempt to download the package +if necessary, then to unpack it in a sandbox directory (/tmp/cheesecake_sandbox +by default). If either of these operations fails, the Cheesecake index for +the package will be 0. If the package can be successfully unpacked, the +cheesecake module will compute the values for a variety of indexes detailed +in the algorithm given at the end of this file.

+

If the package can be successfully downloaded and unpacked, a log file is +created in the sandbox directory and named <package>.log (e.g. the log file +for twill-0.7.4.tar.gz is /tmp/cheesecake_sandbox/twill-0.7.4.tar.gz.log). +The log file is not automatically deleted after the Cheesecake index is +computed, since its purpose is to be inspected for debug information.

+

Command-line examples:

+
+
    +
  1. Compute the Cheesecake index for the Durus package by using setuptools +utilities to download the package from PyPI:

    +
    +python cheesecake.py --name=Durus
    +
    +
  2. +
  3. Compute the Cheesecake index for the Durus package by indicating its URL:

    +
    +python cheesecake.py --url=http://www.mems-exchange.org/software/durus/Durus-3.1.tar.gz
    +
    +
  4. +
  5. Compute the Cheesecake index for the twill package by indicating its path +on the local file system:

    +
    +python cheesecake.py --path=/tmp/twill-latest.tar.gz
    +
    +
  6. +
  7. To increase the verbosity of the output, use the -v or --verbose option. +For more options, run cheesecake.py with -h or --help.

    +
  8. +
+
+
+
+

Obtaining the source code

+

The Cheesecake project has not yet been released as a tarball or +a Python egg. You can obtain the source code from SourceForge via CVS:

+
+cvs -z3 -d:pserver:anonymous@cvs.sourceforge.net:/cvsroot/cheesecake co -P cheesecake
+
+
+
+

Mailing list

+

Developer mailing list: http://lists.sourceforge.net/lists/listinfo/cheesecake-devel

+
+
+

License

+

Cheesecake is licensed under the Python Software Foundation license, +the same license that governs Python itself. The text of the license is +available in the LICENSE file in the source code distribution and +can also be downloaded from +http://www.opensource.org/licenses/PythonSoftFoundation.php.

+
+
+

Author contact info

+

Grig Gheorghiu

+

Email: <grig at gheorghiu dot net>

+

Web site: http://agiletesting.blogspot.com

+
+
+

Algorithm for computing the Cheesecake index

+

The cheesecake.py module uses the following constants:

+
+INDEX_PYPI_DOWNLOAD = 50
+INDEX_PYPI_DISTANCE = 5
+INDEX_URL_DOWNLOAD  = 25
+INDEX_UNPACK        = 25
+INDEX_UNPACK_DIR    = 15
+INDEX_INSTALL       = 50
+INDEX_FILE_CRITICAL = 15
+INDEX_FILE          = 10
+INDEX_FILE_PYC      = 20
+INDEX_DIR_CRITICAL  = 25
+INDEX_DIR           = 20
+INDEX_DIR_EMPTY     = 5
+
+MAX_INDEX_DOCSTRINGS = 100 # max. percentage of modules/classes/methods/functions with docstrings
+MAX_INDEX_PYLINT     = 100 # max. pylint score
+
+

Step 0

+

Initialize the Cheesecake index to 0. Also initialize to 0 +the partial Cheesecake indexes for installability, documentation +and code kwalitee.

+

Compute the maximum overall Cheesecake index that can be reached by +any given package, which is the sum:

+
+INDEX_PYPI_DOWNLOAD + 
+INDEX_UNPACK + INDEX_UNPACK_DIR + 
+INDEX_INSTALL +
+MAX_INDEX_DOCSTRINGS + MAX_INDEX_PYLINT + 
+(INDEX_FILE * number_of_expected_files) +
+(INDEX_FILE_CRITICAL * number_of_expected_critical_files) +
+(INDEX_DIR * number_of_expected_dirs) +
+(INDEX_DIR_CRITICAL * number_of_expected_critical_dirs)
+
+

Compute the maximum Cheesecake index for installability, which is the sum:

+
+INDEX_PYPI_DOWNLOAD + 
+INDEX_UNPACK + INDEX_UNPACK_DIR + 
+INDEX_INSTALL
+
+

Compute the maximum Cheesecake index for documentation, which is the sum:

+
+(INDEX_FILE * number_of_expected_files) +
+(INDEX_FILE_CRITICAL * number_of_expected_critical_files) +
+(INDEX_DIR * number_of_expected_dirs) +
+(INDEX_DIR_CRITICAL * number_of_expected_critical_dirs) +
+MAX_INDEX_DOCSTRINGS
+
+

Compute the maximum Cheesecake index for code kwalitee, which is currently:

+
+MAX_INDEX_PYLINT
+
+

Step 1a

+

If short name of the package was specified with -n or --name, +try to download the package from the PyPI index page by following the links to +the package home page and the package download URL (this is accomplished +using setuptools utilities).

+

If not successful, exit with a Cheesecake index of 0. If successful and +package was found at the Cheese Shop, add INDEX_PYPI_DOWNLOAD to +the overall Cheesecake index and to the installability Cheesecake index.

+

If successful but package was not found at the Cheese Shop, add +INDEX_PYPI_DOWNLOAD - (INDEX_PYPI_DISTANCE * number_of_links_to_package) +to the overall Cheesecake index and to the installability Cheesecake index.

+

Step 1b

+

If full URL of the package was specified with -u or --url, +try to download the package from the specified URL.

+

If not successful, exit with a Cheesecake index of 0. If successful, +add INDEX_URL_DOWNLOAD to the overall Cheesecake index and to +the installability Cheesecake index.

+

Step 1c

+

If path to package on local file system was specified with -p or +--path, copy the package to the sandbox directory.

+

Step 2

+

Unpack the package (currently supported archive types are zip and +tar.gz/tgz; in the near future we will support Python Eggs.)

+

If not successful, exit with a Cheesecake index of 0. If successful, add +INDEX_UNPACK to the overall Cheesecake index and to the installability +Cheesecake index.

+

Step 3

+

Check that the unpack directory has the same name as the package name +(i.e. when unpacking twill-0.7.4.tar.gz, we expect the unpack directory +to be twill-0.7.4.)

+

If the unpack directory name is the same as the package name, add +INDEX_UNPACK_DIR +to the overall Cheesecake index and to the installability Cheesecake index.

+

Step 4

+

Install the package to a temporary directory in a non-default location. +If successful, add INDEX_INSTALL to the overall Cheesecake index and to the +installability Cheesecake index.

+

Step 5

+

Check for existence of specific files. +For each file found, add INDEX_FILE to the overall +Cheesecake index and to the documentation Cheesecake index. +If the file is deemed critical, add INDEX_FILE_CRITICAL instead.

+

The following special files ("cheese_files") are currently checked:

+
+cheese_files = ["install", "changelog",
+                "news", "faq",
+                "todo", "thanks", "announce",
+                "ez_setup.py",
+               ]
+
+

The following files are currently deemed critical:

+
+critical_cheese_files = ["readme", "license", "setup.py"]
+
+

To check if a file FILE is among the cheese files, the following regular +expression is used:

+
+re.search(r"^%s(\.txt)*" % cheese_file, file, re.IGNORECASE)
+
+

Step 6

+

Check for existence of specific directories. +For each directory found, add INDEX_DIR to the overall Cheesecake +index and to the documentation Cheesecake index. +If the directory is deemed critical, add INDEX_DIR_CRITICAL instead. +If the directory is found empty, add INDEX_DIR_EMPTY instead.

+

The following directories ("cheese_dirs") are currently checked:

+
+cheese_dirs = ["example", "demo"]
+
+

The following directories are currently deemed critical:

+
+critical_cheese_dirs = ["doc", "test"]
+
+

To check if a directory DIR is among the cheese directories, +the following regular expression is used:

+
+re.search(r"^%s" % cheese_dir, DIR, re.ignorecase)
+
+

Step 7

+

Check for existence of .pyc files. If found, decrease the score +by subtracting INDEX_FILE_PYC from the overall Cheesecake index +and from the documentation Cheesecake index.

+

Step 8

+

Compute the percentage of modules/classes/methods/functions that have +docstrings associated with them. Only Python modules that are not in test, +doc, demo and example directories are checked. +Round up the percentage and add it to the overall Cheesecake index and to the +documentation Cheesecake index.

+

Step 9

+

If pylint is present on the system, run pylint against all Python files +that are not in the test, docs or demo directories. +Average the non-negative pylint scores, multiply the average by 10 and +add it to the overall Cheesecake index and to the code kwalitee +Cheesecake index.

+

Step 10

+

For each of the partial Cheesecake index types (installability, +documentation and code kwalitee), display the absolute Cheesecake +index for that type as the sum of all indexes of that type computed in +the previous steps. +Also display the relative Cheesecake index for that type as the percentage +of (absolute_index / maximum_index).

+

Display the absolute Cheesecake index for the package as the sum of all +indexes computed in the previous steps. Also display the relative Cheesecake +index for the package as the percentage of (absolute_index / maximum_index).

+
+
+

Sample output

+
+$ python cheesecake.py -n Durus
+[cheesecake:console] Trying to download package durus from PyPI using setuptools utilities
+[cheesecake:console] Downloaded package Durus-3.1.tar.gz from http://www.mems-exchange.org/software/durus/Durus-3.1.tar.gz
+[cheesecake:console] Detailed info available in log file /tmp/cheesecake_sandbox/durus.log
+[cheesecake:console] A given package can currently reach a MAXIMUM number of 555 points
+[cheesecake:console] Starting computation of Cheesecake index for package 'Durus-3.1.tar.gz'
+
+[cheesecake:console] Starting computation of INSTALLABILITY index (max. points = 140)
+index_pypi_download .....................  45 (downloaded package Durus-3.1.tar.gz following 1 link from PyPI)
+index_unpack ............................  25 (package untar-ed successfully)
+index_unpack_dir ........................  15 (unpack directory is Durus-3.1 as expected)
+index_install ...........................  50 (package installed in /tmp/cheesecake_sandbox/tmp_install_Durus-3.1)
+---------------------------------------------
+INSTALLABILITY INDEX (ABSOLUTE) ......... 135
+INSTALLABILITY INDEX (RELATIVE) .........  96 (135 out of a maximum of 140 points is 96%)
+
+[cheesecake:console] Starting computation of DOCUMENTATION index (max. points = 415)
+index_file_announce .....................   0 (file not found)
+index_file_changelog ....................   0 (file not found)
+index_file_ez_setup.py ..................   0 (file not found)
+index_file_faq ..........................  10 (file found)
+index_file_install ......................  10 (file found)
+index_file_license ......................  15 (critical file found)
+index_file_news .........................   0 (file not found)
+index_file_readme .......................  15 (critical file found)
+index_file_setup.py .....................  15 (critical file found)
+index_file_thanks .......................   0 (file not found)
+index_file_todo .........................   0 (file not found)
+index_dir_demo ..........................   0 (directory not found)
+index_dir_doc ...........................  25 (critical directory found)
+index_dir_example .......................   0 (directory not found)
+index_dir_test ..........................  25 (critical directory found)
+index_docstrings ........................  42 (found 104/249=41.77% modules/classes/methods/functions with docstrings)
+---------------------------------------------
+DOCUMENTATION INDEX (ABSOLUTE) .......... 157
+DOCUMENTATION INDEX (RELATIVE) ..........  37 (157 out of a maximum of 415 points is 37%)
+
+[cheesecake:console] Starting computation of CODE KWALITEE index (max. points = 100)
+index_pylint ............................  64 (average score is 6.30 out of 10)
+---------------------------------------------
+CODE KWALITEE INDEX (ABSOLUTE) ..........  64
+CODE KWALITEE INDEX (RELATIVE) ..........  64 (64 out of a maximum of 100 points is 64%)
+
+=============================================
+OVERALL CHEESECAKE INDEX (ABSOLUTE) ..... 356
+OVERALL CHEESECAKE INDEX (RELATIVE) .....  64 (356 out of a maximum of 555 points is 64%)
+
+
+
+

Future plans

+

Cheesecake is under very active development. The immediate goal is to add the unit test +index measurement, followed by other metrics inspired from the +kwalitee indicators. +Please edit the IndexMeasurementIdeas +Wiki page to add things that you would like to see covered +by the Cheesecake metrics.

+
+
+ + + Index: /trunk/cheesecake/logger.py =================================================================== --- /trunk/cheesecake/logger.py (revision 2) +++ /trunk/cheesecake/logger.py (revision 2) @@ -0,0 +1,118 @@ +import sys, re + +######################################################## +############### PRODUCERS ############################## +######################################################## + +class Message(object): + def __init__(self, keywords, args): + self.keywords = keywords + self.args = args + + def content(self): + return " ".join(map(str, self.args)) + + def prefix(self): + return "[%s] " % (":".join(self.keywords)) + + def __str__(self): + return self.prefix() + self.content() + +class Producer(object): + """ Log producer API which sends messages to be logged + to a 'consumer' object, which then prints them to stdout, + stderr, files, etc. + """ + + Message = Message # to allow later customization + keywords2consumer = {} + + def __init__(self, keywords): + if isinstance(keywords, str): + keywords = tuple(keywords.split()) + self.keywords = keywords + + def __repr__(self): + return "" % ":".join(self.keywords) + + def __getattr__(self, name): + if name[0] == '_': + raise AttributeError, name + producer = self.__class__(self.keywords + (name,)) + setattr(self, name, producer) + return producer + + def __call__(self, *args): + func = self._getconsumer(self.keywords) + if func is not None: + func(self.Message(self.keywords, args)) + + def _getconsumer(self, keywords): + for i in range(len(self.keywords), 0, -1): + try: + return self.keywords2consumer[self.keywords[:i]] + except KeyError: + continue + return self.keywords2consumer.get('default', default_consumer) + +default = Producer('default') + +def default_consumer(msg): + print str(msg) + +Producer.keywords2consumer['default'] = default_consumer + +class MultipleProducer(Producer): + + def __call__(self, *args, **kwargs): + for func in self._getconsumer(self.keywords): + if func is not None: + return func(self.Message(self.keywords, args), **kwargs) + + def _getconsumer(self, keywords): + found_consumer = False + for keyword in keywords: + consumer = self.keywords2consumer.get((keyword,)) + found_consumer = True + yield consumer + if not found_consumer: + yield self.keywords2consumer.get('default', default_consumer) + +######################################################## +############### CONSUMERS ############################## +######################################################## + +class File(object): + def __init__(self, f): + assert hasattr(f, 'write') + assert isinstance(f, file) or not hasattr(f, 'open') + self._file = f + + def __call__(self, msg): + print >>self._file, str(msg) + +class Path(File): + def __init__(self, filename, append=False): + mode = append and 'a' or 'w' + f = open(str(filename), mode, buffering=1) + super(Path, self).__init__(f) + +def STDOUT(msg): + print >>sys.stdout, str(msg) + +def STDERR(msg): + print >>sys.stderr, str(msg) + +def setconsumer(keywords, consumer): + # normalize to tuples + if isinstance(keywords, str): + keywords = tuple(map(None, keywords.split())) + elif not isinstance(keywords, tuple): + raise TypeError("key %r is not a string or tuple" % (keywords,)) + if consumer is not None and not callable(consumer): + if not hasattr(consumer, 'write'): + raise TypeError("%r should be None, callable or file-like" % (consumer,)) + consumer = File(consumer) + #print "setting consumer for " + str(keywords) + "to " + str(consumer) + Producer.keywords2consumer[keywords] = consumer + Index: /trunk/cheesecake/cheesecake_index.py =================================================================== --- /trunk/cheesecake/cheesecake_index.py (revision 2) +++ /trunk/cheesecake/cheesecake_index.py (revision 2) @@ -0,0 +1,1049 @@ +#!/usr/bin/env python +""" +Cheesecake: How tasty is your code? + +The idea of the Cheesecake project is to rank Python packages +based on various empiric "kwalitee" factors, such as: + + * whether the package can be downloaded + * whether the package can be unpacked + * whether the package can be installed into an alternate directory + * existence of certain files such as README, INSTALL, LICENSE, setup.py etc. + * existence of certain directories such as doc, test, demo, examples + * percentage of modules/functions/classes/methods with docstrings + * percentage of functions/methods that are unit tested + * average pylint score for all non-test and non-demo modules + * whether the package can be unpacked + * whether the package can be installed into an alternate directory +""" + +import os, sys, re, shutil +import tarfile, zipfile +from optparse import OptionParser +from urllib import urlretrieve +from urlparse import urlparse +from subprocess import call, Popen, PIPE, STDOUT +from inspect import isclass, ismethod, isfunction +from math import ceil +import logger + +INDEX_PYPI_DOWNLOAD = 50 +INDEX_PYPI_DISTANCE = 5 +INDEX_URL_DOWNLOAD = 25 +INDEX_UNPACK = 25 +INDEX_UNPACK_DIR = 15 +INDEX_INSTALL = 50 +INDEX_FILE_CRITICAL = 15 +INDEX_FILE = 10 +INDEX_REQUIRED_FILES = 100 +INDEX_FILE_PYC = -20 +INDEX_DIR_CRITICAL = 25 +INDEX_DIR = 20 +INDEX_DIR_EMPTY = 5 + +MAX_INDEX_DOCSTRINGS = 100 # max. percentage of modules/classes/methods/functions with docstrings +MAX_INDEX_PYLINT = 100 # max. pylint score + +PAD_TEXT = 40 +PAD_VALUE = 4 + +class Index(object): + """ + Encapsulates index attributes such as name, value, details + """ + + def __init__(self, type, name="", value=0, details=""): + self.type = "index_" + type + self.name = self.type + if name: self.name += "_" + name + self.value = value + self.details = details + + def print_info(self): + """ + Print index name padded with dots, followed by value and details + """ + msg = pad_with_dots(self.name) + msg += pad_left_spaces(self.value) + msg += " (" + self.details + ")" + print msg + +class CompositeIndex(object): + """ + Collection of indexes of same type (e.g. files, dirs) + """ + + def __init__(self, type): + """ + Indexes is a dict mapping names to Index objects + """ + self.type = type + self.indexes = {} + + def set_index(self, name, value=0, details=""): + """ + Create new index or update existing index with specified attributes + """ + if self.indexes.has_key(name): + index = self.indexes[name] + index.value = value + index.details = details + else: + self.indexes[name] = Index(self.type, name, value, details) + + def print_info(self): + """ + Print index info for all indexes sorted alphanumerically by name + """ + names = self.indexes.keys() + names.sort() + for name in names: + index = self.indexes[name] + index.print_info() + + def get_value(self): + """ + Return sum of individual index values + """ + value = 0 + for key in self.indexes.keys(): + index = self.indexes[key] + value += index.value + return value + + value = property(get_value) + +class CheesecakeError(Exception): + """ + Custom exception class for Cheesecake-specific errors + """ + pass + +class Cheesecake(object): + """ + Computes 'goodness' of Python packages + + Generates "cheesecake index" that takes into account things like: + + * whether the package can be downloaded + * whether the package can be unpacked + * whether the package can be installed into an alternate directory + * existence of certain files such as README, INSTALL, LICENSE, setup.py etc. + * existence of certain directories such as doc, test, demo, examples + * percentage of modules/functions/classes/methods with docstrings + * percentage of functions/methods that are unit tested + * average pylint score for all non-test and non-demo modules + """ + + def __init__(self, name="", url="", path="", sandbox=None, + verbose=False, quiet=False): + """ + Initialize critical variables, download and unpack package, walk package tree + + """ + self.name = name + self.url = url + self.package_path = path + if not self.name and not self.url and not self.package_path: + self.raise_exception("No package name, URL or path specified ... exiting") + self.sandbox = sandbox or "/tmp/cheesecake_sandbox" + if not os.path.isdir(self.sandbox): + os.mkdir(self.sandbox) + self.verbose = verbose + self.quiet = quiet + + self.package_types = ["tar.gz", "tgz", "zip"] + self.sandbox_pkg_file = "" + self.sandbox_pkg_dir = "" + self.sandbox_install_dir = "" + + self.determine_pkg_name() + self.configure_logging() + self.init_indexes() + self.retrieve_pkg() + self.unpack_pkg() + self.walk_pkg() + + def raise_exception(self, msg): + """ + Cleanup, print error message and raise CheesecakeError + + Don't use logging, since it can be called before logging has been setup + """ + self.cleanup() + os.unlink(os.path.join(self.sandbox, self.logfile)) + + msg += "\n" + pad_msg("CHEESECAKE INDEX", 0) + raise CheesecakeError(msg) + + def cleanup(self): + """ + Delete temporary directories and files that were + created in the sandbox + """ + if os.path.isfile(self.sandbox_pkg_file): + self.log("Removing file %s" % self.sandbox_pkg_file) + os.unlink(self.sandbox_pkg_file) + if os.path.isdir(self.sandbox_pkg_dir): + self.log("Removing directory %s" % self.sandbox_pkg_dir) + shutil.rmtree(self.sandbox_pkg_dir) + if os.path.isdir(self.sandbox_install_dir): + self.log("Removing directory %s" % self.sandbox_install_dir) + shutil.rmtree(self.sandbox_install_dir) + + def determine_pkg_name(self): + if self.name: + self.package = self.name + elif self.package_path: + self.package = self.get_package_from_path(self.package_path) + else: + self.package = self.get_package_from_url() + + def configure_logging(self): + """ + Default settings for logging + + if verbose, log goes to console, else it goes to logfile + log.debug goes to logfile + log.info goes to console + log.warn and log.error go to both logfile and stdout + """ + self.logfile = os.path.join(self.sandbox, self.package + ".log") + + logger.setconsumer('logfile', open(str(self.logfile), 'w', buffering=1)) + logger.setconsumer('console', logger.STDOUT) + logger.setconsumer('null', None) + + if self.verbose: + self.log = logger.MultipleProducer('cheesecake console') + else: + self.log = logger.MultipleProducer('cheesecake logfile') + if self.quiet: + self.log.info = logger.MultipleProducer('cheesecake logfile') + else: + self.log.info = logger.MultipleProducer('cheesecake console') + self.log.debug = logger.MultipleProducer('cheesecake logfile') + self.log.warn = logger.MultipleProducer('cheesecake console') + self.log.error = logger.MultipleProducer('cheesecake console') + + def init_indexes(self): + """ + Initialize variables used in index computation + + * cheesecake_index: overall index for the package + * index: dict holding Index or CompositeIndex objects of various types + """ + self.cheesecake_index = 0 + self.cheesecake_index_installability = 0 + self.cheesecake_index_documentation = 0 + self.cheesecake_index_codekwalitee = 0 + self.max_cheesecake_index = INDEX_PYPI_DOWNLOAD + \ + INDEX_UNPACK + \ + INDEX_UNPACK_DIR + \ + INDEX_INSTALL + \ + MAX_INDEX_DOCSTRINGS + \ + MAX_INDEX_PYLINT + self.max_cheesecake_index_installability = INDEX_PYPI_DOWNLOAD + \ + INDEX_UNPACK + \ + INDEX_UNPACK_DIR + \ + INDEX_INSTALL + self.max_cheesecake_index_documentation = INDEX_REQUIRED_FILES + \ + MAX_INDEX_DOCSTRINGS + self.max_cheesecake_index_codekwalitee = MAX_INDEX_PYLINT + self.index = {} + for index_type in ["file", "dir"]: + self.index[index_type] = CompositeIndex(index_type) + for index_type in ["pypi_download", "url_download", + "unpack_dir", "unpack", "install", + "docstrings", "pylint"]: + self.index[index_type] = Index(index_type) + + self.cheese_files = ["readme", "install", "changelog", + "news", "faq", + "todo", "thanks", + "license", "announce", + "setup.py", "ez_setup.py", + ] + self.critical_cheese_files = ["readme", "license", "setup.py"] + for cheese_file in self.cheese_files: + self.index["file"].set_index(name=cheese_file, details="file not found") + if cheese_file in self.critical_cheese_files: + self.max_cheesecake_index += INDEX_FILE_CRITICAL + self.max_cheesecake_index_documentation += INDEX_FILE_CRITICAL + else: + self.max_cheesecake_index += INDEX_FILE + self.max_cheesecake_index_documentation += INDEX_FILE + self.log.debug("cheese_files: " + ",".join(self.cheese_files)) + self.log.debug("critical_cheese_files: " + ",".join(self.critical_cheese_files)) + + self.cheese_dirs = ["doc", "test", "example", "demo"] + self.critical_cheese_dirs = ["doc", "test"] + for cheese_dir in self.cheese_dirs: + self.index["dir"].set_index(name=cheese_dir, details="directory not found") + if cheese_dir in self.critical_cheese_dirs: + self.max_cheesecake_index += INDEX_DIR_CRITICAL + self.max_cheesecake_index_documentation += INDEX_DIR_CRITICAL + else: + self.max_cheesecake_index += INDEX_DIR + self.max_cheesecake_index_documentation += INDEX_DIR + self.log.debug("cheese_dirs: " + ",".join(self.cheese_dirs)) + self.log.debug("critical_cheese_dirs: " + ",".join(self.critical_cheese_dirs)) + + self.pkg_files = {} + self.pkg_dirs = {} + self.file_types = ["py", "pyc", "test", + ] + for type in self.file_types: + self.pkg_files[type] = [] + + def retrieve_pkg(self): + if self.name: + self.get_pkg_from_pypi() + elif self.url: + self.download_pkg() + else: + self.copy_pkg() + + def get_package_from_url(self): + """ + Use ``urlparse`` to obtain package path from URL + """ + (scheme,location,path,param,query,fragment_id) = urlparse(self.url) + return self.get_package_from_path(path) + + + def get_package_from_path(self, path): + """ + Get package name as file portion of path + """ + dir, file = os.path.split(path) + return file + + def get_pkg_from_pypi(self): + """ + Download package using setuptools utilities + """ + try: + self.log.info("Trying to download package %s from PyPI using setuptools utilities" % self.name) + from setuptools.package_index import PackageIndex + from pkg_resources import Requirement + from distutils import log + # Temporarily set the log verbosity to INFO so we can capture setuptools info messages + old_threshold = log.set_threshold(log.INFO) + pkgindex = PackageIndex() + old_stdout = sys.stdout + sys.stdout = StdoutRedirector() + output = pkgindex.fetch(Requirement.parse(self.name), + self.sandbox, + force_scan=True, + source=True) + captured_stdout = sys.stdout.read_buffer() + sys.stdout = old_stdout + log.set_threshold(old_threshold) + if output is None: + self.raise_exception("Error: Could not find distribution for " + self.name) + download_url = "" + distance_from_pypi = 0 + #print captured_stdout + for line in captured_stdout.split('\n'): + s = re.search(r"Reading http(.*)", line) + if s: + inspected_url = s.group(1) + if not re.search(r"www.python.org\/pypi", inspected_url): + distance_from_pypi += 1 + continue + s = re.search(r"Downloading (.*)", line) + if s: + download_url = s.group(1) + break + self.sandbox_pkg_file = output + self.package = self.get_package_from_path(output) + self.log.info("Downloaded package %s from %s" % (self.package, download_url)) + index_type = "pypi_download" + found_on_cheeseshop = False + if re.search(r"cheeseshop.python.org", download_url): + value = INDEX_PYPI_DOWNLOAD + found_on_cheeseshop = True + else: + value = INDEX_PYPI_DOWNLOAD - distance_from_pypi * INDEX_PYPI_DISTANCE + self.index[index_type].value = value + details = "downloaded package " + self.package + if found_on_cheeseshop: + details += " directly from the Cheese Shop" + elif distance_from_pypi: + details += " following %d link" % distance_from_pypi + if distance_from_pypi > 1: + details += "s" + details += " from PyPI" + else: + details += "from " + download_url + self.index[index_type].details = details + except ImportError, e: + msg = "Error: setuptools is not installed and is required for downloading a package by name\n" + msg += "You can donwload and process a package by its full URL via the -u or --url option\n" + msg += "Example: python cheesecake.py --url=http://www.mems-exchange.org/software/durus/Durus-3.1.tar.gz" + self.raise_exception(msg) + + def download_pkg(self): + """ + Use ``urllib.urlretrieve`` to download package to file in sandbox dir + """ + #self.log("Downloading package %s from URL %s" % (self.package, self.url)) + self.sandbox_pkg_file = os.path.join(self.sandbox, self.package) + try: + downloaded_filename, headers = urlretrieve(self.url, self.sandbox_pkg_file) + except IOError, e: + self.log.error("Error downloading package %s from URL %s" % (self.package, self.url)) + self.raise_exception(str(e)) + #self.log("Downloaded package %s to %s" % (self.package, downloaded_filename)) + if re.search("Content-Type: details/html", str(headers)): + f = open(downloaded_filename) + if re.search("404 Not Found", "".join(f.readlines())): + f.close() + self.raise_exception("Got '404 Not Found' error while trying to download package ... exiting") + f.close() + index_type = "url_download" + self.index[index_type].value = INDEX_URL_DOWNLOAD + self.index[index_type].details = "downloaded package %s from URL %s" % (self.package, self.url) + + def copy_pkg(self): + """ + Copy package file to sandbox directory + """ + self.sandbox_pkg_file = os.path.join(self.sandbox, self.package) + if not os.path.isfile(self.package_path): + self.raise_exception("%s is not a valid file ... exiting" % self.package_path) + self.log("Copying file %s to %s" % (self.package_path, self.sandbox_pkg_file)) + shutil.copyfile(self.package_path, self.sandbox_pkg_file) + + def unpack_pkg(self): + """ + Unpack the package in the sandbox directory + + Currently supported archive types: + + * .tar.gz (handled with ``tarfile`` module) + * .zip (handled with ``zipfile`` module) + """ + self.package_type = "" + for type in self.package_types: + s = re.search(r"(.+)\.%s" % type, self.package) + if s: + # package_name is name of package without file extension (ex. twill-7.3) + self.package_name = s.group(1) + self.package_type = type + break + if not self.package_type: + msg = "Could not determine package type for package '%s'" % self.package + msg += "\nCurrently recognized types: " + " ".join(self.package_types) + self.raise_exception(msg) + self.log.debug("Package name: " + self.package_name) + self.log.debug("Package type: " + self.package_type) + + self.sandbox_pkg_dir = os.path.join(self.sandbox, self.package_name) + if os.path.isdir(self.sandbox_pkg_dir): + shutil.rmtree(self.sandbox_pkg_dir) + + if self.package_type in ["tar.gz", "tgz"]: + self.untar_pkg() + elif self.package_type == "zip": + self.unzip_pkg() + + index_type = "unpack_dir" + details = "unpack directory is " + self.unpack_dir + if self.unpack_dir != self.package_name: + details += " instead of the expected " + self.package_name + self.package_name = self.unpack_dir + else: + details += " as expected" + self.index[index_type].value = INDEX_UNPACK_DIR + self.index[index_type].details = details + + if not self.quiet: + self.log.info("Detailed info available in log file %s" % self.logfile) + + def untar_pkg(self): + """ + Untar the package in the sandbox directory + + Uses tarfile module + """ + try: + t = tarfile.open(self.sandbox_pkg_file) + except tarfile.ReadError, e: + self.raise_exception("Could not read tar file %s ... exiting" % self.sandbox_pkg_file) + + for member in t.getmembers(): + t.extract(member, self.sandbox) + + tarinfo = t.members[0] + self.unpack_dir = tarinfo.name.split(os.sep)[0] + + index_type = "unpack" + self.index[index_type].value = INDEX_UNPACK + self.index[index_type].details = "package untar-ed successfully" + + def unzip_pkg(self): + """ + Unzip the package in the sandbox directory + + Uses zipfile module + """ + try: + z = zipfile.ZipFile(self.sandbox_pkg_file) + except zipfile.error: + self.raise_exception("Error unzipping file %s ... exiting" % self.sandbox_pkg_file) + + # Get directory structure from zip and create it in sandbox + for name in z.namelist(): + (dir, file) = os.path.split(name) + unpack_dir = dir + target_dir = os.path.join(self.sandbox, dir) + if not os.path.exists(target_dir): + os.makedirs(target_dir) + + # Extract files to directory structure + for i, name in enumerate(z.namelist()): + if not name.endswith('/'): + outfile = open(os.path.join(self.sandbox, name), 'wb') + outfile.write(z.read(name)) + outfile.flush() + outfile.close() + + self.unpack_dir = unpack_dir.split(os.sep)[0] + + index_type = "unpack" + self.index[index_type].value = INDEX_UNPACK + self.index[index_type].details = "package unzipped successfully" + + def walk_pkg(self): + """ + Traverse the file system tree rooted at sandbox/package_name + + * Compute indexes for special files and directories + * Identify Python files, test files, etc. + """ + cwd = os.getcwd() + os.chdir(self.sandbox) + for rootdir, dirs, files in os.walk(self.package_name): + head, tail = os.path.split(rootdir) + dirs_in_rootdir = rootdir.split(os.path.sep) + for cheese_dir in self.cheese_dirs: + if re.search("^%s" % cheese_dir, tail): + if files or dirs: + if cheese_dir in self.critical_cheese_dirs: + value = INDEX_DIR_CRITICAL + details = "critical directory found" + self.log.debug("critical_cheese_dir found: " + cheese_dir) + else: + value = INDEX_DIR + details = "directory found" + self.log.debug("cheese_dir found: " + cheese_dir) + else: + value = INDEX_DIR_EMPTY + details = "empty directory found" + self.log.debug("empty cheese_dir found: " + cheese_dir) + self.index["dir"].set_index(cheese_dir, value, details) + for file in files: + fullpath = os.path.join(rootdir, file) + for cheese_file in self.cheese_files: + if re.search(r"^%s(\.txt)*" % cheese_file, file, re.IGNORECASE): + if cheese_file in self.critical_cheese_files: + value = INDEX_FILE_CRITICAL + details = "critical file found" + self.log.debug("critical_cheese_file found: " + cheese_file) + else: + value = INDEX_FILE + details = "file found" + self.log.debug("cheese_file found: " + cheese_file) + self.index["file"].set_index(cheese_file, value, details) + + if self.is_py_file(file, dirs_in_rootdir): + self.pkg_files["py"].append(fullpath) + self.log.debug("py file found: " + fullpath) + if os.path.splitext(file)[1] == ".pyc": + self.pkg_files["pyc"].append(fullpath) + self.log.debug("pyc file found: " + fullpath) + if self.is_test_file(file, dirs_in_rootdir): + self.pkg_files["test"].append(fullpath) + self.log.debug("test file found: " + fullpath) + len_pyc_list = len(self.pkg_files["pyc"]) + if len_pyc_list: + self.index["file"].set_index("pyc", value=-INDEX_FILE_PYC, + details="%d .pyc files found" % len_pyc_list) + self.log.debug("Found %d py files" % len(self.pkg_files["py"])) + self.log.debug("Found %d pyc files" % len(self.pkg_files["pyc"])) + self.log.debug("Found %d test files" % len(self.pkg_files["test"])) + + os.chdir(cwd) + + def is_py_file(self, file, dirs): + """ + Return True if file ends with .py and it is not a special file and it is not + in special directory + """ + if os.path.splitext(file)[1] != ".py": + return False + if file in ["setup.py", "ez_setup.py", "__init__.py", "__pkginfo__.py"]: + return False + for dir in dirs: + if dir.startswith("test") or \ + dir.startswith("docs") or \ + dir.startswith("demo") or \ + dir.startswith("example"): + return False + return True + + def is_test_file(self, file, dirs): + """ + Return True is file is in directory rooted at "test" or "tests" + """ + if file in ["__init__.py"]: + return False + for dir in dirs: + if dir.startswith("test"): + return True + return False + + def index_file(self): + """ + Return CompositeIndex object of type "file" + """ + return self.index["file"] + + def index_dir(self): + """ + Return CompositeIndex object of type "dir" + """ + return self.index["dir"] + + def index_pypi_download(self): + """ + Verify that package can be downloaded from PyPI + + Return Index object of type "pypi_download" + """ + index_type = "pypi_download" + if self.url: + # Package was downloaded directly from URL + self.index[index_type].value = 0 + self.index[index_type].details = "package was downloaded directly from URL" + + if self.package_path: + # Package was processed from file system path + self.index[index_type].value = 0 + self.index[index_type].details = "package was processed from file system path" + + # Otherwise, index["pypi_download"] was already set in get_pkg_from_pypi() + return self.index["pypi_download"] + + def index_url_download(self): + """ + Verify that package can be downloaded from an URL + + Return Index object of type "download" + """ + # index["download"] is already set in download_pkg() + return self.index["url_download"] + + def index_unpack(self): + """ + Verify that package can be unpacked + + Return Index object of type "unpack" + """ + # index["unpack"] is already set in unpack_pkg() + return self.index["unpack"] + + + def index_unpack_dir(self): + """ + Verify that unpack directory has same name as package + + Return Index object of type "unpack_dir" + """ + # index["unpack_dir"] is already set in unpack_pkg() + return self.index["unpack_dir"] + + def index_install(self): + """ + Verify that package can be installed in alternate directory + + Return Index object of type "install" + """ + index_type = "install" + self.sandbox_install_dir = os.path.join(self.sandbox, "tmp_install_%s" % self.package_name) + cwd = os.getcwd() + os.chdir(os.path.join(self.sandbox, self.package_name)) + p = Popen(["python", "setup.py", "install", "--home=%s" % self.sandbox_install_dir], stdout=PIPE, stderr=STDOUT) + output = p.communicate()[0] + if not p.returncode: + # Install succeeded + self.index[index_type].value = INDEX_INSTALL + self.index[index_type].details = details="package installed in %s" % self.sandbox_install_dir + else: + # Install failed + self.index[index_type].details = "could not install package in %s" % self.sandbox_install_dir + os.chdir(cwd) + return self.index[index_type] + + def index_docstrings(self): + """ + Compute docstring index as percentage of modules/classes/methods/functions + that have docstrings associated with them + + Return Index object of type "docstrings" + """ + cnt = 0 + docstring_cnt = 0 + index_type = "docstrings" + for pyfile in self.pkg_files["py"]: + fullpath = os.path.join(self.sandbox, pyfile) + code = CodeParser(fullpath, self.log.debug) + cnt += code.object_count() + docstring_cnt += code.docstring_count() + if cnt: + percent = float(docstring_cnt)/float(cnt) + else: + percent = 0 + index_value = int(ceil(percent*100)) + details = "found %d/%d=%.2f%% modules/classes/methods/functions with docstrings" % (docstring_cnt, cnt, percent*100) + self.index[index_type].value = index_value + self.index[index_type].details = details + return self.index[index_type] + + def index_pylint(self): + """ + Compute pylint index as average of positive pylint scores obtained for + the Python files identified in the package + + Return Index object of type "pylint" + """ + index_type = "pylint" + try: + import pylint + except ImportError, e: + self.index[index_type].details = "pylint not available" + return self.index[index_type] + index_pylint = 0 + cnt = 0 + for pyfile in self.pkg_files["py"]: + (path, filename) = os.path.split(pyfile) + (module, ext) = os.path.splitext(filename) + if module == "setup" or module == "ez_setup" or module.startswith("__"): + continue + fullpath = os.path.join(self.sandbox, pyfile) + self.log.debug("Running pylint on file " + fullpath) + p = Popen(["pylint", fullpath], stdout=PIPE, stderr=STDOUT) + output = p.communicate()[0] + rc = p.returncode + if rc: + # We encountered an error + continue + score_line = output.split("\n")[-3] + s = re.search(r" (\d+\.\d+)/10", score_line) + # We only take positive scores into account + if s: + score = s.group(1) + self.log.debug("pylint score for module %s: %s" % (module, score)) + if score == "0.00": + self.log.debug("Ignoring scores of 0.00") + continue + index_pylint += float(score) + cnt += 1 + avg_value = float(index_pylint)/float(cnt) + index_value = int(ceil(avg_value*10)) + self.index[index_type].value = index_value + self.index[index_type].details = "average score is %.2f out of 10" % avg_value + return self.index[index_type] + + def compute_cheesecake_index(self): + """ + Compute overall Cheesecake index for the package by adding up + specific indexes + """ + self.log.info("A given package can currently reach a MAXIMUM number of %d points" % self.max_cheesecake_index) + self.log.info("Starting computation of Cheesecake index for package '%s'" % (self.package)) + + index_types = [] + #if self.name: + # index_types.append("pypi_download") + index_types.append("pypi_download") + if self.url: + index_types.append("url_download") + index_types += ["unpack", "unpack_dir", "install"] + self.cheesecake_index_installability = self.process_partial_index("INSTALLABILITY",\ + index_types, self.max_cheesecake_index_installability) + + index_types = ["file", "dir", "docstrings"] + self.cheesecake_index_documentation = self.process_partial_index("DOCUMENTATION",\ + index_types, self.max_cheesecake_index_documentation) + + index_types = ["pylint"] + self.cheesecake_index_codekwalitee = self.process_partial_index("CODE KWALITEE",\ + index_types, self.max_cheesecake_index_codekwalitee) + + print + self.print_line("=" * (PAD_TEXT + PAD_VALUE + 1)) + print pad_msg("OVERALL CHEESECAKE INDEX (ABSOLUTE)", self.cheesecake_index) + percentage = (self.cheesecake_index * 100) / self.max_cheesecake_index + msg = pad_msg("OVERALL CHEESECAKE INDEX (RELATIVE)", percentage) + msg += " (%d out of a maximum of %d points is %d%%)" %\ + (self.cheesecake_index, self.max_cheesecake_index, percentage) + print msg + self.cleanup() + + return self.cheesecake_index + + def process_partial_index(self, partial_index_name, index_types, max_value): + print + self.log.info("Starting computation of %s index (max. points = %d)" % \ + (partial_index_name, max_value)) + partial_index_value = 0 + for index_type in index_types: + partial_index_value += self.process_index(index_type) + + self.print_line("-" * (PAD_TEXT + PAD_VALUE + 1)) + print pad_msg("%s INDEX (ABSOLUTE)" % partial_index_name, partial_index_value) + percentage = (partial_index_value * 100) / max_value + msg = pad_msg("%s INDEX (RELATIVE)" % partial_index_name, percentage) + msg += " (%d out of a maximum of %d points is %d%%)" %\ + (partial_index_value, max_value, percentage) + print msg + return partial_index_value + + def process_index(self, index_type): + """ + Compute and print index of specified type + """ + index = self.index[index_type] + index_method = "index_" + index_type + getattr(self, index_method)() + if not self.quiet: + index.print_info() + self.cheesecake_index += index.value + return index.value + + def print_line(self, line): + """ + Print line of text, unless quiet flag was given + """ + if self.quiet: + return + print line + + +class CodeParser(object): + """ + Information about the structure of a Python module + + * Collects classes, methods, functions and any associated docstrings + * Does some dumb grep-style parsing, but in the future may do some real smart parsing + """ + def __init__(self, pyfile, log=None): + if log: + self.log = log.codeparser + else: + self.log = logger.default.codeparser + self.classes = [] + self.methods = [] + self.functions = [] + self.docstrings = {} + self.object_at_page = {} + try: + self.fh = open(pyfile) + except IOError, e: + print str(e) + return + + (path, filename) = os.path.split(pyfile) + (self.module, ext) = os.path.splitext(filename) + self.log("Inspecting file: " + pyfile) + + self.parse_file() + self.log("classes: " + ",".join(self.classes)) + self.log("methods: " + ",".join(self.methods)) + self.log("functions: " + ",".join(self.functions)) + + def parse_file(self): + """ + Parse module text and retrieve classes, methods, functions + and associated docstrings + """ + cls_found = method_found = func_found = 0 + cls = method = func = "" + crt_line = 0 + for line in self.fh: + crt_line += 1 + if not self.object_at_page.has_key(crt_line-1): + s = re.search(r"\"\"\"", line) + if s: + self.docstrings[self.module] = 1 + s = re.search(r"^class (\S+)(\(|:)", line) + if s: + cls = s.group(1) + self.classes.append(cls) + self.object_at_page[crt_line] = cls + self.log("Found class " + cls) + continue + s = re.search(r"^\s+def (\S+)\(", line) + if s: + method = s.group(1) + if method.startswith("__"): + self.log("Skipping method " + method) + continue + self.methods.append(method) + self.object_at_page[crt_line] = method + self.log("Found method " + method) + continue + s = re.search(r"^def (\S+)\(", line) + if s: + func = s.group(1) + self.functions.append(func) + self.object_at_page[crt_line] = func + self.log("Found function " + func) + continue + s1 = re.search(r"\"\"\"", line) + s2 = re.search(r"\".*\S+.*\"", line) + if s1 or s2: + # LOok at object if any on previous line + obj1 = self.object_at_page.get(crt_line-1) + obj2 = None + if crt_line > 1: + # Look at object is any 2 lines before + obj2 = self.object_at_page.get(crt_line-2) + obj = obj1 or obj2 + if obj: + self.docstrings[obj] = 1 + self.log("Found docstring for object " + obj) + + def object_count(self): + """ + Return number of objects found in this module + + * module + * classes + * methods + * functions + """ + module_count = 1 + cls_count = len(self.classes) + method_count = len(self.methods) + func_count = len(self.functions) + return module_count + cls_count + method_count + func_count + + def docstring_count(self): + """ + Return number of docstrings found in this module + """ + return len(self.docstrings.keys()) + +class StdoutRedirector(object): + """ + Redirect stdout to a temp file + """ + + def __init__(self, filename=None): + if filename: + self.fh = open(filename, 'w') + else: + self.fh = os.tmpfile() + + def write(self, buf): + self.fh.write(buf) + + def flush(self): + self.fh.flush() + + def read_buffer(self): + """ + Return contents of the temp file + """ + self.fh.seek(0) + return self.fh.read() + +### Utility functions ### + +def pad_with_dots(msg, length=PAD_TEXT): + """ + Pad text with dots up to given length + """ + length = len(msg) + msg = msg + " " + for i in range(length, PAD_TEXT): + msg += "." + return msg + +def pad_left_spaces(value, length=PAD_VALUE): + """ + Pad value with spaces at left up to given length + """ + msg = "" + diff = length - len(str(value)) + for i in range(diff): + msg += " " + msg += str(value) + return msg + +def pad_msg(msg, value): + """ + Pad message with dots and pad value with spaces + """ + length = len(msg) + msg = msg + " " + for i in range(length, PAD_TEXT): + msg += "." + diff = PAD_VALUE - len(str(value)) + for i in range(diff): + msg += " " + msg += str(value) + return msg + +### End utility functions ### + +def process_cmdline_args(): + """ + Parse command-line options + """ + parser = OptionParser() + parser.add_option("-n", "--name", dest="name", + default="", help="package name (will be retrieved via setuptools utilities, if present)") + parser.add_option("-u", "--url", dest="url", + default="", help="package URL") + parser.add_option("-p", "--path", dest="path", + default="", help="package path on local file system") + parser.add_option("-s", "--sandbox", dest="sandbox", + default="/tmp/cheesecake_sandbox", + help="directory where package will be unpacked (default=/tmp/cheesecake_sandbox)") + parser.add_option("-v", "--verbose", action="store_true", dest="verbose", + default=False, help="verbose output (default=False)") + parser.add_option("-q", "--quiet", action="store_true", dest="quiet", + default=False, help="only print Cheesecake index value (default=False)") + + (options, args) = parser.parse_args() + return options + +def main(): + """ + Display Cheesecake index for package specified via command-line options + """ + options = process_cmdline_args() + name = options.name + url = options.url + path = options.path + sandbox = options.sandbox + verbose = options.verbose + quiet = options.quiet + + if not name and not url and not path: + print "Error: No package name, URL or path specified (see --help)" + sys.exit(1) + + try: + c = Cheesecake(name=name, url=url, path=path, sandbox=sandbox, verbose=verbose, quiet=quiet) + c.compute_cheesecake_index() + except CheesecakeError, e: + print str(e) + +if __name__ == "__main__": + main() Index: /trunk/LICENSE =================================================================== --- /trunk/LICENSE (revision 5) +++ /trunk/LICENSE (revision 5) @@ -0,0 +1,86 @@ +Cheesecake is licensed under the Python Software Foundation license, the same license that governs Python itself. Here is the text of the license, downloaded from : + +Python 2.1.1 license + +This is the official license for the Python 2.1.1 release: +A. HISTORY OF THE SOFTWARE +========================== + +Python was created in the early 1990s by Guido van Rossum at Stichting Mathematisch Centrum (CWI) in the Netherlands as a successor of a language called ABC. Guido is Python's principal author, although it includes many contributions from others. The last version released from CWI was Python 1.2. In 1995, Guido continued his work on Python at the Corporation for National Research Initiatives (CNRI) in Reston, Virginia where he released several versions of the software. Python 1.6 was the last of the versions released by CNRI. In 2000, Guido and the Python core development team moved to BeOpen.com to form the BeOpen PythonLabs team. Python 2.0 was the first and only release from BeOpen.com. + +Following the release of Python 1.6, and after Guido van Rossum left CNRI to work with commercial software developers, it became clear that the ability to use Python with software available under the GNU Public License (GPL) was very desirable. CNRI and the Free Software Foundation (FSF) interacted to develop enabling wording changes to the Python license. Python 1.6.1 is essentially the same as Python 1.6, with a few minor bug fixes, and with a different license that enables later versions to be GPL-compatible. Python 2.1 is a derivative work of Python 1.6.1, as well as of Python 2.0. + +After Python 2.0 was released by BeOpen.com, Guido van Rossum and the other PythonLabs developers joined Digital Creations. All intellectual property added from this point on, starting with Python 2.1 and its alpha and beta releases, is owned by the Python Software Foundation (PSF), a non-profit modeled after the Apache Software Foundation. See http://www.python.org/psf/ for more information about the PSF. + +Thanks to the many outside volunteers who have worked under Guido's direction to make these releases possible. + +B. TERMS AND CONDITIONS FOR ACCESSING OR OTHERWISE USING PYTHON +=============================================================== + +PSF LICENSE AGREEMENT +--------------------- + +1. This LICENSE AGREEMENT is between the Python Software Foundation ("PSF"), and the Individual or Organization ("Licensee") accessing and otherwise using Python 2.1.1 software in source or binary form and its associated documentation. + +2. Subject to the terms and conditions of this License Agreement, PSF hereby grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce, analyze, test, perform and/or display publicly, prepare derivative works, distribute, and otherwise use Python 2.1.1 alone or in any derivative version, provided, however, that PSF's License Agreement and PSF's notice of copyright, i.e., "Copyright (c) 2001 Python Software Foundation; All Rights Reserved" are retained in Python 2.1.1 alone or in any derivative version prepared by Licensee. + +3. In the event Licensee prepares a derivative work that is based on or incorporates Python 2.1.1 or any part thereof, and wants to make the derivative work available to others as provided herein, then Licensee hereby agrees to include in any such work a brief summary of the changes made to Python 2.1.1. + +4. PSF is making Python 2.1.1 available to Licensee on an "AS IS" basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 2.1.1 WILL NOT INFRINGE ANY THIRD PARTY RIGHTS. + +5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON 2.1.1 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 2.1.1, OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. + +6. This License Agreement will automatically terminate upon a material breach of its terms and conditions. + +7. Nothing in this License Agreement shall be deemed to create any relationship of agency, partnership, or joint venture between PSF and Licensee. This License Agreement does not grant permission to use PSF trademarks or trade name in a trademark sense to endorse or promote products or services of Licensee, or any third party. + +8. By copying, installing or otherwise using Python 2.1.1, Licensee agrees to be bound by the terms and conditions of this License Agreement. + +BEOPEN.COM TERMS AND CONDITIONS FOR PYTHON 2.0 +---------------------------------------------- + +BEOPEN PYTHON OPEN SOURCE LICENSE AGREEMENT VERSION 1 + +1. This LICENSE AGREEMENT is between BeOpen.com ("BeOpen"), having an office at 160 Saratoga Avenue, Santa Clara, CA 95051, and the Individual or Organization ("Licensee") accessing and otherwise using this software in source or binary form and its associated documentation ("the Software"). + +2. Subject to the terms and conditions of this BeOpen Python License Agreement, BeOpen hereby grants Licensee a non-exclusive, royalty-free, world-wide license to reproduce, analyze, test, perform and/or display publicly, prepare derivative works, distribute, and otherwise use the Software alone or in any derivative version, provided, however, that the BeOpen Python License is retained in the Software, alone or in any derivative version prepared by Licensee. + +3. BeOpen is making the Software available to Licensee on an "AS IS" basis. BEOPEN MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, BEOPEN MAKES NO AND DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE WILL NOT INFRINGE ANY THIRD PARTY RIGHTS. + +4. BEOPEN SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF THE SOFTWARE FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THE SOFTWARE, OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. + +5. This License Agreement will automatically terminate upon a material breach of its terms and conditions. + +6. This License Agreement shall be governed by and interpreted in all respects by the law of the State of California, excluding conflict of law provisions. Nothing in this License Agreement shall be deemed to create any relationship of agency, partnership, or joint venture between BeOpen and Licensee. This License Agreement does not grant permission to use BeOpen trademarks or trade names in a trademark sense to endorse or promote products or services of Licensee, or any third party. As an exception, the "BeOpen Python" logos available at http://www.pythonlabs.com/logos.html may be used according to the permissions granted on that web page. + +7. By copying, installing or otherwise using the software, Licensee agrees to be bound by the terms and conditions of this License Agreement. + +CNRI OPEN SOURCE GPL-COMPATIBLE LICENSE AGREEMENT +------------------------------------------------- + +1. This LICENSE AGREEMENT is between the Corporation for National Research Initiatives, having an office at 1895 Preston White Drive, Reston, VA 20191 ("CNRI"), and the Individual or Organization ("Licensee") accessing and otherwise using Python 1.6.1 software in source or binary form and its associated documentation. + +2. Subject to the terms and conditions of this License Agreement, CNRI hereby grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce, analyze, test, perform and/or display publicly, prepare derivative works, distribute, and otherwise use Python 1.6.1 alone or in any derivative version, provided, however, that CNRI's License Agreement and CNRI's notice of copyright, i.e., "Copyright (c) 1995-2001 Corporation for National Research Initiatives; All Rights Reserved" are retained in Python 1.6.1 alone or in any derivative version prepared by Licensee. Alternately, in lieu of CNRI's License Agreement, Licensee may substitute the following text (omitting the quotes): "Python 1.6.1 is made available subject to the terms and conditions in CNRI's License Agreement. This Agreement together with Python 1.6.1 may be located on the Internet using the following unique, persistent identifier (known as a handle): 1895.22/1013. This Agreement may also be obtained from a proxy server on the Internet using the following URL: http://hdl.handle.net/1895.22/1013". + +3. In the event Licensee prepares a derivative work that is based on or incorporates Python 1.6.1 or any part thereof, and wants to make the derivative work available to others as provided herein, then Licensee hereby agrees to include in any such work a brief summary of the changes made to Python 1.6.1. + +4. CNRI is making Python 1.6.1 available to Licensee on an "AS IS" basis. CNRI MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, CNRI MAKES NO AND DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 1.6.1 WILL NOT INFRINGE ANY THIRD PARTY RIGHTS. + +5. CNRI SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON 1.6.1 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 1.6.1, OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. + +6. This License Agreement will automatically terminate upon a material breach of its terms and conditions. + +7. This License Agreement shall be governed by the federal intellectual property law of the United States, including without limitation the federal copyright law, and, to the extent such U.S. federal law does not apply, by the law of the Commonwealth of Virginia, excluding Virginia's conflict of law provisions. Notwithstanding the foregoing, with regard to derivative works based on Python 1.6.1 that incorporate non-separable material that was previously distributed under the GNU General Public License (GPL), the law of the Commonwealth of Virginia shall govern this License Agreement only as to issues arising under or with respect to Paragraphs 4, 5, and 7 of this License Agreement. Nothing in this License Agreement shall be deemed to create any relationship of agency, partnership, or joint venture between CNRI and Licensee. This License Agreement does not grant permission to use CNRI trademarks or trade name in a trademark sense to endorse or promote products or services of Licensee, or any third party. + +8. By clicking on the "ACCEPT" button where indicated, or by copying, installing or otherwise using Python 1.6.1, Licensee agrees to be bound by the terms and conditions of this License Agreement. + + ACCEPT + +CWI PERMISSIONS STATEMENT AND DISCLAIMER +---------------------------------------- + +Copyright (c) 1991 - 1995, Stichting Mathematisch Centrum Amsterdam, The Netherlands. All rights reserved. + +Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the name of Stichting Mathematisch Centrum or CWI not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. + +STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. Index: /trunk/tests/test_init_cleanup.py =================================================================== --- /trunk/tests/test_init_cleanup.py (revision 2) +++ /trunk/tests/test_init_cleanup.py (revision 2) @@ -0,0 +1,34 @@ +import _path_cheesecake +from cheesecake.cheesecake_index import Cheesecake +import os +datadir = os.path.abspath(os.path.join(os.path.dirname(__file__), "data")) + +class TestInitCleanup: + + def test_init(self): + self.cheesecake = Cheesecake(path=os.path.join(datadir, "package1.tar.gz")) + self.logfile = os.path.join(self.cheesecake.sandbox, self.cheesecake.logfile) + assert os.path.isdir(self.cheesecake.sandbox_pkg_dir) + assert os.path.isfile(self.cheesecake.sandbox_pkg_file) + assert os.path.isfile(self.logfile) + + def test_cleanup(self): + self.cheesecake = Cheesecake(path=os.path.join(datadir, "package1.tar.gz")) + self.logfile = os.path.join(self.cheesecake.sandbox, self.cheesecake.logfile) + self.cheesecake.cleanup() + assert not os.path.exists(self.cheesecake.sandbox_pkg_dir) + assert not os.path.exists(self.cheesecake.sandbox_pkg_file) + # Log file should not have been deleted + assert os.path.isfile(self.logfile) + + def test_cleanup_after_install(self): + self.cheesecake = Cheesecake(path=os.path.join(datadir, "package1.tar.gz")) + self.cheesecake.index_install() + self.logfile = os.path.join(self.cheesecake.sandbox, self.cheesecake.logfile) + self.cheesecake.cleanup() + assert not os.path.exists(self.cheesecake.sandbox_pkg_dir) + assert not os.path.exists(self.cheesecake.sandbox_pkg_file) + assert not os.path.exists(self.cheesecake.sandbox_install_dir) + # Log file should not have been deleted + assert os.path.isfile(self.logfile) + Index: /trunk/tests/test_index_installability.py =================================================================== --- /trunk/tests/test_index_installability.py (revision 2) +++ /trunk/tests/test_index_installability.py (revision 2) @@ -0,0 +1,36 @@ +import _path_cheesecake +from cheesecake.cheesecake_index import Cheesecake, INDEX_PYPI_DOWNLOAD,\ + INDEX_URL_DOWNLOAD, INDEX_UNPACK, INDEX_UNPACK_DIR, INDEX_INSTALL +import os +datadir = os.path.abspath(os.path.join(os.path.dirname(__file__), "data")) + +class TestIndexInstallability: + + def setUp(self): + self.cheesecake = None + + def tearDown(self): + if not self.cheesecake: + return + self.cheesecake.cleanup() + os.unlink(self.cheesecake.logfile) + + def test_index_installability_local_path(self): + self.cheesecake = Cheesecake(path=os.path.join(datadir, "nose-0.8.3.tar.gz")) + assert self.cheesecake.max_cheesecake_index_installability == INDEX_PYPI_DOWNLOAD + \ + INDEX_UNPACK + INDEX_UNPACK_DIR + INDEX_INSTALL + index_types = ["pypi_download", "unpack", "unpack_dir", "install"] + cheesecake_index_installability = self.cheesecake.process_partial_index("INSTALLABILITY",\ + index_types, self.cheesecake.max_cheesecake_index_installability) + assert cheesecake_index_installability == INDEX_UNPACK + INDEX_UNPACK_DIR + INDEX_INSTALL + + def test_index_installability_url_download(self): + self.cheesecake = Cheesecake(url="http://www.agilistas.org/cheesecake/nose-0.8.3.tar.gz") + assert self.cheesecake.max_cheesecake_index_installability == INDEX_PYPI_DOWNLOAD + \ + INDEX_UNPACK + INDEX_UNPACK_DIR + INDEX_INSTALL + index_types = ["pypi_download", "url_download", "unpack", "unpack_dir", "install"] + cheesecake_index_installability = self.cheesecake.process_partial_index("INSTALLABILITY",\ + index_types, self.cheesecake.max_cheesecake_index_installability) + assert cheesecake_index_installability == INDEX_URL_DOWNLOAD + INDEX_UNPACK + INDEX_UNPACK_DIR + INDEX_INSTALL + + Index: /trunk/tests/_path_cheesecake.py =================================================================== --- /trunk/tests/_path_cheesecake.py (revision 2) +++ /trunk/tests/_path_cheesecake.py (revision 2) @@ -0,0 +1,4 @@ +import sys, os +testdir = os.path.dirname(__file__) +sys.path.insert(0, os.path.join(testdir, '../')) + Index: /trunk/tests/test_index_install.py =================================================================== --- /trunk/tests/test_index_install.py (revision 2) +++ /trunk/tests/test_index_install.py (revision 2) @@ -0,0 +1,29 @@ +import _path_cheesecake +from cheesecake.cheesecake_index import Cheesecake, INDEX_INSTALL +import os +datadir = os.path.abspath(os.path.join(os.path.dirname(__file__), "data")) + +class TestIndexInstall: + + def setUp(self): + self.cheesecake = None + + def tearDown(self): + if not self.cheesecake: + return + self.cheesecake.cleanup() + os.unlink(self.cheesecake.logfile) + + def test_index_install_correct_package(self): + self.cheesecake = Cheesecake(path=os.path.join(datadir, "nose-0.8.3.tar.gz")) + index = self.cheesecake.index_install() + assert index.name == "index_install" + assert index.value == INDEX_INSTALL + assert index.details == "package installed in " + self.cheesecake.sandbox_install_dir + + def test_index_install_incorrect_package(self): + self.cheesecake = Cheesecake(path=os.path.join(datadir, "package1.tar.gz")) + index = self.cheesecake.index_install() + assert index.name == "index_install" + assert index.value == 0 + assert index.details == "could not install package in " + self.cheesecake.sandbox_install_dir Index: /trunk/tests/test_index_url_download.py =================================================================== --- /trunk/tests/test_index_url_download.py (revision 2) +++ /trunk/tests/test_index_url_download.py (revision 2) @@ -0,0 +1,39 @@ +import _path_cheesecake +from cheesecake.cheesecake_index import Cheesecake, CheesecakeError, INDEX_URL_DOWNLOAD, pad_msg + +import os +datadir = os.path.abspath(os.path.join(os.path.dirname(__file__), "data")) + +class TestIndexInstallability: + + def setUp(self): + self.cheesecake = None + + def tearDown(self): + if not self.cheesecake: + return + self.cheesecake.cleanup() + os.unlink(self.cheesecake.logfile) + + def test_index_url_download_valid_url(self): + try: + self.cheesecake = Cheesecake(url="http://www.agilistas.org/cheesecake/nose-0.8.3.tar.gz") + index = self.cheesecake.index_url_download() + assert index.name == "index_url_download" + assert index.value == INDEX_URL_DOWNLOAD + assert index.details == "downloaded package " + self.cheesecake.package + " from URL " + self.cheesecake.url + except CheesecakeError, e: + # it's OK if we get "connection refused" sometimes + msg = "[Errno socket error] (111, 'Connection refused')" + msg += pad_msg("CHEESECAKE INDEX", 0) + if str(e) == msg: + pass + + def test_index_url_download_invalid_url(self): + try: + self.cheesecake = Cheesecake(url="http://www.agilistas.org/cheesecake/not_there.tar.gz") + assert 0 # This statement should not be reached + except CheesecakeError, e: + msg = "Could not read tar file /tmp/cheesecake_sandbox/not_there.tar.gz ... exiting\n" + msg += pad_msg("CHEESECAKE INDEX", 0) + assert str(e) == msg Index: /trunk/tests/data/invalid_package.zip =================================================================== --- /trunk/tests/data/invalid_package.zip (revision 2) +++ /trunk/tests/data/invalid_package.zip (revision 2) @@ -0,0 +1,67 @@ +""" +Docstring for module1 +""" + +class Class1: + """ + Docstring for Class1 + """ + + def __init__(self): + """ + Methods starting with __ should be skipped + """ + pass + + def __another_method__(self): + """Should also be skipped""" + pass + + def method1(self): + """Docstring for method1""" + pass + + def method2(self): + "Docstring for method2" + pass + + def method3(self): + """ + Docstring for method3 + """ + pass + + def method4(self): + # No docstring + pass + +class Class2: + + """ + Docstring one line apart from Class2 + """ + pass + +def func1(): + """Docstring for func1""" + return + +def func2(): + "Docstring for func2" + return + +def func3(): + """ + Docstring for func3 + """ + return + +def func4(): + # No docstring + return + +def __func5__(self): + """ + Functions starting with __ are not skipped + """ + return Index: /trunk/tests/data/invalid_package.tgz =================================================================== --- /trunk/tests/data/invalid_package.tgz (revision 2) +++ /trunk/tests/data/invalid_package.tgz (revision 2) @@ -0,0 +1,67 @@ +""" +Docstring for module1 +""" + +class Class1: + """ + Docstring for Class1 + """ + + def __init__(self): + """ + Methods starting with __ should be skipped + """ + pass + + def __another_method__(self): + """Should also be skipped""" + pass + + def method1(self): + """Docstring for method1""" + pass + + def method2(self): + "Docstring for method2" + pass + + def method3(self): + """ + Docstring for method3 + """ + pass + + def method4(self): + # No docstring + pass + +class Class2: + + """ + Docstring one line apart from Class2 + """ + pass + +def func1(): + """Docstring for func1""" + return + +def func2(): + "Docstring for func2" + return + +def func3(): + """ + Docstring for func3 + """ + return + +def func4(): + # No docstring + return + +def __func5__(self): + """ + Functions starting with __ are not skipped + """ + return Index: /trunk/tests/data/invalid_package.tar.gz =================================================================== --- /trunk/tests/data/invalid_package.tar.gz (revision 2) +++ /trunk/tests/data/invalid_package.tar.gz (revision 2) @@ -0,0 +1,67 @@ +""" +Docstring for module1 +""" + +class Class1: + """ + Docstring for Class1 + """ + + def __init__(self): + """ + Methods starting with __ should be skipped + """ + pass + + def __another_method__(self): + """Should also be skipped""" + pass + + def method1(self): + """Docstring for method1""" + pass + + def method2(self): + "Docstring for method2" + pass + + def method3(self): + """ + Docstring for method3 + """ + pass + + def method4(self): + # No docstring + pass + +class Class2: + + """ + Docstring one line apart from Class2 + """ + pass + +def func1(): + """Docstring for func1""" + return + +def func2(): + "Docstring for func2" + return + +def func3(): + """ + Docstring for func3 + """ + return + +def func4(): + # No docstring + return + +def __func5__(self): + """ + Functions starting with __ are not skipped + """ + return Index: /trunk/tests/data/module1.py =================================================================== --- /trunk/tests/data/module1.py (revision 2) +++ /trunk/tests/data/module1.py (revision 2) @@ -0,0 +1,67 @@ +""" +Docstring for module1 +""" + +class Class1: + """ + Docstring for Class1 + """ + + def __init__(self): + """ + Methods starting with __ should be skipped + """ + pass + + def __another_method__(self): + """Should also be skipped""" + pass + + def method1(self): + """Docstring for method1""" + pass + + def method2(self): + "Docstring for method2" + pass + + def method3(self): + """ + Docstring for method3 + """ + pass + + def method4(self): + # No docstring + pass + +class Class2: + + """ + Docstring one line apart from Class2 + """ + pass + +def func1(): + """Docstring for func1""" + return + +def func2(): + "Docstring for func2" + return + +def func3(): + """ + Docstring for func3 + """ + return + +def func4(): + # No docstring + return + +def __func5__(self): + """ + Functions starting with __ are not skipped + """ + return Index: /trunk/tests/test_code_parser.py =================================================================== --- /trunk/tests/test_code_parser.py (revision 2) +++ /trunk/tests/test_code_parser.py (revision 2) @@ -0,0 +1,32 @@ +import _path_cheesecake +from cheesecake.cheesecake_index import CodeParser +import os +datadir = os.path.abspath(os.path.join(os.path.dirname(__file__), "data")) + +class TestCodeParser: + def setUp(self): + self.code1 = CodeParser(os.path.join(datadir, "module1.py")) + + def test_classes(self): + assert self.code1.classes == ["Class1", "Class2"] + + def test_methods(self): + assert self.code1.methods == ["method1", "method2", "method3", "method4"] + + def test_functions(self): + assert self.code1.functions == ["func1", "func2", "func3", "func4", "__func5__"] + + def test_count(self): + assert self.code1.object_count() == 12 + assert self.code1.docstring_count() == 10 + + def test_docstrings(self): + assert self.code1.docstrings.get("module1") == 1 + for object in ["Class1", "Class2"]: + assert self.code1.docstrings.get(object) == 1 + for object in ["method1", "method2", "method3"]: + assert self.code1.docstrings.get(object) == 1 + assert not self.code1.docstrings.get("method4") + for object in ["func1", "func2", "func3", "__func5__"]: + assert self.code1.docstrings.get(object) == 1 + assert not self.code1.docstrings.get("func4") Index: /trunk/tests/test_index_docstrings.py =================================================================== --- /trunk/tests/test_index_docstrings.py (revision 2) +++ /trunk/tests/test_index_docstrings.py (revision 2) @@ -0,0 +1,22 @@ +import _path_cheesecake +from cheesecake.cheesecake_index import Cheesecake, CodeParser +import os +from math import ceil +datadir = os.path.abspath(os.path.join(os.path.dirname(__file__), "data")) + +class TestIndexDocstrings: + def setUp(self): + self.cheesecake = Cheesecake(path=os.path.join(datadir, "package1.tar.gz")) + self.code = CodeParser(os.path.join(self.cheesecake.sandbox, "package1/module1.py")) + self.index_float = float(self.code.docstring_count()) / float(self.code.object_count()) + self.index_int = int(ceil(self.index_float*100)) + + def tearDown(self): + self.cheesecake.cleanup() + + def test_index_docstrings(self): + index = self.cheesecake.index_docstrings() + assert index.name == "index_docstrings" + assert index.value == self.index_int + assert index.details == "found %d/%d=%.2f%% modules/classes/methods/functions with docstrings" %\ + (self.code.docstring_count(), self.code.object_count(), self.index_float*100) Index: /trunk/tests/test_index_unpack_dir.py =================================================================== --- /trunk/tests/test_index_unpack_dir.py (revision 2) +++ /trunk/tests/test_index_unpack_dir.py (revision 2) @@ -0,0 +1,29 @@ +import _path_cheesecake +from cheesecake.cheesecake_index import Cheesecake, INDEX_UNPACK_DIR +import os +datadir = os.path.abspath(os.path.join(os.path.dirname(__file__), "data")) + +class TestIndexUnpackDir: + + def setUp(self): + self.cheesecake = None + + def tearDown(self): + if not self.cheesecake: + return + self.cheesecake.cleanup() + os.unlink(self.cheesecake.logfile) + + def test_index_unpack_dir_correct_package(self): + self.cheesecake = Cheesecake(path=os.path.join(datadir, "package1.tar.gz")) + index = self.cheesecake.index_unpack_dir() + assert index.name == "index_unpack_dir" + assert index.value == INDEX_UNPACK_DIR + assert index.details == "unpack directory is " + self.cheesecake.package_name + " as expected" + + def test_index_unpack_dir_incorrect_package(self): + self.cheesecake = Cheesecake(path=os.path.join(datadir, "package_renamed.tar.gz")) + index = self.cheesecake.index_unpack_dir() + assert index.name == "index_unpack_dir" + assert index.value == 0 + assert index.details == "unpack directory is package1 instead of the expected package_renamed" Index: /trunk/tests/test_index_unpack.py =================================================================== --- /trunk/tests/test_index_unpack.py (revision 2) +++ /trunk/tests/test_index_unpack.py (revision 2) @@ -0,0 +1,63 @@ +import _path_cheesecake +from cheesecake.cheesecake_index import Cheesecake, CheesecakeError, INDEX_UNPACK, pad_msg +import os +datadir = os.path.abspath(os.path.join(os.path.dirname(__file__), "data")) + +class TestIndexUnpack: + + def setUp(self): + self.cheesecake = None + + def tearDown(self): + if not self.cheesecake: + return + self.cheesecake.cleanup() + os.unlink(self.cheesecake.logfile) + + def test_index_unpack_valid_tar_gz(self): + self.cheesecake = Cheesecake(path=os.path.join(datadir, "package1.tar.gz")) + index = self.cheesecake.index_unpack() + assert index.name == "index_unpack" + assert index.value == INDEX_UNPACK + assert index.details == "package untar-ed successfully" + + def test_index_unpack_valid_tgz(self): + self.cheesecake = Cheesecake(path=os.path.join(datadir, "package1.tgz")) + index = self.cheesecake.index_unpack() + assert index.name == "index_unpack" + assert index.value == INDEX_UNPACK + assert index.details == "package untar-ed successfully" + + def test_index_unpack_valid_zip(self): + self.cheesecake = Cheesecake(path=os.path.join(datadir, "package1.zip")) + index = self.cheesecake.index_unpack() + assert index.name == "index_unpack" + assert index.value == INDEX_UNPACK + assert index.details == "package unzipped successfully" + + def test_index_unpack_invalid_tar_gz(self): + try: + self.cheesecake = Cheesecake(path=os.path.join(datadir, "invalid_package.tar.gz")) + assert 0 # This statement should not be reached + except CheesecakeError, e: + msg = "Could not read tar file /tmp/cheesecake_sandbox/invalid_package.tar.gz ... exiting\n" + msg += pad_msg("CHEESECAKE INDEX", 0) + assert str(e) == msg + + def test_index_unpack_invalid_tgz(self): + try: + self.cheesecake = Cheesecake(path=os.path.join(datadir, "invalid_package.tgz")) + assert 0 # This statement should not be reached + except CheesecakeError, e: + msg = "Could not read tar file /tmp/cheesecake_sandbox/invalid_package.tgz ... exiting\n" + msg += pad_msg("CHEESECAKE INDEX", 0) + assert str(e) == msg + + def test_index_unpack_invalid_zip(self): + try: + self.cheesecake = Cheesecake(path=os.path.join(datadir, "invalid_package.zip")) + assert 0 # This statement should not be reached + except CheesecakeError, e: + msg = "Error unzipping file /tmp/cheesecake_sandbox/invalid_package.zip ... exiting\n" + msg += pad_msg("CHEESECAKE INDEX", 0) + assert str(e) == msg Index: /trunk/cheesecake_index =================================================================== --- /trunk/cheesecake_index (revision 5) +++ /trunk/cheesecake_index (revision 5) @@ -0,0 +1,5 @@ +#!/usr/bin/env python + +from cheesecake.cheesecake_index import main + +main() Index: /trunk/setup.py =================================================================== --- /trunk/setup.py (revision 5) +++ /trunk/setup.py (revision 5) @@ -0,0 +1,25 @@ +#! /usr/bin/env python +import sys +import os.path + +from setuptools import setup +from pkg_resources import require + +setup( + name = 'Cheesecake', + version = '0.1', + + # metadata for upload to PyPI + author = "Grig Gheorghiu", + author_email = "grig@gheorghiu.net", + description = 'Computes "goodness" index for Python packages based on various empirical "kwalitee" factors', + license = "PSF", + keywords = "cheesecake quality index kwalitee cheeseshop pypi", + url = "http://tracos.org/cheesecake", + + packages = ['cheesecake', + ], + scripts = ['cheesecake_index', + ], + test_suite = 'nose.collector', + ) Index: /trunk/docs/epydoc.css =================================================================== --- /trunk/docs/epydoc.css (revision 2) +++ /trunk/docs/epydoc.css (revision 2) @@ -0,0 +1,100 @@ + +/* Body color */ +body { background: #ffffff; color: #000000; } + +/* Tables */ +table.summary, table.details, table.index + { background: #e8f0f8; color: #000000; } +tr.summary, tr.details, tr.index + { background: #70b0f0; color: #000000; + text-align: left; font-size: 120%; } +tr.group { background: #c0e0f8; color: #000000; + text-align: left; font-size: 120%; + font-style: italic; } + +/* Documentation page titles */ +h2.module { margin-top: 0.2em; } +h2.class { margin-top: 0.2em; } + +/* Headings */ +h1.heading { font-size: +140%; font-style: italic; + font-weight: bold; } +h2.heading { font-size: +125%; font-style: italic; + font-weight: bold; } +h3.heading { font-size: +110%; font-style: italic; + font-weight: normal; } + +/* Base tree */ +pre.base-tree { font-size: 80%; margin: 0; } + +/* Details Sections */ +table.func-details { background: #e8f0f8; color: #000000; + border: 2px groove #c0d0d0; + padding: 0 1em 0 1em; margin: 0.4em 0 0 0; } +h3.func-detail { background: transparent; color: #000000; + margin: 0 0 1em 0; } + +table.var-details { background: #e8f0f8; color: #000000; + border: 2px groove #c0d0d0; + padding: 0 1em 0 1em; margin: 0.4em 0 0 0; } +h3.var-details { background: transparent; color: #000000; + margin: 0 0 1em 0; } + +/* Function signatures */ +.sig { background: transparent; color: #000000; + font-weight: bold; } +.sig-name { background: transparent; color: #006080; } +.sig-arg, .sig-kwarg, .sig-vararg + { background: transparent; color: #008060; } +.sig-default { background: transparent; color: #602000; } +.summary-sig { background: transparent; color: #000000; } +.summary-sig-name { background: transparent; color: #204080; } +.summary-sig-arg, .summary-sig-kwarg, .summary-sig-vararg + { background: transparent; color: #008060; } + +/* Doctest blocks */ +.py-src { background: transparent; color: #000000; } +.py-prompt { background: transparent; color: #005050; + font-weight: bold;} +.py-string { background: transparent; color: #006030; } +.py-comment { background: transparent; color: #003060; } +.py-keyword { background: transparent; color: #600000; } +.py-output { background: transparent; color: #404040; } +pre.doctestblock { background: #f4faff; color: #000000; + padding: .5em; margin: 1em; + border: 1px solid #708890; } +table pre.doctestblock + { background: #dce4ec; color: #000000; + padding: .5em; margin: 1em; + border: 1px solid #708890; } + +/* Variable values */ +pre.variable { background: #dce4ec; color: #000000; + padding: .5em; margin: 0; + border: 1px solid #708890; } +.variable-linewrap { background: transparent; color: #604000; } +.variable-ellipsis { background: transparent; color: #604000; } +.variable-quote { background: transparent; color: #604000; } +.re { background: transparent; color: #000000; } +.re-char { background: transparent; color: #006030; } +.re-op { background: transparent; color: #600000; } +.re-group { background: transparent; color: #003060; } +.re-ref { background: transparent; color: #404040; } + +/* Navigation bar */ +table.navbar { background: #a0c0ff; color: #0000ff; + border: 2px groove #c0d0d0; } +th.navbar { background: #a0c0ff; color: #0000ff; } +th.navselect { background: #70b0ff; color: #000000; } +.nomargin { margin: 0; } + +/* Links */ +a:link { background: transparent; color: #0000ff; } +a:visited { background: transparent; color: #204080; } +a.navbar:link { background: transparent; color: #0000ff; + text-decoration: none; } +a.navbar:visited { background: transparent; color: #204080; + text-decoration: none; } + +/* Lists */ +ul { margin-top: 0; } Index: /trunk/docs/index.html =================================================================== --- /trunk/docs/index.html (revision 2) +++ /trunk/docs/index.html (revision 2) @@ -0,0 +1,13 @@ + + + + cheesecake + + + + + + + + + Index: /trunk/docs/private/cheesecake.CheesecakeError-class.html =================================================================== --- /trunk/docs/private/cheesecake.CheesecakeError-class.html (revision 2) +++ /trunk/docs/private/cheesecake.CheesecakeError-class.html (revision 2) @@ -0,0 +1,98 @@ + + + + + cheesecake.CheesecakeError + + + + + + + + + + + + + + + + + +
+ + Module cheesecake :: + Class CheesecakeError +
+
+ + +
[show private | hide private]
[frames | no frames]
+ + +

Class CheesecakeError

+ +
+Exception --+
+            |
+           CheesecakeError
+

+ +
+ +

Custom exception class for Cheesecake-specific errors

+
+ + + + + + + + + + + + + + +
Method Summary
    Inherited from Exception
 __init__(...) +
 __getitem__(...) +
 __str__(...) +

+ + + + + + + + + + + + + + + + + +
Generated by Epydoc 2.1 on Wed Nov 16 09:59:23 2005http://epydoc.sf.net
+ + Index: /trunk/docs/private/cheesecake.CompositeIndex-class.html =================================================================== --- /trunk/docs/private/cheesecake.CompositeIndex-class.html (revision 2) +++ /trunk/docs/private/cheesecake.CompositeIndex-class.html (revision 2) @@ -0,0 +1,228 @@ + + + + + cheesecake.CompositeIndex + + + + + + + + + + + + + + + + + +
+ + Module cheesecake :: + Class CompositeIndex +
+
+ + +
[show private | hide private]
[frames | no frames]
+ + +

Type CompositeIndex

+ +
+object --+
+         |
+        CompositeIndex
+

+ +
+ +

Collection of indexes of same type (e.g. files, dirs)

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Method Summary
 __init__(self, + type) +
+Indexes is a dict mapping names to Index objects
 get_value(self) +
+Return sum of individual index values
 print_info(self) +
+Print index info for all indexes sorted alphanumerically by name
 set_index(self, + name, + value, + details) +
+Create new index or update existing index with specified attributes
    Inherited from object
 __delattr__(...) +
+x.__delattr__('name') <==> del x.name
 __getattribute__(...) +
+x.__getattribute__('name') <==> x.name
 __hash__(x) +
+x.__hash__() <==> hash(x)
 __new__(T, + S, + ...) +
+T.__new__(S, ...) -> a new object with type S, a subtype of T
 __reduce__(...) +
+helper for pickle
 __reduce_ex__(...) +
+helper for pickle
 __repr__(x) +
+x.__repr__() <==> repr(x)
 __setattr__(...) +
+x.__setattr__('name', value) <==> x.name = value
 __str__(x) +
+x.__str__() <==> str(x)

+ + + + + + + +
Property Summary
 value

+ + + + + + +
Method Details
+ + +
+

__init__(self, + type) +
(Constructor) +

+

Indexes is a dict mapping names to Index objects

+
+
Overrides:
+
__builtin__.object.__init__
+
+
+
+ + +
+

get_value(self) +

+

Return sum of individual index values

+
+
+
+ + +
+

print_info(self) +

+

Print index info for all indexes sorted alphanumerically by name

+
+
+
+ + +
+

set_index(self, + name, + value=0, + details='') +

+

Create new index or update existing index with specified attributes

+
+
+
+
+ + + + + + +
Property Details
+
+ + +

value

+
+
+
+
+
Get Method:
+
get_value(self) +
+
+
+

+ + + + + + + + + + + + + + + + + +
Generated by Epydoc 2.1 on Wed Nov 16 09:59:23 2005http://epydoc.sf.net
+ + Index: /trunk/docs/private/logger.Path-class.html =================================================================== --- /trunk/docs/private/logger.Path-class.html (revision 2) +++ /trunk/docs/private/logger.Path-class.html (revision 2) @@ -0,0 +1,137 @@ + + + + + logger.Path + + + + + + + + + + + + + + + + + +
+ + Module logger :: + Class Path +
+
+ + +
[show private | hide private]
[frames | no frames]
+ + +

Type Path

+ +
+object --+    
+         |    
+      File --+
+             |
+            Path
+

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Method Summary
 __init__(self, + filename, + append) +
    Inherited from File
 __call__(self, + msg) +
    Inherited from object
 __delattr__(...) +
+x.__delattr__('name') <==> del x.name
 __getattribute__(...) +
+x.__getattribute__('name') <==> x.name
 __hash__(x) +
+x.__hash__() <==> hash(x)
 __new__(T, + S, + ...) +
+T.__new__(S, ...) -> a new object with type S, a subtype of T
 __reduce__(...) +
+helper for pickle
 __reduce_ex__(...) +
+helper for pickle
 __repr__(x) +
+x.__repr__() <==> repr(x)
 __setattr__(...) +
+x.__setattr__('name', value) <==> x.name = value
 __str__(x) +
+x.__str__() <==> str(x)

+ + + + + + + + + + + + + + + + + +
Generated by Epydoc 2.1 on Wed Nov 16 09:59:23 2005http://epydoc.sf.net
+ + Index: /trunk/docs/private/frames.html =================================================================== --- /trunk/docs/private/frames.html (revision 2) +++ /trunk/docs/private/frames.html (revision 2) @@ -0,0 +1,13 @@ + + + + cheesecake + + + + + + + + + Index: /trunk/docs/private/indices.html =================================================================== --- /trunk/docs/private/indices.html (revision 2) +++ /trunk/docs/private/indices.html (revision 2) @@ -0,0 +1,289 @@ + + + + + Index + + + + + + + + + + + + + + + + + + +
+ + + +
[show private | hide private]
[frames | no frames]
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Identifier Index
objectClass in module __builtin__
__bases__Variable in class __builtin__.type
__basicsize__Variable in class __builtin__.type
__call__Method in class __builtin__.type
typeClass in module __builtin__
__cmp__Method in class __builtin__.type
__delattr__Method in class __builtin__.object
__delattr__Method in class __builtin__.type
__dictoffset__Variable in class __builtin__.type
__flags__Variable in class __builtin__.type
__getattribute__Method in class __builtin__.object
__getattribute__Method in class __builtin__.type
__getitem__Method in class exceptions.Exception
__hash__Method in class __builtin__.object
__hash__Method in class __builtin__.type
__init__Method in class __builtin__.object
__init__Method in class cheesecake.cheesecake_index.Cheesecake
__init__Method in class cheesecake.cheesecake_index.CodeParser
__init__Method in class cheesecake.cheesecake_index.CompositeIndex
__init__Method in class cheesecake.cheesecake_index.Index
__init__Method in class cheesecake.cheesecake_index.StdoutRedirector
__init__Method in class exceptions.Exception
__itemsize__Variable in class __builtin__.type
__mro__Variable in class __builtin__.type
__name__Variable in class __builtin__.type
__new__Method in class __builtin__.object
__new__Method in class __builtin__.type
__reduce__Method in class __builtin__.object
__reduce_ex__Method in class __builtin__.object
__repr__Method in class __builtin__.object
__repr__Method in class __builtin__.type
__setattr__Method in class __builtin__.object
__setattr__Method in class __builtin__.type
__str__Method in class __builtin__.object
__str__Method in class exceptions.Exception
__subclasses__Method in class __builtin__.type
__weakrefoffset__Variable in class __builtin__.type
CheesecakeClass in module cheesecake.cheesecake_index
cheesecake_indexModule in package cheesecake
CheesecakeErrorClass in module cheesecake.cheesecake_index
cleanupMethod in class cheesecake.cheesecake_index.Cheesecake
CodeParserClass in module cheesecake.cheesecake_index
CompositeIndexClass in module cheesecake.cheesecake_index
compute_cheesecake_indexMethod in class cheesecake.cheesecake_index.Cheesecake
configure_loggingMethod in class cheesecake.cheesecake_index.Cheesecake
copy_pkgMethod in class cheesecake.cheesecake_index.Cheesecake
determine_pkg_nameMethod in class cheesecake.cheesecake_index.Cheesecake
docstring_countMethod in class cheesecake.cheesecake_index.CodeParser
download_pkgMethod in class cheesecake.cheesecake_index.Cheesecake
ExceptionClass in module exceptions
flushMethod in class cheesecake.cheesecake_index.StdoutRedirector
get_package_from_pathMethod in class cheesecake.cheesecake_index.Cheesecake
get_package_from_urlMethod in class cheesecake.cheesecake_index.Cheesecake
get_pkg_from_pypiMethod in class cheesecake.cheesecake_index.Cheesecake
get_valueMethod in class cheesecake.cheesecake_index.CompositeIndex
IndexClass in module cheesecake.cheesecake_index
index_dirMethod in class cheesecake.cheesecake_index.Cheesecake
INDEX_DIRVariable in module cheesecake.cheesecake_index
INDEX_DIR_CRITICALVariable in module cheesecake.cheesecake_index
INDEX_DIR_EMPTYVariable in module cheesecake.cheesecake_index
index_docstringsMethod in class cheesecake.cheesecake_index.Cheesecake
index_fileMethod in class cheesecake.cheesecake_index.Cheesecake
INDEX_FILEVariable in module cheesecake.cheesecake_index
INDEX_FILE_CRITICALVariable in module cheesecake.cheesecake_index
INDEX_FILE_PYCVariable in module cheesecake.cheesecake_index
index_installMethod in class cheesecake.cheesecake_index.Cheesecake
INDEX_INSTALLVariable in module cheesecake.cheesecake_index
index_pylintMethod in class cheesecake.cheesecake_index.Cheesecake
INDEX_PYPI_DISTANCEVariable in module cheesecake.cheesecake_index
index_pypi_downloadMethod in class cheesecake.cheesecake_index.Cheesecake
INDEX_PYPI_DOWNLOADVariable in module cheesecake.cheesecake_index
INDEX_REQUIRED_FILESVariable in module cheesecake.cheesecake_index
index_unpackMethod in class cheesecake.cheesecake_index.Cheesecake
INDEX_UNPACKVariable in module cheesecake.cheesecake_index
index_unpack_dirMethod in class cheesecake.cheesecake_index.Cheesecake
INDEX_UNPACK_DIRVariable in module cheesecake.cheesecake_index
index_url_downloadMethod in class cheesecake.cheesecake_index.Cheesecake
INDEX_URL_DOWNLOADVariable in module cheesecake.cheesecake_index
init_indexesMethod in class cheesecake.cheesecake_index.Cheesecake
is_py_fileMethod in class cheesecake.cheesecake_index.Cheesecake
is_test_fileMethod in class cheesecake.cheesecake_index.Cheesecake
mainFunction in module cheesecake.cheesecake_index
mroMethod in class __builtin__.type
objectClass in module __builtin__
object_countMethod in class cheesecake.cheesecake_index.CodeParser
pad_left_spacesFunction in module cheesecake.cheesecake_index
pad_msgFunction in module cheesecake.cheesecake_index
PAD_TEXTVariable in module cheesecake.cheesecake_index
PAD_VALUEVariable in module cheesecake.cheesecake_index
pad_with_dotsFunction in module cheesecake.cheesecake_index
parse_fileMethod in class cheesecake.cheesecake_index.CodeParser
print_infoMethod in class cheesecake.cheesecake_index.CompositeIndex
print_infoMethod in class cheesecake.cheesecake_index.Index
print_lineMethod in class cheesecake.cheesecake_index.Cheesecake
process_cmdline_argsFunction in module cheesecake.cheesecake_index
process_indexMethod in class cheesecake.cheesecake_index.Cheesecake
process_partial_indexMethod in class cheesecake.cheesecake_index.Cheesecake
raise_exceptionMethod in class cheesecake.cheesecake_index.Cheesecake
read_bufferMethod in class cheesecake.cheesecake_index.StdoutRedirector
retrieve_pkgMethod in class cheesecake.cheesecake_index.Cheesecake
set_indexMethod in class cheesecake.cheesecake_index.CompositeIndex
StdoutRedirectorClass in module cheesecake.cheesecake_index
typeClass in module __builtin__
unpack_pkgMethod in class cheesecake.cheesecake_index.Cheesecake
untar_pkgMethod in class cheesecake.cheesecake_index.Cheesecake
unzip_pkgMethod in class cheesecake.cheesecake_index.Cheesecake
valueMethod in class cheesecake.cheesecake_index.Cheesecake in class cheesecake.cheesecake_index.CompositeIndex
walk_pkgMethod in class cheesecake.cheesecake_index.Cheesecake
writeMethod in class cheesecake.cheesecake_index.StdoutRedirector
+
+ + + + + + + + + + + + + + + + + +
Generated by Epydoc 2.1 on Wed Dec 21 17:21:41 2005http://epydoc.sf.net
+ + Index: /trunk/docs/private/cheesecake.cheesecake_index.CodeParser-class.html =================================================================== --- /trunk/docs/private/cheesecake.cheesecake_index.CodeParser-class.html (revision 2) +++ /trunk/docs/private/cheesecake.cheesecake_index.CodeParser-class.html (revision 2) @@ -0,0 +1,188 @@ + + + + + cheesecake.cheesecake_index.CodeParser + + + + + + + + + + + + + + + + + + +
+ + Package cheesecake :: + Module cheesecake_index :: + Class CodeParser +
+
+ + +
[show private | hide private]
[frames | no frames]
+ + +

Type CodeParser

+ +
+object --+
+         |
+        CodeParser
+

+ +
+ +

Information about the structure of a Python module

+* Collects classes, methods, functions and any associated docstrings * +Does some dumb grep-style parsing, but in the future may do some real +smart parsing +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Method Summary
 __init__(self, + pyfile, + log) +
 docstring_count(self) +
+Return number of docstrings found in this module
 object_count(self) +
+Return number of objects found in this module
 parse_file(self) +
+Parse module text and retrieve classes, methods, functions and +associated docstrings
    Inherited from object
 __delattr__(...) +
+x.__delattr__('name') <==> del x.name
 __getattribute__(...) +
+x.__getattribute__('name') <==> x.name
 __hash__(x) +
+x.__hash__() <==> hash(x)
 __new__(T, + S, + ...) +
+T.__new__(S, ...) -> a new object with type S, a subtype of T
 __reduce__(...) +
+helper for pickle
 __reduce_ex__(...) +
+helper for pickle
 __repr__(x) +
+x.__repr__() <==> repr(x)
 __setattr__(...) +
+x.__setattr__('name', value) <==> x.name = value
 __str__(x) +
+x.__str__() <==> str(x)

+ + + + + + +
Method Details
+ + +
+

docstring_count(self) +

+ Return number of docstrings found in this module +
+
+
+ + +
+

object_count(self) +

+

Return number of objects found in this module

+ * module * classes * methods * functions +
+
+
+ + +
+

parse_file(self) +

+ Parse module text and retrieve classes, methods, functions and + associated docstrings +
+
+
+
+ + + + + + + + + + + + + + + + + + +
Generated by Epydoc 2.1 on Wed Dec 21 17:21:41 2005http://epydoc.sf.net
+ + Index: /trunk/docs/private/logger.MultipleProducer-class.html =================================================================== --- /trunk/docs/private/logger.MultipleProducer-class.html (revision 2) +++ /trunk/docs/private/logger.MultipleProducer-class.html (revision 2) @@ -0,0 +1,156 @@ + + + + + logger.MultipleProducer + + + + + + + + + + + + + + + + + +
+ + Module logger :: + Class MultipleProducer +
+
+ + +
[show private | hide private]
[frames | no frames]
+ + +

Type MultipleProducer

+ +
+object --+    
+         |    
+  Producer --+
+             |
+            MultipleProducer
+

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Method Summary
 __call__(self, + *args, + **kwargs) +
 _getconsumer(self, + keywords) +
    Inherited from Producer
 __init__(self, + keywords) +
 __getattr__(self, + name) +
 __repr__(self) +
    Inherited from object
 __delattr__(...) +
+x.__delattr__('name') <==> del x.name
 __getattribute__(...) +
+x.__getattribute__('name') <==> x.name
 __hash__(x) +
+x.__hash__() <==> hash(x)
 __new__(T, + S, + ...) +
+T.__new__(S, ...) -> a new object with type S, a subtype of T
 __reduce__(...) +
+helper for pickle
 __reduce_ex__(...) +
+helper for pickle
 __setattr__(...) +
+x.__setattr__('name', value) <==> x.name = value
 __str__(x) +
+x.__str__() <==> str(x)

+ + + + + + + + + + +
Class Variable Summary
    Inherited from Producer
dictkeywords2consumer = {'default': <function default_consum... +

+ + + + + + + + + + + + + + + + + +
Generated by Epydoc 2.1 on Wed Nov 16 09:59:23 2005http://epydoc.sf.net
+ + Index: /trunk/docs/private/exceptions.Exception-class.html =================================================================== --- /trunk/docs/private/exceptions.Exception-class.html (revision 2) +++ /trunk/docs/private/exceptions.Exception-class.html (revision 2) @@ -0,0 +1,96 @@ + + + + + exceptions.Exception + + + + + + + + + + + + + + + + + + +
+ + Module exceptions :: + Class Exception +
+
+ + +
[show private | hide private]
[frames | no frames]
+ + +

Class Exception

+ +
Known Subclasses:
+
+ CheesecakeError
+ +
+ +Common base class for all exceptions. +
+ + + + + + + + + + + + +
Method Summary
 __init__(...) +
 __getitem__(...) +
 __str__(...) +

+ + + + + + + + + + + + + + + + + + +
Generated by Epydoc 2.1 on Wed Dec 21 17:21:41 2005http://epydoc.sf.net
+ + Index: /trunk/docs/private/toc-logger-module.html =================================================================== --- /trunk/docs/private/toc-logger-module.html (revision 2) +++ /trunk/docs/private/toc-logger-module.html (revision 2) @@ -0,0 +1,39 @@ + + + + + logger + + + +
logger
+
+ + +Classes
+File
+Message
+MultipleProducer
+Path
+Producer
+
+ + +Functions
+default_consumer
+setconsumer
+STDERR
+STDOUT
+
+ + +Variables
+default
+
+ +
+[show private | hide private] + + Index: /trunk/docs/private/__builtin__.type-class.html =================================================================== --- /trunk/docs/private/__builtin__.type-class.html (revision 2) +++ /trunk/docs/private/__builtin__.type-class.html (revision 2) @@ -0,0 +1,516 @@ + + + + + __builtin__.type + + + + + + + + + + + + + + + + + + +
+ + Module __builtin__ :: + Class type +
+
+ + +
[show private | hide private]
[frames | no frames]
+ + +

Type type

+ +
+object --+
+         |
+        type
+

+ +
+ +type(object) -> the object's type type(name, bases, dict) -> a +new type +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Method Summary
 __call__(x, + ...) +
+x.__call__(...) <==> x(...)
 __cmp__(x, + y) +
+x.__cmp__(y) <==> cmp(x,y)
 __delattr__(...) +
+x.__delattr__('name') <==> del x.name
 __getattribute__(...) +
+x.__getattribute__('name') <==> x.name
 __hash__(x) +
+x.__hash__() <==> hash(x)
 __new__(T, + S, + ...) +
+T.__new__(S, ...) -> a new object with type S, a subtype of T
 __repr__(x) +
+x.__repr__() <==> repr(x)
 __setattr__(...) +
+x.__setattr__('name', value) <==> x.name = value
list of immediate subclasses__subclasses__() +
+__subclasses__() -> list of immediate subclasses
listmro() +
+return a type's method resolution order
    Inherited from object
 __init__(...) +
+x.__init__(...) initializes x; see x.__class__.__doc__ for +signature
 __reduce__(...) +
+helper for pickle
 __reduce_ex__(...) +
+helper for pickle
 __str__(x) +
+x.__str__() <==> str(x)

+ + + + + + + + + + + + + + + + + + + + + + + + +
Class Variable Summary
type__base__ = __builtin__.object
tuple__bases__ = (<type 'object'>,) +
int__basicsize__ = 420                                                                   
int__dictoffset__ = 132                                                                   
int__flags__ = 21995                                                                 
int__itemsize__ = 20                                                                    
tuple__mro__ = (<type 'type'>, <type 'object'>) +
str__name__ = 'type' +
int__weakrefoffset__ = 184                                                                   

+ + + + + + +
Method Details
+ + +
+

__call__(x, + ...) +
(Call operator) +

+ x.__call__(...) <==> x(...) +
+
Returns:
+
+
+x(...)
+
+
+
+
+
+ + +
+

__cmp__(x, + y) +
(Comparison operator) +

+ x.__cmp__(y) <==> cmp(x,y) +
+
Returns:
+
+
+cmp(x,y)
+
+
+
+
+
+ + +
+

__delattr__(...) +

+ x.__delattr__('name') <==> del x.name +
+
Overrides:
+
__builtin__.object.__delattr__
+
+
+
+ + +
+

__getattribute__(...) +

+ x.__getattribute__('name') <==> x.name +
+
Overrides:
+
__builtin__.object.__getattribute__
+
+
+
+ + +
+

__hash__(x) +
(Hashing function) +

+ x.__hash__() <==> hash(x) +
+
Returns:
+
+
+hash(x)
+
+
+
+
Overrides:
+
__builtin__.object.__hash__
+
+
+
+ + +
+

__new__(T, + S, + ...) +

+ T.__new__(S, ...) -> a new object with type S, a subtype of T +
+
Returns:
+
+
+a new object with type S, a subtype of T
+
+
+
+
Overrides:
+
__builtin__.object.__new__
+
+
+
+ + +
+

__repr__(x) +
(Representation operator) +

+ x.__repr__() <==> repr(x) +
+
Returns:
+
+
+repr(x)
+
+
+
+
Overrides:
+
__builtin__.object.__repr__
+
+
+
+ + +
+

__setattr__(...) +

+ x.__setattr__('name', value) <==> x.name = value +
+
Overrides:
+
__builtin__.object.__setattr__
+
+
+
+ + +
+

__subclasses__() +

+ __subclasses__() -> list of immediate subclasses +
+
Returns:
+
+list of immediate subclasses
+
+
+
+ + +
+

mro() +

+ return a type's method resolution order +
+
Returns:
+
+list
+
+
+
+
+ + + + + + +
Class Variable Details
+
+ +

__bases__

+
+
+
+
+
Type:
+
+ tuple + +
+
Value:
+
+
+(<type 'object'>,)                                                     
+
+
+
+
+
+ +

__basicsize__

+
+
+
+
+
Type:
+
+ int + +
+
Value:
+
+
+420                                                                   
+
+
+
+
+
+ +

__dictoffset__

+
+
+
+
+
Type:
+
+ int + +
+
Value:
+
+
+132                                                                   
+
+
+
+
+
+ +

__flags__

+
+
+
+
+
Type:
+
+ int + +
+
Value:
+
+
+21995                                                                 
+
+
+
+
+
+ +

__itemsize__

+
+
+
+
+
Type:
+
+ int + +
+
Value:
+
+
+20                                                                    
+
+
+
+
+
+ +

__mro__

+
+
+
+
+
Type:
+
+ tuple + +
+
Value:
+
+
+(<type 'type'>, <type 'object'>)                                       
+
+
+
+
+
+ +

__name__

+
+
+
+
+
Type:
+
+ str + +
+
Value:
+
+
+'type'                                                                 
+
+
+
+
+
+ +

__weakrefoffset__

+
+
+
+
+
Type:
+
+ int + +
+
Value:
+
+
+184                                                                   
+
+
+
+
+
+ + + + + + + + + + + + + + + + + + +
Generated by Epydoc 2.1 on Wed Dec 21 17:21:41 2005http://epydoc.sf.net
+ + Index: /trunk/docs/private/cheesecake.StdoutRedirector-class.html =================================================================== --- /trunk/docs/private/cheesecake.StdoutRedirector-class.html (revision 2) +++ /trunk/docs/private/cheesecake.StdoutRedirector-class.html (revision 2) @@ -0,0 +1,159 @@ + + + + + cheesecake.StdoutRedirector + + + + + + + + + + + + + + + + + +
+ + Module cheesecake :: + Class StdoutRedirector +
+
+ + +
[show private | hide private]
[frames | no frames]
+ + +

Type StdoutRedirector

+ +
+object --+
+         |
+        StdoutRedirector
+

+ +
+ +

Redirect stdout to a temp file

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Method Summary
 __init__(self, + filename) +
 flush(self) +
 read_buffer(self) +
+Return contents of the temp file
 write(self, + buf) +
    Inherited from object
 __delattr__(...) +
+x.__delattr__('name') <==> del x.name
 __getattribute__(...) +
+x.__getattribute__('name') <==> x.name
 __hash__(x) +
+x.__hash__() <==> hash(x)
 __new__(T, + S, + ...) +
+T.__new__(S, ...) -> a new object with type S, a subtype of T
 __reduce__(...) +
+helper for pickle
 __reduce_ex__(...) +
+helper for pickle
 __repr__(x) +
+x.__repr__() <==> repr(x)
 __setattr__(...) +
+x.__setattr__('name', value) <==> x.name = value
 __str__(x) +
+x.__str__() <==> str(x)

+ + + + + + +
Method Details
+ + +
+

read_buffer(self) +

+

Return contents of the temp file

+
+
+
+
+ + + + + + + + + + + + + + + + + +
Generated by Epydoc 2.1 on Wed Nov 16 09:59:23 2005http://epydoc.sf.net
+ + Index: /trunk/docs/private/help.html =================================================================== --- /trunk/docs/private/help.html (revision 2) +++ /trunk/docs/private/help.html (revision 2) @@ -0,0 +1,236 @@ + + + + + Help + + + + + + + + + + + + + + + + + + +
+ + + +
[show private | hide private]
[frames | no frames]
+ +

API Documentation

+ +

This document contains the API (Application Programming Interface) +documentation for cheesecake. Documentation for the Python +objects defined by the project is divided into separate pages for each +package, module, and class. The API documentation also includes two +pages containing information about the project as a whole: a trees +page, and an index page.

+ +

Object Documentation

+ +

Each Package Documentation page contains: +

+ +

Each Module Documentation page contains: +

+ +

Each Class Documentation page contains: +

+ +

Project Documentation

+ +

The Trees page contains the module and class hierarchies: +

+ +

The Index page contains indices of terms and + identifiers: +

+ +

The Table of Contents

+ +

The table of contents occupies the two frames on the left side of +the window. The upper-left frame displays the project +contents, and the lower-left frame displays the module +contents:

+ +
+ + + + + + + + +
+ Project
Contents
...
+ API
Documentation
Frame


+
+ Module
Contents
 
...
 
+

+
+ +

The project contents frame contains a list of all packages +and modules that are defined by the project. Clicking on an entry +will display its contents in the module contents frame. Clicking on a +special entry, labeled "Everything," will display the contents of +the entire project.

+ +

The module contents frame contains a list of every +submodule, class, type, exception, function, and variable defined by a +module or package. Clicking on an entry will display its +documentation in the API documentation frame. Clicking on the name of +the module, at the top of the frame, will display the documentation +for the module itself.

+ +

The "frames" and "no frames" buttons below the top +navigation bar can be used to control whether the table of contents is +displayed or not.

+ +

The Navigation Bar

+ +

A navigation bar is located at the top and bottom of every page. +It indicates what type of page you are currently viewing, and allows +you to go to related pages. The following table describes the labels +on the navigation bar. Note that not some labels (such as +[Parent]) are not displayed on all pages.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
LabelHighlighted when...Links to...
[Parent](never highlighted) the parent of the current package
[Package]viewing a packagethe package containing the current object +
[Module]viewing a modulethe module containing the current object +
[Class]viewing a class the class containing the current object
[Trees]viewing the trees page the trees page
[Index]viewing the index page the index page
[Help]viewing the help page the help page
+ +

The "show private" and "hide private" buttons below +the top navigation bar can be used to control whether documentation +for private objects is displayed. Private objects are usually defined +as objects whose (short) names begin with a single underscore, but do +not end with an underscore. For example, "_x", +"__pprint", and "epydoc.epytext._tokenize" +are private objects; but "re.sub", +"__init__", and "type_" are not. However, +if a module defines the "__all__" variable, then its +contents are used to decide which objects are private.

+ +

A timestamp below the bottom navigation bar indicates when each +page was last updated.

+ + + + + + + + + + + + + + + + + +
Generated by Epydoc 2.1 on Wed Dec 21 17:21:41 2005http://epydoc.sf.net
+ + Index: /trunk/docs/private/cheesecake.cheesecake_index.Index-class.html =================================================================== --- /trunk/docs/private/cheesecake.cheesecake_index.Index-class.html (revision 2) +++ /trunk/docs/private/cheesecake.cheesecake_index.Index-class.html (revision 2) @@ -0,0 +1,158 @@ + + + + + cheesecake.cheesecake_index.Index + + + + + + + + + + + + + + + + + + +
+ + Package cheesecake :: + Module cheesecake_index :: + Class Index +
+
+ + +
[show private | hide private]
[frames | no frames]
+ + +

Type Index

+ +
+object --+
+         |
+        Index
+

+ +
+ +Encapsulates index attributes such as name, value, details +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Method Summary
 __init__(self, + type, + name, + value, + details) +
 print_info(self) +
+Print index name padded with dots, followed by value and details
    Inherited from object
 __delattr__(...) +
+x.__delattr__('name') <==> del x.name
 __getattribute__(...) +
+x.__getattribute__('name') <==> x.name
 __hash__(x) +
+x.__hash__() <==> hash(x)
 __new__(T, + S, + ...) +
+T.__new__(S, ...) -> a new object with type S, a subtype of T
 __reduce__(...) +
+helper for pickle
 __reduce_ex__(...) +
+helper for pickle
 __repr__(x) +
+x.__repr__() <==> repr(x)
 __setattr__(...) +
+x.__setattr__('name', value) <==> x.name = value
 __str__(x) +
+x.__str__() <==> str(x)

+ + + + + + +
Method Details
+ + +
+

print_info(self) +

+ Print index name padded with dots, followed by value and details +
+
+
+
+ + + + + + + + + + + + + + + + + + +
Generated by Epydoc 2.1 on Wed Dec 21 17:21:41 2005http://epydoc.sf.net
+ + Index: /trunk/docs/private/logger.File-class.html =================================================================== --- /trunk/docs/private/logger.File-class.html (revision 2) +++ /trunk/docs/private/logger.File-class.html (revision 2) @@ -0,0 +1,136 @@ + + + + + logger.File + + + + + + + + + + + + + + + + + +
+ + Module logger :: + Class File +
+
+ + +
[show private | hide private]
[frames | no frames]
+ + +

Type File

+ +
+object --+
+         |
+        File
+

+ +
Known Subclasses:
+
+ Path
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Method Summary
 __init__(self, + f) +
 __call__(self, + msg) +
    Inherited from object
 __delattr__(...) +
+x.__delattr__('name') <==> del x.name
 __getattribute__(...) +
+x.__getattribute__('name') <==> x.name
 __hash__(x) +
+x.__hash__() <==> hash(x)
 __new__(T, + S, + ...) +
+T.__new__(S, ...) -> a new object with type S, a subtype of T
 __reduce__(...) +
+helper for pickle
 __reduce_ex__(...) +
+helper for pickle
 __repr__(x) +
+x.__repr__() <==> repr(x)
 __setattr__(...) +
+x.__setattr__('name', value) <==> x.name = value
 __str__(x) +
+x.__str__() <==> str(x)

+ + + + + + + + + + + + + + + + + +
Generated by Epydoc 2.1 on Wed Nov 16 09:59:23 2005http://epydoc.sf.net
+ + Index: /trunk/docs/private/cheesecake.Cheesecake-class.html =================================================================== --- /trunk/docs/private/cheesecake.Cheesecake-class.html (revision 2) +++ /trunk/docs/private/cheesecake.Cheesecake-class.html (revision 2) @@ -0,0 +1,604 @@ + + + + + cheesecake.Cheesecake + + + + + + + + + + + + + + + + + +
+ + Module cheesecake :: + Class Cheesecake +
+
+ + +
[show private | hide private]
[frames | no frames]
+ + +

Type Cheesecake

+ +
+object --+
+         |
+        Cheesecake
+

+ +
+ +

Computes 'goodness' of Python packages

+

Generates "cheesecake index" that takes into account things like:

+
+
    +
  • whether the package can be downloaded
  • +
  • whether the package can be unpacked
  • +
  • whether the package can be installed into an alternate directory
  • +
  • existence of certain files such as README, INSTALL, LICENSE, setup.py etc.
  • +
  • existence of certain directories such as doc, test, demo, examples
  • +
  • percentage of modules/functions/classes/methods with docstrings
  • +
  • percentage of functions/methods that are unit tested
  • +
  • average pylint score for all non-test and non-demo modules
  • +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Method Summary
 __init__(self, + name, + url, + path, + sandbox, + verbose, + quiet) +
+Initialize critical variables, download and unpack package, walk package tree
 cleanup(self) +
+Delete temporary directories and files that were +created in the sandbox
 compute_cheesecake_index(self) +
+Compute overall Cheesecake index for the package by adding up +specific indexes
 configure_logging(self) +
+Default settings for logging
 copy_pkg(self) +
+Copy package file to sandbox directory
 determine_pkg_name(self) +
 download_pkg(self) +
+Use urllib.urlretrieve to download package to file in sandbox dir
 get_package_from_path(self, + path) +
+Get package name as file portion of path
 get_package_from_url(self) +
+Use urlparse to obtain package path from URL
 get_pkg_from_pypi(self) +
+Download package using setuptools utilities
 index_dir(self) +
+Return CompositeIndex object of type "dir"
 index_docstrings(self) +
+Compute docstring index as percentage of modules/classes/methods/functions +that have docstrings associated with them
 index_download(self) +
+Verify that package can be downloaded from an URL
 index_file(self) +
+Return CompositeIndex object of type "file"
 index_install(self) +
+Verify that package can be installed in alternate directory
 index_pylint(self) +
+Compute pylint index as average of positive pylint scores obtained for +the Python files identified in the package
 index_pypi_download(self) +
+Verify that package can be downloaded from PyPI
 index_unpack(self) +
+Verify that package can be unpacked
 index_unpack_dir(self) +
+Verify that unpack directory has same name as package
 init_indexes(self) +
+Initialize variables used in index computation
 is_py_file(self, + file, + dirs) +
+Return True if file ends with .py and it is not a special file and it is not +in special directory
 is_test_file(self, + file, + dirs) +
+Return True is file is in directory rooted at "test" or "tests"
 pad_msg(self, + msg, + value) +
+Pad message with dots and pad value with spaces
 print_line(self, + line) +
+Print line of text, unless quiet flag was given
 process_index(self, + index_type) +
+Compute and print index of specified type
 raise_exception(self, + msg) +
+Cleanup, print error message and raise CheesecakeError
 retrieve_pkg(self) +
 unpack_pkg(self) +
+Unpack the package in the sandbox directory
 untar_pkg(self) +
+Untar the package in the sandbox directory
 unzip_pkg(self) +
+Unzip the package in the sandbox directory
 walk_pkg(self) +
+Traverse the file system tree rooted at sandbox/package_name
    Inherited from object
 __delattr__(...) +
+x.__delattr__('name') <==> del x.name
 __getattribute__(...) +
+x.__getattribute__('name') <==> x.name
 __hash__(x) +
+x.__hash__() <==> hash(x)
 __new__(T, + S, + ...) +
+T.__new__(S, ...) -> a new object with type S, a subtype of T
 __reduce__(...) +
+helper for pickle
 __reduce_ex__(...) +
+helper for pickle
 __repr__(x) +
+x.__repr__() <==> repr(x)
 __setattr__(...) +
+x.__setattr__('name', value) <==> x.name = value
 __str__(x) +
+x.__str__() <==> str(x)

+ + + + + + +
Method Details
+ + +
+

__init__(self, + name='', + url='', + path='', + sandbox=None, + verbose=False, + quiet=False) +
(Constructor) +

+

Initialize critical variables, download and unpack package, walk package tree

+
+
Overrides:
+
__builtin__.object.__init__
+
+
+
+ + +
+

cleanup(self) +

+

Delete temporary directories and files that were +created in the sandbox

+
+
+
+ + +
+

compute_cheesecake_index(self) +

+

Compute overall Cheesecake index for the package by adding up +specific indexes

+
+
+
+ + +
+

configure_logging(self) +

+

Default settings for logging

+

if verbose, log goes to console, else it goes to logfile +log.debug goes to logfile +log.info goes to console +log.warn and log.error go to both logfile and stdout

+
+
+
+ + +
+

copy_pkg(self) +

+

Copy package file to sandbox directory

+
+
+
+ + +
+

download_pkg(self) +

+

Use urllib.urlretrieve to download package to file in sandbox dir

+
+
+
+ + +
+

get_package_from_path(self, + path) +

+

Get package name as file portion of path

+
+
+
+ + +
+

get_package_from_url(self) +

+

Use urlparse to obtain package path from URL

+
+
+
+ + +
+

get_pkg_from_pypi(self) +

+

Download package using setuptools utilities

+
+
+
+ + +
+

index_dir(self) +

+

Return CompositeIndex object of type "dir"

+
+
+
+ + +
+

index_docstrings(self) +

+

Compute docstring index as percentage of modules/classes/methods/functions +that have docstrings associated with them

+

Return Index object of type "docstrings"

+
+
+
+ + +
+

index_download(self) +

+

Verify that package can be downloaded from an URL

+

Return Index object of type "download"

+
+
+
+ + +
+

index_file(self) +

+

Return CompositeIndex object of type "file"

+
+
+
+ + +
+

index_install(self) +

+

Verify that package can be installed in alternate directory

+

Return Index object of type "install"

+
+
+
+ + +
+

index_pylint(self) +

+

Compute pylint index as average of positive pylint scores obtained for +the Python files identified in the package

+

Return Index object of type "pylint"

+
+
+
+ + +
+

index_pypi_download(self) +

+

Verify that package can be downloaded from PyPI

+

Return Index object of type "pypi_download"

+
+
+
+ + +
+

index_unpack(self) +

+

Verify that package can be unpacked

+

Return Index object of type "unpack"

+
+
+
+ + +
+

index_unpack_dir(self) +

+

Verify that unpack directory has same name as package

+

Return Index object of type "unpack_dir"

+
+
+
+ + +
+

init_indexes(self) +

+

Initialize variables used in index computation

+
    +
  • cheesecake_index: overall index for the package
  • +
  • index: dict holding Index or CompositeIndex objects of various types
  • +
+
+
+
+ + +
+

is_py_file(self, + file, + dirs) +

+

Return True if file ends with .py and it is not a special file and it is not +in special directory

+
+
+
+ + +
+

is_test_file(self, + file, + dirs) +

+

Return True is file is in directory rooted at "test" or "tests"

+
+
+
+ + +
+

pad_msg(self, + msg, + value) +

+

Pad message with dots and pad value with spaces

+
+
+
+ + +
+

print_line(self, + line) +

+

Print line of text, unless quiet flag was given

+
+
+
+ + +
+

process_index(self, + index_type) +

+

Compute and print index of specified type

+
+
+
+ + +
+

raise_exception(self, + msg) +

+

Cleanup, print error message and raise CheesecakeError

+

Don't use logging, since it can be called before logging has been setup

+
+
+
+ + +
+

unpack_pkg(self) +

+

Unpack the package in the sandbox directory

+

Currently supported archive types:

+
    +
  • .tar.gz (handled with tarfile module)
  • +
  • .zip (handled with zipfile module)
  • +
+
+
+
+ + +
+

untar_pkg(self) +

+

Untar the package in the sandbox directory

+

Uses tarfile module

+
+
+
+ + +
+

unzip_pkg(self) +

+

Unzip the package in the sandbox directory

+

Uses zipfile module

+
+
+
+ + +
+

walk_pkg(self) +

+

Traverse the file system tree rooted at sandbox/package_name

+
    +
  • Compute indexes for special files and directories
  • +
  • Identify Python files, test files, etc.
  • +
+
+
+
+
+ + + + + + + + + + + + + + + + + +
Generated by Epydoc 2.1 on Wed Nov 16 09:59:23 2005http://epydoc.sf.net
+ + Index: /trunk/docs/private/cheesecake-module.html =================================================================== --- /trunk/docs/private/cheesecake-module.html (revision 2) +++ /trunk/docs/private/cheesecake-module.html (revision 2) @@ -0,0 +1,512 @@ + + + + + cheesecake + + + + + + + + + + + + + + + + + +
+ + Module cheesecake +
+
+ + +
[show private | hide private]
[frames | no frames]
+ + +

Module cheesecake

+ +

Cheesecake: How tasty is your code?

+

The idea of the Cheesecake project is to rank Python packages +based on various empiric "kwalitee" factors, such as:

+
+
    +
  • whether the package can be downloaded
  • +
  • whether the package can be unpacked
  • +
  • whether the package can be installed into an alternate directory
  • +
  • existence of certain files such as README, INSTALL, LICENSE, setup.py etc.
  • +
  • existence of certain directories such as doc, test, demo, examples
  • +
  • percentage of modules/functions/classes/methods with docstrings
  • +
  • percentage of functions/methods that are unit tested
  • +
  • average pylint score for all non-test and non-demo modules
  • +
  • whether the package can be unpacked
  • +
  • whether the package can be installed into an alternate directory
  • +
+
+
+ + + + + + + + + + + + + + + +
Classes
+ CheesecakeComputes 'goodness' of Python packages
+ CodeParserInformation about the structure of a Python module
+ CompositeIndexCollection of indexes of same type (e.g.
+ IndexEncapsulates index attributes such as name, value, details
+ StdoutRedirectorRedirect stdout to a temp file

+ + + + + + + + +
Exceptions
+ CheesecakeErrorCustom exception class for Cheesecake-specific errors

+ + + + + + + + + + + + + + +
Function Summary
 main() +
+Display Cheesecake index for package specified via command-line options
 pad_left_spaces(value, + length) +
+Pad value with spaces at left up to given length
 pad_with_dots(msg, + length) +
+Pad text with dots up to given length
 process_cmdline_args() +
+Parse command-line options

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Variable Summary
intINDEX_DIR = 20                                                                    
intINDEX_DIR_CRITICAL = 25                                                                    
intINDEX_DIR_EMPTY = 5                                                                     
intINDEX_FILE = 10                                                                    
intINDEX_FILE_CRITICAL = 15                                                                    
intINDEX_FILE_PYC = -20                                                                   
intINDEX_INSTALL = 50                                                                    
intINDEX_PYPI_DISTANCE = 5                                                                     
intINDEX_PYPI_DOWNLOAD = 50                                                                    
intINDEX_UNPACK = 25                                                                    
intINDEX_UNPACK_DIR = 15                                                                    
intINDEX_URL_DOWNLOAD = 25                                                                    
intPAD_TEXT = 25                                                                    
intPAD_VALUE = 4                                                                     

+ + + + + + +
Function Details
+ + +
+

main() +

+

Display Cheesecake index for package specified via command-line options

+
+
+
+ + +
+

pad_left_spaces(value, + length=4) +

+

Pad value with spaces at left up to given length

+
+
+
+ + +
+

pad_with_dots(msg, + length=25) +

+

Pad text with dots up to given length

+
+
+
+ + +
+

process_cmdline_args() +

+

Parse command-line options

+
+
+
+
+ + + + + + +
Variable Details
+
+ +

INDEX_DIR

+
+
+
+
+
Type:
+
+ int + +
+
Value:
+
+
+20                                                                    
+
+
+
+
+
+ +

INDEX_DIR_CRITICAL

+
+
+
+
+
Type:
+
+ int + +
+
Value:
+
+
+25                                                                    
+
+
+
+
+
+ +

INDEX_DIR_EMPTY

+
+
+
+
+
Type:
+
+ int + +
+
Value:
+
+
+5                                                                     
+
+
+
+
+
+ +

INDEX_FILE

+
+
+
+
+
Type:
+
+ int + +
+
Value:
+
+
+10                                                                    
+
+
+
+
+
+ +

INDEX_FILE_CRITICAL

+
+
+
+
+
Type:
+
+ int + +
+
Value:
+
+
+15                                                                    
+
+
+
+
+
+ +

INDEX_FILE_PYC

+
+
+
+
+
Type:
+
+ int + +
+
Value:
+
+
+-20                                                                   
+
+
+
+
+
+ +

INDEX_INSTALL

+
+
+
+
+
Type:
+
+ int + +
+
Value:
+
+
+50                                                                    
+
+
+
+
+
+ +

INDEX_PYPI_DISTANCE

+
+
+
+
+
Type:
+
+ int + +
+
Value:
+
+
+5                                                                     
+
+
+
+
+
+ +

INDEX_PYPI_DOWNLOAD

+
+
+
+
+
Type:
+
+ int + +
+
Value:
+
+
+50                                                                    
+
+
+
+
+
+ +

INDEX_UNPACK

+
+
+
+
+
Type:
+
+ int + +
+
Value:
+
+
+25                                                                    
+
+
+
+
+
+ +

INDEX_UNPACK_DIR

+
+
+
+
+
Type:
+
+ int + +
+
Value:
+
+
+15                                                                    
+
+
+
+
+
+ +

INDEX_URL_DOWNLOAD

+
+
+
+
+
Type:
+
+ int + +
+
Value:
+
+
+25                                                                    
+
+
+
+
+
+ +

PAD_TEXT

+
+
+
+
+
Type:
+
+ int + +
+
Value:
+
+
+25                                                                    
+
+
+
+
+
+ +

PAD_VALUE

+
+
+
+
+
Type:
+
+ int + +
+
Value:
+
+
+4                                                                     
+
+
+
+
+
+ + + + + + + + + + + + + + + + + +
Generated by Epydoc 2.1 on Wed Nov 16 09:59:23 2005http://epydoc.sf.net
+ + Index: /trunk/docs/private/logger.Message-class.html =================================================================== --- /trunk/docs/private/logger.Message-class.html (revision 2) +++ /trunk/docs/private/logger.Message-class.html (revision 2) @@ -0,0 +1,134 @@ + + + + + logger.Message + + + + + + + + + + + + + + + + + +
+ + Module logger :: + Class Message +
+
+ + +
[show private | hide private]
[frames | no frames]
+ + +

Type Message

+ +
+object --+
+         |
+        Message
+

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Method Summary
 __init__(self, + keywords, + args) +
 __str__(self) +
 content(self) +
 prefix(self) +
    Inherited from object
 __delattr__(...) +
+x.__delattr__('name') <==> del x.name
 __getattribute__(...) +
+x.__getattribute__('name') <==> x.name
 __hash__(x) +
+x.__hash__() <==> hash(x)
 __new__(T, + S, + ...) +
+T.__new__(S, ...) -> a new object with type S, a subtype of T
 __reduce__(...) +
+helper for pickle
 __reduce_ex__(...) +
+helper for pickle
 __repr__(x) +
+x.__repr__() <==> repr(x)
 __setattr__(...) +
+x.__setattr__('name', value) <==> x.name = value

+ + + + + + + + + + + + + + + + + +
Generated by Epydoc 2.1 on Wed Nov 16 09:59:23 2005http://epydoc.sf.net
+ + Index: /trunk/docs/private/cheesecake.CodeParser-class.html =================================================================== --- /trunk/docs/private/cheesecake.CodeParser-class.html (revision 2) +++ /trunk/docs/private/cheesecake.CodeParser-class.html (revision 2) @@ -0,0 +1,191 @@ + + + + + cheesecake.CodeParser + + + + + + + + + + + + + + + + + +
+ + Module cheesecake :: + Class CodeParser +
+
+ + +
[show private | hide private]
[frames | no frames]
+ + +

Type CodeParser

+ +
+object --+
+         |
+        CodeParser
+

+ +
+ +

Information about the structure of a Python module

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Method Summary
 __init__(self, + pyfile, + log) +
 docstring_count(self) +
+Return number of docstrings found in this module
 object_count(self) +
+Return number of objects found in this module
 parse_file(self) +
+Parse module text and retrieve classes, methods, functions +and associated docstrings
    Inherited from object
 __delattr__(...) +
+x.__delattr__('name') <==> del x.name
 __getattribute__(...) +
+x.__getattribute__('name') <==> x.name
 __hash__(x) +
+x.__hash__() <==> hash(x)
 __new__(T, + S, + ...) +
+T.__new__(S, ...) -> a new object with type S, a subtype of T
 __reduce__(...) +
+helper for pickle
 __reduce_ex__(...) +
+helper for pickle
 __repr__(x) +
+x.__repr__() <==> repr(x)
 __setattr__(...) +
+x.__setattr__('name', value) <==> x.name = value
 __str__(x) +
+x.__str__() <==> str(x)

+ + + + + + +
Method Details
+ + +
+

docstring_count(self) +

+

Return number of docstrings found in this module

+
+
+
+ + +
+

object_count(self) +

+

Return number of objects found in this module

+
    +
  • module
  • +
  • classes
  • +
  • methods
  • +
  • functions
  • +
+
+
+
+ + +
+

parse_file(self) +

+

Parse module text and retrieve classes, methods, functions +and associated docstrings

+
+
+
+
+ + + + + + + + + + + + + + + + + +
Generated by Epydoc 2.1 on Wed Nov 16 09:59:23 2005http://epydoc.sf.net
+ + Index: /trunk/docs/private/__builtin__.object-class.html =================================================================== --- /trunk/docs/private/__builtin__.object-class.html (revision 2) +++ /trunk/docs/private/__builtin__.object-class.html (revision 2) @@ -0,0 +1,277 @@ + + + + + __builtin__.object + + + + + + + + + + + + + + + + + + +
+ + Module __builtin__ :: + Class object +
+
+ + +
[show private | hide private]
[frames | no frames]
+ + +

Type object

+ +
Known Subclasses:
+
+ Cheesecake, + CodeParser, + CompositeIndex, + Index, + StdoutRedirector, + type
+ +
+ +The most base type +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Method Summary
 __init__(...) +
+x.__init__(...) initializes x; see x.__class__.__doc__ for +signature
 __delattr__(...) +
+x.__delattr__('name') <==> del x.name
 __getattribute__(...) +
+x.__getattribute__('name') <==> x.name
 __hash__(x) +
+x.__hash__() <==> hash(x)
 __new__(T, + S, + ...) +
+T.__new__(S, ...) -> a new object with type S, a subtype of T
 __reduce__(...) +
+helper for pickle
 __reduce_ex__(...) +
+helper for pickle
 __repr__(x) +
+x.__repr__() <==> repr(x)
 __setattr__(...) +
+x.__setattr__('name', value) <==> x.name = value
 __str__(x) +
+x.__str__() <==> str(x)

+ + + + + + + + +
Class Variable Summary
type__class__ = __builtin__.type

+ + + + + + +
Method Details
+ + +
+

__init__(...) +
(Constructor) +

+ x.__init__(...) initializes x; see x.__class__.__doc__ for + signature +
+
+
+ + +
+

__delattr__(...) +

+ x.__delattr__('name') <==> del x.name +
+
+
+ + +
+

__getattribute__(...) +

+ x.__getattribute__('name') <==> x.name +
+
+
+ + +
+

__hash__(x) +
(Hashing function) +

+ x.__hash__() <==> hash(x) +
+
Returns:
+
+
+hash(x)
+
+
+
+
+
+ + +
+

__new__(T, + S, + ...) +

+ T.__new__(S, ...) -> a new object with type S, a subtype of T +
+
Returns:
+
+
+a new object with type S, a subtype of T
+
+
+
+
+
+ + +
+

__reduce__(...) +

+ helper for pickle +
+
+
+ + +
+

__reduce_ex__(...) +

+ helper for pickle +
+
+
+ + +
+

__repr__(x) +
(Representation operator) +

+ x.__repr__() <==> repr(x) +
+
Returns:
+
+
+repr(x)
+
+
+
+
+
+ + +
+

__setattr__(...) +

+ x.__setattr__('name', value) <==> x.name = value +
+
+
+ + +
+

__str__(x) +
(Informal representation operator) +

+ x.__str__() <==> str(x) +
+
Returns:
+
+
+str(x)
+
+
+
+
+
+
+ + + + + + + + + + + + + + + + + + +
Generated by Epydoc 2.1 on Wed Dec 21 17:21:41 2005http://epydoc.sf.net
+ + Index: /trunk/docs/private/cheesecake.cheesecake_index.CheesecakeError-class.html =================================================================== --- /trunk/docs/private/cheesecake.cheesecake_index.CheesecakeError-class.html (revision 2) +++ /trunk/docs/private/cheesecake.cheesecake_index.CheesecakeError-class.html (revision 2) @@ -0,0 +1,101 @@ + + + + + cheesecake.cheesecake_index.CheesecakeError + + + + + + + + + + + + + + + + + + +
+ + Package cheesecake :: + Module cheesecake_index :: + Class CheesecakeError +
+
+ + +
[show private | hide private]
[frames | no frames]
+ + +

Class CheesecakeError

+ +
+Exception --+
+            |
+           CheesecakeError
+

+ +
+ +Custom exception class for Cheesecake-specific errors +
+ + + + + + + + + + + + + + +
Method Summary
    Inherited from Exception
 __init__(...) +
 __getitem__(...) +
 __str__(...) +

+ + + + + + + + + + + + + + + + + + +
Generated by Epydoc 2.1 on Wed Dec 21 17:21:41 2005http://epydoc.sf.net
+ + Index: /trunk/docs/private/cheesecake.cheesecake_index.CompositeIndex-class.html =================================================================== --- /trunk/docs/private/cheesecake.cheesecake_index.CompositeIndex-class.html (revision 2) +++ /trunk/docs/private/cheesecake.cheesecake_index.CompositeIndex-class.html (revision 2) @@ -0,0 +1,233 @@ + + + + + cheesecake.cheesecake_index.CompositeIndex + + + + + + + + + + + + + + + + + + +
+ + Package cheesecake :: + Module cheesecake_index :: + Class CompositeIndex +
+
+ + +
[show private | hide private]
[frames | no frames]
+ + +

Type CompositeIndex

+ +
+object --+
+         |
+        CompositeIndex
+

+ +
+ +Collection of indexes of same type (e.g. files, dirs) +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Method Summary
 __init__(self, + type) +
+Indexes is a dict mapping names to Index objects
 get_value(self) +
+Return sum of individual index values
 print_info(self) +
+Print index info for all indexes sorted alphanumerically by name
 set_index(self, + name, + value, + details) +
+Create new index or update existing index with specified +attributes
    Inherited from object
 __delattr__(...) +
+x.__delattr__('name') <==> del x.name
 __getattribute__(...) +
+x.__getattribute__('name') <==> x.name
 __hash__(x) +
+x.__hash__() <==> hash(x)
 __new__(T, + S, + ...) +
+T.__new__(S, ...) -> a new object with type S, a subtype of T
 __reduce__(...) +
+helper for pickle
 __reduce_ex__(...) +
+helper for pickle
 __repr__(x) +
+x.__repr__() <==> repr(x)
 __setattr__(...) +
+x.__setattr__('name', value) <==> x.name = value
 __str__(x) +
+x.__str__() <==> str(x)

+ + + + + + + +
Property Summary
 value

+ + + + + + +
Method Details
+ + +
+

__init__(self, + type) +
(Constructor) +

+ Indexes is a dict mapping names to Index objects +
+
Overrides:
+
__builtin__.object.__init__
+
+
+
+ + +
+

get_value(self) +

+ Return sum of individual index values +
+
+
+ + +
+

print_info(self) +

+ Print index info for all indexes sorted alphanumerically by name +
+
+
+ + +
+

set_index(self, + name, + value=0, + details='') +

+ Create new index or update existing index with specified + attributes +
+
+
+
+ + + + + + +
Property Details
+
+ + +

value

+
+
+
+
+
Get Method:
+
get_value(self) +
+
+
+

+ + + + + + + + + + + + + + + + + + +
Generated by Epydoc 2.1 on Wed Dec 21 17:21:41 2005http://epydoc.sf.net
+ + Index: /trunk/docs/private/trees.html =================================================================== --- /trunk/docs/private/trees.html (revision 2) +++ /trunk/docs/private/trees.html (revision 2) @@ -0,0 +1,112 @@ + + + + + Module and Class Hierarchies + + + + + + + + + + + + + + + + + + +
+ + + +
[show private | hide private]
[frames | no frames]
+ + +

Module Hierarchy

+ + + +

Class Hierarchy

+ + + + + + + + + + + + + + + + + + +
Generated by Epydoc 2.1 on Wed Dec 21 17:21:41 2005http://epydoc.sf.net
+ + Index: /trunk/docs/private/toc.html =================================================================== --- /trunk/docs/private/toc.html (revision 2) +++ /trunk/docs/private/toc.html (revision 2) @@ -0,0 +1,25 @@ + + + + + Table of Contents + + + +
Table of Contents
+
+Everything
+ + +
Packages
+ + +
Modules
+cheesecake.cheesecake_index
+ +

+[show private | hide private] + + Index: /trunk/docs/private/toc-cheesecake-module.html =================================================================== --- /trunk/docs/private/toc-cheesecake-module.html (revision 2) +++ /trunk/docs/private/toc-cheesecake-module.html (revision 2) @@ -0,0 +1,57 @@ + + + + + cheesecake + + + +
cheesecake
+
+ + +Classes
+Cheesecake
+CodeParser
+CompositeIndex
+Index
+StdoutRedirector
+
+ + +Exceptions
+CheesecakeError
+
+ + +Functions
+main
+pad_left_spaces
+pad_with_dots
+process_cmdline_args
+
+ + +Variables
+INDEX_DIR
+INDEX_DIR_CRITICAL
+INDEX_DIR_EMPTY
+INDEX_FILE
+INDEX_FILE_CRITICAL
+INDEX_FILE_PYC
+INDEX_INSTALL
+INDEX_PYPI_DISTANCE
+INDEX_PYPI_DOWNLOAD
+INDEX_UNPACK
+INDEX_UNPACK_DIR
+INDEX_URL_DOWNLOAD
+PAD_TEXT
+PAD_VALUE
+
+ +
+[show private | hide private] + + Index: /trunk/docs/private/cheesecake.Index-class.html =================================================================== --- /trunk/docs/private/cheesecake.Index-class.html (revision 2) +++ /trunk/docs/private/cheesecake.Index-class.html (revision 2) @@ -0,0 +1,155 @@ + + + + + cheesecake.Index + + + + + + + + + + + + + + + + + +
+ + Module cheesecake :: + Class Index +
+
+ + +
[show private | hide private]
[frames | no frames]
+ + +

Type Index

+ +
+object --+
+         |
+        Index
+

+ +
+ +

Encapsulates index attributes such as name, value, details

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Method Summary
 __init__(self, + type, + name, + value, + details) +
 print_info(self) +
+Print index name padded with dots, followed by value and details
    Inherited from object
 __delattr__(...) +
+x.__delattr__('name') <==> del x.name
 __getattribute__(...) +
+x.__getattribute__('name') <==> x.name
 __hash__(x) +
+x.__hash__() <==> hash(x)
 __new__(T, + S, + ...) +
+T.__new__(S, ...) -> a new object with type S, a subtype of T
 __reduce__(...) +
+helper for pickle
 __reduce_ex__(...) +
+helper for pickle
 __repr__(x) +
+x.__repr__() <==> repr(x)
 __setattr__(...) +
+x.__setattr__('name', value) <==> x.name = value
 __str__(x) +
+x.__str__() <==> str(x)

+ + + + + + +
Method Details
+ + +
+

print_info(self) +

+

Print index name padded with dots, followed by value and details

+
+
+
+
+ + + + + + + + + + + + + + + + + +
Generated by Epydoc 2.1 on Wed Nov 16 09:59:23 2005http://epydoc.sf.net
+ + Index: /trunk/docs/private/toc-cheesecake.cheesecake_index-module.html =================================================================== --- /trunk/docs/private/toc-cheesecake.cheesecake_index-module.html (revision 2) +++ /trunk/docs/private/toc-cheesecake.cheesecake_index-module.html (revision 2) @@ -0,0 +1,59 @@ + + + + + cheesecake.cheesecake_index + + + +
cheesecake_index
+
+ + +Classes
+Cheesecake
+CodeParser
+CompositeIndex
+Index
+StdoutRedirector
+
+ + +Exceptions
+CheesecakeError
+
+ + +Functions
+main
+pad_left_spaces
+pad_msg
+pad_with_dots
+process_cmdline_args
+
+ + +Variables
+INDEX_DIR
+INDEX_DIR_CRITICAL
+INDEX_DIR_EMPTY
+INDEX_FILE
+INDEX_FILE_CRITICAL
+INDEX_FILE_PYC
+INDEX_INSTALL
+INDEX_PYPI_DISTANCE
+INDEX_PYPI_DOWNLOAD
+INDEX_REQUIRED_FILES
+INDEX_UNPACK
+INDEX_UNPACK_DIR
+INDEX_URL_DOWNLOAD
+PAD_TEXT
+PAD_VALUE
+
+ +
+[show private | hide private] + + Index: /trunk/docs/private/cheesecake.cheesecake_index.StdoutRedirector-class.html =================================================================== --- /trunk/docs/private/cheesecake.cheesecake_index.StdoutRedirector-class.html (revision 2) +++ /trunk/docs/private/cheesecake.cheesecake_index.StdoutRedirector-class.html (revision 2) @@ -0,0 +1,162 @@ + + + + + cheesecake.cheesecake_index.StdoutRedirector + + + + + + + + + + + + + + + + + + +
+ + Package cheesecake :: + Module cheesecake_index :: + Class StdoutRedirector +
+
+ + +
[show private | hide private]
[frames | no frames]
+ + +

Type StdoutRedirector

+ +
+object --+
+         |
+        StdoutRedirector
+

+ +
+ +Redirect stdout to a temp file +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Method Summary
 __init__(self, + filename) +
 flush(self) +
 read_buffer(self) +
+Return contents of the temp file
 write(self, + buf) +
    Inherited from object
 __delattr__(...) +
+x.__delattr__('name') <==> del x.name
 __getattribute__(...) +
+x.__getattribute__('name') <==> x.name
 __hash__(x) +
+x.__hash__() <==> hash(x)
 __new__(T, + S, + ...) +
+T.__new__(S, ...) -> a new object with type S, a subtype of T
 __reduce__(...) +
+helper for pickle
 __reduce_ex__(...) +
+helper for pickle
 __repr__(x) +
+x.__repr__() <==> repr(x)
 __setattr__(...) +
+x.__setattr__('name', value) <==> x.name = value
 __str__(x) +
+x.__str__() <==> str(x)

+ + + + + + +
Method Details
+ + +
+

read_buffer(self) +

+ Return contents of the temp file +
+
+
+
+ + + + + + + + + + + + + + + + + + +
Generated by Epydoc 2.1 on Wed Dec 21 17:21:41 2005http://epydoc.sf.net
+ + Index: /trunk/docs/private/logger-module.html =================================================================== --- /trunk/docs/private/logger-module.html (revision 2) +++ /trunk/docs/private/logger-module.html (revision 2) @@ -0,0 +1,150 @@ + + + + + logger + + + + + + + + + + + + + + + + + +
+ + Module logger +
+
+ + +
[show private | hide private]
[frames | no frames]
+ + +

Module logger

+ + + + + + + + + + + + + + + + +
Classes
+ File 
+ Message 
+ MultipleProducer 
+ Path 
+ ProducerLog producer API which sends messages to be logged +to a 'consumer' object, which then prints them to stdout, +stderr, files, etc.

+ + + + + + + + + + + + + + +
Function Summary
 default_consumer(msg) +
 setconsumer(keywords, + consumer) +
 STDERR(msg) +
 STDOUT(msg) +

+ + + + + + + + +
Variable Summary
Producerdefault = <Producer default> +

+ + + + + + +
Variable Details
+
+ +

default

+
+
+
+
+
Type:
+
+ Producer + +
+
Value:
+
+
+<Producer default>                                                     
+
+
+
+
+
+ + + + + + + + + + + + + + + + + +
Generated by Epydoc 2.1 on Wed Nov 16 09:59:23 2005http://epydoc.sf.net
+ + Index: /trunk/docs/private/logger.Producer-class.html =================================================================== --- /trunk/docs/private/logger.Producer-class.html (revision 2) +++ /trunk/docs/private/logger.Producer-class.html (revision 2) @@ -0,0 +1,188 @@ + + + + + logger.Producer + + + + + + + + + + + + + + + + + +
+ + Module logger :: + Class Producer +
+
+ + +
[show private | hide private]
[frames | no frames]
+ + +

Type Producer

+ +
+object --+
+         |
+        Producer
+

+ +
Known Subclasses:
+
+ MultipleProducer
+ +
+ +

Log producer API which sends messages to be logged +to a 'consumer' object, which then prints them to stdout, +stderr, files, etc.

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Method Summary
 __init__(self, + keywords) +
 __call__(self, + *args) +
 __getattr__(self, + name) +
 __repr__(self) +
 _getconsumer(self, + keywords) +
    Inherited from object
 __delattr__(...) +
+x.__delattr__('name') <==> del x.name
 __getattribute__(...) +
+x.__getattribute__('name') <==> x.name
 __hash__(x) +
+x.__hash__() <==> hash(x)
 __new__(T, + S, + ...) +
+T.__new__(S, ...) -> a new object with type S, a subtype of T
 __reduce__(...) +
+helper for pickle
 __reduce_ex__(...) +
+helper for pickle
 __setattr__(...) +
+x.__setattr__('name', value) <==> x.name = value
 __str__(x) +
+x.__str__() <==> str(x)

+ + + + + + + + + + +
Class Variable Summary
dictkeywords2consumer = {'default': <function default_consum... +
typeMessage = logger.Message

+ + + + + + +
Class Variable Details
+
+ +

keywords2consumer

+
+
+
+
+
Type:
+
+ dict + +
+
Value:
+
+
+{'default': <function default_consumer at 0x40681d4c>}                 
+
+
+
+
+
+ + + + + + + + + + + + + + + + + +
Generated by Epydoc 2.1 on Wed Nov 16 09:59:23 2005http://epydoc.sf.net
+ + Index: /trunk/docs/private/toc-everything.html =================================================================== --- /trunk/docs/private/toc-everything.html (revision 2) +++ /trunk/docs/private/toc-everything.html (revision 2) @@ -0,0 +1,59 @@ + + + + + Everything + + + +
Everything
+
+ + +All Classes
+cheesecake.cheesecake_index.Cheesecake
+cheesecake.cheesecake_index.CodeParser
+cheesecake.cheesecake_index.CompositeIndex
+cheesecake.cheesecake_index.Index
+cheesecake.cheesecake_index.StdoutRedirector
+
+ + +All Exceptions
+cheesecake.cheesecake_index.CheesecakeError
+
+ + +All Functions
+main
+pad_left_spaces
+pad_msg
+pad_with_dots
+process_cmdline_args
+
+ + +All Variables
+INDEX_DIR
+INDEX_DIR_CRITICAL
+INDEX_DIR_EMPTY
+INDEX_FILE
+INDEX_FILE_CRITICAL
+INDEX_FILE_PYC
+INDEX_INSTALL
+INDEX_PYPI_DISTANCE
+INDEX_PYPI_DOWNLOAD
+INDEX_REQUIRED_FILES
+INDEX_UNPACK
+INDEX_UNPACK_DIR
+INDEX_URL_DOWNLOAD
+PAD_TEXT
+PAD_VALUE
+
+ +
+[show private | hide private] + + Index: /trunk/docs/private/index.html =================================================================== --- /trunk/docs/private/index.html (revision 2) +++ /trunk/docs/private/index.html (revision 2) @@ -0,0 +1,13 @@ + + + + cheesecake + + + + + + + + + Index: /trunk/docs/private/epydoc.css =================================================================== --- /trunk/docs/private/epydoc.css (revision 2) +++ /trunk/docs/private/epydoc.css (revision 2) @@ -0,0 +1,100 @@ + +/* Body color */ +body { background: #ffffff; color: #000000; } + +/* Tables */ +table.summary, table.details, table.index + { background: #e8f0f8; color: #000000; } +tr.summary, tr.details, tr.index + { background: #70b0f0; color: #000000; + text-align: left; font-size: 120%; } +tr.group { background: #c0e0f8; color: #000000; + text-align: left; font-size: 120%; + font-style: italic; } + +/* Documentation page titles */ +h2.module { margin-top: 0.2em; } +h2.class { margin-top: 0.2em; } + +/* Headings */ +h1.heading { font-size: +140%; font-style: italic; + font-weight: bold; } +h2.heading { font-size: +125%; font-style: italic; + font-weight: bold; } +h3.heading { font-size: +110%; font-style: italic; + font-weight: normal; } + +/* Base tree */ +pre.base-tree { font-size: 80%; margin: 0; } + +/* Details Sections */ +table.func-details { background: #e8f0f8; color: #000000; + border: 2px groove #c0d0d0; + padding: 0 1em 0 1em; margin: 0.4em 0 0 0; } +h3.func-detail { background: transparent; color: #000000; + margin: 0 0 1em 0; } + +table.var-details { background: #e8f0f8; color: #000000; + border: 2px groove #c0d0d0; + padding: 0 1em 0 1em; margin: 0.4em 0 0 0; } +h3.var-details { background: transparent; color: #000000; + margin: 0 0 1em 0; } + +/* Function signatures */ +.sig { background: transparent; color: #000000; + font-weight: bold; } +.sig-name { background: transparent; color: #006080; } +.sig-arg, .sig-kwarg, .sig-vararg + { background: transparent; color: #008060; } +.sig-default { background: transparent; color: #602000; } +.summary-sig { background: transparent; color: #000000; } +.summary-sig-name { background: transparent; color: #204080; } +.summary-sig-arg, .summary-sig-kwarg, .summary-sig-vararg + { background: transparent; color: #008060; } + +/* Doctest blocks */ +.py-src { background: transparent; color: #000000; } +.py-prompt { background: transparent; color: #005050; + font-weight: bold;} +.py-string { background: transparent; color: #006030; } +.py-comment { background: transparent; color: #003060; } +.py-keyword { background: transparent; color: #600000; } +.py-output { background: transparent; color: #404040; } +pre.doctestblock { background: #f4faff; color: #000000; + padding: .5em; margin: 1em; + border: 1px solid #708890; } +table pre.doctestblock + { background: #dce4ec; color: #000000; + padding: .5em; margin: 1em; + border: 1px solid #708890; } + +/* Variable values */ +pre.variable { background: #dce4ec; color: #000000; + padding: .5em; margin: 0; + border: 1px solid #708890; } +.variable-linewrap { background: transparent; color: #604000; } +.variable-ellipsis { background: transparent; color: #604000; } +.variable-quote { background: transparent; color: #604000; } +.re { background: transparent; color: #000000; } +.re-char { background: transparent; color: #006030; } +.re-op { background: transparent; color: #600000; } +.re-group { background: transparent; color: #003060; } +.re-ref { background: transparent; color: #404040; } + +/* Navigation bar */ +table.navbar { background: #a0c0ff; color: #0000ff; + border: 2px groove #c0d0d0; } +th.navbar { background: #a0c0ff; color: #0000ff; } +th.navselect { background: #70b0ff; color: #000000; } +.nomargin { margin: 0; } + +/* Links */ +a:link { background: transparent; color: #0000ff; } +a:visited { background: transparent; color: #204080; } +a.navbar:link { background: transparent; color: #0000ff; + text-decoration: none; } +a.navbar:visited { background: transparent; color: #204080; + text-decoration: none; } + +/* Lists */ +ul { margin-top: 0; } Index: /trunk/docs/private/cheesecake.cheesecake_index.Cheesecake-class.html =================================================================== --- /trunk/docs/private/cheesecake.cheesecake_index.Cheesecake-class.html (revision 2) +++ /trunk/docs/private/cheesecake.cheesecake_index.Cheesecake-class.html (revision 2) @@ -0,0 +1,598 @@ + + + + + cheesecake.cheesecake_index.Cheesecake + + + + + + + + + + + + + + + + + + +
+ + Package cheesecake :: + Module cheesecake_index :: + Class Cheesecake +
+
+ + +
[show private | hide private]
[frames | no frames]
+ + +

Type Cheesecake

+ +
+object --+
+         |
+        Cheesecake
+

+ +
+ +
+Computes 'goodness' of Python packages
+
+Generates "cheesecake index" that takes into account things like:
+
+    * whether the package can be downloaded
+    * whether the package can be unpacked
+    * whether the package can be installed into an alternate directory
+    * existence of certain files such as README, INSTALL, LICENSE, setup.py etc.
+    * existence of certain directories such as doc, test, demo, examples
+    * percentage of modules/functions/classes/methods with docstrings
+    * percentage of functions/methods that are unit tested 
+    * average pylint score for all non-test and non-demo modules
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Method Summary
 __init__(self, + name, + url, + path, + sandbox, + verbose, + quiet) +
+Initialize critical variables, download and unpack package, walk +package tree
 cleanup(self) +
+Delete temporary directories and files that were created in the +sandbox
 compute_cheesecake_index(self) +
+Compute overall Cheesecake index for the package by adding up specific +indexes
 configure_logging(self) +
+Default settings for logging
 copy_pkg(self) +
+Copy package file to sandbox directory
 determine_pkg_name(self) +
 download_pkg(self) +
+Use ``urllib.urlretrieve`` to download package to file in sandbox +dir
 get_package_from_path(self, + path) +
+Get package name as file portion of path
 get_package_from_url(self) +
+Use ``urlparse`` to obtain package path from URL
 get_pkg_from_pypi(self) +
+Download package using setuptools utilities
 index_dir(self) +
+Return CompositeIndex object of type "dir"
 index_docstrings(self) +
+Compute docstring index as percentage of +modules/classes/methods/functions that have docstrings associated with +them
 index_file(self) +
+Return CompositeIndex object of type "file"
 index_install(self) +
+Verify that package can be installed in alternate directory
 index_pylint(self) +
+Compute pylint index as average of positive pylint scores obtained for +the Python files identified in the package
 index_pypi_download(self) +
+Verify that package can be downloaded from PyPI
 index_unpack(self) +
+Verify that package can be unpacked
 index_unpack_dir(self) +
+Verify that unpack directory has same name as package
 index_url_download(self) +
+Verify that package can be downloaded from an URL
 init_indexes(self) +
+Initialize variables used in index computation
 is_py_file(self, + file, + dirs) +
+Return True if file ends with .py and it is not a special file and it +is not in special directory
 is_test_file(self, + file, + dirs) +
+Return True is file is in directory rooted at "test" or +"tests"
 print_line(self, + line) +
+Print line of text, unless quiet flag was given
 process_index(self, + index_type) +
+Compute and print index of specified type
 process_partial_index(self, + partial_index_name, + index_types, + max_value) +
 raise_exception(self, + msg) +
+Cleanup, print error message and raise CheesecakeError
 retrieve_pkg(self) +
 unpack_pkg(self) +
+Unpack the package in the sandbox directory
 untar_pkg(self) +
+Untar the package in the sandbox directory
 unzip_pkg(self) +
+Unzip the package in the sandbox directory
 walk_pkg(self) +
+Traverse the file system tree rooted at sandbox/package_name
    Inherited from object
 __delattr__(...) +
+x.__delattr__('name') <==> del x.name
 __getattribute__(...) +
+x.__getattribute__('name') <==> x.name
 __hash__(x) +
+x.__hash__() <==> hash(x)
 __new__(T, + S, + ...) +
+T.__new__(S, ...) -> a new object with type S, a subtype of T
 __reduce__(...) +
+helper for pickle
 __reduce_ex__(...) +
+helper for pickle
 __repr__(x) +
+x.__repr__() <==> repr(x)
 __setattr__(...) +
+x.__setattr__('name', value) <==> x.name = value
 __str__(x) +
+x.__str__() <==> str(x)

+ + + + + + +
Method Details
+ + +
+

__init__(self, + name='', + url='', + path='', + sandbox=None, + verbose=False, + quiet=False) +
(Constructor) +

+ Initialize critical variables, download and unpack package, walk + package tree +
+
Overrides:
+
__builtin__.object.__init__
+
+
+
+ + +
+

cleanup(self) +

+ Delete temporary directories and files that were created in the + sandbox +
+
+
+ + +
+

compute_cheesecake_index(self) +

+ Compute overall Cheesecake index for the package by adding up + specific indexes +
+
+
+ + +
+

configure_logging(self) +

+

Default settings for logging

+ if verbose, log goes to console, else it goes to logfile log.debug + goes to logfile log.info goes to console log.warn and log.error go to + both logfile and stdout +
+
+
+ + +
+

copy_pkg(self) +

+ Copy package file to sandbox directory +
+
+
+ + +
+

download_pkg(self) +

+ Use ``urllib.urlretrieve`` to download package to file in sandbox + dir +
+
+
+ + +
+

get_package_from_path(self, + path) +

+ Get package name as file portion of path +
+
+
+ + +
+

get_package_from_url(self) +

+ Use ``urlparse`` to obtain package path from URL +
+
+
+ + +
+

get_pkg_from_pypi(self) +

+ Download package using setuptools utilities +
+
+
+ + +
+

index_dir(self) +

+ Return CompositeIndex object of type "dir" +
+
+
+ + +
+

index_docstrings(self) +

+

Compute docstring index as percentage of + modules/classes/methods/functions that have docstrings associated with + them

+ Return Index object of type "docstrings" +
+
+
+ + +
+

index_file(self) +

+ Return CompositeIndex object of type "file" +
+
+
+ + +
+

index_install(self) +

+

Verify that package can be installed in alternate directory

+ Return Index object of type "install" +
+
+
+ + +
+

index_pylint(self) +

+

Compute pylint index as average of positive pylint scores obtained + for the Python files identified in the package

+ Return Index object of type "pylint" +
+
+
+ + +
+

index_pypi_download(self) +

+

Verify that package can be downloaded from PyPI

+ Return Index object of type "pypi_download" +
+
+
+ + +
+

index_unpack(self) +

+

Verify that package can be unpacked

+ Return Index object of type "unpack" +
+
+
+ + +
+

index_unpack_dir(self) +

+

Verify that unpack directory has same name as package

+ Return Index object of type "unpack_dir" +
+
+
+ + +
+

index_url_download(self) +

+

Verify that package can be downloaded from an URL

+ Return Index object of type "download" +
+
+
+ + +
+

init_indexes(self) +

+

Initialize variables used in index computation

+ * cheesecake_index: overall index for the package * index: dict + holding Index or CompositeIndex objects of various types +
+
+
+ + +
+

is_py_file(self, + file, + dirs) +

+ Return True if file ends with .py and it is not a special file and + it is not in special directory +
+
+
+ + +
+

is_test_file(self, + file, + dirs) +

+ Return True is file is in directory rooted at "test" or + "tests" +
+
+
+ + +
+

print_line(self, + line) +

+ Print line of text, unless quiet flag was given +
+
+
+ + +
+

process_index(self, + index_type) +

+ Compute and print index of specified type +
+
+
+ + +
+

raise_exception(self, + msg) +

+

Cleanup, print error message and raise CheesecakeError

+ Don't use logging, since it can be called before logging has been + setup +
+
+
+ + +
+

unpack_pkg(self) +

+

Unpack the package in the sandbox directory

+

Currently supported archive types:

+ * .tar.gz (handled with ``tarfile`` module) * .zip (handled with + ``zipfile`` module) +
+
+
+ + +
+

untar_pkg(self) +

+

Untar the package in the sandbox directory

+ Uses tarfile module +
+
+
+ + +
+

unzip_pkg(self) +

+

Unzip the package in the sandbox directory

+ Uses zipfile module +
+
+
+ + +
+

walk_pkg(self) +

+

Traverse the file system tree rooted at sandbox/package_name

+ * Compute indexes for special files and directories * Identify + Python files, test files, etc. +
+
+
+
+ + + + + + + + + + + + + + + + + + +
Generated by Epydoc 2.1 on Wed Dec 21 17:21:41 2005http://epydoc.sf.net
+ + Index: /trunk/docs/private/cheesecake.cheesecake_index-module.html =================================================================== --- /trunk/docs/private/cheesecake.cheesecake_index-module.html (revision 2) +++ /trunk/docs/private/cheesecake.cheesecake_index-module.html (revision 2) @@ -0,0 +1,561 @@ + + + + + cheesecake.cheesecake_index + + + + + + + + + + + + + + + + + + +
+ + Package cheesecake :: + Module cheesecake_index +
+
+ + +
[show private | hide private]
[frames | no frames]
+ + +

Module cheesecake.cheesecake_index

+ +
+Cheesecake: How tasty is your code?
+
+The idea of the Cheesecake project is to rank Python packages
+based on various empiric "kwalitee" factors, such as:
+
+        * whether the package can be downloaded
+        * whether the package can be unpacked
+        * whether the package can be installed into an alternate directory
+        * existence of certain files such as README, INSTALL, LICENSE, setup.py etc.
+        * existence of certain directories such as doc, test, demo, examples
+        * percentage of modules/functions/classes/methods with docstrings
+        * percentage of functions/methods that are unit tested
+        * average pylint score for all non-test and non-demo modules
+        * whether the package can be unpacked
+        * whether the package can be installed into an alternate directory
+
+
+ + + + + + + + + + + + + + + +
Classes
+ CheesecakeComputes 'goodness' of Python packages + +Generates "cheesecake index" that takes into account things like: + + * whether the package can be downloaded + * whether the package can be unpacked + * whether the package can be installed into an alternate directory + * existence of certain files such as README, INSTALL, LICENSE, setup.py etc.
+ CodeParserInformation about the structure of a Python module
+ CompositeIndexCollection of indexes of same type (e.g.
+ IndexEncapsulates index attributes such as name, value, details
+ StdoutRedirectorRedirect stdout to a temp file

+ + + + + + + + +
Exceptions
+ CheesecakeErrorCustom exception class for Cheesecake-specific errors

+ + + + + + + + + + + + + + + + +
Function Summary
 main() +
+Display Cheesecake index for package specified via command-line +options
 pad_left_spaces(value, + length) +
+Pad value with spaces at left up to given length
 pad_msg(msg, + value) +
+Pad message with dots and pad value with spaces
 pad_with_dots(msg, + length) +
+Pad text with dots up to given length
 process_cmdline_args() +
+Parse command-line options

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Variable Summary
intINDEX_DIR = 20                                                                    
intINDEX_DIR_CRITICAL = 25                                                                    
intINDEX_DIR_EMPTY = 5                                                                     
intINDEX_FILE = 10                                                                    
intINDEX_FILE_CRITICAL = 15                                                                    
intINDEX_FILE_PYC = -20                                                                   
intINDEX_INSTALL = 50                                                                    
intINDEX_PYPI_DISTANCE = 5                                                                     
intINDEX_PYPI_DOWNLOAD = 50                                                                    
intINDEX_REQUIRED_FILES = 100                                                                   
intINDEX_UNPACK = 25                                                                    
intINDEX_UNPACK_DIR = 15                                                                    
intINDEX_URL_DOWNLOAD = 25                                                                    
intPAD_TEXT = 40                                                                    
intPAD_VALUE = 4                                                                     

+ + + + + + +
Function Details
+ + +
+

main() +

+ Display Cheesecake index for package specified via command-line + options +
+
+
+ + +
+

pad_left_spaces(value, + length=4) +

+ Pad value with spaces at left up to given length +
+
+
+ + +
+

pad_msg(msg, + value) +

+ Pad message with dots and pad value with spaces +
+
+
+ + +
+

pad_with_dots(msg, + length=40) +

+ Pad text with dots up to given length +
+
+
+ + +
+

process_cmdline_args() +

+ Parse command-line options +
+
+
+
+ + + + + + +
Variable Details
+
+ +

INDEX_DIR

+
+
+
+
+
Type:
+
+ int + +
+
Value:
+
+
+20                                                                    
+
+
+
+
+
+ +

INDEX_DIR_CRITICAL

+
+
+
+
+
Type:
+
+ int + +
+
Value:
+
+
+25                                                                    
+
+
+
+
+
+ +

INDEX_DIR_EMPTY

+
+
+
+
+
Type:
+
+ int + +
+
Value:
+
+
+5                                                                     
+
+
+
+
+
+ +

INDEX_FILE

+
+
+
+
+
Type:
+
+ int + +
+
Value:
+
+
+10                                                                    
+
+
+
+
+
+ +

INDEX_FILE_CRITICAL

+
+
+
+
+
Type:
+
+ int + +
+
Value:
+
+
+15                                                                    
+
+
+
+
+
+ +

INDEX_FILE_PYC

+
+
+
+
+
Type:
+
+ int + +
+
Value:
+
+
+-20                                                                   
+
+
+
+
+
+ +

INDEX_INSTALL

+
+
+
+
+
Type:
+
+ int + +
+
Value:
+
+
+50                                                                    
+
+
+
+
+
+ +

INDEX_PYPI_DISTANCE

+
+
+
+
+
Type:
+
+ int + +
+
Value:
+
+
+5                                                                     
+
+
+
+
+
+ +

INDEX_PYPI_DOWNLOAD

+
+
+
+
+
Type:
+
+ int + +
+
Value:
+
+
+50                                                                    
+
+
+
+
+
+ +

INDEX_REQUIRED_FILES

+
+
+
+
+
Type:
+
+ int + +
+
Value:
+
+
+100                                                                   
+
+
+
+
+
+ +

INDEX_UNPACK

+
+
+
+
+
Type:
+
+ int + +
+
Value:
+
+
+25                                                                    
+
+
+
+
+
+ +

INDEX_UNPACK_DIR

+
+
+
+
+
Type:
+
+ int + +
+
Value:
+
+
+15                                                                    
+
+
+
+
+
+ +

INDEX_URL_DOWNLOAD

+
+
+
+
+
Type:
+
+ int + +
+
Value:
+
+
+25                                                                    
+
+
+
+
+
+ +

PAD_TEXT

+
+
+
+
+
Type:
+
+ int + +
+
Value:
+
+
+40                                                                    
+
+
+
+
+
+ +

PAD_VALUE

+
+
+
+
+
Type:
+
+ int + +
+
Value:
+
+
+4                                                                     
+
+
+
+
+
+ + + + + + + + + + + + + + + + + + +
Generated by Epydoc 2.1 on Wed Dec 21 17:21:41 2005http://epydoc.sf.net
+ + Index: /trunk/docs/public/cheesecake.CheesecakeError-class.html =================================================================== --- /trunk/docs/public/cheesecake.CheesecakeError-class.html (revision 2) +++ /trunk/docs/public/cheesecake.CheesecakeError-class.html (revision 2) @@ -0,0 +1,98 @@ + + + + + cheesecake.CheesecakeError + + + + + + + + + + + + + + + + + +
+ + Module cheesecake :: + Class CheesecakeError +
+
+ + +
[show private | hide private]
[frames | no frames]
+ + +

Class CheesecakeError

+ +
+Exception --+
+            |
+           CheesecakeError
+

+ +
+ +

Custom exception class for Cheesecake-specific errors

+
+ + + + + + + + + + + + + + +
Method Summary
    Inherited from Exception
 __init__(...) +
 __getitem__(...) +
 __str__(...) +

+ + + + + + + + + + + + + + + + + +
Generated by Epydoc 2.1 on Wed Nov 16 09:59:23 2005http://epydoc.sf.net
+ + Index: /trunk/docs/public/cheesecake.CompositeIndex-class.html =================================================================== --- /trunk/docs/public/cheesecake.CompositeIndex-class.html (revision 2) +++ /trunk/docs/public/cheesecake.CompositeIndex-class.html (revision 2) @@ -0,0 +1,228 @@ + + + + + cheesecake.CompositeIndex + + + + + + + + + + + + + + + + + +
+ + Module cheesecake :: + Class CompositeIndex +
+
+ + +
[show private | hide private]
[frames | no frames]
+ + +

Type CompositeIndex

+ +
+object --+
+         |
+        CompositeIndex
+

+ +
+ +

Collection of indexes of same type (e.g. files, dirs)

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Method Summary
 __init__(self, + type) +
+Indexes is a dict mapping names to Index objects
 get_value(self) +
+Return sum of individual index values
 print_info(self) +
+Print index info for all indexes sorted alphanumerically by name
 set_index(self, + name, + value, + details) +
+Create new index or update existing index with specified attributes
    Inherited from object
 __delattr__(...) +
+x.__delattr__('name') <==> del x.name
 __getattribute__(...) +
+x.__getattribute__('name') <==> x.name
 __hash__(x) +
+x.__hash__() <==> hash(x)
 __new__(T, + S, + ...) +
+T.__new__(S, ...) -> a new object with type S, a subtype of T
 __reduce__(...) +
+helper for pickle
 __reduce_ex__(...) +
+helper for pickle
 __repr__(x) +
+x.__repr__() <==> repr(x)
 __setattr__(...) +
+x.__setattr__('name', value) <==> x.name = value
 __str__(x) +
+x.__str__() <==> str(x)

+ + + + + + + +
Property Summary
 value

+ + + + + + +
Method Details
+ + +
+

__init__(self, + type) +
(Constructor) +

+

Indexes is a dict mapping names to Index objects

+
+
Overrides:
+
__builtin__.object.__init__
+
+
+
+ + +
+

get_value(self) +

+

Return sum of individual index values

+
+
+
+ + +
+

print_info(self) +

+

Print index info for all indexes sorted alphanumerically by name

+
+
+
+ + +
+

set_index(self, + name, + value=0, + details='') +

+

Create new index or update existing index with specified attributes

+
+
+
+
+ + + + + + +
Property Details
+
+ + +

value

+
+
+
+
+
Get Method:
+
get_value(self) +
+
+
+

+ + + + + + + + + + + + + + + + + +
Generated by Epydoc 2.1 on Wed Nov 16 09:59:23 2005http://epydoc.sf.net
+ + Index: /trunk/docs/public/logger.Path-class.html =================================================================== --- /trunk/docs/public/logger.Path-class.html (revision 2) +++ /trunk/docs/public/logger.Path-class.html (revision 2) @@ -0,0 +1,137 @@ + + + + + logger.Path + + + + + + + + + + + + + + + + + +
+ + Module logger :: + Class Path +
+
+ + +
[show private | hide private]
[frames | no frames]
+ + +

Type Path

+ +
+object --+    
+         |    
+      File --+
+             |
+            Path
+

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Method Summary
 __init__(self, + filename, + append) +
    Inherited from File
 __call__(self, + msg) +
    Inherited from object
 __delattr__(...) +
+x.__delattr__('name') <==> del x.name
 __getattribute__(...) +
+x.__getattribute__('name') <==> x.name
 __hash__(x) +
+x.__hash__() <==> hash(x)
 __new__(T, + S, + ...) +
+T.__new__(S, ...) -> a new object with type S, a subtype of T
 __reduce__(...) +
+helper for pickle
 __reduce_ex__(...) +
+helper for pickle
 __repr__(x) +
+x.__repr__() <==> repr(x)
 __setattr__(...) +
+x.__setattr__('name', value) <==> x.name = value
 __str__(x) +
+x.__str__() <==> str(x)

+ + + + + + + + + + + + + + + + + +
Generated by Epydoc 2.1 on Wed Nov 16 09:59:23 2005http://epydoc.sf.net
+ + Index: /trunk/docs/public/frames.html =================================================================== --- /trunk/docs/public/frames.html (revision 2) +++ /trunk/docs/public/frames.html (revision 2) @@ -0,0 +1,13 @@ + + + + cheesecake + + + + + + + + + Index: /trunk/docs/public/indices.html =================================================================== --- /trunk/docs/public/indices.html (revision 2) +++ /trunk/docs/public/indices.html (revision 2) @@ -0,0 +1,289 @@ + + + + + Index + + + + + + + + + + + + + + + + + + +
+ + + +
[show private | hide private]
[frames | no frames]
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Identifier Index
objectClass in module __builtin__
__bases__Variable in class __builtin__.type
__basicsize__Variable in class __builtin__.type
__call__Method in class __builtin__.type
typeClass in module __builtin__
__cmp__Method in class __builtin__.type
__delattr__Method in class __builtin__.object
__delattr__Method in class __builtin__.type
__dictoffset__Variable in class __builtin__.type
__flags__Variable in class __builtin__.type
__getattribute__Method in class __builtin__.object
__getattribute__Method in class __builtin__.type
__getitem__Method in class exceptions.Exception
__hash__Method in class __builtin__.object
__hash__Method in class __builtin__.type
__init__Method in class __builtin__.object
__init__Method in class cheesecake.cheesecake_index.Cheesecake
__init__Method in class cheesecake.cheesecake_index.CodeParser
__init__Method in class cheesecake.cheesecake_index.CompositeIndex
__init__Method in class cheesecake.cheesecake_index.Index
__init__Method in class cheesecake.cheesecake_index.StdoutRedirector
__init__Method in class exceptions.Exception
__itemsize__Variable in class __builtin__.type
__mro__Variable in class __builtin__.type
__name__Variable in class __builtin__.type
__new__Method in class __builtin__.object
__new__Method in class __builtin__.type
__reduce__Method in class __builtin__.object
__reduce_ex__Method in class __builtin__.object
__repr__Method in class __builtin__.object
__repr__Method in class __builtin__.type
__setattr__Method in class __builtin__.object
__setattr__Method in class __builtin__.type
__str__Method in class __builtin__.object
__str__Method in class exceptions.Exception
__subclasses__Method in class __builtin__.type
__weakrefoffset__Variable in class __builtin__.type
CheesecakeClass in module cheesecake.cheesecake_index
cheesecake_indexModule in package cheesecake
CheesecakeErrorClass in module cheesecake.cheesecake_index
cleanupMethod in class cheesecake.cheesecake_index.Cheesecake
CodeParserClass in module cheesecake.cheesecake_index
CompositeIndexClass in module cheesecake.cheesecake_index
compute_cheesecake_indexMethod in class cheesecake.cheesecake_index.Cheesecake
configure_loggingMethod in class cheesecake.cheesecake_index.Cheesecake
copy_pkgMethod in class cheesecake.cheesecake_index.Cheesecake
determine_pkg_nameMethod in class cheesecake.cheesecake_index.Cheesecake
docstring_countMethod in class cheesecake.cheesecake_index.CodeParser
download_pkgMethod in class cheesecake.cheesecake_index.Cheesecake
ExceptionClass in module exceptions
flushMethod in class cheesecake.cheesecake_index.StdoutRedirector
get_package_from_pathMethod in class cheesecake.cheesecake_index.Cheesecake
get_package_from_urlMethod in class cheesecake.cheesecake_index.Cheesecake
get_pkg_from_pypiMethod in class cheesecake.cheesecake_index.Cheesecake
get_valueMethod in class cheesecake.cheesecake_index.CompositeIndex
IndexClass in module cheesecake.cheesecake_index
index_dirMethod in class cheesecake.cheesecake_index.Cheesecake
INDEX_DIRVariable in module cheesecake.cheesecake_index
INDEX_DIR_CRITICALVariable in module cheesecake.cheesecake_index
INDEX_DIR_EMPTYVariable in module cheesecake.cheesecake_index
index_docstringsMethod in class cheesecake.cheesecake_index.Cheesecake
index_fileMethod in class cheesecake.cheesecake_index.Cheesecake
INDEX_FILEVariable in module cheesecake.cheesecake_index
INDEX_FILE_CRITICALVariable in module cheesecake.cheesecake_index
INDEX_FILE_PYCVariable in module cheesecake.cheesecake_index
index_installMethod in class cheesecake.cheesecake_index.Cheesecake
INDEX_INSTALLVariable in module cheesecake.cheesecake_index
index_pylintMethod in class cheesecake.cheesecake_index.Cheesecake
INDEX_PYPI_DISTANCEVariable in module cheesecake.cheesecake_index
index_pypi_downloadMethod in class cheesecake.cheesecake_index.Cheesecake
INDEX_PYPI_DOWNLOADVariable in module cheesecake.cheesecake_index
INDEX_REQUIRED_FILESVariable in module cheesecake.cheesecake_index
index_unpackMethod in class cheesecake.cheesecake_index.Cheesecake
INDEX_UNPACKVariable in module cheesecake.cheesecake_index
index_unpack_dirMethod in class cheesecake.cheesecake_index.Cheesecake
INDEX_UNPACK_DIRVariable in module cheesecake.cheesecake_index
index_url_downloadMethod in class cheesecake.cheesecake_index.Cheesecake
INDEX_URL_DOWNLOADVariable in module cheesecake.cheesecake_index
init_indexesMethod in class cheesecake.cheesecake_index.Cheesecake
is_py_fileMethod in class cheesecake.cheesecake_index.Cheesecake
is_test_fileMethod in class cheesecake.cheesecake_index.Cheesecake
mainFunction in module cheesecake.cheesecake_index
mroMethod in class __builtin__.type
objectClass in module __builtin__
object_countMethod in class cheesecake.cheesecake_index.CodeParser
pad_left_spacesFunction in module cheesecake.cheesecake_index
pad_msgFunction in module cheesecake.cheesecake_index
PAD_TEXTVariable in module cheesecake.cheesecake_index
PAD_VALUEVariable in module cheesecake.cheesecake_index
pad_with_dotsFunction in module cheesecake.cheesecake_index
parse_fileMethod in class cheesecake.cheesecake_index.CodeParser
print_infoMethod in class cheesecake.cheesecake_index.CompositeIndex
print_infoMethod in class cheesecake.cheesecake_index.Index
print_lineMethod in class cheesecake.cheesecake_index.Cheesecake
process_cmdline_argsFunction in module cheesecake.cheesecake_index
process_indexMethod in class cheesecake.cheesecake_index.Cheesecake
process_partial_indexMethod in class cheesecake.cheesecake_index.Cheesecake
raise_exceptionMethod in class cheesecake.cheesecake_index.Cheesecake
read_bufferMethod in class cheesecake.cheesecake_index.StdoutRedirector
retrieve_pkgMethod in class cheesecake.cheesecake_index.Cheesecake
set_indexMethod in class cheesecake.cheesecake_index.CompositeIndex
StdoutRedirectorClass in module cheesecake.cheesecake_index
typeClass in module __builtin__
unpack_pkgMethod in class cheesecake.cheesecake_index.Cheesecake
untar_pkgMethod in class cheesecake.cheesecake_index.Cheesecake
unzip_pkgMethod in class cheesecake.cheesecake_index.Cheesecake
valueMethod in class cheesecake.cheesecake_index.Cheesecake in class cheesecake.cheesecake_index.CompositeIndex
walk_pkgMethod in class cheesecake.cheesecake_index.Cheesecake
writeMethod in class cheesecake.cheesecake_index.StdoutRedirector
+
+ + + + + + + + + + + + + + + + + +
Generated by Epydoc 2.1 on Wed Dec 21 17:21:41 2005http://epydoc.sf.net
+ + Index: /trunk/docs/public/cheesecake.cheesecake_index.CodeParser-class.html =================================================================== --- /trunk/docs/public/cheesecake.cheesecake_index.CodeParser-class.html (revision 2) +++ /trunk/docs/public/cheesecake.cheesecake_index.CodeParser-class.html (revision 2) @@ -0,0 +1,188 @@ + + + + + cheesecake.cheesecake_index.CodeParser + + + + + + + + + + + + + + + + + + +
+ + Package cheesecake :: + Module cheesecake_index :: + Class CodeParser +
+
+ + +
[show private | hide private]
[frames | no frames]
+ + +

Type CodeParser

+ +
+object --+
+         |
+        CodeParser
+

+ +
+ +

Information about the structure of a Python module

+* Collects classes, methods, functions and any associated docstrings * +Does some dumb grep-style parsing, but in the future may do some real +smart parsing +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Method Summary
 __init__(self, + pyfile, + log) +
 docstring_count(self) +
+Return number of docstrings found in this module
 object_count(self) +
+Return number of objects found in this module
 parse_file(self) +
+Parse module text and retrieve classes, methods, functions and +associated docstrings
    Inherited from object
 __delattr__(...) +
+x.__delattr__('name') <==> del x.name
 __getattribute__(...) +
+x.__getattribute__('name') <==> x.name
 __hash__(x) +
+x.__hash__() <==> hash(x)
 __new__(T, + S, + ...) +
+T.__new__(S, ...) -> a new object with type S, a subtype of T
 __reduce__(...) +
+helper for pickle
 __reduce_ex__(...) +
+helper for pickle
 __repr__(x) +
+x.__repr__() <==> repr(x)
 __setattr__(...) +
+x.__setattr__('name', value) <==> x.name = value
 __str__(x) +
+x.__str__() <==> str(x)

+ + + + + + +
Method Details
+ + +
+

docstring_count(self) +

+ Return number of docstrings found in this module +
+
+
+ + +
+

object_count(self) +

+

Return number of objects found in this module

+ * module * classes * methods * functions +
+
+
+ + +
+

parse_file(self) +

+ Parse module text and retrieve classes, methods, functions and + associated docstrings +
+
+
+
+ + + + + + + + + + + + + + + + + + +
Generated by Epydoc 2.1 on Wed Dec 21 17:21:41 2005http://epydoc.sf.net
+ + Index: /trunk/docs/public/logger.MultipleProducer-class.html =================================================================== --- /trunk/docs/public/logger.MultipleProducer-class.html (revision 2) +++ /trunk/docs/public/logger.MultipleProducer-class.html (revision 2) @@ -0,0 +1,152 @@ + + + + + logger.MultipleProducer + + + + + + + + + + + + + + + + + +
+ + Module logger :: + Class MultipleProducer +
+
+ + +
[show private | hide private]
[frames | no frames]
+ + +

Type MultipleProducer

+ +
+object --+    
+         |    
+  Producer --+
+             |
+            MultipleProducer
+

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Method Summary
 __call__(self, + *args, + **kwargs) +
    Inherited from Producer
 __init__(self, + keywords) +
 __getattr__(self, + name) +
 __repr__(self) +
    Inherited from object
 __delattr__(...) +
+x.__delattr__('name') <==> del x.name
 __getattribute__(...) +
+x.__getattribute__('name') <==> x.name
 __hash__(x) +
+x.__hash__() <==> hash(x)
 __new__(T, + S, + ...) +
+T.__new__(S, ...) -> a new object with type S, a subtype of T
 __reduce__(...) +
+helper for pickle
 __reduce_ex__(...) +
+helper for pickle
 __setattr__(...) +
+x.__setattr__('name', value) <==> x.name = value
 __str__(x) +
+x.__str__() <==> str(x)

+ + + + + + + + + + +
Class Variable Summary
    Inherited from Producer
dictkeywords2consumer = {'default': <function default_consum... +

+ + + + + + + + + + + + + + + + + +
Generated by Epydoc 2.1 on Wed Nov 16 09:59:23 2005http://epydoc.sf.net
+ + Index: /trunk/docs/public/exceptions.Exception-class.html =================================================================== --- /trunk/docs/public/exceptions.Exception-class.html (revision 2) +++ /trunk/docs/public/exceptions.Exception-class.html (revision 2) @@ -0,0 +1,96 @@ + + + + + exceptions.Exception + + + + + + + + + + + + + + + + + + +
+ + Module exceptions :: + Class Exception +
+
+ + +
[show private | hide private]
[frames | no frames]
+ + +

Class Exception

+ +
Known Subclasses:
+
+ CheesecakeError
+ +
+ +Common base class for all exceptions. +
+ + + + + + + + + + + + +
Method Summary
 __init__(...) +
 __getitem__(...) +
 __str__(...) +

+ + + + + + + + + + + + + + + + + + +
Generated by Epydoc 2.1 on Wed Dec 21 17:21:41 2005http://epydoc.sf.net
+ + Index: /trunk/docs/public/toc-logger-module.html =================================================================== --- /trunk/docs/public/toc-logger-module.html (revision 2) +++ /trunk/docs/public/toc-logger-module.html (revision 2) @@ -0,0 +1,39 @@ + + + + + logger + + + +
logger
+
+ + +Classes
+File
+Message
+MultipleProducer
+Path
+Producer
+
+ + +Functions
+default_consumer
+setconsumer
+STDERR
+STDOUT
+
+ + +Variables
+default
+
+ +
+[show private | hide private] + + Index: /trunk/docs/public/__builtin__.type-class.html =================================================================== --- /trunk/docs/public/__builtin__.type-class.html (revision 2) +++ /trunk/docs/public/__builtin__.type-class.html (revision 2) @@ -0,0 +1,516 @@ + + + + + __builtin__.type + + + + + + + + + + + + + + + + + + +
+ + Module __builtin__ :: + Class type +
+
+ + +
[show private | hide private]
[frames | no frames]
+ + +

Type type

+ +
+object --+
+         |
+        type
+

+ +
+ +type(object) -> the object's type type(name, bases, dict) -> a +new type +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Method Summary
 __call__(x, + ...) +
+x.__call__(...) <==> x(...)
 __cmp__(x, + y) +
+x.__cmp__(y) <==> cmp(x,y)
 __delattr__(...) +
+x.__delattr__('name') <==> del x.name
 __getattribute__(...) +
+x.__getattribute__('name') <==> x.name
 __hash__(x) +
+x.__hash__() <==> hash(x)
 __new__(T, + S, + ...) +
+T.__new__(S, ...) -> a new object with type S, a subtype of T
 __repr__(x) +
+x.__repr__() <==> repr(x)
 __setattr__(...) +
+x.__setattr__('name', value) <==> x.name = value
list of immediate subclasses__subclasses__() +
+__subclasses__() -> list of immediate subclasses
listmro() +
+return a type's method resolution order
    Inherited from object
 __init__(...) +
+x.__init__(...) initializes x; see x.__class__.__doc__ for +signature
 __reduce__(...) +
+helper for pickle
 __reduce_ex__(...) +
+helper for pickle
 __str__(x) +
+x.__str__() <==> str(x)

+ + + + + + + + + + + + + + + + + + + + + + + + +
Class Variable Summary
type__base__ = __builtin__.object
tuple__bases__ = (<type 'object'>,) +
int__basicsize__ = 420                                                                   
int__dictoffset__ = 132                                                                   
int__flags__ = 21995                                                                 
int__itemsize__ = 20                                                                    
tuple__mro__ = (<type 'type'>, <type 'object'>) +
str__name__ = 'type' +
int__weakrefoffset__ = 184                                                                   

+ + + + + + +
Method Details
+ + +
+

__call__(x, + ...) +
(Call operator) +

+ x.__call__(...) <==> x(...) +
+
Returns:
+
+
+x(...)
+
+
+
+
+
+ + +
+

__cmp__(x, + y) +
(Comparison operator) +

+ x.__cmp__(y) <==> cmp(x,y) +
+
Returns:
+
+
+cmp(x,y)
+
+
+
+
+
+ + +
+

__delattr__(...) +

+ x.__delattr__('name') <==> del x.name +
+
Overrides:
+
__builtin__.object.__delattr__
+
+
+
+ + +
+

__getattribute__(...) +

+ x.__getattribute__('name') <==> x.name +
+
Overrides:
+
__builtin__.object.__getattribute__
+
+
+
+ + +
+

__hash__(x) +
(Hashing function) +

+ x.__hash__() <==> hash(x) +
+
Returns:
+
+
+hash(x)
+
+
+
+
Overrides:
+
__builtin__.object.__hash__
+
+
+
+ + +
+

__new__(T, + S, + ...) +

+ T.__new__(S, ...) -> a new object with type S, a subtype of T +
+
Returns:
+
+
+a new object with type S, a subtype of T
+
+
+
+
Overrides:
+
__builtin__.object.__new__
+
+
+
+ + +
+

__repr__(x) +
(Representation operator) +

+ x.__repr__() <==> repr(x) +
+
Returns:
+
+
+repr(x)
+
+
+
+
Overrides:
+
__builtin__.object.__repr__
+
+
+
+ + +
+

__setattr__(...) +

+ x.__setattr__('name', value) <==> x.name = value +
+
Overrides:
+
__builtin__.object.__setattr__
+
+
+
+ + +
+

__subclasses__() +

+ __subclasses__() -> list of immediate subclasses +
+
Returns:
+
+list of immediate subclasses
+
+
+
+ + +
+

mro() +

+ return a type's method resolution order +
+
Returns:
+
+list
+
+
+
+
+ + + + + + +
Class Variable Details
+
+ +

__bases__

+
+
+
+
+
Type:
+
+ tuple + +
+
Value:
+
+
+(<type 'object'>,)                                                     
+
+
+
+
+
+ +

__basicsize__

+
+
+
+
+
Type:
+
+ int + +
+
Value:
+
+
+420                                                                   
+
+
+
+
+
+ +

__dictoffset__

+
+
+
+
+
Type:
+
+ int + +
+
Value:
+
+
+132                                                                   
+
+
+
+
+
+ +

__flags__

+
+
+
+
+
Type:
+
+ int + +
+
Value:
+
+
+21995                                                                 
+
+
+
+
+
+ +

__itemsize__

+
+
+
+
+
Type:
+
+ int + +
+
Value:
+
+
+20                                                                    
+
+
+
+
+
+ +

__mro__

+
+
+
+
+
Type:
+
+ tuple + +
+
Value:
+
+
+(<type 'type'>, <type 'object'>)                                       
+
+
+
+
+
+ +

__name__

+
+
+
+
+
Type:
+
+ str + +
+
Value:
+
+
+'type'                                                                 
+
+
+
+
+
+ +

__weakrefoffset__

+
+
+
+
+
Type:
+
+ int + +
+
Value:
+
+
+184                                                                   
+
+
+
+
+
+ + + + + + + + + + + + + + + + + + +
Generated by Epydoc 2.1 on Wed Dec 21 17:21:41 2005http://epydoc.sf.net
+ + Index: /trunk/docs/public/cheesecake.StdoutRedirector-class.html =================================================================== --- /trunk/docs/public/cheesecake.StdoutRedirector-class.html (revision 2) +++ /trunk/docs/public/cheesecake.StdoutRedirector-class.html (revision 2) @@ -0,0 +1,159 @@ + + + + + cheesecake.StdoutRedirector + + + + + + + + + + + + + + + + + +
+ + Module cheesecake :: + Class StdoutRedirector +
+
+ + +
[show private | hide private]
[frames | no frames]
+ + +

Type StdoutRedirector

+ +
+object --+
+         |
+        StdoutRedirector
+

+ +
+ +

Redirect stdout to a temp file

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Method Summary
 __init__(self, + filename) +
 flush(self) +
 read_buffer(self) +
+Return contents of the temp file
 write(self, + buf) +
    Inherited from object
 __delattr__(...) +
+x.__delattr__('name') <==> del x.name
 __getattribute__(...) +
+x.__getattribute__('name') <==> x.name
 __hash__(x) +
+x.__hash__() <==> hash(x)
 __new__(T, + S, + ...) +
+T.__new__(S, ...) -> a new object with type S, a subtype of T
 __reduce__(...) +
+helper for pickle
 __reduce_ex__(...) +
+helper for pickle
 __repr__(x) +
+x.__repr__() <==> repr(x)
 __setattr__(...) +
+x.__setattr__('name', value) <==> x.name = value
 __str__(x) +
+x.__str__() <==> str(x)

+ + + + + + +
Method Details
+ + +
+

read_buffer(self) +

+

Return contents of the temp file

+
+
+
+
+ + + + + + + + + + + + + + + + + +
Generated by Epydoc 2.1 on Wed Nov 16 09:59:23 2005http://epydoc.sf.net
+ + Index: /trunk/docs/public/help.html =================================================================== --- /trunk/docs/public/help.html (revision 2) +++ /trunk/docs/public/help.html (revision 2) @@ -0,0 +1,236 @@ + + + + + Help + + + + + + + + + + + + + + + + + + +
+ + + +
[show private | hide private]
[frames | no frames]
+ +

API Documentation

+ +

This document contains the API (Application Programming Interface) +documentation for cheesecake. Documentation for the Python +objects defined by the project is divided into separate pages for each +package, module, and class. The API documentation also includes two +pages containing information about the project as a whole: a trees +page, and an index page.

+ +

Object Documentation

+ +

Each Package Documentation page contains: +

+ +

Each Module Documentation page contains: +

+ +

Each Class Documentation page contains: +

+ +

Project Documentation

+ +

The Trees page contains the module and class hierarchies: +

+ +

The Index page contains indices of terms and + identifiers: +

+ +

The Table of Contents

+ +

The table of contents occupies the two frames on the left side of +the window. The upper-left frame displays the project +contents, and the lower-left frame displays the module +contents:

+ +
+ + + + + + + + +
+ Project
Contents
...
+ API
Documentation
Frame


+
+ Module
Contents
 
...
 
+

+
+ +

The project contents frame contains a list of all packages +and modules that are defined by the project. Clicking on an entry +will display its contents in the module contents frame. Clicking on a +special entry, labeled "Everything," will display the contents of +the entire project.

+ +

The module contents frame contains a list of every +submodule, class, type, exception, function, and variable defined by a +module or package. Clicking on an entry will display its +documentation in the API documentation frame. Clicking on the name of +the module, at the top of the frame, will display the documentation +for the module itself.

+ +

The "frames" and "no frames" buttons below the top +navigation bar can be used to control whether the table of contents is +displayed or not.

+ +

The Navigation Bar

+ +

A navigation bar is located at the top and bottom of every page. +It indicates what type of page you are currently viewing, and allows +you to go to related pages. The following table describes the labels +on the navigation bar. Note that not some labels (such as +[Parent]) are not displayed on all pages.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
LabelHighlighted when...Links to...
[Parent](never highlighted) the parent of the current package
[Package]viewing a packagethe package containing the current object +
[Module]viewing a modulethe module containing the current object +
[Class]viewing a class the class containing the current object
[Trees]viewing the trees page the trees page
[Index]viewing the index page the index page
[Help]viewing the help page the help page
+ +

The "show private" and "hide private" buttons below +the top navigation bar can be used to control whether documentation +for private objects is displayed. Private objects are usually defined +as objects whose (short) names begin with a single underscore, but do +not end with an underscore. For example, "_x", +"__pprint", and "epydoc.epytext._tokenize" +are private objects; but "re.sub", +"__init__", and "type_" are not. However, +if a module defines the "__all__" variable, then its +contents are used to decide which objects are private.

+ +

A timestamp below the bottom navigation bar indicates when each +page was last updated.

+ + + + + + + + + + + + + + + + + +
Generated by Epydoc 2.1 on Wed Dec 21 17:21:41 2005http://epydoc.sf.net
+ + Index: /trunk/docs/public/cheesecake.cheesecake_index.Index-class.html =================================================================== --- /trunk/docs/public/cheesecake.cheesecake_index.Index-class.html (revision 2) +++ /trunk/docs/public/cheesecake.cheesecake_index.Index-class.html (revision 2) @@ -0,0 +1,158 @@ + + + + + cheesecake.cheesecake_index.Index + + + + + + + + + + + + + + + + + + +
+ + Package cheesecake :: + Module cheesecake_index :: + Class Index +
+
+ + +
[show private | hide private]
[frames | no frames]
+ + +

Type Index

+ +
+object --+
+         |
+        Index
+

+ +
+ +Encapsulates index attributes such as name, value, details +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Method Summary
 __init__(self, + type, + name, + value, + details) +
 print_info(self) +
+Print index name padded with dots, followed by value and details
    Inherited from object
 __delattr__(...) +
+x.__delattr__('name') <==> del x.name
 __getattribute__(...) +
+x.__getattribute__('name') <==> x.name
 __hash__(x) +
+x.__hash__() <==> hash(x)
 __new__(T, + S, + ...) +
+T.__new__(S, ...) -> a new object with type S, a subtype of T
 __reduce__(...) +
+helper for pickle
 __reduce_ex__(...) +
+helper for pickle
 __repr__(x) +
+x.__repr__() <==> repr(x)
 __setattr__(...) +
+x.__setattr__('name', value) <==> x.name = value
 __str__(x) +
+x.__str__() <==> str(x)

+ + + + + + +
Method Details
+ + +
+

print_info(self) +

+ Print index name padded with dots, followed by value and details +
+
+
+
+ + + + + + + + + + + + + + + + + + +
Generated by Epydoc 2.1 on Wed Dec 21 17:21:41 2005http://epydoc.sf.net
+ + Index: /trunk/docs/public/logger.File-class.html =================================================================== --- /trunk/docs/public/logger.File-class.html (revision 2) +++ /trunk/docs/public/logger.File-class.html (revision 2) @@ -0,0 +1,136 @@ + + + + + logger.File + + + + + + + + + + + + + + + + + +
+ + Module logger :: + Class File +
+
+ + +
[show private | hide private]
[frames | no frames]
+ + +

Type File

+ +
+object --+
+         |
+        File
+

+ +
Known Subclasses:
+
+ Path
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Method Summary
 __init__(self, + f) +
 __call__(self, + msg) +
    Inherited from object
 __delattr__(...) +
+x.__delattr__('name') <==> del x.name
 __getattribute__(...) +
+x.__getattribute__('name') <==> x.name
 __hash__(x) +
+x.__hash__() <==> hash(x)
 __new__(T, + S, + ...) +
+T.__new__(S, ...) -> a new object with type S, a subtype of T
 __reduce__(...) +
+helper for pickle
 __reduce_ex__(...) +
+helper for pickle
 __repr__(x) +
+x.__repr__() <==> repr(x)
 __setattr__(...) +
+x.__setattr__('name', value) <==> x.name = value
 __str__(x) +
+x.__str__() <==> str(x)

+ + + + + + + + + + + + + + + + + +
Generated by Epydoc 2.1 on Wed Nov 16 09:59:23 2005http://epydoc.sf.net
+ + Index: /trunk/docs/public/cheesecake.Cheesecake-class.html =================================================================== --- /trunk/docs/public/cheesecake.Cheesecake-class.html (revision 2) +++ /trunk/docs/public/cheesecake.Cheesecake-class.html (revision 2) @@ -0,0 +1,604 @@ + + + + + cheesecake.Cheesecake + + + + + + + + + + + + + + + + + +
+ + Module cheesecake :: + Class Cheesecake +
+
+ + +
[show private | hide private]
[frames | no frames]
+ + +

Type Cheesecake

+ +
+object --+
+         |
+        Cheesecake
+

+ +
+ +

Computes 'goodness' of Python packages

+

Generates "cheesecake index" that takes into account things like:

+
+
    +
  • whether the package can be downloaded
  • +
  • whether the package can be unpacked
  • +
  • whether the package can be installed into an alternate directory
  • +
  • existence of certain files such as README, INSTALL, LICENSE, setup.py etc.
  • +
  • existence of certain directories such as doc, test, demo, examples
  • +
  • percentage of modules/functions/classes/methods with docstrings
  • +
  • percentage of functions/methods that are unit tested
  • +
  • average pylint score for all non-test and non-demo modules
  • +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Method Summary
 __init__(self, + name, + url, + path, + sandbox, + verbose, + quiet) +
+Initialize critical variables, download and unpack package, walk package tree
 cleanup(self) +
+Delete temporary directories and files that were +created in the sandbox
 compute_cheesecake_index(self) +
+Compute overall Cheesecake index for the package by adding up +specific indexes
 configure_logging(self) +
+Default settings for logging
 copy_pkg(self) +
+Copy package file to sandbox directory
 determine_pkg_name(self) +
 download_pkg(self) +
+Use urllib.urlretrieve to download package to file in sandbox dir
 get_package_from_path(self, + path) +
+Get package name as file portion of path
 get_package_from_url(self) +
+Use urlparse to obtain package path from URL
 get_pkg_from_pypi(self) +
+Download package using setuptools utilities
 index_dir(self) +
+Return CompositeIndex object of type "dir"
 index_docstrings(self) +
+Compute docstring index as percentage of modules/classes/methods/functions +that have docstrings associated with them
 index_download(self) +
+Verify that package can be downloaded from an URL
 index_file(self) +
+Return CompositeIndex object of type "file"
 index_install(self) +
+Verify that package can be installed in alternate directory
 index_pylint(self) +
+Compute pylint index as average of positive pylint scores obtained for +the Python files identified in the package
 index_pypi_download(self) +
+Verify that package can be downloaded from PyPI
 index_unpack(self) +
+Verify that package can be unpacked
 index_unpack_dir(self) +
+Verify that unpack directory has same name as package
 init_indexes(self) +
+Initialize variables used in index computation
 is_py_file(self, + file, + dirs) +
+Return True if file ends with .py and it is not a special file and it is not +in special directory
 is_test_file(self, + file, + dirs) +
+Return True is file is in directory rooted at "test" or "tests"
 pad_msg(self, + msg, + value) +
+Pad message with dots and pad value with spaces
 print_line(self, + line) +
+Print line of text, unless quiet flag was given
 process_index(self, + index_type) +
+Compute and print index of specified type
 raise_exception(self, + msg) +
+Cleanup, print error message and raise CheesecakeError
 retrieve_pkg(self) +
 unpack_pkg(self) +
+Unpack the package in the sandbox directory
 untar_pkg(self) +
+Untar the package in the sandbox directory
 unzip_pkg(self) +
+Unzip the package in the sandbox directory
 walk_pkg(self) +
+Traverse the file system tree rooted at sandbox/package_name
    Inherited from object
 __delattr__(...) +
+x.__delattr__('name') <==> del x.name
 __getattribute__(...) +
+x.__getattribute__('name') <==> x.name
 __hash__(x) +
+x.__hash__() <==> hash(x)
 __new__(T, + S, + ...) +
+T.__new__(S, ...) -> a new object with type S, a subtype of T
 __reduce__(...) +
+helper for pickle
 __reduce_ex__(...) +
+helper for pickle
 __repr__(x) +
+x.__repr__() <==> repr(x)
 __setattr__(...) +
+x.__setattr__('name', value) <==> x.name = value
 __str__(x) +
+x.__str__() <==> str(x)

+ + + + + + +
Method Details
+ + +
+

__init__(self, + name='', + url='', + path='', + sandbox=None, + verbose=False, + quiet=False) +
(Constructor) +

+

Initialize critical variables, download and unpack package, walk package tree

+
+
Overrides:
+
__builtin__.object.__init__
+
+
+
+ + +
+

cleanup(self) +

+

Delete temporary directories and files that were +created in the sandbox

+
+
+
+ + +
+

compute_cheesecake_index(self) +

+

Compute overall Cheesecake index for the package by adding up +specific indexes

+
+
+
+ + +
+

configure_logging(self) +

+

Default settings for logging

+

if verbose, log goes to console, else it goes to logfile +log.debug goes to logfile +log.info goes to console +log.warn and log.error go to both logfile and stdout

+
+
+
+ + +
+

copy_pkg(self) +

+

Copy package file to sandbox directory

+
+
+
+ + +
+

download_pkg(self) +

+

Use urllib.urlretrieve to download package to file in sandbox dir

+
+
+
+ + +
+

get_package_from_path(self, + path) +

+

Get package name as file portion of path

+
+
+
+ + +
+

get_package_from_url(self) +

+

Use urlparse to obtain package path from URL

+
+
+
+ + +
+

get_pkg_from_pypi(self) +

+

Download package using setuptools utilities

+
+
+
+ + +
+

index_dir(self) +

+

Return CompositeIndex object of type "dir"

+
+
+
+ + +
+

index_docstrings(self) +

+

Compute docstring index as percentage of modules/classes/methods/functions +that have docstrings associated with them

+

Return Index object of type "docstrings"

+
+
+
+ + +
+

index_download(self) +

+

Verify that package can be downloaded from an URL

+

Return Index object of type "download"

+
+
+
+ + +
+

index_file(self) +

+

Return CompositeIndex object of type "file"

+
+
+
+ + +
+

index_install(self) +

+

Verify that package can be installed in alternate directory

+

Return Index object of type "install"

+
+
+
+ + +
+

index_pylint(self) +

+

Compute pylint index as average of positive pylint scores obtained for +the Python files identified in the package

+

Return Index object of type "pylint"

+
+
+
+ + +
+

index_pypi_download(self) +

+

Verify that package can be downloaded from PyPI

+

Return Index object of type "pypi_download"

+
+
+
+ + +
+

index_unpack(self) +

+

Verify that package can be unpacked

+

Return Index object of type "unpack"

+
+
+
+ + +
+

index_unpack_dir(self) +

+

Verify that unpack directory has same name as package

+

Return Index object of type "unpack_dir"

+
+
+
+ + +
+

init_indexes(self) +

+

Initialize variables used in index computation

+
    +
  • cheesecake_index: overall index for the package
  • +
  • index: dict holding Index or CompositeIndex objects of various types
  • +
+
+
+
+ + +
+

is_py_file(self, + file, + dirs) +

+

Return True if file ends with .py and it is not a special file and it is not +in special directory

+
+
+
+ + +
+

is_test_file(self, + file, + dirs) +

+

Return True is file is in directory rooted at "test" or "tests"

+
+
+
+ + +
+

pad_msg(self, + msg, + value) +

+

Pad message with dots and pad value with spaces

+
+
+
+ + +
+

print_line(self, + line) +

+

Print line of text, unless quiet flag was given

+
+
+
+ + +
+

process_index(self, + index_type) +

+

Compute and print index of specified type

+
+
+
+ + +
+

raise_exception(self, + msg) +

+

Cleanup, print error message and raise CheesecakeError

+

Don't use logging, since it can be called before logging has been setup

+
+
+
+ + +
+

unpack_pkg(self) +

+

Unpack the package in the sandbox directory

+

Currently supported archive types:

+
    +
  • .tar.gz (handled with tarfile module)
  • +
  • .zip (handled with zipfile module)
  • +
+
+
+
+ + +
+

untar_pkg(self) +

+

Untar the package in the sandbox directory

+

Uses tarfile module

+
+
+
+ + +
+

unzip_pkg(self) +

+

Unzip the package in the sandbox directory

+

Uses zipfile module

+
+
+
+ + +
+

walk_pkg(self) +

+

Traverse the file system tree rooted at sandbox/package_name

+
    +
  • Compute indexes for special files and directories
  • +
  • Identify Python files, test files, etc.
  • +
+
+
+
+
+ + + + + + + + + + + + + + + + + +
Generated by Epydoc 2.1 on Wed Nov 16 09:59:23 2005http://epydoc.sf.net
+ + Index: /trunk/docs/public/cheesecake-module.html =================================================================== --- /trunk/docs/public/cheesecake-module.html (revision 2) +++ /trunk/docs/public/cheesecake-module.html (revision 2) @@ -0,0 +1,512 @@ + + + + + cheesecake + + + + + + + + + + + + + + + + + +
+ + Module cheesecake +
+
+ + +
[show private | hide private]
[frames | no frames]
+ + +

Module cheesecake

+ +

Cheesecake: How tasty is your code?

+

The idea of the Cheesecake project is to rank Python packages +based on various empiric "kwalitee" factors, such as:

+
+
    +
  • whether the package can be downloaded
  • +
  • whether the package can be unpacked
  • +
  • whether the package can be installed into an alternate directory
  • +
  • existence of certain files such as README, INSTALL, LICENSE, setup.py etc.
  • +
  • existence of certain directories such as doc, test, demo, examples
  • +
  • percentage of modules/functions/classes/methods with docstrings
  • +
  • percentage of functions/methods that are unit tested
  • +
  • average pylint score for all non-test and non-demo modules
  • +
  • whether the package can be unpacked
  • +
  • whether the package can be installed into an alternate directory
  • +
+
+
+ + + + + + + + + + + + + + + +
Classes
+ CheesecakeComputes 'goodness' of Python packages
+ CodeParserInformation about the structure of a Python module
+ CompositeIndexCollection of indexes of same type (e.g.
+ IndexEncapsulates index attributes such as name, value, details
+ StdoutRedirectorRedirect stdout to a temp file

+ + + + + + + + +
Exceptions
+ CheesecakeErrorCustom exception class for Cheesecake-specific errors

+ + + + + + + + + + + + + + +
Function Summary
 main() +
+Display Cheesecake index for package specified via command-line options
 pad_left_spaces(value, + length) +
+Pad value with spaces at left up to given length
 pad_with_dots(msg, + length) +
+Pad text with dots up to given length
 process_cmdline_args() +
+Parse command-line options

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Variable Summary
intINDEX_DIR = 20                                                                    
intINDEX_DIR_CRITICAL = 25                                                                    
intINDEX_DIR_EMPTY = 5                                                                     
intINDEX_FILE = 10                                                                    
intINDEX_FILE_CRITICAL = 15                                                                    
intINDEX_FILE_PYC = -20                                                                   
intINDEX_INSTALL = 50                                                                    
intINDEX_PYPI_DISTANCE = 5                                                                     
intINDEX_PYPI_DOWNLOAD = 50                                                                    
intINDEX_UNPACK = 25                                                                    
intINDEX_UNPACK_DIR = 15                                                                    
intINDEX_URL_DOWNLOAD = 25                                                                    
intPAD_TEXT = 25                                                                    
intPAD_VALUE = 4                                                                     

+ + + + + + +
Function Details
+ + +
+

main() +

+

Display Cheesecake index for package specified via command-line options

+
+
+
+ + +
+

pad_left_spaces(value, + length=4) +

+

Pad value with spaces at left up to given length

+
+
+
+ + +
+

pad_with_dots(msg, + length=25) +

+

Pad text with dots up to given length

+
+
+
+ + +
+

process_cmdline_args() +

+

Parse command-line options

+
+
+
+
+ + + + + + +
Variable Details
+
+ +

INDEX_DIR

+
+
+
+
+
Type:
+
+ int + +
+
Value:
+
+
+20                                                                    
+
+
+
+
+
+ +

INDEX_DIR_CRITICAL

+
+
+
+
+
Type:
+
+ int + +
+
Value:
+
+
+25                                                                    
+
+
+
+
+
+ +

INDEX_DIR_EMPTY

+
+
+
+
+
Type:
+
+ int + +
+
Value:
+
+
+5                                                                     
+
+
+
+
+
+ +

INDEX_FILE

+
+
+
+
+
Type:
+
+ int + +
+
Value:
+
+
+10                                                                    
+
+
+
+
+
+ +

INDEX_FILE_CRITICAL

+
+
+
+
+
Type:
+
+ int + +
+
Value:
+
+
+15                                                                    
+
+
+
+
+
+ +

INDEX_FILE_PYC

+
+
+
+
+
Type:
+
+ int + +
+
Value:
+
+
+-20                                                                   
+
+
+
+
+
+ +

INDEX_INSTALL

+
+
+
+
+
Type:
+
+ int + +
+
Value:
+
+
+50                                                                    
+
+
+
+
+
+ +

INDEX_PYPI_DISTANCE

+
+
+
+
+
Type:
+
+ int + +
+
Value:
+
+
+5                                                                     
+
+
+
+
+
+ +

INDEX_PYPI_DOWNLOAD

+
+
+
+
+
Type:
+
+ int + +
+
Value:
+
+
+50                                                                    
+
+
+
+
+
+ +

INDEX_UNPACK

+
+
+
+
+
Type:
+
+ int + +
+
Value:
+
+
+25                                                                    
+
+
+
+
+
+ +

INDEX_UNPACK_DIR

+
+
+
+
+
Type:
+
+ int + +
+
Value:
+
+
+15                                                                    
+
+
+
+
+
+ +

INDEX_URL_DOWNLOAD

+
+
+
+
+
Type:
+
+ int + +
+
Value:
+
+
+25                                                                    
+
+
+
+
+
+ +

PAD_TEXT

+
+
+
+
+
Type:
+
+ int + +
+
Value:
+
+
+25                                                                    
+
+
+
+
+
+ +

PAD_VALUE

+
+
+
+
+
Type:
+
+ int + +
+
Value:
+
+
+4                                                                     
+
+
+
+
+
+ + + + + + + + + + + + + + + + + +
Generated by Epydoc 2.1 on Wed Nov 16 09:59:23 2005http://epydoc.sf.net
+ + Index: /trunk/docs/public/logger.Message-class.html =================================================================== --- /trunk/docs/public/logger.Message-class.html (revision 2) +++ /trunk/docs/public/logger.Message-class.html (revision 2) @@ -0,0 +1,134 @@ + + + + + logger.Message + + + + + + + + + + + + + + + + + +
+ + Module logger :: + Class Message +
+
+ + +
[show private | hide private]
[frames | no frames]
+ + +

Type Message

+ +
+object --+
+         |
+        Message
+

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Method Summary
 __init__(self, + keywords, + args) +
 __str__(self) +
 content(self) +
 prefix(self) +
    Inherited from object
 __delattr__(...) +
+x.__delattr__('name') <==> del x.name
 __getattribute__(...) +
+x.__getattribute__('name') <==> x.name
 __hash__(x) +
+x.__hash__() <==> hash(x)
 __new__(T, + S, + ...) +
+T.__new__(S, ...) -> a new object with type S, a subtype of T
 __reduce__(...) +
+helper for pickle
 __reduce_ex__(...) +
+helper for pickle
 __repr__(x) +
+x.__repr__() <==> repr(x)
 __setattr__(...) +
+x.__setattr__('name', value) <==> x.name = value

+ + + + + + + + + + + + + + + + + +
Generated by Epydoc 2.1 on Wed Nov 16 09:59:23 2005http://epydoc.sf.net
+ + Index: /trunk/docs/public/cheesecake.CodeParser-class.html =================================================================== --- /trunk/docs/public/cheesecake.CodeParser-class.html (revision 2) +++ /trunk/docs/public/cheesecake.CodeParser-class.html (revision 2) @@ -0,0 +1,191 @@ + + + + + cheesecake.CodeParser + + + + + + + + + + + + + + + + + +
+ + Module cheesecake :: + Class CodeParser +
+
+ + +
[show private | hide private]
[frames | no frames]
+ + +

Type CodeParser

+ +
+object --+
+         |
+        CodeParser
+

+ +
+ +

Information about the structure of a Python module

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Method Summary
 __init__(self, + pyfile, + log) +
 docstring_count(self) +
+Return number of docstrings found in this module
 object_count(self) +
+Return number of objects found in this module
 parse_file(self) +
+Parse module text and retrieve classes, methods, functions +and associated docstrings
    Inherited from object
 __delattr__(...) +
+x.__delattr__('name') <==> del x.name
 __getattribute__(...) +
+x.__getattribute__('name') <==> x.name
 __hash__(x) +
+x.__hash__() <==> hash(x)
 __new__(T, + S, + ...) +
+T.__new__(S, ...) -> a new object with type S, a subtype of T
 __reduce__(...) +
+helper for pickle
 __reduce_ex__(...) +
+helper for pickle
 __repr__(x) +
+x.__repr__() <==> repr(x)
 __setattr__(...) +
+x.__setattr__('name', value) <==> x.name = value
 __str__(x) +
+x.__str__() <==> str(x)

+ + + + + + +
Method Details
+ + +
+

docstring_count(self) +

+

Return number of docstrings found in this module

+
+
+
+ + +
+

object_count(self) +

+

Return number of objects found in this module

+
    +
  • module
  • +
  • classes
  • +
  • methods
  • +
  • functions
  • +
+
+
+
+ + +
+

parse_file(self) +

+

Parse module text and retrieve classes, methods, functions +and associated docstrings

+
+
+
+
+ + + + + + + + + + + + + + + + + +
Generated by Epydoc 2.1 on Wed Nov 16 09:59:23 2005http://epydoc.sf.net
+ + Index: /trunk/docs/public/__builtin__.object-class.html =================================================================== --- /trunk/docs/public/__builtin__.object-class.html (revision 2) +++ /trunk/docs/public/__builtin__.object-class.html (revision 2) @@ -0,0 +1,277 @@ + + + + + __builtin__.object + + + + + + + + + + + + + + + + + + +
+ + Module __builtin__ :: + Class object +
+
+ + +
[show private | hide private]
[frames | no frames]
+ + +

Type object

+ +
Known Subclasses:
+
+ Cheesecake, + CodeParser, + CompositeIndex, + Index, + StdoutRedirector, + type
+ +
+ +The most base type +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Method Summary
 __init__(...) +
+x.__init__(...) initializes x; see x.__class__.__doc__ for +signature
 __delattr__(...) +
+x.__delattr__('name') <==> del x.name
 __getattribute__(...) +
+x.__getattribute__('name') <==> x.name
 __hash__(x) +
+x.__hash__() <==> hash(x)
 __new__(T, + S, + ...) +
+T.__new__(S, ...) -> a new object with type S, a subtype of T
 __reduce__(...) +
+helper for pickle
 __reduce_ex__(...) +
+helper for pickle
 __repr__(x) +
+x.__repr__() <==> repr(x)
 __setattr__(...) +
+x.__setattr__('name', value) <==> x.name = value
 __str__(x) +
+x.__str__() <==> str(x)

+ + + + + + + + +
Class Variable Summary
type__class__ = __builtin__.type

+ + + + + + +
Method Details
+ + +
+

__init__(...) +
(Constructor) +

+ x.__init__(...) initializes x; see x.__class__.__doc__ for + signature +
+
+
+ + +
+

__delattr__(...) +

+ x.__delattr__('name') <==> del x.name +
+
+
+ + +
+

__getattribute__(...) +

+ x.__getattribute__('name') <==> x.name +
+
+
+ + +
+

__hash__(x) +
(Hashing function) +

+ x.__hash__() <==> hash(x) +
+
Returns:
+
+
+hash(x)
+
+
+
+
+
+ + +
+

__new__(T, + S, + ...) +

+ T.__new__(S, ...) -> a new object with type S, a subtype of T +
+
Returns:
+
+
+a new object with type S, a subtype of T
+
+
+
+
+
+ + +
+

__reduce__(...) +

+ helper for pickle +
+
+
+ + +
+

__reduce_ex__(...) +

+ helper for pickle +
+
+
+ + +
+

__repr__(x) +
(Representation operator) +

+ x.__repr__() <==> repr(x) +
+
Returns:
+
+
+repr(x)
+
+
+
+
+
+ + +
+

__setattr__(...) +

+ x.__setattr__('name', value) <==> x.name = value +
+
+
+ + +
+

__str__(x) +
(Informal representation operator) +

+ x.__str__() <==> str(x) +
+
Returns:
+
+
+str(x)
+
+
+
+
+
+
+ + + + + + + + + + + + + + + + + + +
Generated by Epydoc 2.1 on Wed Dec 21 17:21:41 2005http://epydoc.sf.net
+ + Index: /trunk/docs/public/cheesecake.cheesecake_index.CheesecakeError-class.html =================================================================== --- /trunk/docs/public/cheesecake.cheesecake_index.CheesecakeError-class.html (revision 2) +++ /trunk/docs/public/cheesecake.cheesecake_index.CheesecakeError-class.html (revision 2) @@ -0,0 +1,101 @@ + + + + + cheesecake.cheesecake_index.CheesecakeError + + + + + + + + + + + + + + + + + + +
+ + Package cheesecake :: + Module cheesecake_index :: + Class CheesecakeError +
+
+ + +
[show private | hide private]
[frames | no frames]
+ + +

Class CheesecakeError

+ +
+Exception --+
+            |
+           CheesecakeError
+

+ +
+ +Custom exception class for Cheesecake-specific errors +
+ + + + + + + + + + + + + + +
Method Summary
    Inherited from Exception
 __init__(...) +
 __getitem__(...) +
 __str__(...) +

+ + + + + + + + + + + + + + + + + + +
Generated by Epydoc 2.1 on Wed Dec 21 17:21:41 2005http://epydoc.sf.net
+ + Index: /trunk/docs/public/cheesecake.cheesecake_index.CompositeIndex-class.html =================================================================== --- /trunk/docs/public/cheesecake.cheesecake_index.CompositeIndex-class.html (revision 2) +++ /trunk/docs/public/cheesecake.cheesecake_index.CompositeIndex-class.html (revision 2) @@ -0,0 +1,233 @@ + + + + + cheesecake.cheesecake_index.CompositeIndex + + + + + + + + + + + + + + + + + + +
+ + Package cheesecake :: + Module cheesecake_index :: + Class CompositeIndex +
+
+ + +
[show private | hide private]
[frames | no frames]
+ + +

Type CompositeIndex

+ +
+object --+
+         |
+        CompositeIndex
+

+ +
+ +Collection of indexes of same type (e.g. files, dirs) +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Method Summary
 __init__(self, + type) +
+Indexes is a dict mapping names to Index objects
 get_value(self) +
+Return sum of individual index values
 print_info(self) +
+Print index info for all indexes sorted alphanumerically by name
 set_index(self, + name, + value, + details) +
+Create new index or update existing index with specified +attributes
    Inherited from object
 __delattr__(...) +
+x.__delattr__('name') <==> del x.name
 __getattribute__(...) +
+x.__getattribute__('name') <==> x.name
 __hash__(x) +
+x.__hash__() <==> hash(x)
 __new__(T, + S, + ...) +
+T.__new__(S, ...) -> a new object with type S, a subtype of T
 __reduce__(...) +
+helper for pickle
 __reduce_ex__(...) +
+helper for pickle
 __repr__(x) +
+x.__repr__() <==> repr(x)
 __setattr__(...) +
+x.__setattr__('name', value) <==> x.name = value
 __str__(x) +
+x.__str__() <==> str(x)

+ + + + + + + +
Property Summary
 value

+ + + + + + +
Method Details
+ + +
+

__init__(self, + type) +
(Constructor) +

+ Indexes is a dict mapping names to Index objects +
+
Overrides:
+
__builtin__.object.__init__
+
+
+
+ + +
+

get_value(self) +

+ Return sum of individual index values +
+
+
+ + +
+

print_info(self) +

+ Print index info for all indexes sorted alphanumerically by name +
+
+
+ + +
+

set_index(self, + name, + value=0, + details='') +

+ Create new index or update existing index with specified + attributes +
+
+
+
+ + + + + + +
Property Details
+
+ + +

value

+
+
+
+
+
Get Method:
+
get_value(self) +
+
+
+

+ + + + + + + + + + + + + + + + + + +
Generated by Epydoc 2.1 on Wed Dec 21 17:21:41 2005http://epydoc.sf.net
+ + Index: /trunk/docs/public/trees.html =================================================================== --- /trunk/docs/public/trees.html (revision 2) +++ /trunk/docs/public/trees.html (revision 2) @@ -0,0 +1,112 @@ + + + + + Module and Class Hierarchies + + + + + + + + + + + + + + + + + + +
+ + + +
[show private | hide private]
[frames | no frames]
+ + +

Module Hierarchy

+ + + +

Class Hierarchy

+ + + + + + + + + + + + + + + + + + +
Generated by Epydoc 2.1 on Wed Dec 21 17:21:41 2005http://epydoc.sf.net
+ + Index: /trunk/docs/public/toc.html =================================================================== --- /trunk/docs/public/toc.html (revision 2) +++ /trunk/docs/public/toc.html (revision 2) @@ -0,0 +1,25 @@ + + + + + Table of Contents + + + +
Table of Contents
+
+Everything
+ + +
Packages
+ + +
Modules
+cheesecake.cheesecake_index
+ +

+[show private | hide private] + + Index: /trunk/docs/public/toc-cheesecake-module.html =================================================================== --- /trunk/docs/public/toc-cheesecake-module.html (revision 2) +++ /trunk/docs/public/toc-cheesecake-module.html (revision 2) @@ -0,0 +1,57 @@ + + + + + cheesecake + + + +
cheesecake
+
+ + +Classes
+Cheesecake
+CodeParser
+CompositeIndex
+Index
+StdoutRedirector
+
+ + +Exceptions
+CheesecakeError
+
+ + +Functions
+main
+pad_left_spaces
+pad_with_dots
+process_cmdline_args
+
+ + +Variables
+INDEX_DIR
+INDEX_DIR_CRITICAL
+INDEX_DIR_EMPTY
+INDEX_FILE
+INDEX_FILE_CRITICAL
+INDEX_FILE_PYC
+INDEX_INSTALL
+INDEX_PYPI_DISTANCE
+INDEX_PYPI_DOWNLOAD
+INDEX_UNPACK
+INDEX_UNPACK_DIR
+INDEX_URL_DOWNLOAD
+PAD_TEXT
+PAD_VALUE
+
+ +
+[show private | hide private] + + Index: /trunk/docs/public/cheesecake.Index-class.html =================================================================== --- /trunk/docs/public/cheesecake.Index-class.html (revision 2) +++ /trunk/docs/public/cheesecake.Index-class.html (revision 2) @@ -0,0 +1,155 @@ + + + + + cheesecake.Index + + + + + + + + + + + + + + + + + +
+ + Module cheesecake :: + Class Index +
+
+ + +
[show private | hide private]
[frames | no frames]
+ + +

Type Index

+ +
+object --+
+         |
+        Index
+

+ +
+ +

Encapsulates index attributes such as name, value, details

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Method Summary
 __init__(self, + type, + name, + value, + details) +
 print_info(self) +
+Print index name padded with dots, followed by value and details
    Inherited from object
 __delattr__(...) +
+x.__delattr__('name') <==> del x.name
 __getattribute__(...) +
+x.__getattribute__('name') <==> x.name
 __hash__(x) +
+x.__hash__() <==> hash(x)
 __new__(T, + S, + ...) +
+T.__new__(S, ...) -> a new object with type S, a subtype of T
 __reduce__(...) +
+helper for pickle
 __reduce_ex__(...) +
+helper for pickle
 __repr__(x) +
+x.__repr__() <==> repr(x)
 __setattr__(...) +
+x.__setattr__('name', value) <==> x.name = value
 __str__(x) +
+x.__str__() <==> str(x)

+ + + + + + +
Method Details
+ + +
+

print_info(self) +

+

Print index name padded with dots, followed by value and details

+
+
+
+
+ + + + + + + + + + + + + + + + + +
Generated by Epydoc 2.1 on Wed Nov 16 09:59:23 2005http://epydoc.sf.net
+ + Index: /trunk/docs/public/toc-cheesecake.cheesecake_index-module.html =================================================================== --- /trunk/docs/public/toc-cheesecake.cheesecake_index-module.html (revision 2) +++ /trunk/docs/public/toc-cheesecake.cheesecake_index-module.html (revision 2) @@ -0,0 +1,59 @@ + + + + + cheesecake.cheesecake_index + + + +
cheesecake_index
+
+ + +Classes
+Cheesecake
+CodeParser
+CompositeIndex
+Index
+StdoutRedirector
+
+ + +Exceptions
+CheesecakeError
+
+ + +Functions
+main
+pad_left_spaces
+pad_msg
+pad_with_dots
+process_cmdline_args
+
+ + +Variables
+INDEX_DIR
+INDEX_DIR_CRITICAL
+INDEX_DIR_EMPTY
+INDEX_FILE
+INDEX_FILE_CRITICAL
+INDEX_FILE_PYC
+INDEX_INSTALL
+INDEX_PYPI_DISTANCE
+INDEX_PYPI_DOWNLOAD
+INDEX_REQUIRED_FILES
+INDEX_UNPACK
+INDEX_UNPACK_DIR
+INDEX_URL_DOWNLOAD
+PAD_TEXT
+PAD_VALUE
+
+ +
+[show private | hide private] + + Index: /trunk/docs/public/cheesecake.cheesecake_index.StdoutRedirector-class.html =================================================================== --- /trunk/docs/public/cheesecake.cheesecake_index.StdoutRedirector-class.html (revision 2) +++ /trunk/docs/public/cheesecake.cheesecake_index.StdoutRedirector-class.html (revision 2) @@ -0,0 +1,162 @@ + + + + + cheesecake.cheesecake_index.StdoutRedirector + + + + + + + + + + + + + + + + + + +
+ + Package cheesecake :: + Module cheesecake_index :: + Class StdoutRedirector +
+
+ + +
[show private | hide private]
[frames | no frames]
+ + +

Type StdoutRedirector

+ +
+object --+
+         |
+        StdoutRedirector
+

+ +
+ +Redirect stdout to a temp file +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Method Summary
 __init__(self, + filename) +
 flush(self) +
 read_buffer(self) +
+Return contents of the temp file
 write(self, + buf) +
    Inherited from object
 __delattr__(...) +
+x.__delattr__('name') <==> del x.name
 __getattribute__(...) +
+x.__getattribute__('name') <==> x.name
 __hash__(x) +
+x.__hash__() <==> hash(x)
 __new__(T, + S, + ...) +
+T.__new__(S, ...) -> a new object with type S, a subtype of T
 __reduce__(...) +
+helper for pickle
 __reduce_ex__(...) +
+helper for pickle
 __repr__(x) +
+x.__repr__() <==> repr(x)
 __setattr__(...) +
+x.__setattr__('name', value) <==> x.name = value
 __str__(x) +
+x.__str__() <==> str(x)

+ + + + + + +
Method Details
+ + +
+

read_buffer(self) +

+ Return contents of the temp file +
+
+
+
+ + + + + + + + + + + + + + + + + + +
Generated by Epydoc 2.1 on Wed Dec 21 17:21:41 2005http://epydoc.sf.net
+ + Index: /trunk/docs/public/logger-module.html =================================================================== --- /trunk/docs/public/logger-module.html (revision 2) +++ /trunk/docs/public/logger-module.html (revision 2) @@ -0,0 +1,150 @@ + + + + + logger + + + + + + + + + + + + + + + + + +
+ + Module logger +
+
+ + +
[show private | hide private]
[frames | no frames]
+ + +

Module logger

+ + + + + + + + + + + + + + + + +
Classes
+ File 
+ Message 
+ MultipleProducer 
+ Path 
+ ProducerLog producer API which sends messages to be logged +to a 'consumer' object, which then prints them to stdout, +stderr, files, etc.

+ + + + + + + + + + + + + + +
Function Summary
 default_consumer(msg) +
 setconsumer(keywords, + consumer) +
 STDERR(msg) +
 STDOUT(msg) +

+ + + + + + + + +
Variable Summary
Producerdefault = <Producer default> +

+ + + + + + +
Variable Details
+
+ +

default

+
+
+
+
+
Type:
+
+ Producer + +
+
Value:
+
+
+<Producer default>                                                     
+
+
+
+
+
+ + + + + + + + + + + + + + + + + +
Generated by Epydoc 2.1 on Wed Nov 16 09:59:23 2005http://epydoc.sf.net
+ + Index: /trunk/docs/public/logger.Producer-class.html =================================================================== --- /trunk/docs/public/logger.Producer-class.html (revision 2) +++ /trunk/docs/public/logger.Producer-class.html (revision 2) @@ -0,0 +1,184 @@ + + + + + logger.Producer + + + + + + + + + + + + + + + + + +
+ + Module logger :: + Class Producer +
+
+ + +
[show private | hide private]
[frames | no frames]
+ + +

Type Producer

+ +
+object --+
+         |
+        Producer
+

+ +
Known Subclasses:
+
+ MultipleProducer
+ +
+ +

Log producer API which sends messages to be logged +to a 'consumer' object, which then prints them to stdout, +stderr, files, etc.

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Method Summary
 __init__(self, + keywords) +
 __call__(self, + *args) +
 __getattr__(self, + name) +
 __repr__(self) +
    Inherited from object
 __delattr__(...) +
+x.__delattr__('name') <==> del x.name
 __getattribute__(...) +
+x.__getattribute__('name') <==> x.name
 __hash__(x) +
+x.__hash__() <==> hash(x)
 __new__(T, + S, + ...) +
+T.__new__(S, ...) -> a new object with type S, a subtype of T
 __reduce__(...) +
+helper for pickle
 __reduce_ex__(...) +
+helper for pickle
 __setattr__(...) +
+x.__setattr__('name', value) <==> x.name = value
 __str__(x) +
+x.__str__() <==> str(x)

+ + + + + + + + + + +
Class Variable Summary
dictkeywords2consumer = {'default': <function default_consum... +
typeMessage = logger.Message

+ + + + + + +
Class Variable Details
+
+ +

keywords2consumer

+
+
+
+
+
Type:
+
+ dict + +
+
Value:
+
+
+{'default': <function default_consumer at 0x40681d4c>}                 
+
+
+
+
+
+ + + + + + + + + + + + + + + + + +
Generated by Epydoc 2.1 on Wed Nov 16 09:59:23 2005http://epydoc.sf.net
+ + Index: /trunk/docs/public/toc-everything.html =================================================================== --- /trunk/docs/public/toc-everything.html (revision 2) +++ /trunk/docs/public/toc-everything.html (revision 2) @@ -0,0 +1,59 @@ + + + + + Everything + + + +
Everything
+
+ + +All Classes
+cheesecake.cheesecake_index.Cheesecake
+cheesecake.cheesecake_index.CodeParser
+cheesecake.cheesecake_index.CompositeIndex
+cheesecake.cheesecake_index.Index
+cheesecake.cheesecake_index.StdoutRedirector
+
+ + +All Exceptions
+cheesecake.cheesecake_index.CheesecakeError
+
+ + +All Functions
+main
+pad_left_spaces
+pad_msg
+pad_with_dots
+process_cmdline_args
+
+ + +All Variables
+INDEX_DIR
+INDEX_DIR_CRITICAL
+INDEX_DIR_EMPTY
+INDEX_FILE
+INDEX_FILE_CRITICAL
+INDEX_FILE_PYC
+INDEX_INSTALL
+INDEX_PYPI_DISTANCE
+INDEX_PYPI_DOWNLOAD
+INDEX_REQUIRED_FILES
+INDEX_UNPACK
+INDEX_UNPACK_DIR
+INDEX_URL_DOWNLOAD
+PAD_TEXT
+PAD_VALUE
+
+ +
+[show private | hide private] + + Index: /trunk/docs/public/index.html =================================================================== --- /trunk/docs/public/index.html (revision 2) +++ /trunk/docs/public/index.html (revision 2) @@ -0,0 +1,13 @@ + + + + cheesecake + + + + + + + + + Index: /trunk/docs/public/epydoc.css =================================================================== --- /trunk/docs/public/epydoc.css (revision 2) +++ /trunk/docs/public/epydoc.css (revision 2) @@ -0,0 +1,100 @@ + +/* Body color */ +body { background: #ffffff; color: #000000; } + +/* Tables */ +table.summary, table.details, table.index + { background: #e8f0f8; color: #000000; } +tr.summary, tr.details, tr.index + { background: #70b0f0; color: #000000; + text-align: left; font-size: 120%; } +tr.group { background: #c0e0f8; color: #000000; + text-align: left; font-size: 120%; + font-style: italic; } + +/* Documentation page titles */ +h2.module { margin-top: 0.2em; } +h2.class { margin-top: 0.2em; } + +/* Headings */ +h1.heading { font-size: +140%; font-style: italic; + font-weight: bold; } +h2.heading { font-size: +125%; font-style: italic; + font-weight: bold; } +h3.heading { font-size: +110%; font-style: italic; + font-weight: normal; } + +/* Base tree */ +pre.base-tree { font-size: 80%; margin: 0; } + +/* Details Sections */ +table.func-details { background: #e8f0f8; color: #000000; + border: 2px groove #c0d0d0; + padding: 0 1em 0 1em; margin: 0.4em 0 0 0; } +h3.func-detail { background: transparent; color: #000000; + margin: 0 0 1em 0; } + +table.var-details { background: #e8f0f8; color: #000000; + border: 2px groove #c0d0d0; + padding: 0 1em 0 1em; margin: 0.4em 0 0 0; } +h3.var-details { background: transparent; color: #000000; + margin: 0 0 1em 0; } + +/* Function signatures */ +.sig { background: transparent; color: #000000; + font-weight: bold; } +.sig-name { background: transparent; color: #006080; } +.sig-arg, .sig-kwarg, .sig-vararg + { background: transparent; color: #008060; } +.sig-default { background: transparent; color: #602000; } +.summary-sig { background: transparent; color: #000000; } +.summary-sig-name { background: transparent; color: #204080; } +.summary-sig-arg, .summary-sig-kwarg, .summary-sig-vararg + { background: transparent; color: #008060; } + +/* Doctest blocks */ +.py-src { background: transparent; color: #000000; } +.py-prompt { background: transparent; color: #005050; + font-weight: bold;} +.py-string { background: transparent; color: #006030; } +.py-comment { background: transparent; color: #003060; } +.py-keyword { background: transparent; color: #600000; } +.py-output { background: transparent; color: #404040; } +pre.doctestblock { background: #f4faff; color: #000000; + padding: .5em; margin: 1em; + border: 1px solid #708890; } +table pre.doctestblock + { background: #dce4ec; color: #000000; + padding: .5em; margin: 1em; + border: 1px solid #708890; } + +/* Variable values */ +pre.variable { background: #dce4ec; color: #000000; + padding: .5em; margin: 0; + border: 1px solid #708890; } +.variable-linewrap { background: transparent; color: #604000; } +.variable-ellipsis { background: transparent; color: #604000; } +.variable-quote { background: transparent; color: #604000; } +.re { background: transparent; color: #000000; } +.re-char { background: transparent; color: #006030; } +.re-op { background: transparent; color: #600000; } +.re-group { background: transparent; color: #003060; } +.re-ref { background: transparent; color: #404040; } + +/* Navigation bar */ +table.navbar { background: #a0c0ff; color: #0000ff; + border: 2px groove #c0d0d0; } +th.navbar { background: #a0c0ff; color: #0000ff; } +th.navselect { background: #70b0ff; color: #000000; } +.nomargin { margin: 0; } + +/* Links */ +a:link { background: transparent; color: #0000ff; } +a:visited { background: transparent; color: #204080; } +a.navbar:link { background: transparent; color: #0000ff; + text-decoration: none; } +a.navbar:visited { background: transparent; color: #204080; + text-decoration: none; } + +/* Lists */ +ul { margin-top: 0; } Index: /trunk/docs/public/cheesecake.cheesecake_index.Cheesecake-class.html =================================================================== --- /trunk/docs/public/cheesecake.cheesecake_index.Cheesecake-class.html (revision 2) +++ /trunk/docs/public/cheesecake.cheesecake_index.Cheesecake-class.html (revision 2) @@ -0,0 +1,598 @@ + + + + + cheesecake.cheesecake_index.Cheesecake + + + + + + + + + + + + + + + + + + +
+ + Package cheesecake :: + Module cheesecake_index :: + Class Cheesecake +
+
+ + +
[show private | hide private]
[frames | no frames]
+ + +

Type Cheesecake

+ +
+object --+
+         |
+        Cheesecake
+

+ +
+ +
+Computes 'goodness' of Python packages
+
+Generates "cheesecake index" that takes into account things like:
+
+    * whether the package can be downloaded
+    * whether the package can be unpacked
+    * whether the package can be installed into an alternate directory
+    * existence of certain files such as README, INSTALL, LICENSE, setup.py etc.
+    * existence of certain directories such as doc, test, demo, examples
+    * percentage of modules/functions/classes/methods with docstrings
+    * percentage of functions/methods that are unit tested 
+    * average pylint score for all non-test and non-demo modules
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Method Summary
 __init__(self, + name, + url, + path, + sandbox, + verbose, + quiet) +
+Initialize critical variables, download and unpack package, walk +package tree
 cleanup(self) +
+Delete temporary directories and files that were created in the +sandbox
 compute_cheesecake_index(self) +
+Compute overall Cheesecake index for the package by adding up specific +indexes
 configure_logging(self) +
+Default settings for logging
 copy_pkg(self) +
+Copy package file to sandbox directory
 determine_pkg_name(self) +
 download_pkg(self) +
+Use ``urllib.urlretrieve`` to download package to file in sandbox +dir
 get_package_from_path(self, + path) +
+Get package name as file portion of path
 get_package_from_url(self) +
+Use ``urlparse`` to obtain package path from URL
 get_pkg_from_pypi(self) +
+Download package using setuptools utilities
 index_dir(self) +
+Return CompositeIndex object of type "dir"
 index_docstrings(self) +
+Compute docstring index as percentage of +modules/classes/methods/functions that have docstrings associated with +them
 index_file(self) +
+Return CompositeIndex object of type "file"
 index_install(self) +
+Verify that package can be installed in alternate directory
 index_pylint(self) +
+Compute pylint index as average of positive pylint scores obtained for +the Python files identified in the package
 index_pypi_download(self) +
+Verify that package can be downloaded from PyPI
 index_unpack(self) +
+Verify that package can be unpacked
 index_unpack_dir(self) +
+Verify that unpack directory has same name as package
 index_url_download(self) +
+Verify that package can be downloaded from an URL
 init_indexes(self) +
+Initialize variables used in index computation
 is_py_file(self, + file, + dirs) +
+Return True if file ends with .py and it is not a special file and it +is not in special directory
 is_test_file(self, + file, + dirs) +
+Return True is file is in directory rooted at "test" or +"tests"
 print_line(self, + line) +
+Print line of text, unless quiet flag was given
 process_index(self, + index_type) +
+Compute and print index of specified type
 process_partial_index(self, + partial_index_name, + index_types, + max_value) +
 raise_exception(self, + msg) +
+Cleanup, print error message and raise CheesecakeError
 retrieve_pkg(self) +
 unpack_pkg(self) +
+Unpack the package in the sandbox directory
 untar_pkg(self) +
+Untar the package in the sandbox directory
 unzip_pkg(self) +
+Unzip the package in the sandbox directory
 walk_pkg(self) +
+Traverse the file system tree rooted at sandbox/package_name
    Inherited from object
 __delattr__(...) +
+x.__delattr__('name') <==> del x.name
 __getattribute__(...) +
+x.__getattribute__('name') <==> x.name
 __hash__(x) +
+x.__hash__() <==> hash(x)
 __new__(T, + S, + ...) +
+T.__new__(S, ...) -> a new object with type S, a subtype of T
 __reduce__(...) +
+helper for pickle
 __reduce_ex__(...) +
+helper for pickle
 __repr__(x) +
+x.__repr__() <==> repr(x)
 __setattr__(...) +
+x.__setattr__('name', value) <==> x.name = value
 __str__(x) +
+x.__str__() <==> str(x)

+ + + + + + +
Method Details
+ + +
+

__init__(self, + name='', + url='', + path='', + sandbox=None, + verbose=False, + quiet=False) +
(Constructor) +

+ Initialize critical variables, download and unpack package, walk + package tree +
+
Overrides:
+
__builtin__.object.__init__
+
+
+
+ + +
+

cleanup(self) +

+ Delete temporary directories and files that were created in the + sandbox +
+
+
+ + +
+

compute_cheesecake_index(self) +

+ Compute overall Cheesecake index for the package by adding up + specific indexes +
+
+
+ + +
+

configure_logging(self) +

+

Default settings for logging

+ if verbose, log goes to console, else it goes to logfile log.debug + goes to logfile log.info goes to console log.warn and log.error go to + both logfile and stdout +
+
+
+ + +
+

copy_pkg(self) +

+ Copy package file to sandbox directory +
+
+
+ + +
+

download_pkg(self) +

+ Use ``urllib.urlretrieve`` to download package to file in sandbox + dir +
+
+
+ + +
+

get_package_from_path(self, + path) +

+ Get package name as file portion of path +
+
+
+ + +
+

get_package_from_url(self) +

+ Use ``urlparse`` to obtain package path from URL +
+
+
+ + +
+

get_pkg_from_pypi(self) +

+ Download package using setuptools utilities +
+
+
+ + +
+

index_dir(self) +

+ Return CompositeIndex object of type "dir" +
+
+
+ + +
+

index_docstrings(self) +

+

Compute docstring index as percentage of + modules/classes/methods/functions that have docstrings associated with + them

+ Return Index object of type "docstrings" +
+
+
+ + +
+

index_file(self) +

+ Return CompositeIndex object of type "file" +
+
+
+ + +
+

index_install(self) +

+

Verify that package can be installed in alternate directory

+ Return Index object of type "install" +
+
+
+ + +
+

index_pylint(self) +

+

Compute pylint index as average of positive pylint scores obtained + for the Python files identified in the package

+ Return Index object of type "pylint" +
+
+
+ + +
+

index_pypi_download(self) +

+

Verify that package can be downloaded from PyPI

+ Return Index object of type "pypi_download" +
+
+
+ + +
+

index_unpack(self) +

+

Verify that package can be unpacked

+ Return Index object of type "unpack" +
+
+
+ + +
+

index_unpack_dir(self) +

+

Verify that unpack directory has same name as package

+ Return Index object of type "unpack_dir" +
+
+
+ + +
+

index_url_download(self) +

+

Verify that package can be downloaded from an URL

+ Return Index object of type "download" +
+
+
+ + +
+

init_indexes(self) +

+

Initialize variables used in index computation

+ * cheesecake_index: overall index for the package * index: dict + holding Index or CompositeIndex objects of various types +
+
+
+ + +
+

is_py_file(self, + file, + dirs) +

+ Return True if file ends with .py and it is not a special file and + it is not in special directory +
+
+
+ + +
+

is_test_file(self, + file, + dirs) +

+ Return True is file is in directory rooted at "test" or + "tests" +
+
+
+ + +
+

print_line(self, + line) +

+ Print line of text, unless quiet flag was given +
+
+
+ + +
+

process_index(self, + index_type) +

+ Compute and print index of specified type +
+
+
+ + +
+

raise_exception(self, + msg) +

+

Cleanup, print error message and raise CheesecakeError

+ Don't use logging, since it can be called before logging has been + setup +
+
+
+ + +
+

unpack_pkg(self) +

+

Unpack the package in the sandbox directory

+

Currently supported archive types:

+ * .tar.gz (handled with ``tarfile`` module) * .zip (handled with + ``zipfile`` module) +
+
+
+ + +
+

untar_pkg(self) +

+

Untar the package in the sandbox directory

+ Uses tarfile module +
+
+
+ + +
+

unzip_pkg(self) +

+

Unzip the package in the sandbox directory

+ Uses zipfile module +
+
+
+ + +
+

walk_pkg(self) +

+

Traverse the file system tree rooted at sandbox/package_name

+ * Compute indexes for special files and directories * Identify + Python files, test files, etc. +
+
+
+
+ + + + + + + + + + + + + + + + + + +
Generated by Epydoc 2.1 on Wed Dec 21 17:21:41 2005http://epydoc.sf.net
+ + Index: /trunk/docs/public/cheesecake.cheesecake_index-module.html =================================================================== --- /trunk/docs/public/cheesecake.cheesecake_index-module.html (revision 2) +++ /trunk/docs/public/cheesecake.cheesecake_index-module.html (revision 2) @@ -0,0 +1,561 @@ + + + + + cheesecake.cheesecake_index + + + + + + + + + + + + + + + + + + +
+ + Package cheesecake :: + Module cheesecake_index +
+
+ + +
[show private | hide private]
[frames | no frames]
+ + +

Module cheesecake.cheesecake_index

+ +
+Cheesecake: How tasty is your code?
+
+The idea of the Cheesecake project is to rank Python packages
+based on various empiric "kwalitee" factors, such as:
+
+        * whether the package can be downloaded
+        * whether the package can be unpacked
+        * whether the package can be installed into an alternate directory
+        * existence of certain files such as README, INSTALL, LICENSE, setup.py etc.
+        * existence of certain directories such as doc, test, demo, examples
+        * percentage of modules/functions/classes/methods with docstrings
+        * percentage of functions/methods that are unit tested
+        * average pylint score for all non-test and non-demo modules
+        * whether the package can be unpacked
+        * whether the package can be installed into an alternate directory
+
+
+ + + + + + + + + + + + + + + +
Classes
+ CheesecakeComputes 'goodness' of Python packages + +Generates "cheesecake index" that takes into account things like: + + * whether the package can be downloaded + * whether the package can be unpacked + * whether the package can be installed into an alternate directory + * existence of certain files such as README, INSTALL, LICENSE, setup.py etc.
+ CodeParserInformation about the structure of a Python module
+ CompositeIndexCollection of indexes of same type (e.g.
+ IndexEncapsulates index attributes such as name, value, details
+ StdoutRedirectorRedirect stdout to a temp file

+ + + + + + + + +
Exceptions
+ CheesecakeErrorCustom exception class for Cheesecake-specific errors

+ + + + + + + + + + + + + + + + +
Function Summary
 main() +
+Display Cheesecake index for package specified via command-line +options
 pad_left_spaces(value, + length) +
+Pad value with spaces at left up to given length
 pad_msg(msg, + value) +
+Pad message with dots and pad value with spaces
 pad_with_dots(msg, + length) +
+Pad text with dots up to given length
 process_cmdline_args() +
+Parse command-line options

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Variable Summary
intINDEX_DIR = 20                                                                    
intINDEX_DIR_CRITICAL = 25                                                                    
intINDEX_DIR_EMPTY = 5                                                                     
intINDEX_FILE = 10                                                                    
intINDEX_FILE_CRITICAL = 15                                                                    
intINDEX_FILE_PYC = -20                                                                   
intINDEX_INSTALL = 50                                                                    
intINDEX_PYPI_DISTANCE = 5                                                                     
intINDEX_PYPI_DOWNLOAD = 50                                                                    
intINDEX_REQUIRED_FILES = 100                                                                   
intINDEX_UNPACK = 25                                                                    
intINDEX_UNPACK_DIR = 15                                                                    
intINDEX_URL_DOWNLOAD = 25                                                                    
intPAD_TEXT = 40                                                                    
intPAD_VALUE = 4                                                                     

+ + + + + + +
Function Details
+ + +
+

main() +

+ Display Cheesecake index for package specified via command-line + options +
+
+
+ + +
+

pad_left_spaces(value, + length=4) +

+ Pad value with spaces at left up to given length +
+
+
+ + +
+

pad_msg(msg, + value) +

+ Pad message with dots and pad value with spaces +
+
+
+ + +
+

pad_with_dots(msg, + length=40) +

+ Pad text with dots up to given length +
+
+
+ + +
+

process_cmdline_args() +

+ Parse command-line options +
+
+
+
+ + + + + + +
Variable Details
+
+ +

INDEX_DIR

+
+
+
+
+
Type:
+
+ int + +
+
Value:
+
+
+20                                                                    
+
+
+
+
+
+ +

INDEX_DIR_CRITICAL

+
+
+
+
+
Type:
+
+ int + +
+
Value:
+
+
+25                                                                    
+
+
+
+
+
+ +

INDEX_DIR_EMPTY

+
+
+
+
+
Type:
+
+ int + +
+
Value:
+
+
+5                                                                     
+
+
+
+
+
+ +

INDEX_FILE

+
+
+
+
+
Type:
+
+ int + +
+
Value:
+
+
+10                                                                    
+
+
+
+
+
+ +

INDEX_FILE_CRITICAL

+
+
+
+
+
Type:
+
+ int + +
+
Value:
+
+
+15                                                                    
+
+
+
+
+
+ +

INDEX_FILE_PYC

+
+
+
+
+
Type:
+
+ int + +
+
Value:
+
+
+-20                                                                   
+
+
+
+
+
+ +

INDEX_INSTALL

+
+
+
+
+
Type:
+
+ int + +
+
Value:
+
+
+50                                                                    
+
+
+
+
+
+ +

INDEX_PYPI_DISTANCE

+
+
+
+
+
Type:
+
+ int + +
+
Value:
+
+
+5                                                                     
+
+
+
+
+
+ +

INDEX_PYPI_DOWNLOAD

+
+
+
+
+
Type:
+
+ int + +
+
Value:
+
+
+50                                                                    
+
+
+
+
+
+ +

INDEX_REQUIRED_FILES

+
+
+
+
+
Type:
+
+ int + +
+
Value:
+
+
+100                                                                   
+
+
+
+
+
+ +

INDEX_UNPACK

+
+
+
+
+
Type:
+
+ int + +
+
Value:
+
+
+25                                                                    
+
+
+
+
+
+ +

INDEX_UNPACK_DIR

+
+
+
+
+
Type:
+
+ int + +
+
Value:
+
+
+15                                                                    
+
+
+
+
+
+ +

INDEX_URL_DOWNLOAD

+
+
+
+
+
Type:
+
+ int + +
+
Value:
+
+
+25                                                                    
+
+
+
+
+
+ +

PAD_TEXT

+
+
+
+
+
Type:
+
+ int + +
+
Value:
+
+
+40                                                                    
+
+
+
+
+
+ +

PAD_VALUE

+
+
+
+
+
Type:
+
+ int + +
+
Value:
+
+
+4                                                                     
+
+
+
+
+
+ + + + + + + + + + + + + + + + + + +
Generated by Epydoc 2.1 on Wed Dec 21 17:21:41 2005http://epydoc.sf.net
+ + Index: /trunk/README =================================================================== --- /trunk/README (revision 5) +++ /trunk/README (revision 5) @@ -0,0 +1,386 @@ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Cheesecake: How tasty is your code? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. contents:: **Table of Contents** + +Summary +------- + +The idea of the Cheesecake project is to rank Python packages based on various +empirical "kwalitee" factors, such as: + + * whether the package can be downloaded from PyPI given its name + * whether the package can be downloaded from a full URL + * whether the package can be unpacked + * whether the unpack directory is the same as the package name + * whether the package can be installed into an alternate directory + * existence of certain files such as README, INSTALL, LICENSE, setup.py etc. + * existence of certain directories such as doc, test, demo, examples + * percentage of modules/functions/classes/methods with docstrings + * percentage of functions/methods that are unit tested (not currently + implemented) + * average pylint score for all non-test and non-demo modules + +Currently, the Cheesecake index is computed for invidual packages obtained +through a variety of methods (detailed below). One of the goals of the +Cheesecake project is to automatically compute the Cheesecake index for +all packages uploaded to the PyPI Cheese Shop (possibly at upload time) and +to maintain a collection of Web pages with statistics related to the +various indexes of the packages. + +Cheesecake currently computes 3 types of indexes: + + * installability index + * documentation index + * code kwalitee index + +The algorithms for computing each index type are detailed below. + +Why Cheesecake? +--------------- + +The concept of "kwalitee" originated in the Perl community. Here's a relevant +quote: + + *It looks like quality, it sounds like quality, but it's not quite quality.* + +Kwalitee is an empiric measure of how good a specific body of code is. It +defines quality indicators and measures the code along them. It is currently +used by the `CPANTS Testing Service `_ +to evaluate the 'goodness' of CPAN packages. + +Since the Python package repository (aka `PyPI `_) +is hosted at the Cheese Shop, +it stands to reason that the quality indicator of a PyPI package should be +called the Cheesecake index! + +Usage examples +-------------- + +To compute the Cheesecake index for a given project, run the cheesecake.py +module from the command line and indicate either: + + * the package short name (e.g. twill) or + * the package URL (e.g. http://darcs.idyll.org/~t/projects/twill-0.7.4.tar.gz) or + * the package path on the file system (e.g. /tmp/twill-latest.tar.gz) + +In all cases, the cheesecake module will attempt to download the package +if necessary, then to unpack it in a sandbox directory (/tmp/cheesecake_sandbox +by default). If either of these operations fails, the Cheesecake index for +the package will be 0. If the package can be successfully unpacked, the +cheesecake module will compute the values for a variety of indexes detailed +in the algorithm given at the end of this file. + +If the package can be successfully downloaded and unpacked, a log file is +created in the sandbox directory and named .log (e.g. the log file +for twill-0.7.4.tar.gz is /tmp/cheesecake_sandbox/twill-0.7.4.tar.gz.log). +The log file is not automatically deleted after the Cheesecake index is +computed, since its purpose is to be inspected for debug information. + +Command-line examples: + + 1. Compute the Cheesecake index for the Durus package by using setuptools + utilities to download the package from PyPI:: + + python cheesecake.py --name=Durus + + 2. Compute the Cheesecake index for the Durus package by indicating its URL:: + + python cheesecake.py --url=http://www.mems-exchange.org/software/durus/Durus-3.1.tar.gz + + 3. Compute the Cheesecake index for the twill package by indicating its path + on the local file system:: + + python cheesecake.py --path=/tmp/twill-latest.tar.gz + + 4. To increase the verbosity of the output, use the -v or --verbose option. + For more options, run cheesecake.py with -h or --help. + +Obtaining the source code +------------------------- + +The Cheesecake project has not yet been released as a tarball or +a Python egg. You can obtain the source code from SourceForge via CVS:: + + cvs -z3 -d:pserver:anonymous@cvs.sourceforge.net:/cvsroot/cheesecake co -P cheesecake + +Mailing list +------------ + +Developer mailing list: http://lists.sourceforge.net/lists/listinfo/cheesecake-devel + +License +------- + +Cheesecake is licensed under the Python Software Foundation license, +the same license that governs Python itself. The text of the license is +available in the ``LICENSE`` file in the source code distribution and +can also be downloaded from +http://www.opensource.org/licenses/PythonSoftFoundation.php. + +Author contact info +------------------- + +Grig Gheorghiu + +Email: + +Web site: http://agiletesting.blogspot.com + +Algorithm for computing the Cheesecake index +-------------------------------------------- + +The cheesecake.py module uses the following constants:: + + INDEX_PYPI_DOWNLOAD = 50 + INDEX_PYPI_DISTANCE = 5 + INDEX_URL_DOWNLOAD = 25 + INDEX_UNPACK = 25 + INDEX_UNPACK_DIR = 15 + INDEX_INSTALL = 50 + INDEX_FILE_CRITICAL = 15 + INDEX_FILE = 10 + INDEX_FILE_PYC = 20 + INDEX_DIR_CRITICAL = 25 + INDEX_DIR = 20 + INDEX_DIR_EMPTY = 5 + + MAX_INDEX_DOCSTRINGS = 100 # max. percentage of modules/classes/methods/functions with docstrings + MAX_INDEX_PYLINT = 100 # max. pylint score + +**Step 0** + +Initialize the Cheesecake index to 0. Also initialize to 0 +the partial Cheesecake indexes for installability, documentation +and code kwalitee. + +Compute the maximum overall Cheesecake index that can be reached by +any given package, which is the sum:: + + INDEX_PYPI_DOWNLOAD + + INDEX_UNPACK + INDEX_UNPACK_DIR + + INDEX_INSTALL + + MAX_INDEX_DOCSTRINGS + MAX_INDEX_PYLINT + + (INDEX_FILE * number_of_expected_files) + + (INDEX_FILE_CRITICAL * number_of_expected_critical_files) + + (INDEX_DIR * number_of_expected_dirs) + + (INDEX_DIR_CRITICAL * number_of_expected_critical_dirs) + +Compute the maximum Cheesecake index for installability, which is the sum:: + + INDEX_PYPI_DOWNLOAD + + INDEX_UNPACK + INDEX_UNPACK_DIR + + INDEX_INSTALL + +Compute the maximum Cheesecake index for documentation, which is the sum:: + + (INDEX_FILE * number_of_expected_files) + + (INDEX_FILE_CRITICAL * number_of_expected_critical_files) + + (INDEX_DIR * number_of_expected_dirs) + + (INDEX_DIR_CRITICAL * number_of_expected_critical_dirs) + + MAX_INDEX_DOCSTRINGS + +Compute the maximum Cheesecake index for code kwalitee, which is currently:: + + MAX_INDEX_PYLINT + +**Step 1a** + +If short name of the package was specified with ``-n`` or ``--name``, +try to download the package from the PyPI index page by following the links to +the package home page and the package download URL (this is accomplished +using setuptools utilities). + +If not successful, exit with a Cheesecake index of 0. If successful and +package was found at the Cheese Shop, add ``INDEX_PYPI_DOWNLOAD`` to +the overall Cheesecake index and to the installability Cheesecake index. + +If successful but package was not found at the Cheese Shop, add +``INDEX_PYPI_DOWNLOAD - (INDEX_PYPI_DISTANCE * number_of_links_to_package)`` +to the overall Cheesecake index and to the installability Cheesecake index. + +**Step 1b** + +If full URL of the package was specified with ``-u`` or ``--url``, +try to download the package from the specified URL. + +If not successful, exit with a Cheesecake index of 0. If successful, +add ``INDEX_URL_DOWNLOAD`` to the overall Cheesecake index and to +the installability Cheesecake index. + +**Step 1c** + +If path to package on local file system was specified with ``-p`` or +``--path``, copy the package to the sandbox directory. + +**Step 2** + +Unpack the package (currently supported archive types are zip and +tar.gz/tgz; in the near future we will support Python Eggs.) + +If not successful, exit with a Cheesecake index of 0. If successful, add +``INDEX_UNPACK`` to the overall Cheesecake index and to the installability +Cheesecake index. + +**Step 3** + +Check that the unpack directory has the same name as the package name +(i.e. when unpacking twill-0.7.4.tar.gz, we expect the unpack directory +to be twill-0.7.4.) + +If the unpack directory name is the same as the package name, add +``INDEX_UNPACK_DIR`` +to the overall Cheesecake index and to the installability Cheesecake index. + +**Step 4** + +Install the package to a temporary directory in a non-default location. +If successful, add ``INDEX_INSTALL`` to the overall Cheesecake index and to the +installability Cheesecake index. + +**Step 5** + +Check for existence of specific files. +For each file found, add ``INDEX_FILE`` to the overall +Cheesecake index and to the documentation Cheesecake index. +If the file is deemed critical, add ``INDEX_FILE_CRITICAL`` instead. + +The following special files ("cheese_files") are currently checked:: + + cheese_files = ["install", "changelog", + "news", "faq", + "todo", "thanks", "announce", + "ez_setup.py", + ] + +The following files are currently deemed critical:: + + critical_cheese_files = ["readme", "license", "setup.py"] + +To check if a file FILE is among the cheese files, the following regular +expression is used:: + + re.search(r"^%s(\.txt)*" % cheese_file, file, re.IGNORECASE) + +**Step 6** + +Check for existence of specific directories. +For each directory found, add ``INDEX_DIR`` to the overall Cheesecake +index and to the documentation Cheesecake index. +If the directory is deemed critical, add ``INDEX_DIR_CRITICAL`` instead. +If the directory is found empty, add ``INDEX_DIR_EMPTY`` instead. + +The following directories ("cheese_dirs") are currently checked:: + + cheese_dirs = ["example", "demo"] + +The following directories are currently deemed critical:: + + critical_cheese_dirs = ["doc", "test"] + +To check if a directory DIR is among the cheese directories, +the following regular expression is used:: + + re.search(r"^%s" % cheese_dir, DIR, re.ignorecase) + +**Step 7** + +Check for existence of .pyc files. If found, decrease the score +by subtracting ``INDEX_FILE_PYC`` from the overall Cheesecake index +and from the documentation Cheesecake index. + +**Step 8** + +Compute the percentage of modules/classes/methods/functions that have +docstrings associated with them. Only Python modules that are not in test, +doc, demo and example directories are checked. +Round up the percentage and add it to the overall Cheesecake index and to the +documentation Cheesecake index. + +**Step 9** + +If pylint is present on the system, run pylint against all Python files +that are not in the test, docs or demo directories. +Average the non-negative pylint scores, multiply the average by 10 and +add it to the overall Cheesecake index and to the code kwalitee +Cheesecake index. + +**Step 10** + +For each of the partial Cheesecake index types (installability, +documentation and code kwalitee), display the absolute Cheesecake +index for that type as the sum of all indexes of that type computed in +the previous steps. +Also display the relative Cheesecake index for that type as the percentage +of ``(absolute_index / maximum_index)``. + +Display the absolute Cheesecake index for the package as the sum of all +indexes computed in the previous steps. Also display the relative Cheesecake +index for the package as the percentage of ``(absolute_index / maximum_index)``. + +Sample output +------------- + +:: + + $ python cheesecake.py -n Durus + [cheesecake:console] Trying to download package durus from PyPI using setuptools utilities + [cheesecake:console] Downloaded package Durus-3.1.tar.gz from http://www.mems-exchange.org/software/durus/Durus-3.1.tar.gz + [cheesecake:console] Detailed info available in log file /tmp/cheesecake_sandbox/durus.log + [cheesecake:console] A given package can currently reach a MAXIMUM number of 555 points + [cheesecake:console] Starting computation of Cheesecake index for package 'Durus-3.1.tar.gz' + + [cheesecake:console] Starting computation of INSTALLABILITY index (max. points = 140) + index_pypi_download ..................... 45 (downloaded package Durus-3.1.tar.gz following 1 link from PyPI) + index_unpack ............................ 25 (package untar-ed successfully) + index_unpack_dir ........................ 15 (unpack directory is Durus-3.1 as expected) + index_install ........................... 50 (package installed in /tmp/cheesecake_sandbox/tmp_install_Durus-3.1) + --------------------------------------------- + INSTALLABILITY INDEX (ABSOLUTE) ......... 135 + INSTALLABILITY INDEX (RELATIVE) ......... 96 (135 out of a maximum of 140 points is 96%) + + [cheesecake:console] Starting computation of DOCUMENTATION index (max. points = 415) + index_file_announce ..................... 0 (file not found) + index_file_changelog .................... 0 (file not found) + index_file_ez_setup.py .................. 0 (file not found) + index_file_faq .......................... 10 (file found) + index_file_install ...................... 10 (file found) + index_file_license ...................... 15 (critical file found) + index_file_news ......................... 0 (file not found) + index_file_readme ....................... 15 (critical file found) + index_file_setup.py ..................... 15 (critical file found) + index_file_thanks ....................... 0 (file not found) + index_file_todo ......................... 0 (file not found) + index_dir_demo .......................... 0 (directory not found) + index_dir_doc ........................... 25 (critical directory found) + index_dir_example ....................... 0 (directory not found) + index_dir_test .......................... 25 (critical directory found) + index_docstrings ........................ 42 (found 104/249=41.77% modules/classes/methods/functions with docstrings) + --------------------------------------------- + DOCUMENTATION INDEX (ABSOLUTE) .......... 157 + DOCUMENTATION INDEX (RELATIVE) .......... 37 (157 out of a maximum of 415 points is 37%) + + [cheesecake:console] Starting computation of CODE KWALITEE index (max. points = 100) + index_pylint ............................ 64 (average score is 6.30 out of 10) + --------------------------------------------- + CODE KWALITEE INDEX (ABSOLUTE) .......... 64 + CODE KWALITEE INDEX (RELATIVE) .......... 64 (64 out of a maximum of 100 points is 64%) + + ============================================= + OVERALL CHEESECAKE INDEX (ABSOLUTE) ..... 356 + OVERALL CHEESECAKE INDEX (RELATIVE) ..... 64 (356 out of a maximum of 555 points is 64%) + +Future plans +------------ +Cheesecake is under very active development. The immediate goal is to add the unit test +index measurement, followed by other metrics inspired from the +`kwalitee indicators `_. +Please edit the `IndexMeasurementIdeas `_ +Wiki page to add things that you would like to see covered +by the Cheesecake metrics. + +.. footer:: Generated with rst2html.py from the + `docutils `_ + distribution. Last modified 2005-12-20 by + `Grig Gheorghiu `_. Index: /ADME.html =================================================================== --- /README.html (revision 2) +++ (revision ) @@ -1,380 +1,0 @@ - - - - - - -Cheesecake: How tasty is your code? - - - -
-

Cheesecake: How tasty is your code?

- -
-

Summary

-

The idea of the Cheesecake project is to rank Python packages based on various -empirical "kwalitee" factors, such as:

-
-
    -
  • whether the package can be downloaded from PyPI given its name
  • -
  • whether the package can be downloaded from a full URL
  • -
  • whether the package can be unpacked
  • -
  • whether the unpack directory is the same as the package name
  • -
  • whether the package can be installed into an alternate directory
  • -
  • existence of certain files such as README, INSTALL, LICENSE, setup.py etc.
  • -
  • existence of certain directories such as doc, test, demo, examples
  • -
  • percentage of modules/functions/classes/methods with docstrings
  • -
  • percentage of functions/methods that are unit tested (not currently -implemented)
  • -
  • average pylint score for all non-test and non-demo modules
  • -
-
-

Currently, the Cheesecake index is computed for invidual packages obtained -through a variety of methods (detailed below). One of the goals of the -Cheesecake project is to automatically compute the Cheesecake index for -all packages uploaded to the PyPI Cheese Shop (possibly at upload time) and -to maintain a collection of Web pages with statistics related to the -various indexes of the packages.

-

Cheesecake currently computes 3 types of indexes:

-
-
    -
  • installability index
  • -
  • documentation index
  • -
  • code kwalitee index
  • -
-
-

The algorithms for computing each index type are detailed below.

-
-
-

Why Cheesecake?

-

The concept of "kwalitee" originated in the Perl community. Here's a relevant -quote:

-
-It looks like quality, it sounds like quality, but it's not quite quality.
-

Kwalitee is an empiric measure of how good a specific body of code is. It -defines quality indicators and measures the code along them. It is currently -used by the CPANTS Testing Service -to evaluate the 'goodness' of CPAN packages.

-

Since the Python package repository (aka PyPI) -is hosted at the Cheese Shop, -it stands to reason that the quality indicator of a PyPI package should be -called the Cheesecake index!

-
-
-

Usage examples

-

To compute the Cheesecake index for a given project, run the cheesecake.py -module from the command line and indicate either:

-
- -
-

In all cases, the cheesecake module will attempt to download the package -if necessary, then to unpack it in a sandbox directory (/tmp/cheesecake_sandbox -by default). If either of these operations fails, the Cheesecake index for -the package will be 0. If the package can be successfully unpacked, the -cheesecake module will compute the values for a variety of indexes detailed -in the algorithm given at the end of this file.

-

If the package can be successfully downloaded and unpacked, a log file is -created in the sandbox directory and named <package>.log (e.g. the log file -for twill-0.7.4.tar.gz is /tmp/cheesecake_sandbox/twill-0.7.4.tar.gz.log). -The log file is not automatically deleted after the Cheesecake index is -computed, since its purpose is to be inspected for debug information.

-

Command-line examples:

-
-
    -
  1. Compute the Cheesecake index for the Durus package by using setuptools -utilities to download the package from PyPI:

    -
    -python cheesecake.py --name=Durus
    -
    -
  2. -
  3. Compute the Cheesecake index for the Durus package by indicating its URL:

    -
    -python cheesecake.py --url=http://www.mems-exchange.org/software/durus/Durus-3.1.tar.gz
    -
    -
  4. -
  5. Compute the Cheesecake index for the twill package by indicating its path -on the local file system:

    -
    -python cheesecake.py --path=/tmp/twill-latest.tar.gz
    -
    -
  6. -
  7. To increase the verbosity of the output, use the -v or --verbose option. -For more options, run cheesecake.py with -h or --help.

    -
  8. -
-
-
-
-

Obtaining the source code

-

The Cheesecake project has not yet been released as a tarball or -a Python egg. You can obtain the source code from SourceForge via CVS:

-
-cvs -z3 -d:pserver:anonymous@cvs.sourceforge.net:/cvsroot/cheesecake co -P cheesecake
-
-
- -
-

License

-

Cheesecake is licensed under the Python Software Foundation license, -the same license that governs Python itself. The text of the license is -available in the LICENSE file in the source code distribution and -can also be downloaded from -http://www.opensource.org/licenses/PythonSoftFoundation.php.

-
-
-

Author contact info

-

Grig Gheorghiu

-

Email: <grig at gheorghiu dot net>

-

Web site: http://agiletesting.blogspot.com

-
-
-

Algorithm for computing the Cheesecake index

-

The cheesecake.py module uses the following constants:

-
-INDEX_PYPI_DOWNLOAD = 50
-INDEX_PYPI_DISTANCE = 5
-INDEX_URL_DOWNLOAD  = 25
-INDEX_UNPACK        = 25
-INDEX_UNPACK_DIR    = 15
-INDEX_INSTALL       = 50
-INDEX_FILE_CRITICAL = 15
-INDEX_FILE          = 10
-INDEX_FILE_PYC      = 20
-INDEX_DIR_CRITICAL  = 25
-INDEX_DIR           = 20
-INDEX_DIR_EMPTY     = 5
-
-MAX_INDEX_DOCSTRINGS = 100 # max. percentage of modules/classes/methods/functions with docstrings
-MAX_INDEX_PYLINT     = 100 # max. pylint score
-
-

Step 0

-

Initialize the Cheesecake index to 0. Also initialize to 0 -the partial Cheesecake indexes for installability, documentation -and code kwalitee.

-

Compute the maximum overall Cheesecake index that can be reached by -any given package, which is the sum:

-
-INDEX_PYPI_DOWNLOAD + 
-INDEX_UNPACK + INDEX_UNPACK_DIR + 
-INDEX_INSTALL +
-MAX_INDEX_DOCSTRINGS + MAX_INDEX_PYLINT + 
-(INDEX_FILE * number_of_expected_files) +
-(INDEX_FILE_CRITICAL * number_of_expected_critical_files) +
-(INDEX_DIR * number_of_expected_dirs) +
-(INDEX_DIR_CRITICAL * number_of_expected_critical_dirs)
-
-

Compute the maximum Cheesecake index for installability, which is the sum:

-
-INDEX_PYPI_DOWNLOAD + 
-INDEX_UNPACK + INDEX_UNPACK_DIR + 
-INDEX_INSTALL
-
-

Compute the maximum Cheesecake index for documentation, which is the sum:

-
-(INDEX_FILE * number_of_expected_files) +
-(INDEX_FILE_CRITICAL * number_of_expected_critical_files) +
-(INDEX_DIR * number_of_expected_dirs) +
-(INDEX_DIR_CRITICAL * number_of_expected_critical_dirs) +
-MAX_INDEX_DOCSTRINGS
-
-

Compute the maximum Cheesecake index for code kwalitee, which is currently:

-
-MAX_INDEX_PYLINT
-
-

Step 1a

-

If short name of the package was specified with -n or --name, -try to download the package from the PyPI index page by following the links to -the package home page and the package download URL (this is accomplished -using setuptools utilities).

-

If not successful, exit with a Cheesecake index of 0. If successful and -package was found at the Cheese Shop, add INDEX_PYPI_DOWNLOAD to -the overall Cheesecake index and to the installability Cheesecake index.

-

If successful but package was not found at the Cheese Shop, add -INDEX_PYPI_DOWNLOAD - (INDEX_PYPI_DISTANCE * number_of_links_to_package) -to the overall Cheesecake index and to the installability Cheesecake index.

-

Step 1b

-

If full URL of the package was specified with -u or --url, -try to download the package from the specified URL.

-

If not successful, exit with a Cheesecake index of 0. If successful, -add INDEX_URL_DOWNLOAD to the overall Cheesecake index and to -the installability Cheesecake index.

-

Step 1c

-

If path to package on local file system was specified with -p or ---path, copy the package to the sandbox directory.

-

Step 2

-

Unpack the package (currently supported archive types are zip and -tar.gz/tgz; in the near future we will support Python Eggs.)

-

If not successful, exit with a Cheesecake index of 0. If successful, add -INDEX_UNPACK to the overall Cheesecake index and to the installability -Cheesecake index.

-

Step 3

-

Check that the unpack directory has the same name as the package name -(i.e. when unpacking twill-0.7.4.tar.gz, we expect the unpack directory -to be twill-0.7.4.)

-

If the unpack directory name is the same as the package name, add -INDEX_UNPACK_DIR -to the overall Cheesecake index and to the installability Cheesecake index.

-

Step 4

-

Install the package to a temporary directory in a non-default location. -If successful, add INDEX_INSTALL to the overall Cheesecake index and to the -installability Cheesecake index.

-

Step 5

-

Check for existence of specific files. -For each file found, add INDEX_FILE to the overall -Cheesecake index and to the documentation Cheesecake index. -If the file is deemed critical, add INDEX_FILE_CRITICAL instead.

-

The following special files ("cheese_files") are currently checked:

-
-cheese_files = ["install", "changelog",
-                "news", "faq",
-                "todo", "thanks", "announce",
-                "ez_setup.py",
-               ]
-
-

The following files are currently deemed critical:

-
-critical_cheese_files = ["readme", "license", "setup.py"]
-
-

To check if a file FILE is among the cheese files, the following regular -expression is used:

-
-re.search(r"^%s(\.txt)*" % cheese_file, file, re.IGNORECASE)
-
-

Step 6

-

Check for existence of specific directories. -For each directory found, add INDEX_DIR to the overall Cheesecake -index and to the documentation Cheesecake index. -If the directory is deemed critical, add INDEX_DIR_CRITICAL instead. -If the directory is found empty, add INDEX_DIR_EMPTY instead.

-

The following directories ("cheese_dirs") are currently checked:

-
-cheese_dirs = ["example", "demo"]
-
-

The following directories are currently deemed critical:

-
-critical_cheese_dirs = ["doc", "test"]
-
-

To check if a directory DIR is among the cheese directories, -the following regular expression is used:

-
-re.search(r"^%s" % cheese_dir, DIR, re.ignorecase)
-
-

Step 7

-

Check for existence of .pyc files. If found, decrease the score -by subtracting INDEX_FILE_PYC from the overall Cheesecake index -and from the documentation Cheesecake index.

-

Step 8

-

Compute the percentage of modules/classes/methods/functions that have -docstrings associated with them. Only Python modules that are not in test, -doc, demo and example directories are checked. -Round up the percentage and add it to the overall Cheesecake index and to the -documentation Cheesecake index.

-

Step 9

-

If pylint is present on the system, run pylint against all Python files -that are not in the test, docs or demo directories. -Average the non-negative pylint scores, multiply the average by 10 and -add it to the overall Cheesecake index and to the code kwalitee -Cheesecake index.

-

Step 10

-

For each of the partial Cheesecake index types (installability, -documentation and code kwalitee), display the absolute Cheesecake -index for that type as the sum of all indexes of that type computed in -the previous steps. -Also display the relative Cheesecake index for that type as the percentage -of (absolute_index / maximum_index).

-

Display the absolute Cheesecake index for the package as the sum of all -indexes computed in the previous steps. Also display the relative Cheesecake -index for the package as the percentage of (absolute_index / maximum_index).

-
-
-

Sample output

-
-$ python cheesecake.py -n Durus
-[cheesecake:console] Trying to download package durus from PyPI using setuptools utilities
-[cheesecake:console] Downloaded package Durus-3.1.tar.gz from http://www.mems-exchange.org/software/durus/Durus-3.1.tar.gz
-[cheesecake:console] Detailed info available in log file /tmp/cheesecake_sandbox/durus.log
-[cheesecake:console] A given package can currently reach a MAXIMUM number of 555 points
-[cheesecake:console] Starting computation of Cheesecake index for package 'Durus-3.1.tar.gz'
-
-[cheesecake:console] Starting computation of INSTALLABILITY index (max. points = 140)
-index_pypi_download .....................  45 (downloaded package Durus-3.1.tar.gz following 1 link from PyPI)
-index_unpack ............................  25 (package untar-ed successfully)
-index_unpack_dir ........................  15 (unpack directory is Durus-3.1 as expected)
-index_install ...........................  50 (package installed in /tmp/cheesecake_sandbox/tmp_install_Durus-3.1)
----------------------------------------------
-INSTALLABILITY INDEX (ABSOLUTE) ......... 135
-INSTALLABILITY INDEX (RELATIVE) .........  96 (135 out of a maximum of 140 points is 96%)
-
-[cheesecake:console] Starting computation of DOCUMENTATION index (max. points = 415)
-index_file_announce .....................   0 (file not found)
-index_file_changelog ....................   0 (file not found)
-index_file_ez_setup.py ..................   0 (file not found)
-index_file_faq ..........................  10 (file found)
-index_file_install ......................  10 (file found)
-index_file_license ......................  15 (critical file found)
-index_file_news .........................   0 (file not found)
-index_file_readme .......................  15 (critical file found)
-index_file_setup.py .....................  15 (critical file found)
-index_file_thanks .......................   0 (file not found)
-index_file_todo .........................   0 (file not found)
-index_dir_demo ..........................   0 (directory not found)
-index_dir_doc ...........................  25 (critical directory found)
-index_dir_example .......................   0 (directory not found)
-index_dir_test ..........................  25 (critical directory found)
-index_docstrings ........................  42 (found 104/249=41.77% modules/classes/methods/functions with docstrings)
----------------------------------------------
-DOCUMENTATION INDEX (ABSOLUTE) .......... 157
-DOCUMENTATION INDEX (RELATIVE) ..........  37 (157 out of a maximum of 415 points is 37%)
-
-[cheesecake:console] Starting computation of CODE KWALITEE index (max. points = 100)
-index_pylint ............................  64 (average score is 6.30 out of 10)
----------------------------------------------
-CODE KWALITEE INDEX (ABSOLUTE) ..........  64
-CODE KWALITEE INDEX (RELATIVE) ..........  64 (64 out of a maximum of 100 points is 64%)
-
-=============================================
-OVERALL CHEESECAKE INDEX (ABSOLUTE) ..... 356
-OVERALL CHEESECAKE INDEX (RELATIVE) .....  64 (356 out of a maximum of 555 points is 64%)
-
-
-
-

Future plans

-

Cheesecake is under very active development. The immediate goal is to add the unit test -index measurement, followed by other metrics inspired from the -kwalitee indicators. -Please edit the IndexMeasurementIdeas -Wiki page to add things that you would like to see covered -by the Cheesecake metrics.

-
-
- - - Index: /CENSE =================================================================== --- /LICENSE (revision 2) +++ (revision ) @@ -1,86 +1,0 @@ -Cheesecake is licensed under the Python Software Foundation license, the same license that governs Python itself. Here is the text of the license, downloaded from : - -Python 2.1.1 license - -This is the official license for the Python 2.1.1 release: -A. HISTORY OF THE SOFTWARE -========================== - -Python was created in the early 1990s by Guido van Rossum at Stichting Mathematisch Centrum (CWI) in the Netherlands as a successor of a language called ABC. Guido is Python's principal author, although it includes many contributions from others. The last version released from CWI was Python 1.2. In 1995, Guido continued his work on Python at the Corporation for National Research Initiatives (CNRI) in Reston, Virginia where he released several versions of the software. Python 1.6 was the last of the versions released by CNRI. In 2000, Guido and the Python core development team moved to BeOpen.com to form the BeOpen PythonLabs team. Python 2.0 was the first and only release from BeOpen.com. - -Following the release of Python 1.6, and after Guido van Rossum left CNRI to work with commercial software developers, it became clear that the ability to use Python with software available under the GNU Public License (GPL) was very desirable. CNRI and the Free Software Foundation (FSF) interacted to develop enabling wording changes to the Python license. Python 1.6.1 is essentially the same as Python 1.6, with a few minor bug fixes, and with a different license that enables later versions to be GPL-compatible. Python 2.1 is a derivative work of Python 1.6.1, as well as of Python 2.0. - -After Python 2.0 was released by BeOpen.com, Guido van Rossum and the other PythonLabs developers joined Digital Creations. All intellectual property added from this point on, starting with Python 2.1 and its alpha and beta releases, is owned by the Python Software Foundation (PSF), a non-profit modeled after the Apache Software Foundation. See http://www.python.org/psf/ for more information about the PSF. - -Thanks to the many outside volunteers who have worked under Guido's direction to make these releases possible. - -B. TERMS AND CONDITIONS FOR ACCESSING OR OTHERWISE USING PYTHON -=============================================================== - -PSF LICENSE AGREEMENT ---------------------- - -1. This LICENSE AGREEMENT is between the Python Software Foundation ("PSF"), and the Individual or Organization ("Licensee") accessing and otherwise using Python 2.1.1 software in source or binary form and its associated documentation. - -2. Subject to the terms and conditions of this License Agreement, PSF hereby grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce, analyze, test, perform and/or display publicly, prepare derivative works, distribute, and otherwise use Python 2.1.1 alone or in any derivative version, provided, however, that PSF's License Agreement and PSF's notice of copyright, i.e., "Copyright (c) 2001 Python Software Foundation; All Rights Reserved" are retained in Python 2.1.1 alone or in any derivative version prepared by Licensee. - -3. In the event Licensee prepares a derivative work that is based on or incorporates Python 2.1.1 or any part thereof, and wants to make the derivative work available to others as provided herein, then Licensee hereby agrees to include in any such work a brief summary of the changes made to Python 2.1.1. - -4. PSF is making Python 2.1.1 available to Licensee on an "AS IS" basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 2.1.1 WILL NOT INFRINGE ANY THIRD PARTY RIGHTS. - -5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON 2.1.1 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 2.1.1, OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. - -6. This License Agreement will automatically terminate upon a material breach of its terms and conditions. - -7. Nothing in this License Agreement shall be deemed to create any relationship of agency, partnership, or joint venture between PSF and Licensee. This License Agreement does not grant permission to use PSF trademarks or trade name in a trademark sense to endorse or promote products or services of Licensee, or any third party. - -8. By copying, installing or otherwise using Python 2.1.1, Licensee agrees to be bound by the terms and conditions of this License Agreement. - -BEOPEN.COM TERMS AND CONDITIONS FOR PYTHON 2.0 ----------------------------------------------- - -BEOPEN PYTHON OPEN SOURCE LICENSE AGREEMENT VERSION 1 - -1. This LICENSE AGREEMENT is between BeOpen.com ("BeOpen"), having an office at 160 Saratoga Avenue, Santa Clara, CA 95051, and the Individual or Organization ("Licensee") accessing and otherwise using this software in source or binary form and its associated documentation ("the Software"). - -2. Subject to the terms and conditions of this BeOpen Python License Agreement, BeOpen hereby grants Licensee a non-exclusive, royalty-free, world-wide license to reproduce, analyze, test, perform and/or display publicly, prepare derivative works, distribute, and otherwise use the Software alone or in any derivative version, provided, however, that the BeOpen Python License is retained in the Software, alone or in any derivative version prepared by Licensee. - -3. BeOpen is making the Software available to Licensee on an "AS IS" basis. BEOPEN MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, BEOPEN MAKES NO AND DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE WILL NOT INFRINGE ANY THIRD PARTY RIGHTS. - -4. BEOPEN SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF THE SOFTWARE FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THE SOFTWARE, OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. - -5. This License Agreement will automatically terminate upon a material breach of its terms and conditions. - -6. This License Agreement shall be governed by and interpreted in all respects by the law of the State of California, excluding conflict of law provisions. Nothing in this License Agreement shall be deemed to create any relationship of agency, partnership, or joint venture between BeOpen and Licensee. This License Agreement does not grant permission to use BeOpen trademarks or trade names in a trademark sense to endorse or promote products or services of Licensee, or any third party. As an exception, the "BeOpen Python" logos available at http://www.pythonlabs.com/logos.html may be used according to the permissions granted on that web page. - -7. By copying, installing or otherwise using the software, Licensee agrees to be bound by the terms and conditions of this License Agreement. - -CNRI OPEN SOURCE GPL-COMPATIBLE LICENSE AGREEMENT -------------------------------------------------- - -1. This LICENSE AGREEMENT is between the Corporation for National Research Initiatives, having an office at 1895 Preston White Drive, Reston, VA 20191 ("CNRI"), and the Individual or Organization ("Licensee") accessing and otherwise using Python 1.6.1 software in source or binary form and its associated documentation. - -2. Subject to the terms and conditions of this License Agreement, CNRI hereby grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce, analyze, test, perform and/or display publicly, prepare derivative works, distribute, and otherwise use Python 1.6.1 alone or in any derivative version, provided, however, that CNRI's License Agreement and CNRI's notice of copyright, i.e., "Copyright (c) 1995-2001 Corporation for National Research Initiatives; All Rights Reserved" are retained in Python 1.6.1 alone or in any derivative version prepared by Licensee. Alternately, in lieu of CNRI's License Agreement, Licensee may substitute the following text (omitting the quotes): "Python 1.6.1 is made available subject to the terms and conditions in CNRI's License Agreement. This Agreement together with Python 1.6.1 may be located on the Internet using the following unique, persistent identifier (known as a handle): 1895.22/1013. This Agreement may also be obtained from a proxy server on the Internet using the following URL: http://hdl.handle.net/1895.22/1013". - -3. In the event Licensee prepares a derivative work that is based on or incorporates Python 1.6.1 or any part thereof, and wants to make the derivative work available to others as provided herein, then Licensee hereby agrees to include in any such work a brief summary of the changes made to Python 1.6.1. - -4. CNRI is making Python 1.6.1 available to Licensee on an "AS IS" basis. CNRI MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, CNRI MAKES NO AND DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 1.6.1 WILL NOT INFRINGE ANY THIRD PARTY RIGHTS. - -5. CNRI SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON 1.6.1 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 1.6.1, OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. - -6. This License Agreement will automatically terminate upon a material breach of its terms and conditions. - -7. This License Agreement shall be governed by the federal intellectual property law of the United States, including without limitation the federal copyright law, and, to the extent such U.S. federal law does not apply, by the law of the Commonwealth of Virginia, excluding Virginia's conflict of law provisions. Notwithstanding the foregoing, with regard to derivative works based on Python 1.6.1 that incorporate non-separable material that was previously distributed under the GNU General Public License (GPL), the law of the Commonwealth of Virginia shall govern this License Agreement only as to issues arising under or with respect to Paragraphs 4, 5, and 7 of this License Agreement. Nothing in this License Agreement shall be deemed to create any relationship of agency, partnership, or joint venture between CNRI and Licensee. This License Agreement does not grant permission to use CNRI trademarks or trade name in a trademark sense to endorse or promote products or services of Licensee, or any third party. - -8. By clicking on the "ACCEPT" button where indicated, or by copying, installing or otherwise using Python 1.6.1, Licensee agrees to be bound by the terms and conditions of this License Agreement. - - ACCEPT - -CWI PERMISSIONS STATEMENT AND DISCLAIMER ----------------------------------------- - -Copyright (c) 1991 - 1995, Stichting Mathematisch Centrum Amsterdam, The Netherlands. All rights reserved. - -Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the name of Stichting Mathematisch Centrum or CWI not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. - -STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. Index: /eesecake_index =================================================================== --- /cheesecake_index (revision 2) +++ (revision ) @@ -1,5 +1,0 @@ -#!/usr/bin/env python - -from cheesecake.cheesecake_index import main - -main() Index: /tup.py =================================================================== --- /setup.py (revision 2) +++ (revision ) @@ -1,25 +1,0 @@ -#! /usr/bin/env python -import sys -import os.path - -from setuptools import setup -from pkg_resources import require - -setup( - name = 'Cheesecake', - version = '0.1', - - # metadata for upload to PyPI - author = "Grig Gheorghiu", - author_email = "grig@gheorghiu.net", - description = 'Computes "goodness" index for Python packages based on various empirical "kwalitee" factors', - license = "PSF", - keywords = "cheesecake quality index kwalitee cheeseshop pypi", - url = "http://tracos.org/cheesecake", - - packages = ['cheesecake', - ], - scripts = ['cheesecake_index', - ], - test_suite = 'nose.collector', - ) Index: /ADME =================================================================== --- /README (revision 2) +++ (revision ) @@ -1,386 +1,0 @@ -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Cheesecake: How tasty is your code? -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. contents:: **Table of Contents** - -Summary -------- - -The idea of the Cheesecake project is to rank Python packages based on various -empirical "kwalitee" factors, such as: - - * whether the package can be downloaded from PyPI given its name - * whether the package can be downloaded from a full URL - * whether the package can be unpacked - * whether the unpack directory is the same as the package name - * whether the package can be installed into an alternate directory - * existence of certain files such as README, INSTALL, LICENSE, setup.py etc. - * existence of certain directories such as doc, test, demo, examples - * percentage of modules/functions/classes/methods with docstrings - * percentage of functions/methods that are unit tested (not currently - implemented) - * average pylint score for all non-test and non-demo modules - -Currently, the Cheesecake index is computed for invidual packages obtained -through a variety of methods (detailed below). One of the goals of the -Cheesecake project is to automatically compute the Cheesecake index for -all packages uploaded to the PyPI Cheese Shop (possibly at upload time) and -to maintain a collection of Web pages with statistics related to the -various indexes of the packages. - -Cheesecake currently computes 3 types of indexes: - - * installability index - * documentation index - * code kwalitee index - -The algorithms for computing each index type are detailed below. - -Why Cheesecake? ---------------- - -The concept of "kwalitee" originated in the Perl community. Here's a relevant -quote: - - *It looks like quality, it sounds like quality, but it's not quite quality.* - -Kwalitee is an empiric measure of how good a specific body of code is. It -defines quality indicators and measures the code along them. It is currently -used by the `CPANTS Testing Service `_ -to evaluate the 'goodness' of CPAN packages. - -Since the Python package repository (aka `PyPI `_) -is hosted at the Cheese Shop, -it stands to reason that the quality indicator of a PyPI package should be -called the Cheesecake index! - -Usage examples --------------- - -To compute the Cheesecake index for a given project, run the cheesecake.py -module from the command line and indicate either: - - * the package short name (e.g. twill) or - * the package URL (e.g. http://darcs.idyll.org/~t/projects/twill-0.7.4.tar.gz) or - * the package path on the file system (e.g. /tmp/twill-latest.tar.gz) - -In all cases, the cheesecake module will attempt to download the package -if necessary, then to unpack it in a sandbox directory (/tmp/cheesecake_sandbox -by default). If either of these operations fails, the Cheesecake index for -the package will be 0. If the package can be successfully unpacked, the -cheesecake module will compute the values for a variety of indexes detailed -in the algorithm given at the end of this file. - -If the package can be successfully downloaded and unpacked, a log file is -created in the sandbox directory and named .log (e.g. the log file -for twill-0.7.4.tar.gz is /tmp/cheesecake_sandbox/twill-0.7.4.tar.gz.log). -The log file is not automatically deleted after the Cheesecake index is -computed, since its purpose is to be inspected for debug information. - -Command-line examples: - - 1. Compute the Cheesecake index for the Durus package by using setuptools - utilities to download the package from PyPI:: - - python cheesecake.py --name=Durus - - 2. Compute the Cheesecake index for the Durus package by indicating its URL:: - - python cheesecake.py --url=http://www.mems-exchange.org/software/durus/Durus-3.1.tar.gz - - 3. Compute the Cheesecake index for the twill package by indicating its path - on the local file system:: - - python cheesecake.py --path=/tmp/twill-latest.tar.gz - - 4. To increase the verbosity of the output, use the -v or --verbose option. - For more options, run cheesecake.py with -h or --help. - -Obtaining the source code -------------------------- - -The Cheesecake project has not yet been released as a tarball or -a Python egg. You can obtain the source code from SourceForge via CVS:: - - cvs -z3 -d:pserver:anonymous@cvs.sourceforge.net:/cvsroot/cheesecake co -P cheesecake - -Mailing list ------------- - -Developer mailing list: http://lists.sourceforge.net/lists/listinfo/cheesecake-devel - -License -------- - -Cheesecake is licensed under the Python Software Foundation license, -the same license that governs Python itself. The text of the license is -available in the ``LICENSE`` file in the source code distribution and -can also be downloaded from -http://www.opensource.org/licenses/PythonSoftFoundation.php. - -Author contact info -------------------- - -Grig Gheorghiu - -Email: - -Web site: http://agiletesting.blogspot.com - -Algorithm for computing the Cheesecake index --------------------------------------------- - -The cheesecake.py module uses the following constants:: - - INDEX_PYPI_DOWNLOAD = 50 - INDEX_PYPI_DISTANCE = 5 - INDEX_URL_DOWNLOAD = 25 - INDEX_UNPACK = 25 - INDEX_UNPACK_DIR = 15 - INDEX_INSTALL = 50 - INDEX_FILE_CRITICAL = 15 - INDEX_FILE = 10 - INDEX_FILE_PYC = 20 - INDEX_DIR_CRITICAL = 25 - INDEX_DIR = 20 - INDEX_DIR_EMPTY = 5 - - MAX_INDEX_DOCSTRINGS = 100 # max. percentage of modules/classes/methods/functions with docstrings - MAX_INDEX_PYLINT = 100 # max. pylint score - -**Step 0** - -Initialize the Cheesecake index to 0. Also initialize to 0 -the partial Cheesecake indexes for installability, documentation -and code kwalitee. - -Compute the maximum overall Cheesecake index that can be reached by -any given package, which is the sum:: - - INDEX_PYPI_DOWNLOAD + - INDEX_UNPACK + INDEX_UNPACK_DIR + - INDEX_INSTALL + - MAX_INDEX_DOCSTRINGS + MAX_INDEX_PYLINT + - (INDEX_FILE * number_of_expected_files) + - (INDEX_FILE_CRITICAL * number_of_expected_critical_files) + - (INDEX_DIR * number_of_expected_dirs) + - (INDEX_DIR_CRITICAL * number_of_expected_critical_dirs) - -Compute the maximum Cheesecake index for installability, which is the sum:: - - INDEX_PYPI_DOWNLOAD + - INDEX_UNPACK + INDEX_UNPACK_DIR + - INDEX_INSTALL - -Compute the maximum Cheesecake index for documentation, which is the sum:: - - (INDEX_FILE * number_of_expected_files) + - (INDEX_FILE_CRITICAL * number_of_expected_critical_files) + - (INDEX_DIR * number_of_expected_dirs) + - (INDEX_DIR_CRITICAL * number_of_expected_critical_dirs) + - MAX_INDEX_DOCSTRINGS - -Compute the maximum Cheesecake index for code kwalitee, which is currently:: - - MAX_INDEX_PYLINT - -**Step 1a** - -If short name of the package was specified with ``-n`` or ``--name``, -try to download the package from the PyPI index page by following the links to -the package home page and the package download URL (this is accomplished -using setuptools utilities). - -If not successful, exit with a Cheesecake index of 0. If successful and -package was found at the Cheese Shop, add ``INDEX_PYPI_DOWNLOAD`` to -the overall Cheesecake index and to the installability Cheesecake index. - -If successful but package was not found at the Cheese Shop, add -``INDEX_PYPI_DOWNLOAD - (INDEX_PYPI_DISTANCE * number_of_links_to_package)`` -to the overall Cheesecake index and to the installability Cheesecake index. - -**Step 1b** - -If full URL of the package was specified with ``-u`` or ``--url``, -try to download the package from the specified URL. - -If not successful, exit with a Cheesecake index of 0. If successful, -add ``INDEX_URL_DOWNLOAD`` to the overall Cheesecake index and to -the installability Cheesecake index. - -**Step 1c** - -If path to package on local file system was specified with ``-p`` or -``--path``, copy the package to the sandbox directory. - -**Step 2** - -Unpack the package (currently supported archive types are zip and -tar.gz/tgz; in the near future we will support Python Eggs.) - -If not successful, exit with a Cheesecake index of 0. If successful, add -``INDEX_UNPACK`` to the overall Cheesecake index and to the installability -Cheesecake index. - -**Step 3** - -Check that the unpack directory has the same name as the package name -(i.e. when unpacking twill-0.7.4.tar.gz, we expect the unpack directory -to be twill-0.7.4.) - -If the unpack directory name is the same as the package name, add -``INDEX_UNPACK_DIR`` -to the overall Cheesecake index and to the installability Cheesecake index. - -**Step 4** - -Install the package to a temporary directory in a non-default location. -If successful, add ``INDEX_INSTALL`` to the overall Cheesecake index and to the -installability Cheesecake index. - -**Step 5** - -Check for existence of specific files. -For each file found, add ``INDEX_FILE`` to the overall -Cheesecake index and to the documentation Cheesecake index. -If the file is deemed critical, add ``INDEX_FILE_CRITICAL`` instead. - -The following special files ("cheese_files") are currently checked:: - - cheese_files = ["install", "changelog", - "news", "faq", - "todo", "thanks", "announce", - "ez_setup.py", - ] - -The following files are currently deemed critical:: - - critical_cheese_files = ["readme", "license", "setup.py"] - -To check if a file FILE is among the cheese files, the following regular -expression is used:: - - re.search(r"^%s(\.txt)*" % cheese_file, file, re.IGNORECASE) - -**Step 6** - -Check for existence of specific directories. -For each directory found, add ``INDEX_DIR`` to the overall Cheesecake -index and to the documentation Cheesecake index. -If the directory is deemed critical, add ``INDEX_DIR_CRITICAL`` instead. -If the directory is found empty, add ``INDEX_DIR_EMPTY`` instead. - -The following directories ("cheese_dirs") are currently checked:: - - cheese_dirs = ["example", "demo"] - -The following directories are currently deemed critical:: - - critical_cheese_dirs = ["doc", "test"] - -To check if a directory DIR is among the cheese directories, -the following regular expression is used:: - - re.search(r"^%s" % cheese_dir, DIR, re.ignorecase) - -**Step 7** - -Check for existence of .pyc files. If found, decrease the score -by subtracting ``INDEX_FILE_PYC`` from the overall Cheesecake index -and from the documentation Cheesecake index. - -**Step 8** - -Compute the percentage of modules/classes/methods/functions that have -docstrings associated with them. Only Python modules that are not in test, -doc, demo and example directories are checked. -Round up the percentage and add it to the overall Cheesecake index and to the -documentation Cheesecake index. - -**Step 9** - -If pylint is present on the system, run pylint against all Python files -that are not in the test, docs or demo directories. -Average the non-negative pylint scores, multiply the average by 10 and -add it to the overall Cheesecake index and to the code kwalitee -Cheesecake index. - -**Step 10** - -For each of the partial Cheesecake index types (installability, -documentation and code kwalitee), display the absolute Cheesecake -index for that type as the sum of all indexes of that type computed in -the previous steps. -Also display the relative Cheesecake index for that type as the percentage -of ``(absolute_index / maximum_index)``. - -Display the absolute Cheesecake index for the package as the sum of all -indexes computed in the previous steps. Also display the relative Cheesecake -index for the package as the percentage of ``(absolute_index / maximum_index)``. - -Sample output -------------- - -:: - - $ python cheesecake.py -n Durus - [cheesecake:console] Trying to download package durus from PyPI using setuptools utilities - [cheesecake:console] Downloaded package Durus-3.1.tar.gz from http://www.mems-exchange.org/software/durus/Durus-3.1.tar.gz - [cheesecake:console] Detailed info available in log file /tmp/cheesecake_sandbox/durus.log - [cheesecake:console] A given package can currently reach a MAXIMUM number of 555 points - [cheesecake:console] Starting computation of Cheesecake index for package 'Durus-3.1.tar.gz' - - [cheesecake:console] Starting computation of INSTALLABILITY index (max. points = 140) - index_pypi_download ..................... 45 (downloaded package Durus-3.1.tar.gz following 1 link from PyPI) - index_unpack ............................ 25 (package untar-ed successfully) - index_unpack_dir ........................ 15 (unpack directory is Durus-3.1 as expected) - index_install ........................... 50 (package installed in /tmp/cheesecake_sandbox/tmp_install_Durus-3.1) - --------------------------------------------- - INSTALLABILITY INDEX (ABSOLUTE) ......... 135 - INSTALLABILITY INDEX (RELATIVE) ......... 96 (135 out of a maximum of 140 points is 96%) - - [cheesecake:console] Starting computation of DOCUMENTATION index (max. points = 415) - index_file_announce ..................... 0 (file not found) - index_file_changelog .................... 0 (file not found) - index_file_ez_setup.py .................. 0 (file not found) - index_file_faq .......................... 10 (file found) - index_file_install ...................... 10 (file found) - index_file_license ...................... 15 (critical file found) - index_file_news ......................... 0 (file not found) - index_file_readme ....................... 15 (critical file found) - index_file_setup.py ..................... 15 (critical file found) - index_file_thanks ....................... 0 (file not found) - index_file_todo ......................... 0 (file not found) - index_dir_demo .......................... 0 (directory not found) - index_dir_doc ........................... 25 (critical directory found) - index_dir_example ....................... 0 (directory not found) - index_dir_test .......................... 25 (critical directory found) - index_docstrings ........................ 42 (found 104/249=41.77% modules/classes/methods/functions with docstrings) - --------------------------------------------- - DOCUMENTATION INDEX (ABSOLUTE) .......... 157 - DOCUMENTATION INDEX (RELATIVE) .......... 37 (157 out of a maximum of 415 points is 37%) - - [cheesecake:console] Starting computation of CODE KWALITEE index (max. points = 100) - index_pylint ............................ 64 (average score is 6.30 out of 10) - --------------------------------------------- - CODE KWALITEE INDEX (ABSOLUTE) .......... 64 - CODE KWALITEE INDEX (RELATIVE) .......... 64 (64 out of a maximum of 100 points is 64%) - - ============================================= - OVERALL CHEESECAKE INDEX (ABSOLUTE) ..... 356 - OVERALL CHEESECAKE INDEX (RELATIVE) ..... 64 (356 out of a maximum of 555 points is 64%) - -Future plans ------------- -Cheesecake is under very active development. The immediate goal is to add the unit test -index measurement, followed by other metrics inspired from the -`kwalitee indicators `_. -Please edit the `IndexMeasurementIdeas `_ -Wiki page to add things that you would like to see covered -by the Cheesecake metrics. - -.. footer:: Generated with rst2html.py from the - `docutils `_ - distribution. Last modified 2005-12-20 by - `Grig Gheorghiu `_.