sentinels-1.0.0/0000775000175000017500000000000012761231565013130 5ustar travistravissentinels-1.0.0/sentinels/0000775000175000017500000000000012761231565015134 5ustar travistravissentinels-1.0.0/sentinels/__init__.py0000664000175000017500000000221612761231552017242 0ustar travistravisfrom .__version__ import __version__ try: # python3 renamed copy_reg to copyreg import copyreg except ImportError: import copy_reg as copyreg class Sentinel(object): _existing_instances = {} def __init__(self, name): super(Sentinel, self).__init__() self._name = name self._existing_instances[self._name] = self def __repr__(self): return "<{0}>".format(self._name) def __getnewargs__(self): return (self._name,) def __new__(cls, name, obj_id=None): # obj_id is for compatibility with previous versions existing_instance = cls._existing_instances.get(name) if existing_instance is not None: return existing_instance return super(Sentinel, cls).__new__(cls) def _sentinel_unpickler(name, obj_id=None): # obj_id is for compat. with prev. versions if name in Sentinel._existing_instances: return Sentinel._existing_instances[name] return Sentinel(name) def _sentinel_pickler(sentinel): return _sentinel_unpickler, sentinel.__getnewargs__() copyreg.pickle(Sentinel, _sentinel_pickler, _sentinel_unpickler) NOTHING = Sentinel('NOTHING') sentinels-1.0.0/sentinels/__version__.py0000664000175000017500000000002612761231552017761 0ustar travistravis__version__ = "1.0.0" sentinels-1.0.0/sentinels.egg-info/0000775000175000017500000000000012761231565016626 5ustar travistravissentinels-1.0.0/sentinels.egg-info/PKG-INFO0000664000175000017500000000110012761231565017713 0ustar travistravisMetadata-Version: 1.0 Name: sentinels Version: 1.0.0 Summary: Various objects to denote special meanings in python Home-page: UNKNOWN Author: Rotem Yaari Author-email: vmalloc@gmail.com License: BSD Description: UNKNOWN Platform: UNKNOWN Classifier: Development Status :: 4 - Beta Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: BSD License Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3.3 Classifier: Programming Language :: Python :: 3.4 Classifier: Programming Language :: Python :: 3.5 sentinels-1.0.0/sentinels.egg-info/SOURCES.txt0000664000175000017500000000051112761231565020507 0ustar travistravisLICENSE MANIFEST.in README.rst setup.py tox.ini sentinels/__init__.py sentinels/__version__.py sentinels.egg-info/PKG-INFO sentinels.egg-info/SOURCES.txt sentinels.egg-info/dependency_links.txt sentinels.egg-info/namespace_packages.txt sentinels.egg-info/top_level.txt tests/test__readme_doctest.py tests/test__readme_doctest.pycsentinels-1.0.0/sentinels.egg-info/dependency_links.txt0000664000175000017500000000000112761231565022674 0ustar travistravis sentinels-1.0.0/sentinels.egg-info/namespace_packages.txt0000664000175000017500000000000112761231565023150 0ustar travistravis sentinels-1.0.0/sentinels.egg-info/top_level.txt0000664000175000017500000000001212761231565021351 0ustar travistravissentinels sentinels-1.0.0/tests/0000775000175000017500000000000012761231565014272 5ustar travistravissentinels-1.0.0/tests/test__readme_doctest.py0000664000175000017500000000065012761231552021021 0ustar travistravisfrom unittest import TestCase import os import doctest class ReadMeDocTest(TestCase): def test__readme_doctests(self): readme_path = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "README.rst")) self.assertTrue(os.path.exists(readme_path)) result = doctest.testfile(readme_path, module_relative=False) self.assertEqual(result.failed, 0, "%s tests failed!" % result.failed)sentinels-1.0.0/tests/test__readme_doctest.pyc0000664000175000017500000000177612761231557021203 0ustar travistravisŃň j3ĹWc@sBddklZddkZddkZdefd„ƒYZdS(i˙˙˙˙(tTestCaseNt ReadMeDocTestcBseZd„ZRS(cCstiitiitiitƒddƒƒ}|itii|ƒƒti |dt ƒ}|i |i dd|i ƒdS(Ns..s README.rsttmodule_relativeis%s tests failed!( tostpathtabspathtjointdirnamet__file__t assertTruetexiststdoctestttestfiletFalset assertEqualtfailed(tselft readme_pathtresult((sB/home/travis/build/vmalloc/sentinels/tests/test__readme_doctest.pyttest__readme_doctestss0(t__name__t __module__R(((sB/home/travis/build/vmalloc/sentinels/tests/test__readme_doctest.pyRs(tunittestRRR R(((sB/home/travis/build/vmalloc/sentinels/tests/test__readme_doctest.pyts  sentinels-1.0.0/LICENSE0000664000175000017500000000276612761231552014144 0ustar travistravis# Copyright (c) 2011, Rotem Yaari # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # * Neither the name of organization nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY Rotem Yaari ''AS IS'' AND ANY # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL Rotem Yaari BE LIABLE FOR ANY # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. sentinels-1.0.0/MANIFEST.in0000664000175000017500000000010612761231552014657 0ustar travistravisinclude MANIFEST.in tests/* tox.ini travis_build.py .pylintrc LICENSE sentinels-1.0.0/README.rst0000664000175000017500000000442512761231552014620 0ustar travistravisOverview -------- The sentinels module is a small utility providing the Sentinel class, along with useful instances. What are Sentinels? ------------------- Sentinels are objects with special meanings. They can be thought of as singletons, but they service the need of having 'special' values in your code, that have special meanings (see example below). Why Do I Need Sentinels? ------------------------ Let's take *NOTHING* for example. This sentinel is automatically provided with the sentinels import:: >>> from sentinels import NOTHING Let's say you're writing a wrapper around a Python dictionary, which supports a special kind of method, *get_default_or_raise*. This method behaves like *get*, but when it does not receive a default and the key does not exist, it raises a *KeyError*. How would you implement such a thing? The naive method is this:: >>> class MyDict(dict): ... def get_default_or_raise(self, key, default=None): ... if key not in self and default is None: ... raise KeyError(key) ... return self.get(key, default) Or even this:: >>> class MyDict(dict): ... def get_default_or_raise(self, key, default=None): ... returned = self.get(key, default) ... if returned is None: ... raise KeyError(key) ... return returned But the problem with the above two pieces of code is the same -- when writing a general utility class, we don't know how it will be used later on. More importantly, **None might be a perfectly valid dictionary value!** This is where NOTHING comes in handy:: >>> class MyDict(dict): ... def get_default_or_raise(self, key, default=NOTHING): ... returned = self.get(key, default) ... if returned is NOTHING: ... raise KeyError(key) ... return returned And Tada! Semantics --------- Sentinels are always equal to themselves:: >>> NOTHING == NOTHING True But never to another object:: >>> from sentinels import Sentinel >>> NOTHING == 2 False >>> NOTHING == "NOTHING" False Copying sentinels returns the same object:: >>> import copy >>> copy.deepcopy(NOTHING) is NOTHING True And of course also pickling/unpickling:: >>> import pickle >>> NOTHING is pickle.loads(pickle.dumps(NOTHING)) True sentinels-1.0.0/setup.py0000664000175000017500000000163712761231552014645 0ustar travistravis import os import itertools from setuptools import setup, find_packages with open(os.path.join(os.path.dirname(__file__), "sentinels", "__version__.py")) as version_file: exec(version_file.read()) setup(name="sentinels", classifiers = [ "Development Status :: 4 - Beta", "Intended Audience :: Developers", "License :: OSI Approved :: BSD License", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3.3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5", ], description="Various objects to denote special meanings in python", license="BSD", author="Rotem Yaari", author_email="vmalloc@gmail.com", version=__version__, packages=find_packages(exclude=["tests"]), install_requires=[], scripts=[], namespace_packages=[] ) sentinels-1.0.0/tox.ini0000664000175000017500000000017312761231552014440 0ustar travistravis[tox] envlist = py27,py32,py33,py34,py35 [testenv] deps=nose commands=nosetests -w {toxinidir}/tests changedir = {envdir} sentinels-1.0.0/PKG-INFO0000664000175000017500000000110012761231565014215 0ustar travistravisMetadata-Version: 1.0 Name: sentinels Version: 1.0.0 Summary: Various objects to denote special meanings in python Home-page: UNKNOWN Author: Rotem Yaari Author-email: vmalloc@gmail.com License: BSD Description: UNKNOWN Platform: UNKNOWN Classifier: Development Status :: 4 - Beta Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: BSD License Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3.3 Classifier: Programming Language :: Python :: 3.4 Classifier: Programming Language :: Python :: 3.5 sentinels-1.0.0/setup.cfg0000664000175000017500000000007312761231565014751 0ustar travistravis[egg_info] tag_build = tag_date = 0 tag_svn_revision = 0