Ticket #5158: 5158.2.diff

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

    diff --git c/twisted/python/dist.py w/twisted/python/dist.py
    index 0d358ee..9b0af2c 100644
    c w  
    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 
     
    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('.'): 
     
    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. 
     
    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] 
     
    140147                 and (not n.endswith('.py'))] 
    141148    return names 
    142149 
     150 
    143151def relativeTo(base, relativee): 
    144152    """ 
    145153    Gets 'relativee' relative to 'basepath'. 
     
    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 
     
    231240    return res 
    232241 
    233242 
    234  
    235243def getScripts(projname, basedir=''): 
    236244    """ 
    237245    Returns a list of scripts for a Twisted subproject; this works in 
     
    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  
    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" 
     
    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