././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1698535065.6352432 constantly-23.10.4/0000755000076500000240000000000014517313232013126 5ustar00glyphstaff././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1585809983.0 constantly-23.10.4/CREDITS0000644000076500000240000000012713641305077014153 0ustar00glyphstaffAmber Hawkie Brown Glyph Lefkowitz Jean-Paul Calderone Richard Wall Wilfredo Sánchez ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1585809983.0 constantly-23.10.4/LICENSE0000644000076500000240000000213413641305077014140 0ustar00glyphstaffCopyright (c) 2011-2015 Twisted Matrix Laboratories & Individual Contributors (see CREDITS) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1585809983.0 constantly-23.10.4/MANIFEST.in0000644000076500000240000000015013641305077014665 0ustar00glyphstaffinclude versioneer.py include constantly/_version.py include README.rst include LICENSE include CREDITS ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1698535065.6350608 constantly-23.10.4/PKG-INFO0000644000076500000240000000334314517313232014226 0ustar00glyphstaffMetadata-Version: 2.1 Name: constantly Version: 23.10.4 Summary: Symbolic constants in Python Maintainer: Twisted Matrix Labs Developers License: MIT Project-URL: Homepage, https://github.com/twisted/constantly Keywords: constants,enum,twisted Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: MIT License Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3 :: Only Classifier: Programming Language :: Python :: 3.8 Classifier: Programming Language :: Python :: 3.9 Classifier: Programming Language :: Python :: 3.10 Classifier: Programming Language :: Python :: 3.11 Classifier: Programming Language :: Python :: 3.12 Classifier: Programming Language :: Python :: Implementation :: CPython Classifier: Programming Language :: Python :: Implementation :: PyPy Classifier: Topic :: Software Development :: Libraries :: Python Modules Requires-Python: >=3.8 Description-Content-Type: text/x-rst License-File: LICENSE Constantly ========== A library that provides symbolic constant support. It includes collections and constants with text, numeric, and bit flag values. Originally ``twisted.python.constants`` from the `Twisted `_ project. Installing ---------- constantly is available in `PyPI `_, and can be installed via pip:: $ pip install constantly Documentation ------------------------- Documentation is available at ``_. Tests ----- To run tests:: $ tox This will run tests on Python 2.7, 3.3, 3.4, and PyPy, as well as doing coverage and pyflakes checks. ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1698534902.0 constantly-23.10.4/README.rst0000644000076500000240000000125014517312766014626 0ustar00glyphstaffConstantly ========== A library that provides symbolic constant support. It includes collections and constants with text, numeric, and bit flag values. Originally ``twisted.python.constants`` from the `Twisted `_ project. Installing ---------- constantly is available in `PyPI `_, and can be installed via pip:: $ pip install constantly Documentation ------------------------- Documentation is available at ``_. Tests ----- To run tests:: $ tox This will run tests on Python 2.7, 3.3, 3.4, and PyPy, as well as doing coverage and pyflakes checks. ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1698535065.6341403 constantly-23.10.4/constantly/0000755000076500000240000000000014517313232015324 5ustar00glyphstaff././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1698532976.0 constantly-23.10.4/constantly/__init__.py0000644000076500000240000000076114517307160017444 0ustar00glyphstaff# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. from constantly._constants import ( NamedConstant, Names, ValueConstant, Values, FlagConstant, Flags ) from . import _version __version__ = _version.get_versions()['version'] __author__ = "Twisted Matrix Laboratories" __license__ = "MIT" __copyright__ = "Copyright 2011-2015 {0}".format(__author__) __all__ = [ 'NamedConstant', 'ValueConstant', 'FlagConstant', 'Names', 'Values', 'Flags', ] ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1585809983.0 constantly-23.10.4/constantly/_constants.py0000644000076500000240000003720513641305077020065 0ustar00glyphstaff# -*- test-case-name: constantly.test.test_constants -*- # Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. """ Symbolic constant support, including collections and constants with text, numeric, and bit flag values. """ from __future__ import division, absolute_import __all__ = [] from functools import partial from itertools import count from operator import and_, or_, xor _unspecified = object() _constantOrder = partial(next, count()) class _Constant(object): """ @ivar _index: A C{int} allocated from a shared counter in order to keep track of the order in which L{_Constant}s are instantiated. @ivar name: A C{str} giving the name of this constant; only set once the constant is initialized by L{_ConstantsContainer}. @ivar _container: The L{_ConstantsContainer} subclass this constant belongs to; C{None} until the constant is initialized by that subclass. """ def __init__(self): self._container = None self._index = _constantOrder() def __repr__(self): """ Return text identifying both which constant this is and which collection it belongs to. """ return "<%s=%s>" % (self._container.__name__, self.name) def __lt__(self, other): """ Implements C{<}. Order is defined by instantiation order. @param other: An object. @return: C{NotImplemented} if C{other} is not a constant belonging to the same container as this constant, C{True} if this constant is defined before C{other}, otherwise C{False}. """ if ( not isinstance(other, self.__class__) or not self._container == other._container ): return NotImplemented return self._index < other._index def __le__(self, other): """ Implements C{<=}. Order is defined by instantiation order. @param other: An object. @return: C{NotImplemented} if C{other} is not a constant belonging to the same container as this constant, C{True} if this constant is defined before or equal to C{other}, otherwise C{False}. """ if ( not isinstance(other, self.__class__) or not self._container == other._container ): return NotImplemented return self is other or self._index < other._index def __gt__(self, other): """ Implements C{>}. Order is defined by instantiation order. @param other: An object. @return: C{NotImplemented} if C{other} is not a constant belonging to the same container as this constant, C{True} if this constant is defined after C{other}, otherwise C{False}. """ if ( not isinstance(other, self.__class__) or not self._container == other._container ): return NotImplemented return self._index > other._index def __ge__(self, other): """ Implements C{>=}. Order is defined by instantiation order. @param other: An object. @return: C{NotImplemented} if C{other} is not a constant belonging to the same container as this constant, C{True} if this constant is defined after or equal to C{other}, otherwise C{False}. """ if ( not isinstance(other, self.__class__) or not self._container == other._container ): return NotImplemented return self is other or self._index > other._index def _realize(self, container, name, value): """ Complete the initialization of this L{_Constant}. @param container: The L{_ConstantsContainer} subclass this constant is part of. @param name: The name of this constant in its container. @param value: The value of this constant; not used, as named constants have no value apart from their identity. """ self._container = container self.name = name class _ConstantsContainerType(type): """ L{_ConstantsContainerType} is a metaclass for creating constants container classes. """ def __new__(self, name, bases, attributes): """ Create a new constants container class. If C{attributes} includes a value of C{None} for the C{"_constantType"} key, the new class will not be initialized as a constants container and it will behave as a normal class. @param name: The name of the container class. @type name: L{str} @param bases: A tuple of the base classes for the new container class. @type bases: L{tuple} of L{_ConstantsContainerType} instances @param attributes: The attributes of the new container class, including any constants it is to contain. @type attributes: L{dict} """ cls = super(_ConstantsContainerType, self).__new__( self, name, bases, attributes) # Only realize constants in concrete _ConstantsContainer subclasses. # Ignore intermediate base classes. constantType = getattr(cls, '_constantType', None) if constantType is None: return cls constants = [] for (name, descriptor) in attributes.items(): if isinstance(descriptor, cls._constantType): if descriptor._container is not None: raise ValueError( "Cannot use %s as the value of an attribute on %s" % ( descriptor, cls.__name__)) constants.append((descriptor._index, name, descriptor)) enumerants = {} for (index, enumerant, descriptor) in sorted(constants): value = cls._constantFactory(enumerant, descriptor) descriptor._realize(cls, enumerant, value) enumerants[enumerant] = descriptor # Save the dictionary which contains *only* constants (distinct from # any other attributes the application may have given the container) # where the class can use it later (eg for lookupByName). cls._enumerants = enumerants return cls # In Python3 metaclasses are defined using a C{metaclass} keyword argument in # the class definition. This would cause a syntax error in Python2. # So we use L{type} to introduce an intermediate base class with the desired # metaclass. # See: # * http://docs.python.org/2/library/functions.html#type # * http://docs.python.org/3/reference/datamodel.html#customizing-class-creation class _ConstantsContainer(_ConstantsContainerType('', (object,), {})): """ L{_ConstantsContainer} is a class with attributes used as symbolic constants. It is up to subclasses to specify what kind of constants are allowed. @cvar _constantType: Specified by a L{_ConstantsContainer} subclass to specify the type of constants allowed by that subclass. @cvar _enumerants: A C{dict} mapping the names of constants (eg L{NamedConstant} instances) found in the class definition to those instances. """ _constantType = None def __new__(cls): """ Classes representing constants containers are not intended to be instantiated. The class object itself is used directly. """ raise TypeError("%s may not be instantiated." % (cls.__name__,)) @classmethod def _constantFactory(cls, name, descriptor): """ Construct the value for a new constant to add to this container. @param name: The name of the constant to create. @param descriptor: An instance of a L{_Constant} subclass (eg L{NamedConstant}) which is assigned to C{name}. @return: L{NamedConstant} instances have no value apart from identity, so return a meaningless dummy value. """ return _unspecified @classmethod def lookupByName(cls, name): """ Retrieve a constant by its name or raise a C{ValueError} if there is no constant associated with that name. @param name: A C{str} giving the name of one of the constants defined by C{cls}. @raise ValueError: If C{name} is not the name of one of the constants defined by C{cls}. @return: The L{NamedConstant} associated with C{name}. """ if name in cls._enumerants: return getattr(cls, name) raise ValueError(name) @classmethod def iterconstants(cls): """ Iteration over a L{Names} subclass results in all of the constants it contains. @return: an iterator the elements of which are the L{NamedConstant} instances defined in the body of this L{Names} subclass. """ constants = cls._enumerants.values() return iter( sorted(constants, key=lambda descriptor: descriptor._index)) class NamedConstant(_Constant): """ L{NamedConstant} defines an attribute to be a named constant within a collection defined by a L{Names} subclass. L{NamedConstant} is only for use in the definition of L{Names} subclasses. Do not instantiate L{NamedConstant} elsewhere and do not subclass it. """ class Names(_ConstantsContainer): """ A L{Names} subclass contains constants which differ only in their names and identities. """ _constantType = NamedConstant class ValueConstant(_Constant): """ L{ValueConstant} defines an attribute to be a named constant within a collection defined by a L{Values} subclass. L{ValueConstant} is only for use in the definition of L{Values} subclasses. Do not instantiate L{ValueConstant} elsewhere and do not subclass it. """ def __init__(self, value): _Constant.__init__(self) self.value = value class Values(_ConstantsContainer): """ A L{Values} subclass contains constants which are associated with arbitrary values. """ _constantType = ValueConstant @classmethod def lookupByValue(cls, value): """ Retrieve a constant by its value or raise a C{ValueError} if there is no constant associated with that value. @param value: The value of one of the constants defined by C{cls}. @raise ValueError: If C{value} is not the value of one of the constants defined by C{cls}. @return: The L{ValueConstant} associated with C{value}. """ for constant in cls.iterconstants(): if constant.value == value: return constant raise ValueError(value) def _flagOp(op, left, right): """ Implement a binary operator for a L{FlagConstant} instance. @param op: A two-argument callable implementing the binary operation. For example, C{operator.or_}. @param left: The left-hand L{FlagConstant} instance. @param right: The right-hand L{FlagConstant} instance. @return: A new L{FlagConstant} instance representing the result of the operation. """ value = op(left.value, right.value) names = op(left.names, right.names) result = FlagConstant() result._realize(left._container, names, value) return result class FlagConstant(_Constant): """ L{FlagConstant} defines an attribute to be a flag constant within a collection defined by a L{Flags} subclass. L{FlagConstant} is only for use in the definition of L{Flags} subclasses. Do not instantiate L{FlagConstant} elsewhere and do not subclass it. """ def __init__(self, value=_unspecified): _Constant.__init__(self) self.value = value def _realize(self, container, names, value): """ Complete the initialization of this L{FlagConstant}. This implementation differs from other C{_realize} implementations in that a L{FlagConstant} may have several names which apply to it, due to flags being combined with various operators. @param container: The L{Flags} subclass this constant is part of. @param names: When a single-flag value is being initialized, a C{str} giving the name of that flag. This is the case which happens when a L{Flags} subclass is being initialized and L{FlagConstant} instances from its body are being realized. Otherwise, a C{set} of C{str} giving names of all the flags set on this L{FlagConstant} instance. This is the case when two flags are combined using C{|}, for example. """ if isinstance(names, str): name = names names = set([names]) elif len(names) == 1: (name,) = names else: name = "{" + ",".join(sorted(names)) + "}" _Constant._realize(self, container, name, value) self.value = value self.names = names def __or__(self, other): """ Define C{|} on two L{FlagConstant} instances to create a new L{FlagConstant} instance with all flags set in either instance set. """ return _flagOp(or_, self, other) def __and__(self, other): """ Define C{&} on two L{FlagConstant} instances to create a new L{FlagConstant} instance with only flags set in both instances set. """ return _flagOp(and_, self, other) def __xor__(self, other): """ Define C{^} on two L{FlagConstant} instances to create a new L{FlagConstant} instance with only flags set on exactly one instance set. """ return _flagOp(xor, self, other) def __invert__(self): """ Define C{~} on a L{FlagConstant} instance to create a new L{FlagConstant} instance with all flags not set on this instance set. """ result = FlagConstant() result._realize(self._container, set(), 0) for flag in self._container.iterconstants(): if flag.value & self.value == 0: result |= flag return result def __iter__(self): """ @return: An iterator of flags set on this instance set. """ return (self._container.lookupByName(name) for name in self.names) def __contains__(self, flag): """ @param flag: The flag to test for membership in this instance set. @return: C{True} if C{flag} is in this instance set, else C{False}. """ # Optimization for testing membership without iteration. return bool(flag & self) def __nonzero__(self): """ @return: C{False} if this flag's value is 0, else C{True}. """ return bool(self.value) __bool__ = __nonzero__ class Flags(Values): """ A L{Flags} subclass contains constants which can be combined using the common bitwise operators (C{|}, C{&}, etc) similar to a I{bitvector} from a language like C. """ _constantType = FlagConstant _value = 1 @classmethod def _constantFactory(cls, name, descriptor): """ For L{FlagConstant} instances with no explicitly defined value, assign the next power of two as its value. @param name: The name of the constant to create. @param descriptor: An instance of a L{FlagConstant} which is assigned to C{name}. @return: Either the value passed to the C{descriptor} constructor, or the next power of 2 value which will be assigned to C{descriptor}, relative to the value of the last defined L{FlagConstant}. """ if descriptor.value is _unspecified: value = cls._value cls._value <<= 1 else: value = descriptor.value cls._value = value << 1 return value ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1698535065.6353793 constantly-23.10.4/constantly/_version.py0000644000076500000240000000076314517313232017530 0ustar00glyphstaff # This file was generated by 'versioneer.py' (0.29) from # revision-control system data, or from the parent directory name of an # unpacked source archive. Distribution tarballs contain a pre-generated copy # of this file. import json version_json = ''' { "date": "2023-10-28T16:14:45-0700", "dirty": false, "error": null, "full-revisionid": "c63aa51794c314778b5699dd1cec9b3547fe6911", "version": "23.10.4" } ''' # END VERSION_JSON def get_versions(): return json.loads(version_json) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1698535065.6348457 constantly-23.10.4/constantly/test/0000755000076500000240000000000014517313232016303 5ustar00glyphstaff././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1585809983.0 constantly-23.10.4/constantly/test/__init__.py0000644000076500000240000000015013641305077020415 0ustar00glyphstaff# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. """ Tests for Constantly. """ ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1585809983.0 constantly-23.10.4/constantly/test/test_constants.py0000644000076500000240000011076413641305077021746 0ustar00glyphstaff# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. """ Unit tests for L{constantly}. """ from __future__ import division, absolute_import from twisted.trial.unittest import TestCase from constantly import ( NamedConstant, Names, ValueConstant, Values, FlagConstant, Flags ) class NamedConstantTests(TestCase): """ Tests for the L{constantly.NamedConstant} class which is used to represent individual values. """ def setUp(self): """ Create a dummy container into which constants can be placed. """ class foo(Names): pass self.container = foo def test_name(self): """ The C{name} attribute of a L{NamedConstant} refers to the value passed for the C{name} parameter to C{_realize}. """ name = NamedConstant() name._realize(self.container, "bar", None) self.assertEqual("bar", name.name) def test_representation(self): """ The string representation of an instance of L{NamedConstant} includes the container the instances belongs to as well as the instance's name. """ name = NamedConstant() name._realize(self.container, "bar", None) self.assertEqual("", repr(name)) def test_equality(self): """ A L{NamedConstant} instance compares equal to itself. """ name = NamedConstant() name._realize(self.container, "bar", None) self.assertTrue(name == name) self.assertFalse(name != name) def test_nonequality(self): """ Two different L{NamedConstant} instances do not compare equal to each other. """ first = NamedConstant() first._realize(self.container, "bar", None) second = NamedConstant() second._realize(self.container, "bar", None) self.assertFalse(first == second) self.assertTrue(first != second) def test_hash(self): """ Because two different L{NamedConstant} instances do not compare as equal to each other, they also have different hashes to avoid collisions when added to a C{dict} or C{set}. """ first = NamedConstant() first._realize(self.container, "bar", None) second = NamedConstant() second._realize(self.container, "bar", None) self.assertNotEqual(hash(first), hash(second)) class _ConstantsTestsMixin(object): """ Mixin defining test helpers common to multiple types of constants collections. """ def _notInstantiableTest(self, name, cls): """ Assert that an attempt to instantiate the constants class raises C{TypeError}. @param name: A C{str} giving the name of the constants collection. @param cls: The constants class to test. """ exc = self.assertRaises(TypeError, cls) self.assertEqual(name + " may not be instantiated.", str(exc)) def _initializedOnceTest(self, container, constantName): """ Assert that C{container._enumerants} does not change as a side-effect of one of its attributes being accessed. @param container: A L{_ConstantsContainer} subclass which will be tested. @param constantName: The name of one of the constants which is an an attribute of C{container}. """ first = container._enumerants # Accessing an attribute of the container should not have any # observable side-effect on the _enumerants attribute. getattr(container, constantName) second = container._enumerants self.assertIdentical(first, second) class NamesTests(TestCase, _ConstantsTestsMixin): """ Tests for L{constantly.Names}, a base class for containers of related constaints. """ def setUp(self): """ Create a fresh new L{Names} subclass for each unit test to use. Since L{Names} is stateful, re-using the same subclass across test methods makes exercising all of the implementation code paths difficult. """ class METHOD(Names): """ A container for some named constants to use in unit tests for L{Names}. """ GET = NamedConstant() PUT = NamedConstant() POST = NamedConstant() DELETE = NamedConstant() extra = object() self.METHOD = METHOD def test_notInstantiable(self): """ A subclass of L{Names} raises C{TypeError} if an attempt is made to instantiate it. """ self._notInstantiableTest("METHOD", self.METHOD) def test_symbolicAttributes(self): """ Each name associated with a L{NamedConstant} instance in the definition of a L{Names} subclass is available as an attribute on the resulting class. """ self.assertTrue(hasattr(self.METHOD, "GET")) self.assertTrue(hasattr(self.METHOD, "PUT")) self.assertTrue(hasattr(self.METHOD, "POST")) self.assertTrue(hasattr(self.METHOD, "DELETE")) def test_withoutOtherAttributes(self): """ As usual, names not defined in the class scope of a L{Names} subclass are not available as attributes on the resulting class. """ self.assertFalse(hasattr(self.METHOD, "foo")) def test_representation(self): """ The string representation of a constant on a L{Names} subclass includes the name of the L{Names} subclass and the name of the constant itself. """ self.assertEqual("", repr(self.METHOD.GET)) def test_lookupByName(self): """ Constants can be looked up by name using L{Names.lookupByName}. """ method = self.METHOD.lookupByName("GET") self.assertIdentical(self.METHOD.GET, method) def test_notLookupMissingByName(self): """ Names not defined with a L{NamedConstant} instance cannot be looked up using L{Names.lookupByName}. """ self.assertRaises(ValueError, self.METHOD.lookupByName, "lookupByName") self.assertRaises(ValueError, self.METHOD.lookupByName, "__init__") self.assertRaises(ValueError, self.METHOD.lookupByName, "foo") self.assertRaises(ValueError, self.METHOD.lookupByName, "extra") def test_name(self): """ The C{name} attribute of one of the named constants gives that constant's name. """ self.assertEqual("GET", self.METHOD.GET.name) def test_attributeIdentity(self): """ Repeated access of an attribute associated with a L{NamedConstant} value in a L{Names} subclass results in the same object. """ self.assertIdentical(self.METHOD.GET, self.METHOD.GET) def test_iterconstants(self): """ L{Names.iterconstants} returns an iterator over all of the constants defined in the class, in the order they were defined. """ constants = list(self.METHOD.iterconstants()) self.assertEqual( [self.METHOD.GET, self.METHOD.PUT, self.METHOD.POST, self.METHOD.DELETE], constants) def test_attributeIterconstantsIdentity(self): """ The constants returned from L{Names.iterconstants} are identical to the constants accessible using attributes. """ constants = list(self.METHOD.iterconstants()) self.assertIdentical(self.METHOD.GET, constants[0]) self.assertIdentical(self.METHOD.PUT, constants[1]) self.assertIdentical(self.METHOD.POST, constants[2]) self.assertIdentical(self.METHOD.DELETE, constants[3]) def test_iterconstantsIdentity(self): """ The constants returned from L{Names.iterconstants} are identical on each call to that method. """ constants = list(self.METHOD.iterconstants()) again = list(self.METHOD.iterconstants()) self.assertIdentical(again[0], constants[0]) self.assertIdentical(again[1], constants[1]) self.assertIdentical(again[2], constants[2]) self.assertIdentical(again[3], constants[3]) def test_initializedOnce(self): """ L{Names._enumerants} is initialized once and its value re-used on subsequent access. """ self._initializedOnceTest(self.METHOD, "GET") def test_asForeignClassAttribute(self): """ A constant defined on a L{Names} subclass may be set as an attribute of another class and then retrieved using that attribute. """ class Another(object): something = self.METHOD.GET self.assertIdentical(self.METHOD.GET, Another.something) def test_asForeignClassAttributeViaInstance(self): """ A constant defined on a L{Names} subclass may be set as an attribute of another class and then retrieved from an instance of that class using that attribute. """ class Another(object): something = self.METHOD.GET self.assertIdentical(self.METHOD.GET, Another().something) def test_notAsAlternateContainerAttribute(self): """ It is explicitly disallowed (via a L{ValueError}) to use a constant defined on a L{Names} subclass as the value of an attribute of another L{Names} subclass. """ def defineIt(): class AnotherNames(Names): something = self.METHOD.GET exc = self.assertRaises(ValueError, defineIt) self.assertEqual( "Cannot use as the value of an attribute on " "AnotherNames", str(exc)) class ValuesTests(TestCase, _ConstantsTestsMixin): """ Tests for L{constantly.Names}, a base class for containers of related constaints with arbitrary values. """ def setUp(self): """ Create a fresh new L{Values} subclass for each unit test to use. Since L{Values} is stateful, re-using the same subclass across test methods makes exercising all of the implementation code paths difficult. """ class STATUS(Values): OK = ValueConstant("200") NOT_FOUND = ValueConstant("404") self.STATUS = STATUS def test_notInstantiable(self): """ A subclass of L{Values} raises C{TypeError} if an attempt is made to instantiate it. """ self._notInstantiableTest("STATUS", self.STATUS) def test_symbolicAttributes(self): """ Each name associated with a L{ValueConstant} instance in the definition of a L{Values} subclass is available as an attribute on the resulting class. """ self.assertTrue(hasattr(self.STATUS, "OK")) self.assertTrue(hasattr(self.STATUS, "NOT_FOUND")) def test_withoutOtherAttributes(self): """ As usual, names not defined in the class scope of a L{Values} subclass are not available as attributes on the resulting class. """ self.assertFalse(hasattr(self.STATUS, "foo")) def test_representation(self): """ The string representation of a constant on a L{Values} subclass includes the name of the L{Values} subclass and the name of the constant itself. """ self.assertEqual("", repr(self.STATUS.OK)) def test_lookupByName(self): """ Constants can be looked up by name using L{Values.lookupByName}. """ method = self.STATUS.lookupByName("OK") self.assertIdentical(self.STATUS.OK, method) def test_notLookupMissingByName(self): """ Names not defined with a L{ValueConstant} instance cannot be looked up using L{Values.lookupByName}. """ self.assertRaises(ValueError, self.STATUS.lookupByName, "lookupByName") self.assertRaises(ValueError, self.STATUS.lookupByName, "__init__") self.assertRaises(ValueError, self.STATUS.lookupByName, "foo") def test_lookupByValue(self): """ Constants can be looked up by their associated value, defined by the argument passed to L{ValueConstant}, using L{Values.lookupByValue}. """ status = self.STATUS.lookupByValue("200") self.assertIdentical(self.STATUS.OK, status) def test_lookupDuplicateByValue(self): """ If more than one constant is associated with a particular value, L{Values.lookupByValue} returns whichever of them is defined first. """ class TRANSPORT_MESSAGE(Values): """ Message types supported by an SSH transport. """ KEX_DH_GEX_REQUEST_OLD = ValueConstant(30) KEXDH_INIT = ValueConstant(30) self.assertIdentical( TRANSPORT_MESSAGE.lookupByValue(30), TRANSPORT_MESSAGE.KEX_DH_GEX_REQUEST_OLD) def test_notLookupMissingByValue(self): """ L{Values.lookupByValue} raises L{ValueError} when called with a value with which no constant is associated. """ self.assertRaises(ValueError, self.STATUS.lookupByValue, "OK") self.assertRaises(ValueError, self.STATUS.lookupByValue, 200) self.assertRaises(ValueError, self.STATUS.lookupByValue, "200.1") def test_name(self): """ The C{name} attribute of one of the constants gives that constant's name. """ self.assertEqual("OK", self.STATUS.OK.name) def test_attributeIdentity(self): """ Repeated access of an attribute associated with a L{ValueConstant} value in a L{Values} subclass results in the same object. """ self.assertIdentical(self.STATUS.OK, self.STATUS.OK) def test_iterconstants(self): """ L{Values.iterconstants} returns an iterator over all of the constants defined in the class, in the order they were defined. """ constants = list(self.STATUS.iterconstants()) self.assertEqual( [self.STATUS.OK, self.STATUS.NOT_FOUND], constants) def test_attributeIterconstantsIdentity(self): """ The constants returned from L{Values.iterconstants} are identical to the constants accessible using attributes. """ constants = list(self.STATUS.iterconstants()) self.assertIdentical(self.STATUS.OK, constants[0]) self.assertIdentical(self.STATUS.NOT_FOUND, constants[1]) def test_iterconstantsIdentity(self): """ The constants returned from L{Values.iterconstants} are identical on each call to that method. """ constants = list(self.STATUS.iterconstants()) again = list(self.STATUS.iterconstants()) self.assertIdentical(again[0], constants[0]) self.assertIdentical(again[1], constants[1]) def test_initializedOnce(self): """ L{Values._enumerants} is initialized once and its value re-used on subsequent access. """ self._initializedOnceTest(self.STATUS, "OK") class _FlagsTestsMixin(object): """ Mixin defining setup code for any tests for L{Flags} subclasses. @ivar FXF: A L{Flags} subclass created for each test method. """ def setUp(self): """ Create a fresh new L{Flags} subclass for each unit test to use. Since L{Flags} is stateful, re-using the same subclass across test methods makes exercising all of the implementation code paths difficult. """ class FXF(Flags): # Implicitly assign three flag values based on definition order READ = FlagConstant() WRITE = FlagConstant() APPEND = FlagConstant() # Explicitly assign one flag value by passing it in EXCLUSIVE = FlagConstant(0x20) # Implicitly assign another flag value, following the previously # specified explicit value. TEXT = FlagConstant() self.FXF = FXF class FlagsTests(_FlagsTestsMixin, TestCase, _ConstantsTestsMixin): """ Tests for L{constantly.Flags}, a base class for containers of related, combinable flag or bitvector-like constants. """ def test_notInstantiable(self): """ A subclass of L{Flags} raises L{TypeError} if an attempt is made to instantiate it. """ self._notInstantiableTest("FXF", self.FXF) def test_symbolicAttributes(self): """ Each name associated with a L{FlagConstant} instance in the definition of a L{Flags} subclass is available as an attribute on the resulting class. """ self.assertTrue(hasattr(self.FXF, "READ")) self.assertTrue(hasattr(self.FXF, "WRITE")) self.assertTrue(hasattr(self.FXF, "APPEND")) self.assertTrue(hasattr(self.FXF, "EXCLUSIVE")) self.assertTrue(hasattr(self.FXF, "TEXT")) def test_withoutOtherAttributes(self): """ As usual, names not defined in the class scope of a L{Flags} subclass are not available as attributes on the resulting class. """ self.assertFalse(hasattr(self.FXF, "foo")) def test_representation(self): """ The string representation of a constant on a L{Flags} subclass includes the name of the L{Flags} subclass and the name of the constant itself. """ self.assertEqual("", repr(self.FXF.READ)) def test_lookupByName(self): """ Constants can be looked up by name using L{Flags.lookupByName}. """ flag = self.FXF.lookupByName("READ") self.assertIdentical(self.FXF.READ, flag) def test_notLookupMissingByName(self): """ Names not defined with a L{FlagConstant} instance cannot be looked up using L{Flags.lookupByName}. """ self.assertRaises(ValueError, self.FXF.lookupByName, "lookupByName") self.assertRaises(ValueError, self.FXF.lookupByName, "__init__") self.assertRaises(ValueError, self.FXF.lookupByName, "foo") def test_lookupByValue(self): """ Constants can be looked up by their associated value, defined implicitly by the position in which the constant appears in the class definition or explicitly by the argument passed to L{FlagConstant}. """ flag = self.FXF.lookupByValue(0x01) self.assertIdentical(flag, self.FXF.READ) flag = self.FXF.lookupByValue(0x02) self.assertIdentical(flag, self.FXF.WRITE) flag = self.FXF.lookupByValue(0x04) self.assertIdentical(flag, self.FXF.APPEND) flag = self.FXF.lookupByValue(0x20) self.assertIdentical(flag, self.FXF.EXCLUSIVE) flag = self.FXF.lookupByValue(0x40) self.assertIdentical(flag, self.FXF.TEXT) def test_lookupDuplicateByValue(self): """ If more than one constant is associated with a particular value, L{Flags.lookupByValue} returns whichever of them is defined first. """ class TIMEX(Flags): # (timex.mode) ADJ_OFFSET = FlagConstant(0x0001) # time offset # xntp 3.4 compatibility names MOD_OFFSET = FlagConstant(0x0001) self.assertIdentical(TIMEX.lookupByValue(0x0001), TIMEX.ADJ_OFFSET) def test_notLookupMissingByValue(self): """ L{Flags.lookupByValue} raises L{ValueError} when called with a value with which no constant is associated. """ self.assertRaises(ValueError, self.FXF.lookupByValue, 0x10) def test_name(self): """ The C{name} attribute of one of the constants gives that constant's name. """ self.assertEqual("READ", self.FXF.READ.name) def test_attributeIdentity(self): """ Repeated access of an attribute associated with a L{FlagConstant} value in a L{Flags} subclass results in the same object. """ self.assertIdentical(self.FXF.READ, self.FXF.READ) def test_iterconstants(self): """ L{Flags.iterconstants} returns an iterator over all of the constants defined in the class, in the order they were defined. """ constants = list(self.FXF.iterconstants()) self.assertEqual( [self.FXF.READ, self.FXF.WRITE, self.FXF.APPEND, self.FXF.EXCLUSIVE, self.FXF.TEXT], constants) def test_attributeIterconstantsIdentity(self): """ The constants returned from L{Flags.iterconstants} are identical to the constants accessible using attributes. """ constants = list(self.FXF.iterconstants()) self.assertIdentical(self.FXF.READ, constants[0]) self.assertIdentical(self.FXF.WRITE, constants[1]) self.assertIdentical(self.FXF.APPEND, constants[2]) self.assertIdentical(self.FXF.EXCLUSIVE, constants[3]) self.assertIdentical(self.FXF.TEXT, constants[4]) def test_iterconstantsIdentity(self): """ The constants returned from L{Flags.iterconstants} are identical on each call to that method. """ constants = list(self.FXF.iterconstants()) again = list(self.FXF.iterconstants()) self.assertIdentical(again[0], constants[0]) self.assertIdentical(again[1], constants[1]) self.assertIdentical(again[2], constants[2]) self.assertIdentical(again[3], constants[3]) self.assertIdentical(again[4], constants[4]) def test_initializedOnce(self): """ L{Flags._enumerants} is initialized once and its value re-used on subsequent access. """ self._initializedOnceTest(self.FXF, "READ") class FlagConstantSimpleOrTests(_FlagsTestsMixin, TestCase): """ Tests for the C{|} operator as defined for L{FlagConstant} instances, used to create new L{FlagConstant} instances representing both of two existing L{FlagConstant} instances from the same L{Flags} class. """ def test_value(self): """ The value of the L{FlagConstant} which results from C{|} has all of the bits set which were set in either of the values of the two original constants. """ flag = self.FXF.READ | self.FXF.WRITE self.assertEqual( self.FXF.READ.value | self.FXF.WRITE.value, flag.value ) def test_name(self): """ The name of the L{FlagConstant} instance which results from C{|} includes the names of both of the two original constants. """ flag = self.FXF.READ | self.FXF.WRITE self.assertEqual("{READ,WRITE}", flag.name) def test_representation(self): """ The string representation of a L{FlagConstant} instance which results from C{|} includes the names of both of the two original constants. """ flag = self.FXF.READ | self.FXF.WRITE self.assertEqual("", repr(flag)) def test_iterate(self): """ A L{FlagConstant} instance which results from C{|} can be iterated upon to yield the original constants. """ self.assertEqual( set(self.FXF.WRITE & self.FXF.READ), # No flags set(())) self.assertEqual( set(self.FXF.WRITE), set((self.FXF.WRITE,))) self.assertEqual( set(self.FXF.WRITE | self.FXF.EXCLUSIVE), set((self.FXF.WRITE, self.FXF.EXCLUSIVE))) def test_membership(self): """ A L{FlagConstant} instance which results from C{|} can be tested for membership. """ flags = self.FXF.WRITE | self.FXF.EXCLUSIVE self.assertIn(self.FXF.WRITE, flags) self.assertNotIn(self.FXF.READ, flags) def test_truthiness(self): """ Empty flags is false, non-empty flags is true. """ self.assertTrue(self.FXF.WRITE) self.assertTrue(self.FXF.WRITE | self.FXF.EXCLUSIVE) self.assertFalse(self.FXF.WRITE & self.FXF.EXCLUSIVE) class FlagConstantSimpleAndTests(_FlagsTestsMixin, TestCase): """ Tests for the C{&} operator as defined for L{FlagConstant} instances, used to create new L{FlagConstant} instances representing the common parts of two existing L{FlagConstant} instances from the same L{Flags} class. """ def test_value(self): """ The value of the L{FlagConstant} which results from C{&} has all of the bits set which were set in both of the values of the two original constants. """ readWrite = (self.FXF.READ | self.FXF.WRITE) writeAppend = (self.FXF.WRITE | self.FXF.APPEND) flag = readWrite & writeAppend self.assertEqual(self.FXF.WRITE.value, flag.value) def test_name(self): """ The name of the L{FlagConstant} instance which results from C{&} includes the names of only the flags which were set in both of the two original constants. """ readWrite = (self.FXF.READ | self.FXF.WRITE) writeAppend = (self.FXF.WRITE | self.FXF.APPEND) flag = readWrite & writeAppend self.assertEqual("WRITE", flag.name) def test_representation(self): """ The string representation of a L{FlagConstant} instance which results from C{&} includes the names of only the flags which were set in both both of the two original constants. """ readWrite = (self.FXF.READ | self.FXF.WRITE) writeAppend = (self.FXF.WRITE | self.FXF.APPEND) flag = readWrite & writeAppend self.assertEqual("", repr(flag)) class FlagConstantSimpleExclusiveOrTests(_FlagsTestsMixin, TestCase): """ Tests for the C{^} operator as defined for L{FlagConstant} instances, used to create new L{FlagConstant} instances representing the uncommon parts of two existing L{FlagConstant} instances from the same L{Flags} class. """ def test_value(self): """ The value of the L{FlagConstant} which results from C{^} has all of the bits set which were set in exactly one of the values of the two original constants. """ readWrite = (self.FXF.READ | self.FXF.WRITE) writeAppend = (self.FXF.WRITE | self.FXF.APPEND) flag = readWrite ^ writeAppend self.assertEqual( self.FXF.READ.value | self.FXF.APPEND.value, flag.value ) def test_name(self): """ The name of the L{FlagConstant} instance which results from C{^} includes the names of only the flags which were set in exactly one of the two original constants. """ readWrite = (self.FXF.READ | self.FXF.WRITE) writeAppend = (self.FXF.WRITE | self.FXF.APPEND) flag = readWrite ^ writeAppend self.assertEqual("{APPEND,READ}", flag.name) def test_representation(self): """ The string representation of a L{FlagConstant} instance which results from C{^} includes the names of only the flags which were set in exactly one of the two original constants. """ readWrite = (self.FXF.READ | self.FXF.WRITE) writeAppend = (self.FXF.WRITE | self.FXF.APPEND) flag = readWrite ^ writeAppend self.assertEqual("", repr(flag)) class FlagConstantNegationTests(_FlagsTestsMixin, TestCase): """ Tests for the C{~} operator as defined for L{FlagConstant} instances, used to create new L{FlagConstant} instances representing all the flags from a L{Flags} class not set in a particular L{FlagConstant} instance. """ def test_value(self): """ The value of the L{FlagConstant} which results from C{~} has all of the bits set which were not set in the original constant. """ flag = ~self.FXF.READ self.assertEqual( self.FXF.WRITE.value | self.FXF.APPEND.value | self.FXF.EXCLUSIVE.value | self.FXF.TEXT.value, flag.value) flag = ~self.FXF.WRITE self.assertEqual( self.FXF.READ.value | self.FXF.APPEND.value | self.FXF.EXCLUSIVE.value | self.FXF.TEXT.value, flag.value) def test_name(self): """ The name of the L{FlagConstant} instance which results from C{~} includes the names of all the flags which were not set in the original constant. """ flag = ~self.FXF.WRITE self.assertEqual("{APPEND,EXCLUSIVE,READ,TEXT}", flag.name) def test_representation(self): """ The string representation of a L{FlagConstant} instance which results from C{~} includes the names of all the flags which were not set in the original constant. """ flag = ~self.FXF.WRITE self.assertEqual("", repr(flag)) class OrderedConstantsTests(TestCase): """ Tests for the ordering of constants. All constants are ordered by the order in which they are defined in their container class. The ordering of constants that are not in the same container is not defined. """ def test_orderedNameConstants_lt(self): """ L{constantly.NamedConstant} preserves definition order in C{<} comparisons. """ self.assertTrue(NamedLetters.alpha < NamedLetters.beta) def test_orderedNameConstants_le(self): """ L{constantly.NamedConstant} preserves definition order in C{<=} comparisons. """ self.assertTrue(NamedLetters.alpha <= NamedLetters.alpha) self.assertTrue(NamedLetters.alpha <= NamedLetters.beta) def test_orderedNameConstants_gt(self): """ L{constantly.NamedConstant} preserves definition order in C{>} comparisons. """ self.assertTrue(NamedLetters.beta > NamedLetters.alpha) def test_orderedNameConstants_ge(self): """ L{constantly.NamedConstant} preserves definition order in C{>=} comparisons. """ self.assertTrue(NamedLetters.alpha >= NamedLetters.alpha) self.assertTrue(NamedLetters.beta >= NamedLetters.alpha) def test_orderedValueConstants_lt(self): """ L{constantly.ValueConstant} preserves definition order in C{<} comparisons. """ self.assertTrue(ValuedLetters.alpha < ValuedLetters.digamma) self.assertTrue(ValuedLetters.digamma < ValuedLetters.zeta) def test_orderedValueConstants_le(self): """ L{constantly.ValueConstant} preserves definition order in C{<=} comparisons. """ self.assertTrue(ValuedLetters.alpha <= ValuedLetters.alpha) self.assertTrue(ValuedLetters.alpha <= ValuedLetters.digamma) self.assertTrue(ValuedLetters.digamma <= ValuedLetters.zeta) def test_orderedValueConstants_gt(self): """ L{constantly.ValueConstant} preserves definition order in C{>} comparisons. """ self.assertTrue(ValuedLetters.digamma > ValuedLetters.alpha) self.assertTrue(ValuedLetters.zeta > ValuedLetters.digamma) def test_orderedValueConstants_ge(self): """ L{constantly.ValueConstant} preserves definition order in C{>=} comparisons. """ self.assertTrue(ValuedLetters.alpha >= ValuedLetters.alpha) self.assertTrue(ValuedLetters.digamma >= ValuedLetters.alpha) self.assertTrue(ValuedLetters.zeta >= ValuedLetters.digamma) def test_orderedFlagConstants_lt(self): """ L{constantly.FlagConstant} preserves definition order in C{<} comparisons. """ self.assertTrue(PizzaToppings.mozzarella < PizzaToppings.pesto) self.assertTrue(PizzaToppings.pesto < PizzaToppings.pepperoni) def test_orderedFlagConstants_le(self): """ L{constantly.FlagConstant} preserves definition order in C{<=} comparisons. """ self.assertTrue(PizzaToppings.mozzarella <= PizzaToppings.mozzarella) self.assertTrue(PizzaToppings.mozzarella <= PizzaToppings.pesto) self.assertTrue(PizzaToppings.pesto <= PizzaToppings.pepperoni) def test_orderedFlagConstants_gt(self): """ L{constantly.FlagConstant} preserves definition order in C{>} comparisons. """ self.assertTrue(PizzaToppings.pesto > PizzaToppings.mozzarella) self.assertTrue(PizzaToppings.pepperoni > PizzaToppings.pesto) def test_orderedFlagConstants_ge(self): """ L{constantly.FlagConstant} preserves definition order in C{>=} comparisons. """ self.assertTrue(PizzaToppings.mozzarella >= PizzaToppings.mozzarella) self.assertTrue(PizzaToppings.pesto >= PizzaToppings.mozzarella) self.assertTrue(PizzaToppings.pepperoni >= PizzaToppings.pesto) def test_orderedDifferentConstants_lt(self): """ L{constantly._constants._Constant.__lt__} returns C{NotImplemented} when comparing constants of different types. """ self.assertEquals( NotImplemented, NamedLetters.alpha.__lt__(ValuedLetters.alpha) ) def test_orderedDifferentConstants_le(self): """ L{constantly._constants._Constant.__le__} returns C{NotImplemented} when comparing constants of different types. """ self.assertEquals( NotImplemented, NamedLetters.alpha.__le__(ValuedLetters.alpha) ) def test_orderedDifferentConstants_gt(self): """ L{constantly._constants._Constant.__gt__} returns C{NotImplemented} when comparing constants of different types. """ self.assertEquals( NotImplemented, NamedLetters.alpha.__gt__(ValuedLetters.alpha) ) def test_orderedDifferentConstants_ge(self): """ L{constantly._constants._Constant.__ge__} returns C{NotImplemented} when comparing constants of different types. """ self.assertEquals( NotImplemented, NamedLetters.alpha.__ge__(ValuedLetters.alpha) ) def test_orderedDifferentContainers_lt(self): """ L{constantly._constants._Constant.__lt__} returns C{NotImplemented} when comparing constants belonging to different containers. """ self.assertEquals( NotImplemented, NamedLetters.alpha.__lt__(MoreNamedLetters.digamma) ) def test_orderedDifferentContainers_le(self): """ L{constantly._constants._Constant.__le__} returns C{NotImplemented} when comparing constants belonging to different containers. """ self.assertEquals( NotImplemented, NamedLetters.alpha.__le__(MoreNamedLetters.digamma) ) def test_orderedDifferentContainers_gt(self): """ L{constantly._constants._Constant.__gt__} returns C{NotImplemented} when comparing constants belonging to different containers. """ self.assertEquals( NotImplemented, NamedLetters.alpha.__gt__(MoreNamedLetters.digamma) ) def test_orderedDifferentContainers_ge(self): """ L{constantly._constants._Constant.__ge__} returns C{NotImplemented} when comparing constants belonging to different containers. """ self.assertEquals( NotImplemented, NamedLetters.alpha.__ge__(MoreNamedLetters.digamma) ) class NamedLetters(Names): """ Some letters, named. """ alpha = NamedConstant() beta = NamedConstant() class MoreNamedLetters(Names): """ Some more letters, named. """ digamma = NamedConstant() zeta = NamedConstant() class ValuedLetters(Values): """ Some more letters, with cooresponding unicode values. """ # Note u'\u0391' < u'\u03dc' > u'\u0396'. We are ensuring here that the # definition is order different from the order of the values, which lets us # test that we're not somehow ordering by value and happen the get the same # results. alpha = ValueConstant(u'\u0391') digamma = ValueConstant(u'\u03dc') zeta = ValueConstant(u'\u0396') class PizzaToppings(Flags): """ Some pizza toppings, with obviously meaningful bitwise values. """ # Note 1<<1 < 1<<4 > 1<<2, so we are ensuring here that the definition # order is different from the order of the values, which lets us test that # we're not somehow ordering by value and happen the get the same results. mozzarella = FlagConstant(1 << 1) pesto = FlagConstant(1 << 4) pepperoni = FlagConstant(1 << 2) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1698535065.6346095 constantly-23.10.4/constantly.egg-info/0000755000076500000240000000000014517313232017016 5ustar00glyphstaff././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1698535065.0 constantly-23.10.4/constantly.egg-info/PKG-INFO0000644000076500000240000000334314517313231020115 0ustar00glyphstaffMetadata-Version: 2.1 Name: constantly Version: 23.10.4 Summary: Symbolic constants in Python Maintainer: Twisted Matrix Labs Developers License: MIT Project-URL: Homepage, https://github.com/twisted/constantly Keywords: constants,enum,twisted Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: MIT License Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3 :: Only Classifier: Programming Language :: Python :: 3.8 Classifier: Programming Language :: Python :: 3.9 Classifier: Programming Language :: Python :: 3.10 Classifier: Programming Language :: Python :: 3.11 Classifier: Programming Language :: Python :: 3.12 Classifier: Programming Language :: Python :: Implementation :: CPython Classifier: Programming Language :: Python :: Implementation :: PyPy Classifier: Topic :: Software Development :: Libraries :: Python Modules Requires-Python: >=3.8 Description-Content-Type: text/x-rst License-File: LICENSE Constantly ========== A library that provides symbolic constant support. It includes collections and constants with text, numeric, and bit flag values. Originally ``twisted.python.constants`` from the `Twisted `_ project. Installing ---------- constantly is available in `PyPI `_, and can be installed via pip:: $ pip install constantly Documentation ------------------------- Documentation is available at ``_. Tests ----- To run tests:: $ tox This will run tests on Python 2.7, 3.3, 3.4, and PyPy, as well as doing coverage and pyflakes checks. ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1698535065.0 constantly-23.10.4/constantly.egg-info/SOURCES.txt0000644000076500000240000000051314517313231020700 0ustar00glyphstaffCREDITS LICENSE MANIFEST.in README.rst pyproject.toml setup.py constantly/__init__.py constantly/_constants.py constantly/_version.py constantly.egg-info/PKG-INFO constantly.egg-info/SOURCES.txt constantly.egg-info/dependency_links.txt constantly.egg-info/top_level.txt constantly/test/__init__.py constantly/test/test_constants.py././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1698535065.0 constantly-23.10.4/constantly.egg-info/dependency_links.txt0000644000076500000240000000000114517313231023063 0ustar00glyphstaff ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1698535065.0 constantly-23.10.4/constantly.egg-info/top_level.txt0000644000076500000240000000001314517313231021541 0ustar00glyphstaffconstantly ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1698532976.0 constantly-23.10.4/pyproject.toml0000644000076500000240000000264314517307160016052 0ustar00glyphstaff[build-system] requires = ["setuptools>=68.2", "versioneer[toml]==0.29"] build-backend = "setuptools.build_meta" [project] classifiers = [ "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3 :: Only", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", "Topic :: Software Development :: Libraries :: Python Modules", ] description = "Symbolic constants in Python" readme = "README.rst" keywords = ["constants", "enum", "twisted"] license = {text = "MIT"} name = "constantly" maintainers = [{name = "Twisted Matrix Labs Developers"}] urls = {Homepage = "https://github.com/twisted/constantly"} requires-python = ">= 3.8" dynamic = ["version"] [tool.setuptools] include-package-data = false [tool.setuptools.packages] find = {namespaces = false} [tool.versioneer] VCS = "git" style = "pep440" versionfile_source = "constantly/_version.py" versionfile_build = "constantly/_version.py" tag_prefix = "" parentdir_prefix = "constantly-" ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1698535065.6352842 constantly-23.10.4/setup.cfg0000644000076500000240000000004614517313232014747 0ustar00glyphstaff[egg_info] tag_build = tag_date = 0 ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1698532976.0 constantly-23.10.4/setup.py0000644000076500000240000000032114517307160014637 0ustar00glyphstaff# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. import versioneer from setuptools import setup setup( version=versioneer.get_version(), cmdclass=versioneer.get_cmdclass(), )