@@ -214,7 +214,7 @@ def make_extension(name, files, *args, **kwargs):
214
214
Any additional arguments are passed to the
215
215
`distutils.core.Extension` constructor.
216
216
"""
217
- ext = Extension (name , files , * args , ** kwargs )
217
+ ext = DelayedExtension (name , files , * args , ** kwargs )
218
218
for dir in get_base_dirs ():
219
219
include_dir = os .path .join (dir , 'include' )
220
220
if os .path .exists (include_dir ):
@@ -390,6 +390,14 @@ def get_install_requires(self):
390
390
"""
391
391
return []
392
392
393
+ def get_setup_requires (self ):
394
+ """
395
+ Get a list of Python packages that we require at build time.
396
+ pip/easy_install will attempt to download and install this
397
+ package if it is not installed.
398
+ """
399
+ return []
400
+
393
401
def _check_for_pkg_config (self , package , include_file , min_version = None ,
394
402
version = None ):
395
403
"""
@@ -647,42 +655,101 @@ def get_install_requires(self):
647
655
return ['nose' ]
648
656
649
657
658
+ class DelayedExtension (Extension , object ):
659
+ """
660
+ A distutils Extension subclass where some of its members
661
+ may have delayed computation until reaching the build phase.
662
+
663
+ This is so we can, for example, get the Numpy include dirs
664
+ after pip has installed Numpy for us if it wasn't already
665
+ on the system.
666
+ """
667
+ def __init__ (self , * args , ** kwargs ):
668
+ super (DelayedExtension , self ).__init__ (* args , ** kwargs )
669
+ self ._finalized = False
670
+ self ._hooks = {}
671
+
672
+ def add_hook (self , member , func ):
673
+ """
674
+ Add a hook to dynamically compute a member.
675
+
676
+ Parameters
677
+ ----------
678
+ member : string
679
+ The name of the member
680
+
681
+ func : callable
682
+ The function to call to get dynamically-computed values
683
+ for the member.
684
+ """
685
+ self ._hooks [member ] = func
686
+
687
+ def finalize (self ):
688
+ self ._finalized = True
689
+
690
+ class DelayedMember (property ):
691
+ def __init__ (self , name ):
692
+ self ._name = name
693
+
694
+ def __get__ (self , obj , objtype = None ):
695
+ result = getattr (obj , '_' + self ._name , [])
696
+
697
+ if obj ._finalized :
698
+ if self ._name in obj ._hooks :
699
+ result = obj ._hooks [self ._name ]() + result
700
+
701
+ return result
702
+
703
+ def __set__ (self , obj , value ):
704
+ setattr (obj , '_' + self ._name , value )
705
+
706
+ include_dirs = DelayedMember ('include_dirs' )
707
+
708
+
650
709
class Numpy (SetupPackage ):
651
710
name = "numpy"
652
711
712
+ @staticmethod
713
+ def include_dirs_hook ():
714
+ import numpy
715
+
716
+ ext = Extension ('test' , [])
717
+ ext .include_dirs .append (numpy .get_include ())
718
+ if not has_include_file (
719
+ ext .include_dirs , os .path .join ("numpy" , "arrayobject.h" )):
720
+ warnings .warn (
721
+ "The C headers for numpy could not be found. "
722
+ "You may need to install the development package" )
723
+
724
+ return [numpy .get_include ()]
725
+
653
726
def check (self ):
654
727
min_version = extract_versions ()['__version__numpy__' ]
655
728
try :
656
729
import numpy
657
730
except ImportError :
658
- raise SystemExit (
659
- "Requires numpy %s or later to build. (Numpy not found)" %
660
- min_version )
731
+ return 'not found. pip may install it below.'
661
732
662
733
if not is_min_version (numpy .__version__ , min_version ):
663
734
raise SystemExit (
664
735
"Requires numpy %s or later to build. (Found %s)" %
665
736
(min_version , numpy .__version__ ))
666
737
667
- ext = make_extension ('test' , [])
668
- ext .include_dirs .append (numpy .get_include ())
669
- if not has_include_file (
670
- ext .include_dirs , os .path .join ("numpy" , "arrayobject.h" )):
671
- raise CheckFailed (
672
- "The C headers for numpy could not be found. You"
673
- "may need to install the development package." )
674
-
675
738
return 'version %s' % numpy .__version__
676
739
677
740
def add_flags (self , ext ):
678
- import numpy
679
-
680
741
# Ensure that PY_ARRAY_UNIQUE_SYMBOL is uniquely defined for
681
742
# each extension
682
743
array_api_name = 'MPL_' + ext .name .replace ('.' , '_' ) + '_ARRAY_API'
683
744
684
- ext .include_dirs .append (numpy .get_include ())
685
745
ext .define_macros .append (('PY_ARRAY_UNIQUE_SYMBOL' , array_api_name ))
746
+ ext .add_hook ('include_dirs' , self .include_dirs_hook )
747
+
748
+ def get_setup_requires (self ):
749
+ return ['numpy>=1.5' ]
750
+
751
+ def get_install_requires (self ):
752
+ return ['numpy>=1.5' ]
686
753
687
754
688
755
class CXX (SetupPackage ):
0 commit comments