Ticket #5158: 5158.2.diff

File 5158.2.diff, 10.3 KB (added by lvh, 3 years ago)
  • twisted/python/dist.py

    diff --git c/twisted/python/dist.py w/twisted/python/dist.py
    index 0d358ee..9b0af2c 100644
    c w Don't use this outside of Twisted. 
    66Maintainer: Christopher Armstrong 
    77""" 
    88 
    9 import sys, os 
    109from distutils.command import build_scripts, install_data, build_ext, build_py 
    1110from distutils.errors import CompileError 
    1211from distutils import core 
    1312from distutils.core import Extension 
     13import fnmatch 
     14import os 
     15import platform 
     16import sys 
     17 
    1418 
    1519twisted_subprojects = ["conch", "lore", "mail", "names", 
    1620                       "news", "pair", "runner", "web", 
    1721                       "words"] 
    1822 
    1923 
     24 
    2025class ConditionalExtension(Extension): 
    2126    """ 
    2227    An extension module that will only be compiled if certain conditions are 
    def setup(**kw): 
    4651    """ 
    4752    return core.setup(**get_setup_args(**kw)) 
    4853 
     54 
    4955def get_setup_args(**kw): 
    5056    if 'twisted_subproject' in kw: 
    5157        if 'twisted' not in os.listdir('.'): 
    def get_setup_args(**kw): 
    100106        kw.setdefault('cmdclass', {})['build_ext'] = my_build_ext 
    101107    return kw 
    102108 
     109 
    103110def getVersion(proj, base="twisted"): 
    104111    """ 
    105112    Extract the version number for a given project. 
    EXCLUDE_NAMES = ["{arch}", "CVS", ".cvsignore", "_darcs", 
    125132                 "RCS", "SCCS", ".svn"] 
    126133EXCLUDE_PATTERNS = ["*.py[cdo]", "*.s[ol]", ".#*", "*~", "*.py"] 
    127134 
    128 import fnmatch 
    129135 
    130136def _filterNames(names): 
    131     """Given a list of file names, return those names that should be copied. 
     137    """ 
     138    Given a list of file names, return those names that should be copied. 
    132139    """ 
    133140    names = [n for n in names 
    134141             if n not in EXCLUDE_NAMES] 
    def _filterNames(names): 
    140147                 and (not n.endswith('.py'))] 
    141148    return names 
    142149 
     150 
    143151def relativeTo(base, relativee): 
    144152    """ 
    145153    Gets 'relativee' relative to 'basepath'. 
    def getDataFiles(dname, ignore=None, parent=None): 
    201209                            for filename in resultfiles])) 
    202210    return result 
    203211 
     212 
    204213def getPackages(dname, pkgname=None, results=None, ignore=None, parent=None): 
    205214    """ 
    206215    Get all packages which are under dname. This is necessary for 
    def getPackages(dname, pkgname=None, results=None, ignore=None, parent=None): 
    231240    return res 
    232241 
    233242 
    234  
    235243def getScripts(projname, basedir=''): 
    236244    """ 
    237245    Returns a list of scripts for a Twisted subproject; this works in 
    class build_ext_twisted(build_ext.build_ext): 
    360368        self.compiler.announce("checking for %s ..." % header_name, 0) 
    361369        return self._compile_helper("#include <%s>\n" % header_name) 
    362370 
     371 
     372 
     373def _checkCPython(sys=sys, platform=platform): 
     374    """ 
     375    Checks if this implementation is CPython. 
     376 
     377    On recent versions of Python, will use L{platform.python_implementation}. 
     378    On 2.5, it will try to extract the implementation from sys.subversion. On 
     379    older versions (currently the only supported older version is 2.4), checks 
     380    if C{__pypy__} is in L{sys.modules}, since PyPy is the implementation we 
     381    really care about. If it isn't, assumes CPython. 
     382 
     383    This takes C{sys} and C{platform} kwargs that by default use the real 
     384    modules. You shouldn't care about these -- they are for testing purposes 
     385    only. 
     386 
     387    @return: C{False} if the implementation is definitely not CPython, C{True} 
     388        otherwise. 
     389    """ 
     390    try: 
     391        return platform.python_implementation() == "CPython" 
     392    except AttributeError: 
     393        # For 2.5: 
     394        try: 
     395            implementation, _, _ = sys.subversion 
     396            return implementation == "CPython" 
     397        except AttributeError: 
     398            pass 
     399 
     400        # Are we on Pypy? 
     401        if "__pypy__" in sys.modules: 
     402            return False 
     403 
     404        # No? Well, then we're *probably* on CPython. 
     405        return True 
     406 
     407 
     408_isCPython = _checkCPython() 
     409 
     410 
     411def _hasEpoll(builder): 
     412    """ 
     413    Checks if the header for building epoll (C{sys/epoll.h}) is available. 
     414 
     415    @return: C{True} if the header is available, C{False} otherwise. 
     416    """ 
     417    return builder._check_header("sys/epoll.h") 
  • twisted/python/test/test_dist.py

    diff --git c/twisted/python/test/test_dist.py w/twisted/python/test/test_dist.py
    index a27ff94..39f4438 100644
    c w class GetScriptsTest(TestCase): 
    190190        os.mkdir(basedir) 
    191191        scripts = dist.getScripts('noscripts', basedir=basedir) 
    192192        self.assertEqual(scripts, []) 
     193 
     194 
     195 
     196class FakeModule(object): 
     197    """ 
     198    A fake module, suitable for dependency injection in testing. 
     199    """ 
     200    def __init__(self, attrs): 
     201        """ 
     202        Initializes a fake module. 
     203 
     204        @param attrs: The attrs that will be accessible on the module. 
     205        @type attrs: C{dict} of C{str} (Python names) to objects 
     206        """ 
     207        self._attrs = attrs 
     208 
     209    def __getattr__(self, name): 
     210        """ 
     211        Gets an attribute of this fake module from its attrs. 
     212 
     213        @raise AttributeError: When the requested attribute is missing. 
     214        """ 
     215        try: 
     216            return self._attrs[name] 
     217        except KeyError: 
     218            raise AttributeError() 
     219 
     220 
     221 
     222fakeCPythonPlatform = FakeModule({"python_implementation": lambda: "CPython"}) 
     223fakeOtherPlatform = FakeModule({"python_implementation": lambda: "lvhpy"}) 
     224emptyPlatform = FakeModule({}) 
     225 
     226 
     227 
     228class WithPlatformTest(TestCase): 
     229    """ 
     230    Tests if L{_checkCPython} works correctly with (fake) recent 
     231    C{platform} modules. 
     232    """ 
     233    def test_cpython(self): 
     234        """ 
     235        Tests that L{_checkCPython} returns C{True} when 
     236        C{platform.python_implementation} says we're running on CPython. 
     237        """ 
     238        self.assertTrue(dist._checkCPython(platform=fakeCPythonPlatform)) 
     239 
     240 
     241    def test_other(self): 
     242        """ 
     243        Tests that L{_checkCPython} returns C{True} when 
     244        C{platform.python_implementation} says we're not running on CPython. 
     245        """ 
     246        self.assertFalse(dist._checkCPython(platform=fakeOtherPlatform)) 
     247 
     248 
     249 
     250fakeCPythonSys = FakeModule({"subversion": ("CPython", None, None)}) 
     251fakeOtherSys = FakeModule({"subversion": ("lvhpy", None, None)}) 
     252 
     253 
     254def _checkCPythonWithEmptyPlatform(sys): 
     255    """ 
     256    A partially applied L{_checkCPython} that uses an empty C{platform} 
     257    module (otherwise the code this test case is supposed to test won't 
     258    even be called). 
     259    """ 
     260    return dist._checkCPython(platform=emptyPlatform, sys=sys) 
     261 
     262 
     263 
     264class WithSubversionTest(TestCase): 
     265    """ 
     266    Tests if L{_checkCPython} works correctly with (fake) recent (2.5+) 
     267    C{sys.subversion}. This is effectively only relevant for 2.5, since 2.6 
     268    and beyond have L{platform.python_implementation}, which is tried first. 
     269    """ 
     270    def test_cpython(self): 
     271        """ 
     272        Tests that L{_checkCPython} returns C{True} when 
     273        C{platform.python_implementation} is unavailable and C{sys.subversion} 
     274        says we're running on CPython. 
     275        """ 
     276        isCPython = _checkCPythonWithEmptyPlatform(fakeCPythonSys) 
     277        self.assertTrue(isCPython) 
     278 
     279 
     280    def test_other(self): 
     281        """ 
     282        Tests that L{_checkCPython} returns C{False} when 
     283        C{platform.python_implementation} is unavailable and C{sys.subversion} 
     284        says we're not running on CPython. 
     285        """ 
     286        isCPython = _checkCPythonWithEmptyPlatform(fakeOtherSys) 
     287        self.assertFalse(isCPython) 
     288 
     289 
     290 
     291oldCPythonSys = FakeModule({"modules": {}}) 
     292oldPypySys = FakeModule({"modules": {"__pypy__": None}}) 
     293 
     294 
     295class OldPythonsFallbackTest(TestCase): 
     296    """ 
     297    Tests if L{_checkCPython} correctly recognizes PyPy on 2.4, when neither 
     298    C{platform.python_implementation} or C{sys.subversion} is available. 
     299    """ 
     300    def test_cpython(self): 
     301        """ 
     302        Tests that L{_checkCPython} returns C{True} when both 
     303        C{platform.python_implementation} and C{sys.subversion} are 
     304        unavailable and there is no C{__pypy__} module in C{sys.modules}. 
     305        """ 
     306        isCPython = _checkCPythonWithEmptyPlatform(oldCPythonSys) 
     307        self.assertTrue(isCPython) 
     308 
     309 
     310    def test_pypy(self): 
     311        """ 
     312        Tests that L{_checkCPython} returns C{False} when both 
     313        C{platform.python_implementation} and C{sys.subversion} are 
     314        unavailable and there is a C{__pypy__} module in C{sys.modules}. 
     315        """ 
     316        isCPython = _checkCPythonWithEmptyPlatform(oldPypySys) 
     317        self.assertFalse(isCPython) 
  • twisted/topfiles/setup.py

    diff --git c/twisted/topfiles/setup.py w/twisted/topfiles/setup.py
    index a1e0ae7..807dde2 100644
    c w  
    66Distutils installer for Twisted. 
    77""" 
    88 
    9 import os, sys 
     9import os 
     10import sys 
    1011 
    1112if sys.version_info < (2,3): 
    1213    print >>sys.stderr, "You must use at least Python 2.3 for Twisted" 
    if os.path.exists('twisted'): 
    1718from twisted import copyright 
    1819from twisted.python.dist import setup, ConditionalExtension as Extension 
    1920from twisted.python.dist import getPackages, getDataFiles, getScripts 
    20 from twisted.python.dist import twisted_subprojects 
    21  
     21from twisted.python.dist import twisted_subprojects, _isCPython, _hasEpoll 
    2222 
    2323 
    2424extensions = [ 
    2525    Extension("twisted.test.raiser", 
    26               ["twisted/test/raiser.c"]), 
     26              ["twisted/test/raiser.c"], 
     27              condition=lambda _: _isCPython), 
    2728 
    2829    Extension("twisted.python._epoll", 
    2930              ["twisted/python/_epoll.c"], 
    30               condition=lambda builder: builder._check_header("sys/epoll.h")), 
     31              condition=lambda builder: _isCPython and _hasEpoll(builder)), 
    3132 
    3233    Extension("twisted.internet.iocpreactor.iocpsupport", 
    3334              ["twisted/internet/iocpreactor/iocpsupport/iocpsupport.c", 
    3435               "twisted/internet/iocpreactor/iocpsupport/winsock_pointers.c"], 
    3536              libraries=["ws2_32"], 
    36               condition=lambda builder: sys.platform == "win32"), 
     37              condition=lambda _: _isCPython and sys.platform == "win32"), 
    3738 
    3839    Extension("twisted.python._initgroups", 
    3940              ["twisted/python/_initgroups.c"]), 
    4041    Extension("twisted.internet._sigchld", 
    4142              ["twisted/internet/_sigchld.c"], 
    42               condition=lambda builder: sys.platform != "win32"), 
     43              condition=lambda _: sys.platform != "win32"), 
    4344] 
    4445 
    4546# Figure out which plugins to include: all plugins except subproject ones