flufl.enum-3.3.2/0000775000175000017500000000000011744104775014066 5ustar barrybarry00000000000000flufl.enum-3.3.2/setup.py0000664000175000017500000000423611744103336015575 0ustar barrybarry00000000000000# Copyright (C) 2004-2012 by Barry A. Warsaw # # This file is part of flufl.enum. # # flufl.enum is free software: you can redistribute it and/or modify it under # the terms of the GNU Lesser General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) # any later version. # # flufl.enum is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License # for more details. # # You should have received a copy of the GNU Lesser General Public License # along with flufl.enum. If not, see . import distribute_setup distribute_setup.use_setuptools() from setup_helpers import ( description, get_version, long_description, require_python) from setuptools import setup, find_packages require_python(0x20600f0) __version__ = get_version('flufl/enum/__init__.py') setup( name='flufl.enum', version=__version__, namespace_packages=['flufl'], packages=find_packages(), include_package_data=True, maintainer='Barry Warsaw', maintainer_email='barry@python.org', description=description('README.rst'), long_description=long_description('README.rst', 'flufl/enum/NEWS.rst'), license='LGPLv3', url='http://launchpad.net/flufl.enum', download_url='https://launchpad.net/flufl.enum/+download', test_suite='flufl.enum.tests', classifiers=[ 'Development Status :: 5 - Production/Stable', 'Intended Audience :: Developers', 'License :: OSI Approved :: ' 'GNU Lesser General Public License v3 or later (LGPLv3+)', 'Operating System :: POSIX', 'Operating System :: Microsoft :: Windows', 'Operating System :: MacOS :: MacOS X', 'Programming Language :: Python', 'Programming Language :: Python :: 2.6', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', 'Topic :: Software Development :: Libraries', 'Topic :: Software Development :: Libraries :: Python Modules', ] ) flufl.enum-3.3.2/setup.cfg0000664000175000017500000000022111744104775015702 0ustar barrybarry00000000000000[build_sphinx] source_dir = flufl/enum [upload_docs] upload_dir = build/sphinx/html [egg_info] tag_build = tag_date = 0 tag_svn_revision = 0 flufl.enum-3.3.2/setup_helpers.py0000664000175000017500000001204211744104324017307 0ustar barrybarry00000000000000# Copyright (C) 2009-2012 by Barry A. Warsaw # # This file is part of flufl.enum # # flufl.enum is free software: you can redistribute it and/or modify it under # the terms of the GNU Lesser General Public License as published by the Free # Software Foundation, version 3 of the License. # # flufl.enum is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License # for more details. # # You should have received a copy of the GNU Lesser General Public License # along with flufl.enum. If not, see . """setup.py helper functions.""" from __future__ import absolute_import, print_function, unicode_literals __metaclass__ = type __all__ = [ 'description', 'find_doctests', 'get_version', 'long_description', 'require_python', ] import os import re import sys DEFAULT_VERSION_RE = re.compile(r'(?P\d+\.\d+(?:\.\d+)?)') EMPTYSTRING = '' __version__ = '2.1' def require_python(minimum): """Require at least a minimum Python version. The version number is expressed in terms of `sys.hexversion`. E.g. to require a minimum of Python 2.6, use:: >>> require_python(0x206000f0) :param minimum: Minimum Python version supported. :type minimum: integer """ if sys.hexversion < minimum: hversion = hex(minimum)[2:] if len(hversion) % 2 != 0: hversion = '0' + hversion split = list(hversion) parts = [] while split: parts.append(int(''.join((split.pop(0), split.pop(0))), 16)) major, minor, micro, release = parts if release == 0xf0: print('Python {0}.{1}.{2} or better is required'.format( major, minor, micro)) else: print('Python {0}.{1}.{2} ({3}) or better is required'.format( major, minor, micro, hex(release)[2:])) sys.exit(1) def get_version(filename, pattern=None): """Extract the __version__ from a file without importing it. While you could get the __version__ by importing the module, the very act of importing can cause unintended consequences. For example, Distribute's automatic 2to3 support will break. Instead, this searches the file for a line that starts with __version__, and extract the version number by regular expression matching. By default, two or three dot-separated digits are recognized, but by passing a pattern parameter, you can recognize just about anything. Use the `version` group name to specify the match group. :param filename: The name of the file to search. :type filename: string :param pattern: Optional alternative regular expression pattern to use. :type pattern: string :return: The version that was extracted. :rtype: string """ if pattern is None: cre = DEFAULT_VERSION_RE else: cre = re.compile(pattern) with open(filename) as fp: for line in fp: if line.startswith('__version__'): mo = cre.search(line) assert mo, 'No valid __version__ string found' return mo.group('version') raise AssertionError('No __version__ assignment found') def find_doctests(start='.', extension='.rst'): """Find separate-file doctests in the package. This is useful for Distribute's automatic 2to3 conversion support. The `setup()` keyword argument `convert_2to3_doctests` requires file names, which may be difficult to track automatically as you add new doctests. :param start: Directory to start searching in (default is cwd) :type start: string :param extension: Doctest file extension (default is .txt) :type extension: string :return: The doctest files found. :rtype: list """ doctests = [] for dirpath, dirnames, filenames in os.walk(start): doctests.extend(os.path.join(dirpath, filename) for filename in filenames if filename.endswith(extension)) return doctests def long_description(*filenames): """Provide a long description.""" res = [''] for filename in filenames: with open(filename) as fp: for line in fp: res.append(' ' + line) res.append('') res.append('\n') return EMPTYSTRING.join(res) def description(filename): """Provide a short description.""" # This ends up in the Summary header for PKG-INFO and it should be a # one-liner. It will get rendered on the package page just below the # package version header but above the long_description, which ironically # gets stuff into the Description header. It should not include reST, so # pick out the first single line after the double header. with open(filename) as fp: for lineno, line in enumerate(fp): if lineno < 3: continue line = line.strip() if len(line) > 0: return line flufl.enum-3.3.2/flufl/0000775000175000017500000000000011744104775015176 5ustar barrybarry00000000000000flufl.enum-3.3.2/flufl/enum/0000775000175000017500000000000011744104775016142 5ustar barrybarry00000000000000flufl.enum-3.3.2/flufl/enum/docs/0000775000175000017500000000000011744104775017072 5ustar barrybarry00000000000000flufl.enum-3.3.2/flufl/enum/docs/using.rst0000664000175000017500000002646411706071514020755 0ustar barrybarry00000000000000============================ Using the flufl.enum library ============================ The ``flufl.enum`` package provides yet another enumeration data type for Python. While this is similar intent to the reject `PEP 354`_, this package defines an alternative syntax and semantics. An enumeration is a set of symbolic names bound to unique, constant integer values. Within an enumeration, the values can be compared by identity, and the enumeration itself can be iterated over. Enumeration items can be converted to and from their integer equivalents, supporting use cases such as storing enumeration values in a database. Motivation ========== [Lifted from PEP 354] The properties of an enumeration are useful for defining an immutable, related set of constant values that have a defined sequence but no inherent semantic meaning. Classic examples are days of the week (Sunday through Saturday) and school assessment grades ('A' through 'D', and 'F'). Other examples include error status values and states within a defined process. It is possible to simply define a sequence of values of some other basic type, such as ``int`` or ``str``, to represent discrete arbitrary values. However, an enumeration ensures that such values are distinct from any others, and that operations without meaning ("Wednesday times two") are not defined for these values. Creating an Enum ================ Enumerations are created using the class syntax, which makes them easy to read and write. Every enumeration value must have a unique integer value and the only restriction on their names is that they must be valid Python identifiers. To define an enumeration, derive from the Enum class and add attributes with assignment to their integer values. >>> from flufl.enum import Enum >>> class Colors(Enum): ... red = 1 ... green = 2 ... blue = 3 Enumeration values are compared by identity. >>> Colors.red is Colors.red True >>> Colors.blue is Colors.blue True >>> Colors.red is not Colors.blue True >>> Colors.blue is Colors.red False Enumeration values have nice, human readable string representations... >>> print(Colors.red) Colors.red ...while their repr has more information. >>> print(repr(Colors.red)) The enumeration value names are available through the class members. >>> for member in Colors.__members__: ... print(member) red green blue Let's say you wanted to encode an enumeration value in a database. You might want to get the enumeration class object from an enumeration value. >>> cls = Colors.red.enum >>> print(cls.__name__) Colors Enums also have a property that contains just their item name. >>> print(Colors.red.name) red >>> print(Colors.green.name) green >>> print(Colors.blue.name) blue The str and repr of the enumeration class also provides useful information. >>> print(Colors) >>> print(repr(Colors)) You can extend previously defined Enums by subclassing. >>> class MoreColors(Colors): ... pink = 4 ... cyan = 5 When extended in this way, the base enumeration's values are identical to the same named values in the derived class. >>> Colors.red is MoreColors.red True >>> Colors.blue is MoreColors.blue True However, these are not doing comparisons against the integer equivalent values, because if you define an enumeration with similar item names and integer values, they will not be identical. >>> class OtherColors(Enum): ... red = 1 ... blue = 2 ... yellow = 3 >>> Colors.red is OtherColors.red False >>> Colors.blue is not OtherColors.blue True These enumeration values are not equal, nor do they hash equally. >>> Colors.red == OtherColors.red False >>> len(set((Colors.red, OtherColors.red))) 2 Ordered comparisons between enumeration values are *not* supported. Enums are not integers! >>> Colors.red < Colors.blue Traceback (most recent call last): ... NotImplementedError >>> Colors.red <= Colors.blue Traceback (most recent call last): ... NotImplementedError >>> Colors.blue > Colors.green Traceback (most recent call last): ... NotImplementedError >>> Colors.blue >= Colors.green Traceback (most recent call last): ... NotImplementedError Equality comparisons are defined though. >>> Colors.blue == Colors.blue True >>> Colors.green != Colors.blue True Enumeration values do not support ordered comparisons. >>> Colors.red < Colors.blue Traceback (most recent call last): ... NotImplementedError >>> Colors.red < 3 Traceback (most recent call last): ... NotImplementedError >>> Colors.red <= 3 Traceback (most recent call last): ... NotImplementedError >>> Colors.blue > 2 Traceback (most recent call last): ... NotImplementedError >>> Colors.blue >= 2 Traceback (most recent call last): ... NotImplementedError While equality comparisons are allowed, comparisons against non-enumeration values will always compare not equal. >>> Colors.green == 2 False >>> Colors.blue == 3 False >>> Colors.green != 3 True >>> Colors.green == 'green' False If you really want the integer equivalent values, you can convert enumeration values explicitly using the ``int()`` built-in. This is quite convenient for storing enums in a database for example. >>> int(Colors.red) 1 >>> int(Colors.green) 2 >>> int(Colors.blue) 3 You can also convert back to the enumeration value by calling the Enum class, passing in the integer value for the item you want. >>> Colors(1) >>> Colors(2) >>> Colors(3) >>> Colors(1) is Colors.red True The Enum class also accepts the string name of the enumeration value. >>> Colors('red') >>> Colors('blue') is Colors.blue True You get exceptions though, if you try to use invalid arguments. >>> Colors('magenta') Traceback (most recent call last): ... ValueError: magenta >>> Colors(99) Traceback (most recent call last): ... ValueError: 99 The Enum base class also supports getitem syntax, exactly equivalent to the class's call semantics. >>> Colors[1] >>> Colors[2] >>> Colors[3] >>> Colors[1] is Colors.red True >>> Colors['red'] >>> Colors['blue'] is Colors.blue True >>> Colors['magenta'] Traceback (most recent call last): ... ValueError: magenta >>> Colors[99] Traceback (most recent call last): ... ValueError: 99 The integer equivalent values serve another purpose. You may not define two enumeration values with the same integer value. >>> class Bad(Enum): ... cartman = 1 ... stan = 2 ... kyle = 3 ... kenny = 3 # Oops! ... butters = 4 Traceback (most recent call last): ... TypeError: Multiple enum values: 3 You also may not duplicate values in derived enumerations. >>> class BadColors(Colors): ... yellow = 4 ... chartreuse = 2 # Oops! Traceback (most recent call last): ... TypeError: Multiple enum values: 2 The Enum class support iteration. Enumeration values are returned in the sorted order of their integer equivalent values. >>> [v.name for v in MoreColors] ['red', 'green', 'blue', 'pink', 'cyan'] >>> [int(v) for v in MoreColors] [1, 2, 3, 4, 5] Enumeration values are hashable, so they can be used in dictionaries and sets. >>> apples = {} >>> apples[Colors.red] = 'red delicious' >>> apples[Colors.green] = 'granny smith' >>> for color in sorted(apples, key=int): ... print(color.name, '->', apples[color]) red -> red delicious green -> granny smith Pickling ======== Enumerations created with the class syntax can also be pickled and unpickled: >>> from flufl.enum.tests.fruit import Fruit >>> from pickle import dumps, loads >>> Fruit.tomato is loads(dumps(Fruit.tomato)) True Alternative API =============== You can also create enumerations using the convenience function `make()`, which takes an iterable object or dictionary to provide the item names and values. `make()` is a static method. .. note:: The `make_enum()` function from earlier releases is deprecated. Use `make()` instead. The first argument to `make()` is the name of the enumeration, and it returns the so-named `Enum` subclass. The second argument is a `source` which can be either an iterable or a dictionary. In the most basic usage, `source` returns a sequence of strings which name the enumeration items. In this case, the values are automatically assigned starting from 1:: >>> from flufl.enum import make >>> make('Animals', ('ant', 'bee', 'cat', 'dog')) The items in source can also be 2-tuples, where the first item is the enumeration value name and the second is the integer value to assign to the value. If 2-tuples are used, all items must be 2-tuples. >>> def enumiter(): ... start = 1 ... while True: ... yield start ... start <<= 1 >>> make('Flags', zip(list('abcdefg'), enumiter())) Differences from PEP 354 ======================== Unlike PEP 354, enumeration values are not defined as a sequence of strings, but as attributes of a class. This design was chosen because it was felt that class syntax is more readable. Unlike PEP 354, enumeration values require an explicit integer value. This difference recognizes that enumerations often represent real-world values, or must interoperate with external real-world systems. For example, to store an enumeration in a database, it is better to convert it to an integer on the way in and back to an enumeration on the way out. Providing an integer value also provides an explicit ordering. However, there is no automatic conversion to and from the integer values, because explicit is better than implicit. Unlike PEP 354, this implementation does use a metaclass to define the enumeration's syntax, and allows for extended base-enumerations so that the common values in derived classes are identical (a singleton model). While PEP 354 dismisses this approach for its complexity, in practice any perceived complexity, though minimal, is hidden from users of the enumeration. Unlike PEP 354, enumeration values can only be tested by identity comparison. This is to emphasis the fact that enumeration values are singletons, much like ``None``. Acknowledgments =============== The ``flufl.enum`` implementation is based on an example by Jeremy Hylton. It has been modified and extended by Barry Warsaw for use in the `GNU Mailman`_ project. Ben Finney is the author of the earlier enumeration PEP 354. .. _`PEP 354`: http://www.python.org/dev/peps/pep-0354/ .. _enum: http://cheeseshop.python.org/pypi/enum/ .. _`GNU Mailman`: http://www.list.org flufl.enum-3.3.2/flufl/enum/docs/__init__.py0000664000175000017500000000000011624413056021161 0ustar barrybarry00000000000000flufl.enum-3.3.2/flufl/enum/NEWS.rst0000664000175000017500000000455411744104714017451 0ustar barrybarry00000000000000=================== NEWS for flufl.enum =================== 3.3.2 (2012-04-19) ================== * Add classifiers to setup.py and make the long description more compatible with the Cheeseshop. * Other changes to make the Cheeseshop page look nicer. (LP: #680136) * setup_helper.py version 2.1. 3.3.1 (2012-01-19) ================== * Fix Python 3 compatibility with Sphinx's conf.py ($python setup.py install). 3.3 (2012-01-19) ================ * Remove the dependency on 2to3 for Python 3 support; support Python 3 directly with a single code base. * flufl.enum.make_enum() is deprecated in favor of flufl.enum.make() which provides a better API. (LP: #839529) * Updated to distribute 0.6.19. * Moved all documentation to .rst suffix. * Make test_deprecations() compatible with Python 3 and Python 2. * Removed markup for pylint. * Improve documentation to illustrate that enum values with similar names and integer representations still do not hash equally. (Found by Jeroen Vermeulen). 3.2 (2011-08-19) ================ * make_enum() accepts an optional `iterable` argument to provide the values for the enums. * The .enumclass and .enumname attributes are deprecated. Use .enum and .name instead, respectively. * Improve the documentation regarding ordered comparisons and equality tests. (LP: #794853) * make_enum() now enforces the use of valid Python identifiers. (LP: #803570) 3.1 (2011-03-01) ================ * New convenience function `make_enum()`. (Contributed by Michael Foord) * Fix `from flufl.enum import *`. * Enums created with the class syntax can be pickled and unpickled. (Suggestion and basic implementation idea by Phillip Eby). 3.0.1 (2010-06-07) ================== * Fixed typo which caused the package to break. 3.0 (2010-04-24) ================ * Package renamed to flufl.enum. 2.0.2 (2010-01-29) ================== * Fixed some test failures when running under 2to3. 2.0.1 (2010-01-08) ================== * Fix the manifest and clarify license. 2.0 (2010-01-07) ================ * Use Sphinx to build the documentation. * Updates to better package Debian/Ubuntu. * Use distribute_setup instead of ez_setup. * Rename pep-xxxx.txt; this won't be submitted as a PEP. * Remove dependencies on nose and setuptools_bzr * Support Python 3 via 2to3. Earlier ======= Try `bzr log lp:flufl.enum` for details. flufl.enum-3.3.2/flufl/enum/__init__.py0000664000175000017500000000164611744077111020253 0ustar barrybarry00000000000000# Copyright (C) 2004-2012 by Barry A. Warsaw # # This file is part of flufl.enum # # flufl.enum is free software: you can redistribute it and/or modify it under # the terms of the GNU Lesser General Public License as published by the Free # Software Foundation, version 3 of the License. # # flufl.enum is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License # for more details. # # You should have received a copy of the GNU Lesser General Public License # along with flufl.enum. If not, see . """Package init.""" from __future__ import absolute_import, print_function, unicode_literals __metaclass__ = type __all__ = [ 'Enum', '__version__', 'make_enum', ] __version__ = '3.3.2' from ._enum import Enum, make, make_enum flufl.enum-3.3.2/flufl/enum/conf.py0000664000175000017500000001533111706107317017435 0ustar barrybarry00000000000000# -*- coding: utf-8 -*- # # flufl.enum documentation build configuration file, created by # sphinx-quickstart on Thu Jan 7 18:41:30 2010. # # This file is execfile()d with the current directory set to its containing dir. # # Note that not all possible configuration values are present in this # autogenerated file. # # All configuration values have a default; values that are commented out # serve to show the default. from __future__ import print_function import sys, os # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. #sys.path.append(os.path.abspath('.')) # -- General configuration ----------------------------------------------------- # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. extensions = ['sphinx.ext.autodoc'] # Add any paths that contain templates here, relative to this directory. templates_path = ['../../_templates'] # The suffix of source filenames. source_suffix = '.rst' # The encoding of source files. #source_encoding = 'utf-8' # The master toctree document. master_doc = 'README' # General information about the project. project = 'flufl.enum' copyright = '2004-2012, Barry A. Warsaw' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # from flufl.enum import __version__ # The short X.Y version. version = __version__ # The full version, including alpha/beta/rc tags. release = __version__ # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. #language = None # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: #today = '' # Else, today_fmt is used as the format for a strftime call. #today_fmt = '%B %d, %Y' # List of documents that shouldn't be included in the build. #unused_docs = [] # List of directories, relative to source directory, that shouldn't be searched # for source files. exclude_trees = ['_build', 'build', 'flufl.enum.egg-info', 'distribute-0.6.10'] # The reST default role (used for this markup: `text`) to use for all documents. #default_role = None # If true, '()' will be appended to :func: etc. cross-reference text. #add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). #add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. #show_authors = False # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' # A list of ignored prefixes for module index sorting. #modindex_common_prefix = [] # -- Options for HTML output --------------------------------------------------- # The theme to use for HTML and HTML Help pages. Major themes that come with # Sphinx are currently 'default' and 'sphinxdoc'. html_theme = 'default' # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. #html_theme_options = {} # Add any paths that contain custom themes here, relative to this directory. #html_theme_path = [] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". #html_title = None # A shorter title for the navigation bar. Default is the same as html_title. #html_short_title = None # The name of an image file (relative to this directory) to place at the top # of the sidebar. #html_logo = None # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. #html_favicon = None # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['../../_static'] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. #html_last_updated_fmt = '%b %d, %Y' # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. #html_use_smartypants = True # Custom sidebar templates, maps document names to template names. #html_sidebars = {} # Additional templates that should be rendered to pages, maps page names to # template names. #html_additional_pages = {} # If false, no module index is generated. #html_use_modindex = True # If false, no index is generated. #html_use_index = True # If true, the index is split into individual pages for each letter. #html_split_index = False # If true, links to the reST sources are added to the pages. #html_show_sourcelink = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. #html_use_opensearch = '' # If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml"). #html_file_suffix = '' # Output file base name for HTML help builder. htmlhelp_basename = 'fluflenumdoc' # -- Options for LaTeX output -------------------------------------------------- # The paper size ('letter' or 'a4'). #latex_paper_size = 'letter' # The font size ('10pt', '11pt' or '12pt'). #latex_font_size = '10pt' # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, documentclass [howto/manual]). latex_documents = [ ('README.rst', 'fluflenum.tex', 'flufl.enum Documentation', 'Barry A. Warsaw', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of # the title page. #latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. #latex_use_parts = False # Additional stuff for the LaTeX preamble. #latex_preamble = '' # Documents to append as an appendix to all manuals. #latex_appendices = [] # If false, no module index is generated. #latex_use_modindex = True import errno def index_html(): cwd = os.getcwd() try: os.chdir('build/sphinx/html') try: os.symlink('README.html', 'index.html') except OSError as error: if error.errno != errno.EEXIST: raise print('index.html -> README.html') finally: os.chdir(cwd) import atexit atexit.register(index_html) flufl.enum-3.3.2/flufl/enum/_enum.py0000664000175000017500000002170411706071514017613 0ustar barrybarry00000000000000# Copyright (C) 2004-2012 by Barry A. Warsaw # # This file is part of flufl.enum # # flufl.enum is free software: you can redistribute it and/or modify it under # the terms of the GNU Lesser General Public License as published by the Free # Software Foundation, version 3 of the License. # # flufl.enum is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License # for more details. # # You should have received a copy of the GNU Lesser General Public License # along with flufl.enum. If not, see . """Python enumerations.""" from __future__ import absolute_import, print_function, unicode_literals __metaclass__ = type __all__ = [ 'Enum', 'make_enum', ] import re import warnings COMMASPACE = ', ' SPACE = ' ' IDENTIFIER_RE = r'[a-zA-Z_][a-zA-Z0-0_]*' class EnumMetaclass(type): """Meta class for Enums.""" def __init__(cls, name, bases, attributes): """Create an Enum class. :param cls: The class being defined. :param name: The name of the class. :param bases: The class's base classes. :param attributes: The class attributes. """ super(EnumMetaclass, cls).__init__(name, bases, attributes) # Store EnumValues here for easy access. cls._enums = {} # Figure out the set of enum values on the base classes, to ensure # that we don't get any duplicate values (which would screw up # conversion from integer). for basecls in cls.__mro__: if hasattr(basecls, '_enums'): cls._enums.update(basecls._enums) # For each class attribute, create an EnumValue and store that back on # the class instead of the int. Skip Python reserved names. Also add # a mapping from the integer to the instance so we can return the same # object on conversion. for attr in attributes: if not (attr.startswith('__') and attr.endswith('__')): intval = attributes[attr] enumval = EnumValue(cls, intval, attr) if intval in cls._enums: raise TypeError('Multiple enum values: %s' % intval) # Store as an attribute on the class, and save the attr name setattr(cls, attr, enumval) cls._enums[intval] = attr def __getattr__(cls, name): if name == '__members__': return cls._enums.values() raise AttributeError(name) def __repr__(cls): enums = ['{0}: {1:d}'.format( cls._enums[k], k) for k in sorted(cls._enums)] return '<{0} {{{1}}}>'.format(cls.__name__, COMMASPACE.join(enums)) def __iter__(cls): for i in sorted(cls._enums): yield getattr(cls, cls._enums[i]) def __getitem__(cls, i): # i can be an integer or a string attr = cls._enums.get(i) if attr is None: # It wasn't an integer -- try attribute name try: return getattr(cls, i) except (AttributeError, TypeError): raise ValueError(i) return getattr(cls, attr) # Support both MyEnum[i] and MyEnum(i) __call__ = __getitem__ class EnumValue: """Class to represent an enumeration value. EnumValue('Color', 'red', 12) prints as 'Color.red' and can be converted to the integer 12. """ def __init__(self, cls, value, name): self._enum = cls self._value = value self._name = name def __repr__(self): return ''.format( self._enum.__name__, self._name, self._value) def __str__(self): return '{0}.{1}'.format(self._enum.__name__, self._name) def __int__(self): return self._value def __reduce__(self): return getattr, (self._enum, self._name) @property def enum(self): """Return the class associated with the enum value.""" return self._enum @property def name(self): """Return the name of the enum value.""" return self._name @property def enumclass(self): """Return the class associated with the enum value.""" warnings.warn('.enumclass is deprecated; use .enum instead', DeprecationWarning) return self._enum @property def enumname(self): """Return the name of the enum value.""" warnings.warn('.enumname is deprecated; use .name instead', DeprecationWarning) return self._name # Support only comparison by identity and equality. Ordered comparisions # are not supported. def __eq__(self, other): return self is other def __ne__(self, other): return self is not other def __lt__(self, other): raise NotImplementedError __gt__ = __lt__ __le__ = __lt__ __ge__ = __lt__ __hash__ = object.__hash__ # Define the Enum class using metaclass syntax compatible with both Python 2 # and Python 3. Enum = EnumMetaclass(str('Enum'), (), { '__doc__': 'The public API Enum class.', }) def make(name, source): """Return an Enum class from a name and source. This is a convenience function for defining a new enumeration given an existing sequence. When an sequence is used, it is iterated over to get the enumeration value items. The sequence iteration can either return strings or 2-tuples. When strings are used, values are automatically assigned starting from 1. When 2-tuples are used, the first item of the tuple is a string and the second item is the integer value. `source` must be homogeneous. You cannot mix string-only and 2-tuple items in the sequence. :param name: The resulting enum's class name. :type name: byte string (or ASCII-only unicode string) :param source: An object giving the enumeration value items. :type source: A sequence of strings or 2-tuples. :return: The new enumeration class. :rtype: instance of `EnumMetaClass` :raises ValueError: when a heterogeneous source is given, or when non-identifiers are used as enumeration value names. """ namespace = {} illegals = [] have_strings = None try: # Python 2 string_type = basestring except NameError: # Python 3 string_type = str for i, item in enumerate(source, start=1): if isinstance(item, string_type): if have_strings is None: have_strings = True elif not have_strings: raise ValueError('heterogeneous source') namespace[item] = i if re.match(IDENTIFIER_RE, item) is None: illegals.append(item) else: if have_strings is None: have_strings = False elif have_strings: raise ValueError('heterogeneous souce') item_name, item_value = item namespace[item_name] = item_value if re.match(IDENTIFIER_RE, item_name) is None: illegals.append(item_name) if len(illegals) > 0: raise ValueError('non-identifiers: {0}'.format(SPACE.join(illegals))) return EnumMetaclass(str(name), (Enum,), namespace) def make_enum(name, value_string, iterable=None): """Return an Enum class from a name and a value string. *This function is deprecated; use `make()` instead.* This is a convenience function for defining a new enumeration when you don't care about the values of the items. The values are automatically created by splitting the value string on spaces. Normally, values are assigned to sequentially increasing integers starting at one. With optional `iterable`, integer values are extracted one at a time and assigned to the values. :param name: The resulting enum's class name. :type name: byte string (or ASCII-only unicode string) :param value_string: A string of enumeration item names, separated by spaces, e.g. 'one two three'. :type value_string: byte string (or ASCII-only unicode string) :param iterable: A sequence of integers. :type iterable: iterator over int :return: The new enumeration class. :rtype: instance of `EnumMetaClass` """ warnings.warn('make_enum() is deprecated; use make() instead', DeprecationWarning) value_names = value_string.split() illegals = [value for value in value_names if re.match(IDENTIFIER_RE, value) is None] if len(illegals) > 0: raise ValueError('non-identifiers: {0}'.format(SPACE.join(illegals))) if iterable is None: namespace = dict((str(value), i) for i, value in enumerate(value_names, 1)) else: namespace = dict((str(value), i) for i, value in zip(iterable, value_names)) return EnumMetaclass(str(name), (Enum,), namespace) flufl.enum-3.3.2/flufl/enum/README.rst0000664000175000017500000000525011706107435017625 0ustar barrybarry00000000000000========================================= flufl.enum - A Python enumeration package ========================================= This package is called ``flufl.enum``. It is yet another Python enumeration package, but with a slightly different take on syntax and semantics than earlier such packages. The goals of ``flufl.enum`` are to produce simple, specific, concise semantics in an easy to read and write syntax. ``flufl.enum`` has just enough of the features needed to make enumerations useful, but without a lot of extra baggage to weigh them down. This work grew out of the Mailman 3.0 project and it is the enum package used there. Until version 3.0, this package was called ``munepy``. Requirements ============ ``flufl.enum`` requires Python 2.6 or newer, and is compatible with Python 3. Documentation ============= A `simple guide`_ to using the library is available within this package, in the form of doctests. The manual is also available online in the Cheeseshop at: http://package.python.org/flufl.enum Project details =============== The project home page is: http://launchpad.net/flufl.enum You should report bugs at: http://bugs.launchpad.net/flufl.enum You can download the latest version of the package either from the Cheeseshop: http://pypi.python.org/pypi/flufl.enum or from the Launchpad page above. Of course you can also just install it with ``pip`` or ``easy_install`` from the command line:: % sudo pip flufl.enum % sudo easy_install flufl.enum You can grab the latest development copy of the code using Bazaar, from the Launchpad home page above. See http://bazaar-vcs.org for details on the Bazaar distributed revision control system. If you have Bazaar installed, you can grab your own branch of the code like this:: bzr branch lp:flufl.enum You may contact the author via barry@python.org. Copyright ========= Copyright (C) 2004-2012 Barry A. Warsaw This file is part of flufl.enum. flufl.enum is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. flufl.enum is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with flufl.enum. If not, see . Table of Contents ================= .. toctree:: docs/using.rst NEWS.rst .. _`simple guide`: docs/using.html flufl.enum-3.3.2/flufl/enum/tests/0000775000175000017500000000000011744104775017304 5ustar barrybarry00000000000000flufl.enum-3.3.2/flufl/enum/tests/fruit.py0000664000175000017500000000165611706071514021007 0ustar barrybarry00000000000000# Copyright (C) 2010-2012 by Barry A. Warsaw # # This file is part of flufl.enum # # flufl.enum is free software: you can redistribute it and/or modify it under # the terms of the GNU Lesser General Public License as published by the Free # Software Foundation, version 3 of the License. # # flufl.enum is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License # for more details. # # You should have received a copy of the GNU Lesser General Public License # along with flufl.enum. If not, see . """A class for testing pickling.""" from __future__ import absolute_import, print_function, unicode_literals __metaclass__ = type __all__ = [ 'Fruit', ] from flufl.enum import Enum class Fruit(Enum): kiwi = 1 banana = 2 tomato = 3 flufl.enum-3.3.2/flufl/enum/tests/__init__.py0000664000175000017500000000000011624413056021373 0ustar barrybarry00000000000000flufl.enum-3.3.2/flufl/enum/tests/test_enum.py0000664000175000017500000001022011706071514021644 0ustar barrybarry00000000000000# Copyright (C) 2011-2012 by Barry A. Warsaw # # This file is part of flufl.enum. # # flufl.enum is free software: you can redistribute it and/or modify it under # the terms of the GNU Lesser General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) # any later version. # # flufl.enum is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License # for more details. # # You should have received a copy of the GNU Lesser General Public License # along with flufl.enum. If not, see . """Additional package tests.""" from __future__ import absolute_import, print_function, unicode_literals __metaclass__ = type __all__ = [ 'TestEnum', ] import unittest import warnings from flufl.enum import Enum, make, make_enum class TestEnum(unittest.TestCase): """Additional unit tests.""" def test_deprecations(self): # Enum.enumclass and Enum.enumname are deprecated. class Animals(Enum): ant = 1 bee = 2 cat = 3 with warnings.catch_warnings(record=True) as seen: # Cause all warnings to always be triggered. warnings.simplefilter('always') Animals.ant.enumclass self.assertEqual(len(seen), 1) self.assertTrue(issubclass(seen[0].category, DeprecationWarning)) self.assertEqual(seen[0].message.args[0], '.enumclass is deprecated; use .enum instead') with warnings.catch_warnings(record=True) as seen: # Cause all warnings to always be triggered. warnings.simplefilter('always') Animals.ant.enumname self.assertEqual(len(seen), 1) self.assertTrue(issubclass(seen[0].category, DeprecationWarning)) self.assertEqual(seen[0].message.args[0], '.enumname is deprecated; use .name instead') def test_make_enum_identifiers_bug_803570(self): # LP: #803570 describes that make_enum() allows non-identifiers as # enum value names. try: make_enum('Foo', '1 2 3') except ValueError as exc: self.assertEqual(exc.args[0], 'non-identifiers: 1 2 3') else: raise AssertionError('Expected a ValueError') def test_make_enum_deprecated(self): # LP: #839529: deprecate the make_enum() API and use the much better # make() API. with warnings.catch_warnings(record=True) as seen: # Cause all warnings to always be triggered. warnings.simplefilter('always') make_enum('Foo', 'a b c') self.assertEqual(len(seen), 1) self.assertTrue(issubclass(seen[0].category, DeprecationWarning)) self.assertEqual(seen[0].message.args[0], 'make_enum() is deprecated; use make() instead') def test_enum_make_not_all_2_tuples(self): # If 2-tuples are used, all items must be 2-tuples. self.assertRaises(ValueError, make, 'Animals', ( ('ant', 1), ('bee', 2), 'cat', ('dog', 4), )) self.assertRaises(ValueError, make, 'Animals', ( ('ant', 1), ('bee', 2), ('cat',), ('dog', 4), )) self.assertRaises(ValueError, make, 'Animals', ( ('ant', 1), ('bee', 2), ('cat', 3, 'oops'), ('dog', 4), )) def test_make_identifiers(self): # Ensure that the make() interface also enforces identifiers. try: make('Foo', ('1', '2', '3')) except ValueError as exc: self.assertEqual(exc.args[0], 'non-identifiers: 1 2 3') else: raise AssertionError('Expected a ValueError') try: make('Foo', (('ant', 1), ('bee', 2), ('3', 'cat'))) except ValueError as exc: self.assertEqual(exc.args[0], 'non-identifiers: 3') else: raise AssertionError('Expected a ValueError') flufl.enum-3.3.2/flufl/enum/tests/test_documentation.py0000664000175000017500000000506111706071514023560 0ustar barrybarry00000000000000# Copyright (C) 2004-2012 by Barry A. Warsaw # # This file is part of flufl.enum. # # flufl.enum is free software: you can redistribute it and/or modify it under # the terms of the GNU Lesser General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) # any later version. # # flufl.enum is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License # for more details. # # You should have received a copy of the GNU Lesser General Public License # along with flufl.enum. If not, see . """Test harness for doctests.""" from __future__ import absolute_import, print_function, unicode_literals __metaclass__ = type __all__ = [ 'additional_tests', ] import os import atexit import doctest import unittest from pkg_resources import ( resource_filename, resource_exists, resource_listdir, cleanup_resources) COMMASPACE = ', ' DOT = '.' DOCTEST_FLAGS = ( doctest.ELLIPSIS | doctest.NORMALIZE_WHITESPACE | doctest.REPORT_NDIFF) def stop(): """Call into pdb.set_trace()""" # Do the import here so that you get the wacky special hacked pdb instead # of Python's normal pdb. import pdb pdb.set_trace() def setup(testobj): """Test setup.""" # Make sure future statements in our doctests match the Python code. When # run with 2to3, the future import gets removed and these names are not # defined. try: testobj.globs['absolute_import'] = absolute_import testobj.globs['print_function'] = print_function testobj.globs['unicode_literals'] = unicode_literals except NameError: pass testobj.globs['stop'] = stop def additional_tests(): "Run the doc tests (README.rst and docs/*, if any exist)" doctest_files = [ os.path.abspath(resource_filename('flufl.enum', 'README.rst'))] if resource_exists('flufl.enum', 'docs'): for name in resource_listdir('flufl.enum', 'docs'): if name.endswith('.rst'): doctest_files.append( os.path.abspath( resource_filename('flufl.enum', 'docs/%s' % name))) kwargs = dict(module_relative=False, optionflags=DOCTEST_FLAGS, setUp=setup, ) atexit.register(cleanup_resources) return unittest.TestSuite(( doctest.DocFileSuite(*doctest_files, **kwargs))) flufl.enum-3.3.2/flufl/__init__.py0000664000175000017500000000156611706071514017307 0ustar barrybarry00000000000000# Copyright (C) 2004-2012 by Barry A. Warsaw # # This file is part of flufl.enum. # # flufl.enum is free software: you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation, version 3 of the License. # # flufl.enum is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public # License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with flufl.enum. If not, see . # this is a namespace package try: import pkg_resources pkg_resources.declare_namespace(__name__) except ImportError: import pkgutil __path__ = pkgutil.extend_path(__path__, __name__) flufl.enum-3.3.2/distribute_setup.py0000664000175000017500000003661511643700345020042 0ustar barrybarry00000000000000#!python """Bootstrap distribute installation If you want to use setuptools in your package's setup.py, just include this file in the same directory with it, and add this to the top of your setup.py:: from distribute_setup import use_setuptools use_setuptools() If you want to require a specific version of setuptools, set a download mirror, or use an alternate download directory, you can do so by supplying the appropriate options to ``use_setuptools()``. This file can also be run as a script to install or upgrade setuptools. """ import os import sys import time import fnmatch import tempfile import tarfile from distutils import log try: from site import USER_SITE except ImportError: USER_SITE = None try: import subprocess def _python_cmd(*args): args = (sys.executable,) + args return subprocess.call(args) == 0 except ImportError: # will be used for python 2.3 def _python_cmd(*args): args = (sys.executable,) + args # quoting arguments if windows if sys.platform == 'win32': def quote(arg): if ' ' in arg: return '"%s"' % arg return arg args = [quote(arg) for arg in args] return os.spawnl(os.P_WAIT, sys.executable, *args) == 0 DEFAULT_VERSION = "0.6.19" DEFAULT_URL = "http://pypi.python.org/packages/source/d/distribute/" SETUPTOOLS_FAKED_VERSION = "0.6c11" SETUPTOOLS_PKG_INFO = """\ Metadata-Version: 1.0 Name: setuptools Version: %s Summary: xxxx Home-page: xxx Author: xxx Author-email: xxx License: xxx Description: xxx """ % SETUPTOOLS_FAKED_VERSION def _install(tarball): # extracting the tarball tmpdir = tempfile.mkdtemp() log.warn('Extracting in %s', tmpdir) old_wd = os.getcwd() try: os.chdir(tmpdir) tar = tarfile.open(tarball) _extractall(tar) tar.close() # going in the directory subdir = os.path.join(tmpdir, os.listdir(tmpdir)[0]) os.chdir(subdir) log.warn('Now working in %s', subdir) # installing log.warn('Installing Distribute') if not _python_cmd('setup.py', 'install'): log.warn('Something went wrong during the installation.') log.warn('See the error message above.') finally: os.chdir(old_wd) def _build_egg(egg, tarball, to_dir): # extracting the tarball tmpdir = tempfile.mkdtemp() log.warn('Extracting in %s', tmpdir) old_wd = os.getcwd() try: os.chdir(tmpdir) tar = tarfile.open(tarball) _extractall(tar) tar.close() # going in the directory subdir = os.path.join(tmpdir, os.listdir(tmpdir)[0]) os.chdir(subdir) log.warn('Now working in %s', subdir) # building an egg log.warn('Building a Distribute egg in %s', to_dir) _python_cmd('setup.py', '-q', 'bdist_egg', '--dist-dir', to_dir) finally: os.chdir(old_wd) # returning the result log.warn(egg) if not os.path.exists(egg): raise IOError('Could not build the egg.') def _do_download(version, download_base, to_dir, download_delay): egg = os.path.join(to_dir, 'distribute-%s-py%d.%d.egg' % (version, sys.version_info[0], sys.version_info[1])) if not os.path.exists(egg): tarball = download_setuptools(version, download_base, to_dir, download_delay) _build_egg(egg, tarball, to_dir) sys.path.insert(0, egg) import setuptools setuptools.bootstrap_install_from = egg def use_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir, download_delay=15, no_fake=True): # making sure we use the absolute path to_dir = os.path.abspath(to_dir) was_imported = 'pkg_resources' in sys.modules or \ 'setuptools' in sys.modules try: try: import pkg_resources if not hasattr(pkg_resources, '_distribute'): if not no_fake: _fake_setuptools() raise ImportError except ImportError: return _do_download(version, download_base, to_dir, download_delay) try: pkg_resources.require("distribute>="+version) return except pkg_resources.VersionConflict: e = sys.exc_info()[1] if was_imported: sys.stderr.write( "The required version of distribute (>=%s) is not available,\n" "and can't be installed while this script is running. Please\n" "install a more recent version first, using\n" "'easy_install -U distribute'." "\n\n(Currently using %r)\n" % (version, e.args[0])) sys.exit(2) else: del pkg_resources, sys.modules['pkg_resources'] # reload ok return _do_download(version, download_base, to_dir, download_delay) except pkg_resources.DistributionNotFound: return _do_download(version, download_base, to_dir, download_delay) finally: if not no_fake: _create_fake_setuptools_pkg_info(to_dir) def download_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir, delay=15): """Download distribute from a specified location and return its filename `version` should be a valid distribute version number that is available as an egg for download under the `download_base` URL (which should end with a '/'). `to_dir` is the directory where the egg will be downloaded. `delay` is the number of seconds to pause before an actual download attempt. """ # making sure we use the absolute path to_dir = os.path.abspath(to_dir) try: from urllib.request import urlopen except ImportError: from urllib2 import urlopen tgz_name = "distribute-%s.tar.gz" % version url = download_base + tgz_name saveto = os.path.join(to_dir, tgz_name) src = dst = None if not os.path.exists(saveto): # Avoid repeated downloads try: log.warn("Downloading %s", url) src = urlopen(url) # Read/write all in one block, so we don't create a corrupt file # if the download is interrupted. data = src.read() dst = open(saveto, "wb") dst.write(data) finally: if src: src.close() if dst: dst.close() return os.path.realpath(saveto) def _no_sandbox(function): def __no_sandbox(*args, **kw): try: from setuptools.sandbox import DirectorySandbox if not hasattr(DirectorySandbox, '_old'): def violation(*args): pass DirectorySandbox._old = DirectorySandbox._violation DirectorySandbox._violation = violation patched = True else: patched = False except ImportError: patched = False try: return function(*args, **kw) finally: if patched: DirectorySandbox._violation = DirectorySandbox._old del DirectorySandbox._old return __no_sandbox def _patch_file(path, content): """Will backup the file then patch it""" existing_content = open(path).read() if existing_content == content: # already patched log.warn('Already patched.') return False log.warn('Patching...') _rename_path(path) f = open(path, 'w') try: f.write(content) finally: f.close() return True _patch_file = _no_sandbox(_patch_file) def _same_content(path, content): return open(path).read() == content def _rename_path(path): new_name = path + '.OLD.%s' % time.time() log.warn('Renaming %s into %s', path, new_name) os.rename(path, new_name) return new_name def _remove_flat_installation(placeholder): if not os.path.isdir(placeholder): log.warn('Unkown installation at %s', placeholder) return False found = False for file in os.listdir(placeholder): if fnmatch.fnmatch(file, 'setuptools*.egg-info'): found = True break if not found: log.warn('Could not locate setuptools*.egg-info') return log.warn('Removing elements out of the way...') pkg_info = os.path.join(placeholder, file) if os.path.isdir(pkg_info): patched = _patch_egg_dir(pkg_info) else: patched = _patch_file(pkg_info, SETUPTOOLS_PKG_INFO) if not patched: log.warn('%s already patched.', pkg_info) return False # now let's move the files out of the way for element in ('setuptools', 'pkg_resources.py', 'site.py'): element = os.path.join(placeholder, element) if os.path.exists(element): _rename_path(element) else: log.warn('Could not find the %s element of the ' 'Setuptools distribution', element) return True _remove_flat_installation = _no_sandbox(_remove_flat_installation) def _after_install(dist): log.warn('After install bootstrap.') placeholder = dist.get_command_obj('install').install_purelib _create_fake_setuptools_pkg_info(placeholder) def _create_fake_setuptools_pkg_info(placeholder): if not placeholder or not os.path.exists(placeholder): log.warn('Could not find the install location') return pyver = '%s.%s' % (sys.version_info[0], sys.version_info[1]) setuptools_file = 'setuptools-%s-py%s.egg-info' % \ (SETUPTOOLS_FAKED_VERSION, pyver) pkg_info = os.path.join(placeholder, setuptools_file) if os.path.exists(pkg_info): log.warn('%s already exists', pkg_info) return log.warn('Creating %s', pkg_info) f = open(pkg_info, 'w') try: f.write(SETUPTOOLS_PKG_INFO) finally: f.close() pth_file = os.path.join(placeholder, 'setuptools.pth') log.warn('Creating %s', pth_file) f = open(pth_file, 'w') try: f.write(os.path.join(os.curdir, setuptools_file)) finally: f.close() _create_fake_setuptools_pkg_info = _no_sandbox(_create_fake_setuptools_pkg_info) def _patch_egg_dir(path): # let's check if it's already patched pkg_info = os.path.join(path, 'EGG-INFO', 'PKG-INFO') if os.path.exists(pkg_info): if _same_content(pkg_info, SETUPTOOLS_PKG_INFO): log.warn('%s already patched.', pkg_info) return False _rename_path(path) os.mkdir(path) os.mkdir(os.path.join(path, 'EGG-INFO')) pkg_info = os.path.join(path, 'EGG-INFO', 'PKG-INFO') f = open(pkg_info, 'w') try: f.write(SETUPTOOLS_PKG_INFO) finally: f.close() return True _patch_egg_dir = _no_sandbox(_patch_egg_dir) def _before_install(): log.warn('Before install bootstrap.') _fake_setuptools() def _under_prefix(location): if 'install' not in sys.argv: return True args = sys.argv[sys.argv.index('install')+1:] for index, arg in enumerate(args): for option in ('--root', '--prefix'): if arg.startswith('%s=' % option): top_dir = arg.split('root=')[-1] return location.startswith(top_dir) elif arg == option: if len(args) > index: top_dir = args[index+1] return location.startswith(top_dir) if arg == '--user' and USER_SITE is not None: return location.startswith(USER_SITE) return True def _fake_setuptools(): log.warn('Scanning installed packages') try: import pkg_resources except ImportError: # we're cool log.warn('Setuptools or Distribute does not seem to be installed.') return ws = pkg_resources.working_set try: setuptools_dist = ws.find(pkg_resources.Requirement.parse('setuptools', replacement=False)) except TypeError: # old distribute API setuptools_dist = ws.find(pkg_resources.Requirement.parse('setuptools')) if setuptools_dist is None: log.warn('No setuptools distribution found') return # detecting if it was already faked setuptools_location = setuptools_dist.location log.warn('Setuptools installation detected at %s', setuptools_location) # if --root or --preix was provided, and if # setuptools is not located in them, we don't patch it if not _under_prefix(setuptools_location): log.warn('Not patching, --root or --prefix is installing Distribute' ' in another location') return # let's see if its an egg if not setuptools_location.endswith('.egg'): log.warn('Non-egg installation') res = _remove_flat_installation(setuptools_location) if not res: return else: log.warn('Egg installation') pkg_info = os.path.join(setuptools_location, 'EGG-INFO', 'PKG-INFO') if (os.path.exists(pkg_info) and _same_content(pkg_info, SETUPTOOLS_PKG_INFO)): log.warn('Already patched.') return log.warn('Patching...') # let's create a fake egg replacing setuptools one res = _patch_egg_dir(setuptools_location) if not res: return log.warn('Patched done.') _relaunch() def _relaunch(): log.warn('Relaunching...') # we have to relaunch the process # pip marker to avoid a relaunch bug if sys.argv[:3] == ['-c', 'install', '--single-version-externally-managed']: sys.argv[0] = 'setup.py' args = [sys.executable] + sys.argv sys.exit(subprocess.call(args)) def _extractall(self, path=".", members=None): """Extract all members from the archive to the current working directory and set owner, modification time and permissions on directories afterwards. `path' specifies a different directory to extract to. `members' is optional and must be a subset of the list returned by getmembers(). """ import copy import operator from tarfile import ExtractError directories = [] if members is None: members = self for tarinfo in members: if tarinfo.isdir(): # Extract directories with a safe mode. directories.append(tarinfo) tarinfo = copy.copy(tarinfo) tarinfo.mode = 448 # decimal for oct 0700 self.extract(tarinfo, path) # Reverse sort directories. if sys.version_info < (2, 4): def sorter(dir1, dir2): return cmp(dir1.name, dir2.name) directories.sort(sorter) directories.reverse() else: directories.sort(key=operator.attrgetter('name'), reverse=True) # Set correct owner, mtime and filemode on directories. for tarinfo in directories: dirpath = os.path.join(path, tarinfo.name) try: self.chown(tarinfo, dirpath) self.utime(tarinfo, dirpath) self.chmod(tarinfo, dirpath) except ExtractError: e = sys.exc_info()[1] if self.errorlevel > 1: raise else: self._dbg(1, "tarfile: %s" % e) def main(argv, version=DEFAULT_VERSION): """Install or upgrade setuptools and EasyInstall""" tarball = download_setuptools() _install(tarball) if __name__ == '__main__': main(sys.argv[1:]) flufl.enum-3.3.2/PKG-INFO0000664000175000017500000001306311744104775015166 0ustar barrybarry00000000000000Metadata-Version: 1.1 Name: flufl.enum Version: 3.3.2 Summary: A Python enumeration package. Home-page: http://launchpad.net/flufl.enum Author: Barry Warsaw Author-email: barry@python.org License: LGPLv3 Download-URL: https://launchpad.net/flufl.enum/+download Description: ========== flufl.enum ========== A Python enumeration package. The ``flufl.enum`` library is yet another Python enumeration package. Its goal is to provide simple, specific, concise semantics in an easy to read and write syntax. ``flufl.enum`` has just enough of the features needed to make enumerations useful, but without a lot of extra baggage to weigh them down. This work grew out of the Mailman 3.0 project. License ======= This file is part of flufl.enum. flufl.enum is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, version 3 of the License. flufl.enum is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with flufl.enum. If not, see . =================== NEWS for flufl.enum =================== 3.3.2 (2012-04-19) ================== * Add classifiers to setup.py and make the long description more compatible with the Cheeseshop. * Other changes to make the Cheeseshop page look nicer. (LP: #680136) * setup_helper.py version 2.1. 3.3.1 (2012-01-19) ================== * Fix Python 3 compatibility with Sphinx's conf.py ($python setup.py install). 3.3 (2012-01-19) ================ * Remove the dependency on 2to3 for Python 3 support; support Python 3 directly with a single code base. * flufl.enum.make_enum() is deprecated in favor of flufl.enum.make() which provides a better API. (LP: #839529) * Updated to distribute 0.6.19. * Moved all documentation to .rst suffix. * Make test_deprecations() compatible with Python 3 and Python 2. * Removed markup for pylint. * Improve documentation to illustrate that enum values with similar names and integer representations still do not hash equally. (Found by Jeroen Vermeulen). 3.2 (2011-08-19) ================ * make_enum() accepts an optional `iterable` argument to provide the values for the enums. * The .enumclass and .enumname attributes are deprecated. Use .enum and .name instead, respectively. * Improve the documentation regarding ordered comparisons and equality tests. (LP: #794853) * make_enum() now enforces the use of valid Python identifiers. (LP: #803570) 3.1 (2011-03-01) ================ * New convenience function `make_enum()`. (Contributed by Michael Foord) * Fix `from flufl.enum import *`. * Enums created with the class syntax can be pickled and unpickled. (Suggestion and basic implementation idea by Phillip Eby). 3.0.1 (2010-06-07) ================== * Fixed typo which caused the package to break. 3.0 (2010-04-24) ================ * Package renamed to flufl.enum. 2.0.2 (2010-01-29) ================== * Fixed some test failures when running under 2to3. 2.0.1 (2010-01-08) ================== * Fix the manifest and clarify license. 2.0 (2010-01-07) ================ * Use Sphinx to build the documentation. * Updates to better package Debian/Ubuntu. * Use distribute_setup instead of ez_setup. * Rename pep-xxxx.txt; this won't be submitted as a PEP. * Remove dependencies on nose and setuptools_bzr * Support Python 3 via 2to3. Earlier ======= Try `bzr log lp:flufl.enum` for details. Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: GNU Lesser General Public License v3 or later (LGPLv3+) Classifier: Operating System :: POSIX Classifier: Operating System :: Microsoft :: Windows Classifier: Operating System :: MacOS :: MacOS X Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 2.6 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 Classifier: Topic :: Software Development :: Libraries Classifier: Topic :: Software Development :: Libraries :: Python Modules flufl.enum-3.3.2/template.py0000664000175000017500000000146611706071514016252 0ustar barrybarry00000000000000# Copyright (C) 2011-2012 by Barry A. Warsaw # # This file is part of flufl.enum # # flufl.enum is free software: you can redistribute it and/or modify it under # the terms of the GNU Lesser General Public License as published by the Free # Software Foundation, version 3 of the License. # # flufl.enum is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License # for more details. # # You should have received a copy of the GNU Lesser General Public License # along with flufl.enum. If not, see . """Module contents.""" from __future__ import absolute_import, print_function, unicode_literals __metaclass__ = type __all__ = [ ] flufl.enum-3.3.2/README.rst0000664000175000017500000000203411744101644015544 0ustar barrybarry00000000000000========== flufl.enum ========== A Python enumeration package. The ``flufl.enum`` library is yet another Python enumeration package. Its goal is to provide simple, specific, concise semantics in an easy to read and write syntax. ``flufl.enum`` has just enough of the features needed to make enumerations useful, but without a lot of extra baggage to weigh them down. This work grew out of the Mailman 3.0 project. License ======= This file is part of flufl.enum. flufl.enum is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, version 3 of the License. flufl.enum is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with flufl.enum. If not, see . flufl.enum-3.3.2/flufl.enum.egg-info/0000775000175000017500000000000011744104775017633 5ustar barrybarry00000000000000flufl.enum-3.3.2/flufl.enum.egg-info/SOURCES.txt0000664000175000017500000000111311744104775021513 0ustar barrybarry00000000000000README.rst distribute_setup.py setup.cfg setup.py setup_helpers.py template.py flufl/__init__.py flufl.enum.egg-info/PKG-INFO flufl.enum.egg-info/PKG-INFO~ flufl.enum.egg-info/SOURCES.txt flufl.enum.egg-info/dependency_links.txt flufl.enum.egg-info/namespace_packages.txt flufl.enum.egg-info/top_level.txt flufl/enum/NEWS.rst flufl/enum/README.rst flufl/enum/__init__.py flufl/enum/_enum.py flufl/enum/conf.py flufl/enum/docs/__init__.py flufl/enum/docs/using.rst flufl/enum/tests/__init__.py flufl/enum/tests/fruit.py flufl/enum/tests/test_documentation.py flufl/enum/tests/test_enum.pyflufl.enum-3.3.2/flufl.enum.egg-info/top_level.txt0000664000175000017500000000000611744104775022361 0ustar barrybarry00000000000000flufl flufl.enum-3.3.2/flufl.enum.egg-info/dependency_links.txt0000664000175000017500000000000111744104775023701 0ustar barrybarry00000000000000 flufl.enum-3.3.2/flufl.enum.egg-info/namespace_packages.txt0000664000175000017500000000000611744104775024162 0ustar barrybarry00000000000000flufl flufl.enum-3.3.2/flufl.enum.egg-info/PKG-INFO0000664000175000017500000001306311744104775020733 0ustar barrybarry00000000000000Metadata-Version: 1.1 Name: flufl.enum Version: 3.3.2 Summary: A Python enumeration package. Home-page: http://launchpad.net/flufl.enum Author: Barry Warsaw Author-email: barry@python.org License: LGPLv3 Download-URL: https://launchpad.net/flufl.enum/+download Description: ========== flufl.enum ========== A Python enumeration package. The ``flufl.enum`` library is yet another Python enumeration package. Its goal is to provide simple, specific, concise semantics in an easy to read and write syntax. ``flufl.enum`` has just enough of the features needed to make enumerations useful, but without a lot of extra baggage to weigh them down. This work grew out of the Mailman 3.0 project. License ======= This file is part of flufl.enum. flufl.enum is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, version 3 of the License. flufl.enum is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with flufl.enum. If not, see . =================== NEWS for flufl.enum =================== 3.3.2 (2012-04-19) ================== * Add classifiers to setup.py and make the long description more compatible with the Cheeseshop. * Other changes to make the Cheeseshop page look nicer. (LP: #680136) * setup_helper.py version 2.1. 3.3.1 (2012-01-19) ================== * Fix Python 3 compatibility with Sphinx's conf.py ($python setup.py install). 3.3 (2012-01-19) ================ * Remove the dependency on 2to3 for Python 3 support; support Python 3 directly with a single code base. * flufl.enum.make_enum() is deprecated in favor of flufl.enum.make() which provides a better API. (LP: #839529) * Updated to distribute 0.6.19. * Moved all documentation to .rst suffix. * Make test_deprecations() compatible with Python 3 and Python 2. * Removed markup for pylint. * Improve documentation to illustrate that enum values with similar names and integer representations still do not hash equally. (Found by Jeroen Vermeulen). 3.2 (2011-08-19) ================ * make_enum() accepts an optional `iterable` argument to provide the values for the enums. * The .enumclass and .enumname attributes are deprecated. Use .enum and .name instead, respectively. * Improve the documentation regarding ordered comparisons and equality tests. (LP: #794853) * make_enum() now enforces the use of valid Python identifiers. (LP: #803570) 3.1 (2011-03-01) ================ * New convenience function `make_enum()`. (Contributed by Michael Foord) * Fix `from flufl.enum import *`. * Enums created with the class syntax can be pickled and unpickled. (Suggestion and basic implementation idea by Phillip Eby). 3.0.1 (2010-06-07) ================== * Fixed typo which caused the package to break. 3.0 (2010-04-24) ================ * Package renamed to flufl.enum. 2.0.2 (2010-01-29) ================== * Fixed some test failures when running under 2to3. 2.0.1 (2010-01-08) ================== * Fix the manifest and clarify license. 2.0 (2010-01-07) ================ * Use Sphinx to build the documentation. * Updates to better package Debian/Ubuntu. * Use distribute_setup instead of ez_setup. * Rename pep-xxxx.txt; this won't be submitted as a PEP. * Remove dependencies on nose and setuptools_bzr * Support Python 3 via 2to3. Earlier ======= Try `bzr log lp:flufl.enum` for details. Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: GNU Lesser General Public License v3 or later (LGPLv3+) Classifier: Operating System :: POSIX Classifier: Operating System :: Microsoft :: Windows Classifier: Operating System :: MacOS :: MacOS X Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 2.6 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 Classifier: Topic :: Software Development :: Libraries Classifier: Topic :: Software Development :: Libraries :: Python Modules flufl.enum-3.3.2/flufl.enum.egg-info/PKG-INFO~0000664000175000017500000001255211744103671021125 0ustar barrybarry00000000000000Metadata-Version: 1.1 Name: flufl.enum Version: 3.3.2 Summary: A Python enumeration package. Home-page: http://launchpad.net/flufl.enum Author: Barry Warsaw Author-email: barry@python.org License: LGPLv3 Download-URL: https://launchpad.net/flufl.enum/+download Description: ========== flufl.enum ========== A Python enumeration package. The ``flufl.enum`` library is yet another Python enumeration package. Its goal is to provide simple, specific, concise semantics in an easy to read and write syntax. ``flufl.enum`` has just enough of the features needed to make enumerations useful, but without a lot of extra baggage to weigh them down. This work grew out of the Mailman 3.0 project. License ======= This file is part of flufl.enum. flufl.enum is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, version 3 of the License. flufl.enum is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with flufl.enum. If not, see . =================== NEWS for flufl.enum =================== 3.3.2 (2012-04-19) ================== * Add classifiers to setup.py and make the long description more compatible with the Cheeseshop. 3.3.1 (2012-01-19) ================== * Fix Python 3 compatibility with Sphinx's conf.py ($python setup.py install). 3.3 (2012-01-19) ================ * Remove the dependency on 2to3 for Python 3 support; support Python 3 directly with a single code base. * flufl.enum.make_enum() is deprecated in favor of flufl.enum.make() which provides a better API. (LP: #839529) * Updated to distribute 0.6.19. * Moved all documentation to .rst suffix. * Make test_deprecations() compatible with Python 3 and Python 2. * Removed markup for pylint. * Improve documentation to illustrate that enum values with similar names and integer representations still do not hash equally. (Found by Jeroen Vermeulen). 3.2 (2011-08-19) ================ * make_enum() accepts an optional `iterable` argument to provide the values for the enums. * The .enumclass and .enumname attributes are deprecated. Use .enum and .name instead, respectively. * Improve the documentation regarding ordered comparisons and equality tests. (LP: #794853) * make_enum() now enforces the use of valid Python identifiers. (LP: #803570) 3.1 (2011-03-01) ================ * New convenience function `make_enum()`. (Contributed by Michael Foord) * Fix `from flufl.enum import *`. * Enums created with the class syntax can be pickled and unpickled. (Suggestion and basic implementation idea by Phillip Eby). 3.0.1 (2010-06-07) ================== * Fixed typo which caused the package to break. 3.0 (2010-04-24) ================ * Package renamed to flufl.enum. 2.0.2 (2010-01-29) ================== * Fixed some test failures when running under 2to3. 2.0.1 (2010-01-08) ================== * Fix the manifest and clarify license. 2.0 (2010-01-07) ================ * Use Sphinx to build the documentation. * Updates to better package Debian/Ubuntu. * Use distribute_setup instead of ez_setup. * Rename pep-xxxx.txt; this won't be submitted as a PEP. * Remove dependencies on nose and setuptools_bzr * Support Python 3 via 2to3. Earlier ======= Try `bzr log` for details. Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: GNU Lesser General Public License v3 or later (LGPLv3+) Classifier: Operating System :: POSIX Classifier: Operating System :: Microsoft :: Windows Classifier: Operating System :: MacOS :: MacOS X Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 2.6 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 Classifier: Topic :: Software Development :: Libraries Classifier: Topic :: Software Development :: Libraries :: Python Modules