Recently conda-forge updated their packaging so that sequential
Mumps is a separate package,
[mumps-seq](https://anaconda.org/conda-forge/mumps-seq),
which names the libraries with a suffix '_seq' (contrary to how
Debian does it).
In addition we no longer need to explicitly link against Scotch,
pord or gfortran as the conda-forge built mumps libraries already
do this.
All tests still pass without explicitly linking against mpiseq,
so it is left out.
... | ... |
@@ -381,18 +381,13 @@ def search_mumps(): |
381 | 381 |
libmumps-scotch-dev and the MUMPS binaries in the conda-forge channel.""" |
382 | 382 |
lib_sets = [ |
383 | 383 |
# Debian |
384 |
- ['zmumps_scotch', 'mumps_common_scotch', 'mpiseq_scotch'], |
|
384 |
+ ['zmumps_scotch', 'mumps_common_scotch', 'mpiseq_scotch', |
|
385 |
+ 'pord', 'gfortran'], |
|
385 | 386 |
# Conda (via conda-forge). |
386 |
- # TODO: remove dependency libs (scotch, metis...) when conda-forge |
|
387 |
- # packaged mumps/scotch are built as properly linked shared libs |
|
388 |
- # 'openblas' provides Lapack and BLAS symbols |
|
389 |
- ['zmumps', 'mumps_common', 'metis', 'esmumps', 'scotch', |
|
390 |
- 'scotcherr', 'mpiseq', 'openblas'], |
|
387 |
+ ['zmumps_seq', 'mumps_common_seq'], |
|
391 | 388 |
] |
392 |
- common_libs = ['pord', 'gfortran'] |
|
393 |
- |
|
394 | 389 |
for libs in lib_sets: |
395 |
- found_libs = search_libs(libs + common_libs) |
|
390 |
+ found_libs = search_libs(libs) |
|
396 | 391 |
if found_libs: |
397 | 392 |
return found_libs |
398 | 393 |
return [] |
... | ... |
@@ -585,7 +585,8 @@ def main(): |
585 | 585 |
'tinyarray >= 1.2'], |
586 | 586 |
extras_require={ |
587 | 587 |
# The oldest versions between: Debian stable, Ubuntu LTS |
588 |
- 'plotting': 'matplotlib >= 2.1.1', |
|
588 |
+ 'plotting': ['matplotlib >= 2.1.1', |
|
589 |
+ 'plotly >= 2.2.2'], |
|
589 | 590 |
'continuum': 'sympy >= 1.1.1', |
590 | 591 |
# qsymm is only packaged on PyPI |
591 | 592 |
'qsymm': 'qsymm >= 1.2.6', |
It has been > 6 months since the release of Ubuntu 18.04 LTS.
Joseph Weston authored on 09/09/2019 10:32:59... | ... |
@@ -517,7 +517,7 @@ def maybe_add_numpy_include(exts): |
517 | 517 |
|
518 | 518 |
|
519 | 519 |
def main(): |
520 |
- check_python_version((3, 5)) |
|
520 |
+ check_python_version((3, 6)) |
|
521 | 521 |
check_versions() |
522 | 522 |
|
523 | 523 |
exts = collections.OrderedDict([ |
... | ... |
@@ -581,12 +581,12 @@ def main(): |
581 | 581 |
'build_ext': build_ext, |
582 | 582 |
'test': test}, |
583 | 583 |
ext_modules=exts, |
584 |
- install_requires=['numpy >= 1.11.0', 'scipy >= 0.17.0', |
|
584 |
+ install_requires=['numpy >= 1.13.3', 'scipy >= 0.19.1', |
|
585 | 585 |
'tinyarray >= 1.2'], |
586 | 586 |
extras_require={ |
587 | 587 |
# The oldest versions between: Debian stable, Ubuntu LTS |
588 |
- 'plotting': 'matplotlib >= 1.5.1', |
|
589 |
- 'continuum': 'sympy >= 0.7.6', |
|
588 |
+ 'plotting': 'matplotlib >= 2.1.1', |
|
589 |
+ 'continuum': 'sympy >= 1.1.1', |
|
590 | 590 |
# qsymm is only packaged on PyPI |
591 | 591 |
'qsymm': 'qsymm >= 1.2.6', |
592 | 592 |
}, |
... | ... |
@@ -588,7 +588,7 @@ def main(): |
588 | 588 |
'plotting': 'matplotlib >= 1.5.1', |
589 | 589 |
'continuum': 'sympy >= 0.7.6', |
590 | 590 |
# qsymm is only packaged on PyPI |
591 |
- 'qsymm': 'qsymm >= 1.2.4', |
|
591 |
+ 'qsymm': 'qsymm >= 1.2.6', |
|
592 | 592 |
}, |
593 | 593 |
classifiers=[c.strip() for c in classifiers.split('\n')]) |
594 | 594 |
|
The test suite uses features from the 1.2 release of qsymm.
Joseph Weston authored on 19/10/2019 18:24:50... | ... |
@@ -588,7 +588,7 @@ def main(): |
588 | 588 |
'plotting': 'matplotlib >= 1.5.1', |
589 | 589 |
'continuum': 'sympy >= 0.7.6', |
590 | 590 |
# qsymm is only packaged on PyPI |
591 |
- 'qsymm': 'qsymm >= 1.1.2', |
|
591 |
+ 'qsymm': 'qsymm >= 1.2.4', |
|
592 | 592 |
}, |
593 | 593 |
classifiers=[c.strip() for c in classifiers.split('\n')]) |
594 | 594 |
|
This allows third party modules to subclass Kwant's cdef classes.
https://cython.readthedocs.io/en/latest/src/userguide/sharing_declarations.html#search-paths-for-definition-files
... | ... |
@@ -562,6 +562,7 @@ def main(): |
562 | 562 |
Operating System :: MacOS :: MacOS X |
563 | 563 |
Operating System :: Microsoft :: Windows""" |
564 | 564 |
|
565 |
+ packages = find_packages('.') |
|
565 | 566 |
setup(name='kwant', |
566 | 567 |
version=version, |
567 | 568 |
author='C. W. Groth (CEA), M. Wimmer, ' |
... | ... |
@@ -573,7 +574,8 @@ def main(): |
573 | 574 |
platforms=["Unix", "Linux", "Mac OS-X", "Windows"], |
574 | 575 |
url="http://kwant-project.org/", |
575 | 576 |
license="BSD", |
576 |
- packages=find_packages('.'), |
|
577 |
+ packages=packages, |
|
578 |
+ package_data={p: ['*.pxd', '*.h'] for p in packages}, |
|
577 | 579 |
cmdclass={'build': build, |
578 | 580 |
'sdist': sdist, |
579 | 581 |
'build_ext': build_ext, |
... | ... |
@@ -270,9 +270,8 @@ class sdist(sdist_orig): |
270 | 270 |
sub_commands = [('build', None)] + sdist_orig.sub_commands |
271 | 271 |
|
272 | 272 |
def run(self): |
273 |
- """ |
|
274 |
- Create MANIFEST.in from git if possible, otherwise check that MANIFEST.in |
|
275 |
- is present. |
|
273 |
+ """Create MANIFEST.in from git if possible, otherwise check that |
|
274 |
+ MANIFEST.in is present. |
|
276 | 275 |
|
277 | 276 |
Right now (2015) generating MANIFEST.in seems to be the only way to |
278 | 277 |
include files in the source distribution that setuptools does not think |
Also update CI to install qsymm on relevant platforms, and update
pytest config to skip kwant.qsymm tests when qsymm is not installed
... | ... |
@@ -1,6 +1,6 @@ |
1 | 1 |
#!/usr/bin/env python3 |
2 | 2 |
|
3 |
-# Copyright 2011-2017 Kwant authors. |
|
3 |
+# Copyright 2011-2018 Kwant authors. |
|
4 | 4 |
# |
5 | 5 |
# This file is part of Kwant. It is subject to the license terms in the file |
6 | 6 |
# LICENSE.rst found in the top-level directory of this distribution and at |
... | ... |
@@ -586,6 +586,8 @@ def main(): |
586 | 586 |
# The oldest versions between: Debian stable, Ubuntu LTS |
587 | 587 |
'plotting': 'matplotlib >= 1.5.1', |
588 | 588 |
'continuum': 'sympy >= 0.7.6', |
589 |
+ # qsymm is only packaged on PyPI |
|
590 |
+ 'qsymm': 'qsymm >= 1.1.2', |
|
589 | 591 |
}, |
590 | 592 |
classifiers=[c.strip() for c in classifiers.split('\n')]) |
591 | 593 |
|
Co-authored-by: Pablo Piskunow <pablo.perez.piskunow@gmail.com>
Co-authored-by: Daniel Varjas <dvarjas@gmail.com>
... | ... |
@@ -532,6 +532,8 @@ def main(): |
532 | 532 |
dict(sources=['kwant/graph/core.pyx'], |
533 | 533 |
depends=['kwant/graph/core.pxd', 'kwant/graph/defs.h', |
534 | 534 |
'kwant/graph/defs.pxd'])), |
535 |
+ ('kwant.graph.dijkstra', |
|
536 |
+ dict(sources=['kwant/graph/dijkstra.pyx'])), |
|
535 | 537 |
('kwant.linalg.lapack', |
536 | 538 |
dict(sources=['kwant/linalg/lapack.pyx'])), |
537 | 539 |
('kwant.linalg._mumps', |
Kwant no longer builds with Cython 0.22, and our oldest
supported operating systems ship with at least 0.24.3
as of now.
Closes #204
This can always be resurrected from Git if it is really needed,
but at the moment its just 3000 lines that aren't used.
... | ... |
@@ -533,20 +533,6 @@ def main(): |
533 | 533 |
dict(sources=['kwant/graph/core.pyx'], |
534 | 534 |
depends=['kwant/graph/core.pxd', 'kwant/graph/defs.h', |
535 | 535 |
'kwant/graph/defs.pxd'])), |
536 |
- ('kwant.graph.utils', |
|
537 |
- dict(sources=['kwant/graph/utils.pyx'], |
|
538 |
- depends=['kwant/graph/defs.h', 'kwant/graph/defs.pxd', |
|
539 |
- 'kwant/graph/core.pxd'])), |
|
540 |
- ('kwant.graph.slicer', |
|
541 |
- dict(sources=['kwant/graph/slicer.pyx', |
|
542 |
- 'kwant/graph/c_slicer/partitioner.cc', |
|
543 |
- 'kwant/graph/c_slicer/slicer.cc'], |
|
544 |
- depends=['kwant/graph/defs.h', 'kwant/graph/defs.pxd', |
|
545 |
- 'kwant/graph/core.pxd', 'kwant/graph/c_slicer.pxd', |
|
546 |
- 'kwant/graph/c_slicer/bucket_list.h', |
|
547 |
- 'kwant/graph/c_slicer/graphwrap.h', |
|
548 |
- 'kwant/graph/c_slicer/partitioner.h', |
|
549 |
- 'kwant/graph/c_slicer/slicer.h'])), |
|
550 | 536 |
('kwant.linalg.lapack', |
551 | 537 |
dict(sources=['kwant/linalg/lapack.pyx'])), |
552 | 538 |
('kwant.linalg._mumps', |
Closes #188.
Joseph Weston authored on 23/02/2018 12:23:21... | ... |
@@ -15,7 +15,7 @@ import sys |
15 | 15 |
import re |
16 | 16 |
import os |
17 | 17 |
import glob |
18 |
-import imp |
|
18 |
+import importlib |
|
19 | 19 |
import subprocess |
20 | 20 |
import configparser |
21 | 21 |
import collections |
... | ... |
@@ -123,10 +123,9 @@ def check_versions(): |
123 | 123 |
|
124 | 124 |
# Let Kwant itself determine its own version. We cannot simply import |
125 | 125 |
# kwant, as it is not built yet. |
126 |
- _dont_write_bytecode_saved = sys.dont_write_bytecode |
|
127 |
- sys.dont_write_bytecode = True |
|
128 |
- version_module = imp.load_source('version', 'kwant/version.py') |
|
129 |
- sys.dont_write_bytecode = _dont_write_bytecode_saved |
|
126 |
+ spec = importlib.util.spec_from_file_location('version', 'kwant/version.py') |
|
127 |
+ version_module = importlib.util.module_from_spec(spec) |
|
128 |
+ spec.loader.exec_module(version_module) |
|
130 | 129 |
|
131 | 130 |
version_module.ensure_python() |
132 | 131 |
version = version_module.version |
Previously, the numpy 'include_dirs' would be shadowed by
any 'include_dirs' provided in 'build.conf'. We want to avoid
burdening people with remembering to specify the numpy 'include_dirs'
every time, and if custom numpy headers is the desired behaviour, these
can still be specified in 'build.conf', and will take precedence.
... | ... |
@@ -505,6 +505,20 @@ def maybe_cythonize(exts): |
505 | 505 |
return result |
506 | 506 |
|
507 | 507 |
|
508 |
+def maybe_add_numpy_include(exts): |
|
509 |
+ # Add NumPy header path to include_dirs of all the extensions. |
|
510 |
+ try: |
|
511 |
+ import numpy |
|
512 |
+ except ImportError: |
|
513 |
+ print(banner(' Caution '), 'NumPy header directory cannot be determined' |
|
514 |
+ ' ("import numpy" failed).', banner(), sep='\n', file=sys.stderr) |
|
515 |
+ else: |
|
516 |
+ numpy_include = numpy.get_include() |
|
517 |
+ for ext in exts.values(): |
|
518 |
+ ext.setdefault('include_dirs', []).append(numpy_include) |
|
519 |
+ return exts |
|
520 |
+ |
|
521 |
+ |
|
508 | 522 |
def main(): |
509 | 523 |
check_python_version((3, 5)) |
510 | 524 |
check_versions() |
... | ... |
@@ -540,17 +554,6 @@ def main(): |
540 | 554 |
dict(sources=['kwant/linalg/_mumps.pyx'], |
541 | 555 |
depends=['kwant/linalg/cmumps.pxd']))]) |
542 | 556 |
|
543 |
- # Add NumPy header path to include_dirs of all the extensions. |
|
544 |
- try: |
|
545 |
- import numpy |
|
546 |
- except ImportError: |
|
547 |
- print(banner(' Caution '), 'NumPy header directory cannot be determined' |
|
548 |
- ' ("import numpy" failed).', banner(), sep='\n', file=sys.stderr) |
|
549 |
- else: |
|
550 |
- numpy_include = numpy.get_include() |
|
551 |
- for ext in exts.values(): |
|
552 |
- ext.setdefault('include_dirs', []).append(numpy_include) |
|
553 |
- |
|
554 | 557 |
aliases = [('mumps', 'kwant.linalg._mumps')] |
555 | 558 |
|
556 | 559 |
init_cython() |
... | ... |
@@ -559,6 +562,7 @@ def main(): |
559 | 562 |
build_summary = [] |
560 | 563 |
exts = configure_extensions(exts, aliases, build_summary) |
561 | 564 |
exts = configure_special_extensions(exts, build_summary) |
565 |
+ exts = maybe_add_numpy_include(exts) |
|
562 | 566 |
exts = maybe_cythonize(exts) |
563 | 567 |
|
564 | 568 |
classifiers = """\ |
This completes 9fdd41e8483043d4.
Christoph Groth authored on 26/10/2017 11:01:41... | ... |
@@ -250,8 +250,7 @@ def git_lsfiles(): |
250 | 250 |
|
251 | 251 |
# Make the command "sdist" depend on "build". This verifies that the |
252 | 252 |
# distribution in the current state actually builds. It also makes sure that |
253 |
-# the Cython-made C files and the tutorial will be included in the source |
|
254 |
-# distribution and that they will be up-to-date. |
|
253 |
+# the Cython-made C files will be up-to-date and included in the source. |
|
255 | 254 |
class sdist(sdist_orig): |
256 | 255 |
sub_commands = [('build', None)] + sdist_orig.sub_commands |
257 | 256 |
|
We use Cython's import mechanism to use the the same lapack used
by Scipy, so we no longer need to explicitly link against lapack
or blas.
... | ... |
@@ -388,8 +388,9 @@ def search_mumps(): |
388 | 388 |
# Conda (via conda-forge). |
389 | 389 |
# TODO: remove dependency libs (scotch, metis...) when conda-forge |
390 | 390 |
# packaged mumps/scotch are built as properly linked shared libs |
391 |
+ # 'openblas' provides Lapack and BLAS symbols |
|
391 | 392 |
['zmumps', 'mumps_common', 'metis', 'esmumps', 'scotch', |
392 |
- 'scotcherr', 'mpiseq'], |
|
393 |
+ 'scotcherr', 'mpiseq', 'openblas'], |
|
393 | 394 |
] |
394 | 395 |
common_libs = ['pord', 'gfortran'] |
395 | 396 |
|
... | ... |
@@ -400,34 +401,7 @@ def search_mumps(): |
400 | 401 |
return [] |
401 | 402 |
|
402 | 403 |
|
403 |
-def search_lapack(): |
|
404 |
- """Return the BLAS variant that is installed.""" |
|
405 |
- lib_sets = [ |
|
406 |
- # Debian |
|
407 |
- ['blas', 'lapack'], |
|
408 |
- # Conda (via conda-forge). Openblas contains lapack symbols |
|
409 |
- ['openblas', 'gfortran'], |
|
410 |
- ] |
|
411 |
- |
|
412 |
- for libs in lib_sets: |
|
413 |
- found_libs = search_libs(libs) |
|
414 |
- if found_libs: |
|
415 |
- return found_libs |
|
416 |
- |
|
417 |
- print('Error: BLAS/LAPACK are required but were not found.', |
|
418 |
- file=sys.stderr) |
|
419 |
- sys.exit(1) |
|
420 |
- |
|
421 |
- |
|
422 | 404 |
def configure_special_extensions(exts, build_summary): |
423 |
- #### Special config for LAPACK. |
|
424 |
- lapack = exts['kwant.linalg.lapack'] |
|
425 |
- if 'libraries' in lapack: |
|
426 |
- build_summary.append('User-configured LAPACK and BLAS') |
|
427 |
- else: |
|
428 |
- lapack['libraries'] = search_lapack() |
|
429 |
- build_summary.append('Default LAPACK and BLAS') |
|
430 |
- |
|
431 | 405 |
#### Special config for MUMPS. |
432 | 406 |
mumps = exts['kwant.linalg._mumps'] |
433 | 407 |
if 'libraries' in mumps: |
... | ... |
@@ -442,12 +416,6 @@ def configure_special_extensions(exts, build_summary): |
442 | 416 |
del exts['kwant.linalg._mumps'] |
443 | 417 |
build_summary.append('No MUMPS support') |
444 | 418 |
|
445 |
- if mumps: |
|
446 |
- # Copy config from LAPACK. |
|
447 |
- for key, value in lapack.items(): |
|
448 |
- if key not in ['sources', 'depends']: |
|
449 |
- mumps.setdefault(key, []).extend(value) |
|
450 |
- |
|
451 | 419 |
return exts |
452 | 420 |
|
453 | 421 |
|
... | ... |
@@ -567,8 +535,7 @@ def main(): |
567 | 535 |
'kwant/graph/c_slicer/partitioner.h', |
568 | 536 |
'kwant/graph/c_slicer/slicer.h'])), |
569 | 537 |
('kwant.linalg.lapack', |
570 |
- dict(sources=['kwant/linalg/lapack.pyx'], |
|
571 |
- depends=['kwant/linalg/f_lapack.pxd'])), |
|
538 |
+ dict(sources=['kwant/linalg/lapack.pyx'])), |
|
572 | 539 |
('kwant.linalg._mumps', |
573 | 540 |
dict(sources=['kwant/linalg/_mumps.pyx'], |
574 | 541 |
depends=['kwant/linalg/cmumps.pxd']))]) |
... | ... |
@@ -584,8 +551,7 @@ def main(): |
584 | 551 |
for ext in exts.values(): |
585 | 552 |
ext.setdefault('include_dirs', []).append(numpy_include) |
586 | 553 |
|
587 |
- aliases = [('lapack', 'kwant.linalg.lapack'), |
|
588 |
- ('mumps', 'kwant.linalg._mumps')] |
|
554 |
+ aliases = [('mumps', 'kwant.linalg._mumps')] |
|
589 | 555 |
|
590 | 556 |
init_cython() |
591 | 557 |
|
This reverts commit 1e6c086067360dfaab56d81013ab649275ab1756, reversing
changes made to 2c5da944a0b524b23949c438d22f30c7a254742b.
The changes to Kwant's Lapack wrappers depend on features from
Scipy 0.16, so it cannot be merged into stable branch, which
depends on Scipy 0.14.
... | ... |
@@ -372,9 +372,8 @@ def search_mumps(): |
372 | 372 |
# Conda (via conda-forge). |
373 | 373 |
# TODO: remove dependency libs (scotch, metis...) when conda-forge |
374 | 374 |
# packaged mumps/scotch are built as properly linked shared libs |
375 |
- # 'openblas' provides Lapack and BLAS symbols |
|
376 | 375 |
['zmumps', 'mumps_common', 'metis', 'esmumps', 'scotch', |
377 |
- 'scotcherr', 'mpiseq', 'openblas'], |
|
376 |
+ 'scotcherr', 'mpiseq'], |
|
378 | 377 |
] |
379 | 378 |
common_libs = ['pord', 'gfortran'] |
380 | 379 |
|
... | ... |
@@ -385,7 +384,34 @@ def search_mumps(): |
385 | 384 |
return [] |
386 | 385 |
|
387 | 386 |
|
387 |
+def search_lapack(): |
|
388 |
+ """Return the BLAS variant that is installed.""" |
|
389 |
+ lib_sets = [ |
|
390 |
+ # Debian |
|
391 |
+ ['blas', 'lapack'], |
|
392 |
+ # Conda (via conda-forge). Openblas contains lapack symbols |
|
393 |
+ ['openblas', 'gfortran'], |
|
394 |
+ ] |
|
395 |
+ |
|
396 |
+ for libs in lib_sets: |
|
397 |
+ found_libs = search_libs(libs) |
|
398 |
+ if found_libs: |
|
399 |
+ return found_libs |
|
400 |
+ |
|
401 |
+ print('Error: BLAS/LAPACK are required but were not found.', |
|
402 |
+ file=sys.stderr) |
|
403 |
+ sys.exit(1) |
|
404 |
+ |
|
405 |
+ |
|
388 | 406 |
def configure_special_extensions(exts, build_summary): |
407 |
+ #### Special config for LAPACK. |
|
408 |
+ lapack = exts['kwant.linalg.lapack'] |
|
409 |
+ if 'libraries' in lapack: |
|
410 |
+ build_summary.append('User-configured LAPACK and BLAS') |
|
411 |
+ else: |
|
412 |
+ lapack['libraries'] = search_lapack() |
|
413 |
+ build_summary.append('Default LAPACK and BLAS') |
|
414 |
+ |
|
389 | 415 |
#### Special config for MUMPS. |
390 | 416 |
mumps = exts['kwant.linalg._mumps'] |
391 | 417 |
if 'libraries' in mumps: |
... | ... |
@@ -400,6 +426,12 @@ def configure_special_extensions(exts, build_summary): |
400 | 426 |
del exts['kwant.linalg._mumps'] |
401 | 427 |
build_summary.append('No MUMPS support') |
402 | 428 |
|
429 |
+ if mumps: |
|
430 |
+ # Copy config from LAPACK. |
|
431 |
+ for key, value in lapack.items(): |
|
432 |
+ if key not in ['sources', 'depends']: |
|
433 |
+ mumps.setdefault(key, []).extend(value) |
|
434 |
+ |
|
403 | 435 |
return exts |
404 | 436 |
|
405 | 437 |
|
... | ... |
@@ -518,7 +550,8 @@ def main(): |
518 | 550 |
'kwant/graph/c_slicer/partitioner.h', |
519 | 551 |
'kwant/graph/c_slicer/slicer.h'])), |
520 | 552 |
('kwant.linalg.lapack', |
521 |
- dict(sources=['kwant/linalg/lapack.pyx'])), |
|
553 |
+ dict(sources=['kwant/linalg/lapack.pyx'], |
|
554 |
+ depends=['kwant/linalg/f_lapack.pxd'])), |
|
522 | 555 |
('kwant.linalg._mumps', |
523 | 556 |
dict(sources=['kwant/linalg/_mumps.pyx'], |
524 | 557 |
depends=['kwant/linalg/cmumps.pxd']))]) |
... | ... |
@@ -534,7 +567,8 @@ def main(): |
534 | 567 |
for ext in exts.values(): |
535 | 568 |
ext.setdefault('include_dirs', []).append(numpy_include) |
536 | 569 |
|
537 |
- aliases = [('mumps', 'kwant.linalg._mumps')] |
|
570 |
+ aliases = [('lapack', 'kwant.linalg.lapack'), |
|
571 |
+ ('mumps', 'kwant.linalg._mumps')] |
|
538 | 572 |
|
539 | 573 |
init_cython() |
540 | 574 |
|
We use Cython's import mechanism to use the the same lapack used
by Scipy, so we no longer need to explicitly link against lapack
or blas.
... | ... |
@@ -372,8 +372,9 @@ def search_mumps(): |
372 | 372 |
# Conda (via conda-forge). |
373 | 373 |
# TODO: remove dependency libs (scotch, metis...) when conda-forge |
374 | 374 |
# packaged mumps/scotch are built as properly linked shared libs |
375 |
+ # 'openblas' provides Lapack and BLAS symbols |
|
375 | 376 |
['zmumps', 'mumps_common', 'metis', 'esmumps', 'scotch', |
376 |
- 'scotcherr', 'mpiseq'], |
|
377 |
+ 'scotcherr', 'mpiseq', 'openblas'], |
|
377 | 378 |
] |
378 | 379 |
common_libs = ['pord', 'gfortran'] |
379 | 380 |
|
... | ... |
@@ -384,34 +385,7 @@ def search_mumps(): |
384 | 385 |
return [] |
385 | 386 |
|
386 | 387 |
|
387 |
-def search_lapack(): |
|
388 |
- """Return the BLAS variant that is installed.""" |
|
389 |
- lib_sets = [ |
|
390 |
- # Debian |
|
391 |
- ['blas', 'lapack'], |
|
392 |
- # Conda (via conda-forge). Openblas contains lapack symbols |
|
393 |
- ['openblas', 'gfortran'], |
|
394 |
- ] |
|
395 |
- |
|
396 |
- for libs in lib_sets: |
|
397 |
- found_libs = search_libs(libs) |
|
398 |
- if found_libs: |
|
399 |
- return found_libs |
|
400 |
- |
|
401 |
- print('Error: BLAS/LAPACK are required but were not found.', |
|
402 |
- file=sys.stderr) |
|
403 |
- sys.exit(1) |
|
404 |
- |
|
405 |
- |
|
406 | 388 |
def configure_special_extensions(exts, build_summary): |
407 |
- #### Special config for LAPACK. |
|
408 |
- lapack = exts['kwant.linalg.lapack'] |
|
409 |
- if 'libraries' in lapack: |
|
410 |
- build_summary.append('User-configured LAPACK and BLAS') |
|
411 |
- else: |
|
412 |
- lapack['libraries'] = search_lapack() |
|
413 |
- build_summary.append('Default LAPACK and BLAS') |
|
414 |
- |
|
415 | 389 |
#### Special config for MUMPS. |
416 | 390 |
mumps = exts['kwant.linalg._mumps'] |
417 | 391 |
if 'libraries' in mumps: |
... | ... |
@@ -426,12 +400,6 @@ def configure_special_extensions(exts, build_summary): |
426 | 400 |
del exts['kwant.linalg._mumps'] |
427 | 401 |
build_summary.append('No MUMPS support') |
428 | 402 |
|
429 |
- if mumps: |
|
430 |
- # Copy config from LAPACK. |
|
431 |
- for key, value in lapack.items(): |
|
432 |
- if key not in ['sources', 'depends']: |
|
433 |
- mumps.setdefault(key, []).extend(value) |
|
434 |
- |
|
435 | 403 |
return exts |
436 | 404 |
|
437 | 405 |
|
... | ... |
@@ -550,8 +518,7 @@ def main(): |
550 | 518 |
'kwant/graph/c_slicer/partitioner.h', |
551 | 519 |
'kwant/graph/c_slicer/slicer.h'])), |
552 | 520 |
('kwant.linalg.lapack', |
553 |
- dict(sources=['kwant/linalg/lapack.pyx'], |
|
554 |
- depends=['kwant/linalg/f_lapack.pxd'])), |
|
521 |
+ dict(sources=['kwant/linalg/lapack.pyx'])), |
|
555 | 522 |
('kwant.linalg._mumps', |
556 | 523 |
dict(sources=['kwant/linalg/_mumps.pyx'], |
557 | 524 |
depends=['kwant/linalg/cmumps.pxd']))]) |
... | ... |
@@ -567,8 +534,7 @@ def main(): |
567 | 534 |
for ext in exts.values(): |
568 | 535 |
ext.setdefault('include_dirs', []).append(numpy_include) |
569 | 536 |
|
570 |
- aliases = [('lapack', 'kwant.linalg.lapack'), |
|
571 |
- ('mumps', 'kwant.linalg._mumps')] |
|
537 |
+ aliases = [('mumps', 'kwant.linalg._mumps')] |
|
572 | 538 |
|
573 | 539 |
init_cython() |
574 | 540 |
|
I assume that most people encounter the tutorial example scripts by
reading the documentation, and not by viewing the tutorial subdirectory
of a checked-out Kwant source.
That's the motivation for moving all the manipulations of tutorial
scripts from setup.py to doc/Makefile. Previously, a successful 'make
html' would require a preceding execution of 'setup.py build_tut'. Now,
a simple 'make html' is enough.
While at it, I reorganized where the example scripts and their outputs
are stored. Everything is now in 'doc/source/code' with its three
subdirectories 'download' (to be shown to readers), 'include' (with
include markers), and 'figure' (figure generation & figures). This
organization is clearer and also makes the generation of figures
separate from the tutorial.
... | ... |
@@ -227,40 +227,7 @@ Build configuration was: |
227 | 227 |
""" |
228 | 228 |
|
229 | 229 |
|
230 |
-class build_tut(Command): |
|
231 |
- description = "build the tutorial scripts" |
|
232 |
- user_options = [] |
|
233 |
- |
|
234 |
- def initialize_options(self): |
|
235 |
- pass |
|
236 |
- |
|
237 |
- def finalize_options(self): |
|
238 |
- pass |
|
239 |
- |
|
240 |
- def run(self): |
|
241 |
- tut_dir = 'tutorial' |
|
242 |
- if not os.path.exists(tut_dir): |
|
243 |
- os.mkdir(tut_dir) |
|
244 |
- for in_fname in glob.glob('doc/source/tutorial/*.py'): |
|
245 |
- basename = os.path.basename(in_fname) |
|
246 |
- if basename == 'faq.py': |
|
247 |
- # The FAQ script is not meant as an example. |
|
248 |
- continue |
|
249 |
- out_fname = os.path.join(tut_dir, basename) |
|
250 |
- with open(in_fname, 'rb') as in_file: |
|
251 |
- with open(out_fname, 'wb') as out_file: |
|
252 |
- for line in in_file: |
|
253 |
- if not line.startswith(b'#HIDDEN'): |
|
254 |
- out_file.write(line) |
|
255 |
- |
|
256 |
- |
|
257 |
-# Our version of the "build" command also makes sure the tutorial is made. |
|
258 |
-# Even though the tutorial is not necessary for installation, and "build" is |
|
259 |
-# supposed to make everything needed to install, this is a robust way to ensure |
|
260 |
-# that the tutorial is present. |
|
261 | 230 |
class build(build_orig): |
262 |
- sub_commands = [('build_tut', None)] + build_orig.sub_commands |
|
263 |
- |
|
264 | 231 |
def run(self): |
265 | 232 |
super().run() |
266 | 233 |
write_version(os.path.join(self.build_lib, *STATIC_VERSION_PATH)) |
... | ... |
@@ -638,7 +605,6 @@ def main(): |
638 | 605 |
cmdclass={'build': build, |
639 | 606 |
'sdist': sdist, |
640 | 607 |
'build_ext': build_ext, |
641 |
- 'build_tut': build_tut, |
|
642 | 608 |
'test': test}, |
643 | 609 |
ext_modules=exts, |
644 | 610 |
install_requires=['numpy >= 1.8.1', 'scipy >= 0.14', |
lowercase FAQ.rst, FAQ.py, etc., give meaningful names to labels,
and stop building an user-visible tutorial/faq.py
... | ... |
@@ -242,7 +242,11 @@ class build_tut(Command): |
242 | 242 |
if not os.path.exists(tut_dir): |
243 | 243 |
os.mkdir(tut_dir) |
244 | 244 |
for in_fname in glob.glob('doc/source/tutorial/*.py'): |
245 |
- out_fname = os.path.join(tut_dir, os.path.basename(in_fname)) |
|
245 |
+ basename = os.path.basename(in_fname) |
|
246 |
+ if basename == 'faq.py': |
|
247 |
+ # The FAQ script is not meant as an example. |
|
248 |
+ continue |
|
249 |
+ out_fname = os.path.join(tut_dir, basename) |
|
246 | 250 |
with open(in_fname, 'rb') as in_file: |
247 | 251 |
with open(out_fname, 'wb') as out_file: |
248 | 252 |
for line in in_file: |
Add check for this in setup.py to avoid potentially confusing
tracebacks later.
... | ... |
@@ -124,6 +124,16 @@ def configure_extensions(exts, aliases=(), build_summary=None): |
124 | 124 |
return exts |
125 | 125 |
|
126 | 126 |
|
127 |
+def check_python_version(min_version): |
|
128 |
+ installed_version = sys.version_info[:3] |
|
129 |
+ if installed_version < min_version: |
|
130 |
+ print('Error: Python {} required, but {} is installed'.format( |
|
131 |
+ '.'.join(map(str, min_version)), |
|
132 |
+ '.'.join(map(str, installed_version))) |
|
133 |
+ ) |
|
134 |
+ sys.exit(1) |
|
135 |
+ |
|
136 |
+ |
|
127 | 137 |
def check_versions(): |
128 | 138 |
global version, version_is_from_git |
129 | 139 |
|
... | ... |
@@ -557,6 +567,7 @@ def maybe_cythonize(exts): |
557 | 567 |
|
558 | 568 |
|
559 | 569 |
def main(): |
570 |
+ check_python_version((3, 5)) |
|
560 | 571 |
check_versions() |
561 | 572 |
|
562 | 573 |
exts = collections.OrderedDict([ |
Remove fixes for unsupported versions of numpy, scipy and matplotlib.
Joseph Weston authored on 19/06/2017 12:00:53... | ... |
@@ -643,11 +643,11 @@ def main(): |
643 | 643 |
'build_tut': build_tut, |
644 | 644 |
'test': test}, |
645 | 645 |
ext_modules=exts, |
646 |
- install_requires=['numpy >= 1.8.1', 'scipy >= 0.14', |
|
646 |
+ install_requires=['numpy >= 1.11.0', 'scipy >= 0.17.0', |
|
647 | 647 |
'tinyarray >= 1.2'], |
648 | 648 |
extras_require={ |
649 |
- 'plotting': 'matplotlib >= 1.4.2', |
|
650 |
- # Ubuntu 16.04 is the oldest supported distro with python3-sympy |
|
649 |
+ # The oldest versions between: Debian stable, Ubuntu LTS |
|
650 |
+ 'plotting': 'matplotlib >= 1.5.1', |
|
651 | 651 |
'continuum': 'sympy >= 0.7.6', |
652 | 652 |
}, |
653 | 653 |
classifiers=[c.strip() for c in classifiers.split('\n')]) |
This is the only sane behaviour, otherwise we don't know if our
build is misconfigured because 'build.conf' was silently used instead.
Fixes #133.
... | ... |
@@ -45,10 +45,12 @@ def configure_extensions(exts, aliases=(), build_summary=None): |
45 | 45 |
|
46 | 46 |
#### Determine the name of the configuration file. |
47 | 47 |
config_file_option = '--configfile' |
48 |
+ config_file_option_present = False |
|
48 | 49 |
# Handle command line option |
49 | 50 |
for i, opt in enumerate(sys.argv): |
50 | 51 |
if not opt.startswith(config_file_option): |
51 | 52 |
continue |
53 |
+ config_file_option_present = True |
|
52 | 54 |
l, _, config_file = opt.partition('=') |
53 | 55 |
if l != config_file_option or not config_file: |
54 | 56 |
print('Error: Expecting {}=PATH'.format(config_file_option), |
... | ... |
@@ -66,6 +68,10 @@ def configure_extensions(exts, aliases=(), build_summary=None): |
66 | 68 |
configs.read_file(f) |
67 | 69 |
except IOError: |
68 | 70 |
config_file_present = False |
71 |
+ if config_file_option_present: |
|
72 |
+ print("Error: '{}' option was provided, but '{}' does not exist" |
|
73 |
+ .format(config_file_option, config_file)) |
|
74 |
+ sys.exit(1) |
|
69 | 75 |
else: |
70 | 76 |
config_file_present = True |
71 | 77 |
|
... | ... |
@@ -364,7 +364,7 @@ def write_version(fname): |
364 | 364 |
def long_description(): |
365 | 365 |
text = [] |
366 | 366 |
try: |
367 |
- with open('README.rst') as f: |
|
367 |
+ with open('README.rst', encoding='utf8') as f: |
|
368 | 368 |
for line in f: |
369 | 369 |
if line.startswith('See also in this directory:'): |
370 | 370 |
break |
... | ... |
@@ -243,10 +243,10 @@ class build_tut(Command): |
243 | 243 |
os.mkdir(tut_dir) |
244 | 244 |
for in_fname in glob.glob('doc/source/tutorial/*.py'): |
245 | 245 |
out_fname = os.path.join(tut_dir, os.path.basename(in_fname)) |
246 |
- with open(in_fname) as in_file: |
|
247 |
- with open(out_fname, 'w') as out_file: |
|
246 |
+ with open(in_fname, 'rb') as in_file: |
|
247 |
+ with open(out_fname, 'wb') as out_file: |
|
248 | 248 |
for line in in_file: |
249 |
- if not line.startswith('#HIDDEN'): |
|
249 |
+ if not line.startswith(b'#HIDDEN'): |
|
250 | 250 |
out_file.write(line) |
251 | 251 |
|
252 | 252 |
|
... | ... |
@@ -637,8 +637,8 @@ def main(): |
637 | 637 |
'build_tut': build_tut, |
638 | 638 |
'test': test}, |
639 | 639 |
ext_modules=exts, |
640 |
- install_requires=['numpy >= 1.8.1', 'scipy >= 0.14.0', |
|
641 |
- 'tinyarray >= 1.2.0'], |
|
640 |
+ install_requires=['numpy >= 1.8.1', 'scipy >= 0.14', |
|
641 |
+ 'tinyarray >= 1.2'], |
|
642 | 642 |
extras_require={ |
643 | 643 |
'plotting': 'matplotlib >= 1.4.2', |
644 | 644 |
# Ubuntu 16.04 is the oldest supported distro with python3-sympy |
Our baseline is Debian stable (Jessie) where possible. The only
dependency that cannot be satisfied is sympy; Debian stable does not
have a Python 3 package for this. We set the required sympy version to
that present in Ubuntu 16.04 LTS.
... | ... |
@@ -1,6 +1,6 @@ |
1 | 1 |
#!/usr/bin/env python3 |
2 | 2 |
|
3 |
-# Copyright 2011-2016 Kwant authors. |
|
3 |
+# Copyright 2011-2017 Kwant authors. |
|
4 | 4 |
# |
5 | 5 |
# This file is part of Kwant. It is subject to the license terms in the file |
6 | 6 |
# LICENSE.rst found in the top-level directory of this distribution and at |
... | ... |
@@ -637,9 +637,10 @@ def main(): |
637 | 637 |
'build_tut': build_tut, |
638 | 638 |
'test': test}, |
639 | 639 |
ext_modules=exts, |
640 |
- install_requires=['numpy >= 1.8.1', 'scipy >= 0.13.3', 'tinyarray >= 1.2.0'], |
|
640 |
+ install_requires=['numpy >= 1.8.1', 'scipy >= 0.14.0', |
|
641 |
+ 'tinyarray >= 1.2.0'], |
|
641 | 642 |
extras_require={ |
642 |
- 'plotting': 'matplotlib >= 1.3.1', |
|
643 |
+ 'plotting': 'matplotlib >= 1.4.2', |
|
643 | 644 |
# Ubuntu 16.04 is the oldest supported distro with python3-sympy |
644 | 645 |
'continuum': 'sympy >= 0.7.6', |
645 | 646 |
}, |
... | ... |
@@ -637,7 +637,7 @@ def main(): |
637 | 637 |
'build_tut': build_tut, |
638 | 638 |
'test': test}, |
639 | 639 |
ext_modules=exts, |
640 |
- install_requires=['numpy >= 1.8.1', 'scipy >= 0.13.3', 'tinyarray'], |
|
640 |
+ install_requires=['numpy >= 1.8.1', 'scipy >= 0.13.3', 'tinyarray >= 1.2.0'], |
|
641 | 641 |
extras_require={ |
642 | 642 |
'plotting': 'matplotlib >= 1.3.1', |
643 | 643 |
# Ubuntu 16.04 is the oldest supported distro with python3-sympy |
... | ... |
@@ -51,7 +51,7 @@ def configure_extensions(exts, aliases=(), build_summary=None): |
51 | 51 |
continue |
52 | 52 |
l, _, config_file = opt.partition('=') |
53 | 53 |
if l != config_file_option or not config_file: |
54 |
- print('error: Expecting {}=PATH'.format(config_file_option), |
|
54 |
+ print('Error: Expecting {}=PATH'.format(config_file_option), |
|
55 | 55 |
file=sys.stderr) |
56 | 56 |
sys.exit(1) |
57 | 57 |
sys.argv.pop(i) |
... | ... |
@@ -426,7 +426,10 @@ def search_lapack(): |
426 | 426 |
found_libs = search_libs(libs) |
427 | 427 |
if found_libs: |
428 | 428 |
return found_libs |
429 |
- return [] |
|
429 |
+ |
|
430 |
+ print('Error: BLAS/LAPACK are required but were not found.', |
|
431 |
+ file=sys.stderr) |
|
432 |
+ sys.exit(1) |
|
430 | 433 |
|
431 | 434 |
|
432 | 435 |
def configure_special_extensions(exts, build_summary): |
... | ... |
@@ -634,9 +634,9 @@ def main(): |
634 | 634 |
'build_tut': build_tut, |
635 | 635 |
'test': test}, |
636 | 636 |
ext_modules=exts, |
637 |
- install_requires=['numpy > 1.6.1', 'scipy >= 0.11.0', 'tinyarray'], |
|
637 |
+ install_requires=['numpy >= 1.8.1', 'scipy >= 0.13.3', 'tinyarray'], |
|
638 | 638 |
extras_require={ |
639 |
- 'plotting': 'matplotlib >= 1.2', |
|
639 |
+ 'plotting': 'matplotlib >= 1.3.1', |
|
640 | 640 |
# Ubuntu 16.04 is the oldest supported distro with python3-sympy |
641 | 641 |
'continuum': 'sympy >= 0.7.6', |
642 | 642 |
}, |
This allows to provide a helpful error message when someone tries to
import Kwant with Python 2.
Note that I moved the version code into a module of its own:
kwant.version. The rationale is to separate this code from unrelated
stuff in kwant._common that requires various external libs. The
kwant.version module should work on its own without any third-party
libraries.
... | ... |
@@ -12,19 +12,6 @@ from __future__ import print_function |
12 | 12 |
|
13 | 13 |
import sys |
14 | 14 |
|
15 |
- |
|
16 |
-def ensure_python(required_version): |
|
17 |
- v = sys.version_info |
|
18 |
- if v[:3] < required_version: |
|
19 |
- error = "This version of Kwant requires Python {} or above.".format( |
|
20 |
- ".".join(str(p) for p in required_version)) |
|
21 |
- if v[0] == 2: |
|
22 |
- error += "\nKwant 1.1 is the last version to support Python 2." |
|
23 |
- print(error, file=sys.stderr) |
|
24 |
- sys.exit(1) |
|
25 |
- |
|
26 |
-ensure_python((3, 4)) |
|
27 |
- |
|
28 | 15 |
import re |
29 | 16 |
import os |
30 | 17 |
import glob |
... | ... |
@@ -131,18 +118,19 @@ def configure_extensions(exts, aliases=(), build_summary=None): |
131 | 118 |
return exts |
132 | 119 |
|
133 | 120 |
|
134 |
-def get_version(): |
|
121 |
+def check_versions(): |
|
135 | 122 |
global version, version_is_from_git |
136 | 123 |
|
137 | 124 |
# Let Kwant itself determine its own version. We cannot simply import |
138 | 125 |
# kwant, as it is not built yet. |
139 | 126 |
_dont_write_bytecode_saved = sys.dont_write_bytecode |
140 | 127 |
sys.dont_write_bytecode = True |
141 |
- _common = imp.load_source('_common', 'kwant/_common.py') |
|
128 |
+ version_module = imp.load_source('version', 'kwant/version.py') |
|
142 | 129 |
sys.dont_write_bytecode = _dont_write_bytecode_saved |
143 | 130 |
|
144 |
- version = _common.version |
|
145 |
- version_is_from_git = _common.version_is_from_git |
|
131 |
+ version_module.ensure_python() |
|
132 |
+ version = version_module.version |
|
133 |
+ version_is_from_git = version_module.version_is_from_git |
|
146 | 134 |
|
147 | 135 |
|
148 | 136 |
def init_cython(): |
... | ... |
@@ -560,6 +548,8 @@ def maybe_cythonize(exts): |
560 | 548 |
|
561 | 549 |
|
562 | 550 |
def main(): |
551 |
+ check_versions() |
|
552 |
+ |
|
563 | 553 |
exts = collections.OrderedDict([ |
564 | 554 |
('kwant._system', |
565 | 555 |
dict(sources=['kwant/_system.pyx'], |
... | ... |
@@ -606,7 +596,6 @@ def main(): |
606 | 596 |
aliases = [('lapack', 'kwant.linalg.lapack'), |
607 | 597 |
('mumps', 'kwant.linalg._mumps')] |
608 | 598 |
|
609 |
- get_version() |
|
610 | 599 |
init_cython() |
611 | 600 |
|
612 | 601 |
global build_summary |
Previously the testing/importing 'continuum' would fail if sympy was not
installed. Now we do the following:
* add sympy as an optional dependency in 'extras_require'
* force pytest to ignore tests in packages that have uninstalled
dependencies by defining a hook in 'conftest.py'
* use the 'class as a module' hack when importing 'continuum'.
When sympy is not installed the continuum module will be replaced
with an instance of 'ExtensionUnavailable' that will raise a runtime
error on attribute access.
* no warning is raised if sympy is not installed (it is an
optional dependency).
... | ... |
@@ -646,7 +646,11 @@ def main(): |
646 | 646 |
'test': test}, |
647 | 647 |
ext_modules=exts, |
648 | 648 |
install_requires=['numpy > 1.6.1', 'scipy >= 0.11.0', 'tinyarray'], |
649 |
- extras_require={'plotting': 'matplotlib >= 1.2'}, |
|
649 |
+ extras_require={ |
|
650 |
+ 'plotting': 'matplotlib >= 1.2', |
|
651 |
+ # Ubuntu 16.04 is the oldest supported distro with python3-sympy |
|
652 |
+ 'continuum': 'sympy >= 0.7.6', |
|
653 |
+ }, |
|
650 | 654 |
classifiers=[c.strip() for c in classifiers.split('\n')]) |
651 | 655 |
|
652 | 656 |
if __name__ == '__main__': |
... | ... |
@@ -388,15 +388,7 @@ def long_description(): |
388 | 388 |
return '\n'.join(text) |
389 | 389 |
|
390 | 390 |
|
391 |
-def search_mumps(): |
|
392 |
- """Return the configuration for MUMPS if it is available in a known way. |
|
393 |
- |
|
394 |
- This is known to work with the MUMPS provided by the Debian package |
|
395 |
- libmumps-scotch-dev.""" |
|
396 |
- |
|
397 |
- libs = ['zmumps_scotch', 'mumps_common_scotch', 'pord', 'mpiseq_scotch', |
|
398 |
- 'gfortran'] |
|
399 |
- |
|
391 |
+def search_libs(libs): |
|
400 | 392 |
cmd = ['gcc'] |
401 | 393 |
cmd.extend(['-l' + lib for lib in libs]) |
402 | 394 |
cmd.extend(['-o/dev/null', '-xc', '-']) |
... | ... |
@@ -407,8 +399,46 @@ def search_mumps(): |
407 | 399 |
else: |
408 | 400 |
p.communicate(input=b'int main() {}\n') |
409 | 401 |
if p.wait() == 0: |
410 |
- return {'libraries': libs} |
|
411 |
- return {} |
|
402 |
+ return libs |
|
403 |
+ |
|
404 |
+ |
|
405 |
+def search_mumps(): |
|
406 |
+ """Return the configuration for MUMPS if it is available in a known way. |
|
407 |
+ |
|
408 |
+ This is known to work with the MUMPS provided by the Debian package |
|
409 |
+ libmumps-scotch-dev and the MUMPS binaries in the conda-forge channel.""" |
|
410 |
+ lib_sets = [ |
|
411 |
+ # Debian |
|
412 |
+ ['zmumps_scotch', 'mumps_common_scotch', 'mpiseq_scotch'], |
|
413 |
+ # Conda (via conda-forge). |
|
414 |
+ # TODO: remove dependency libs (scotch, metis...) when conda-forge |
|
415 |
+ # packaged mumps/scotch are built as properly linked shared libs |
|
416 |
+ ['zmumps', 'mumps_common', 'metis', 'esmumps', 'scotch', |
|
417 |
+ 'scotcherr', 'mpiseq'], |
|
418 |
+ ] |
|
419 |
+ common_libs = ['pord', 'gfortran'] |
|
420 |
+ |
|
421 |
+ for libs in lib_sets: |
|
422 |
+ found_libs = search_libs(libs + common_libs) |
|
423 |
+ if found_libs: |
|
424 |
+ return found_libs |
|
425 |
+ return [] |
|
426 |
+ |
|
427 |
+ |
|
428 |
+def search_lapack(): |
|
429 |
+ """Return the BLAS variant that is installed.""" |
|
430 |
+ lib_sets = [ |
|
431 |
+ # Debian |
|
432 |
+ ['blas', 'lapack'], |
|
433 |
+ # Conda (via conda-forge). Openblas contains lapack symbols |
|
434 |
+ ['openblas', 'gfortran'], |
|
435 |
+ ] |
|
436 |
+ |
|
437 |
+ for libs in lib_sets: |
|
438 |
+ found_libs = search_libs(libs) |
|
439 |
+ if found_libs: |
|
440 |
+ return found_libs |
|
441 |
+ return [] |
|
412 | 442 |
|
413 | 443 |
|
414 | 444 |
def configure_special_extensions(exts, build_summary): |
... | ... |
@@ -417,7 +447,7 @@ def configure_special_extensions(exts, build_summary): |
417 | 447 |
if 'libraries' in lapack: |
418 | 448 |
build_summary.append('User-configured LAPACK and BLAS') |
419 | 449 |
else: |
420 |
- lapack['libraries'] = ['lapack', 'blas'] |
|
450 |
+ lapack['libraries'] = search_lapack() |
|
421 | 451 |
build_summary.append('Default LAPACK and BLAS') |
422 | 452 |
|
423 | 453 |
#### Special config for MUMPS. |
... | ... |
@@ -425,10 +455,9 @@ def configure_special_extensions(exts, build_summary): |
425 | 455 |
if 'libraries' in mumps: |
426 | 456 |
build_summary.append('User-configured MUMPS') |
427 | 457 |
else: |
428 |
- kwargs = search_mumps() |
|
429 |
- if kwargs: |
|
430 |
- for key, value in kwargs.items(): |
|
431 |
- mumps.setdefault(key, []).extend(value) |
|
458 |
+ mumps_libs = search_mumps() |
|
459 |
+ if mumps_libs: |
|
460 |
+ mumps['libraries'] = mumps_libs |
|
432 | 461 |
build_summary.append('Auto-configured MUMPS') |
433 | 462 |
else: |
434 | 463 |
mumps = None |
This reverts commit e34b4b737ccd7fc762042b74fbc10ca7e1c42724.
Anton Akhmerov authored on 16/01/2017 14:15:58It has the same problems as setup_requires.
Christoph Groth authored on 20/12/2016 17:44:19... | ... |
@@ -616,7 +616,6 @@ def main(): |
616 | 616 |
'build_tut': build_tut, |
617 | 617 |
'test': test}, |
618 | 618 |
ext_modules=exts, |
619 |
- tests_require=['numpy > 1.6.1', 'pytest >= 2.6.3'], |
|
620 | 619 |
install_requires=['numpy > 1.6.1', 'scipy >= 0.11.0', 'tinyarray'], |
621 | 620 |
extras_require={'plotting': 'matplotlib >= 1.2'}, |
622 | 621 |
classifiers=[c.strip() for c in classifiers.split('\n')]) |
... | ... |
@@ -66,7 +66,7 @@ def configure_extensions(exts, aliases=(), build_summary=None): |
66 | 66 |
if l != config_file_option or not config_file: |
67 | 67 |
print('error: Expecting {}=PATH'.format(config_file_option), |
68 | 68 |
file=sys.stderr) |
69 |
- exit(1) |
|
69 |
+ sys.exit(1) |
|
70 | 70 |
sys.argv.pop(i) |
71 | 71 |
break |
72 | 72 |
else: |
... | ... |
@@ -88,7 +88,7 @@ def configure_extensions(exts, aliases=(), build_summary=None): |
88 | 88 |
if long in configs: |
89 | 89 |
print('Error: both {} and {} sections present in {}.'.format( |
90 | 90 |
short, long, config_file)) |
91 |
- exit(1) |
|
91 |
+ sys.exit(1) |
|
92 | 92 |
configs[long] = configs[short] |
93 | 93 |
del configs[short] |
94 | 94 |
|
... | ... |
@@ -126,7 +126,7 @@ def configure_extensions(exts, aliases=(), build_summary=None): |
126 | 126 |
if unknown_sections: |
127 | 127 |
print('Error: Unknown sections in file {}: {}'.format( |
128 | 128 |
config_file, ', '.join(unknown_sections))) |
129 |
- exit(1) |
|
129 |
+ sys.exit(1) |
|
130 | 130 |
|
131 | 131 |
return exts |
132 | 132 |
|
... | ... |
@@ -314,7 +314,7 @@ class sdist(sdist_orig): |
314 | 314 |
print("Error:", manifest_in_file, |
315 | 315 |
"file is missing and Git is not available" |
316 | 316 |
" to regenerate it.", file=sys.stderr) |
317 |
- exit(1) |
|
317 |
+ sys.exit(1) |
|
318 | 318 |
else: |
319 | 319 |
with open(manifest, 'w') as f: |
320 | 320 |
for name in names: |
... | ... |
@@ -356,7 +356,7 @@ class test(test_orig): |
356 | 356 |
except: |
357 | 357 |
print('The Python package "pytest" is required to run tests.', |
358 | 358 |
file=sys.stderr) |
359 |
- exit(1) |
|
359 |
+ sys.exit(1) |
|
360 | 360 |
errno = pytest.main(shlex.split(self.pytest_args)) |
361 | 361 |
sys.exit(errno) |
362 | 362 |
|
... | ... |
@@ -475,7 +475,7 @@ def maybe_cythonize(exts): |
475 | 475 |
ext = '.cpp' |
476 | 476 |
else: |
477 | 477 |
print('Unknown language: {}'.format(language), file=sys.stderr) |
478 |
- exit(1) |
|
478 |
+ sys.exit(1) |
|
479 | 479 |
|
480 | 480 |
pyx_files = [] |
481 | 481 |
cythonized_files = [] |
... | ... |
@@ -496,7 +496,7 @@ def maybe_cythonize(exts): |
496 | 496 |
msg = "Cython-generated file {} is missing." |
497 | 497 |
print(banner(" Error "), msg.format(f), "", |
498 | 498 |
cython_help, banner(), sep="\n", file=sys.stderr) |
499 |
- exit(1) |
|
499 |
+ sys.exit(1) |
|
500 | 500 |
|
501 | 501 |
for f in pyx_files + kwargs.get('depends', []): |
502 | 502 |
if f == config_file: |
... | ... |
@@ -525,7 +525,7 @@ def maybe_cythonize(exts): |
525 | 525 |
print(banner(" Error " if error else " Caution "), msg, "", |
526 | 526 |
cython_help, banner(), sep="\n", file=sys.stderr) |
527 | 527 |
if error: |
528 |
- exit(1) |
|
528 |
+ sys.exit(1) |
|
529 | 529 |
|
530 | 530 |
return result |
531 | 531 |
|
Packages that are mentionned there are installed in a way that bypasses
pip:
https://pip.pypa.io/en/stable/user_guide/?highlight=setup_requires#installation-bundles
... | ... |
@@ -33,10 +33,17 @@ from distutils.errors import DistutilsError, DistutilsModuleError, \ |
33 | 33 |
from distutils.command.build import build as build_orig |
34 | 34 |
from setuptools.command.sdist import sdist as sdist_orig |
35 | 35 |
from setuptools.command.build_ext import build_ext as build_ext_orig |
36 |
+from setuptools.command.test import test as test_orig |
|
37 |
+ |
|
38 |
+def banner(title=''): |
|
39 |
+ starred = title.center(79, '*') |
|
40 |
+ return '\n' + starred if title else starred |
|
36 | 41 |
|
37 | 42 |
try: |
38 | 43 |
import numpy |
39 | 44 |
except ImportError: |
45 |
+ print(banner(' Caution '), 'NumPy header directory cannot be determined' |
|
46 |
+ ' ("import numpy" failed).', banner(), sep='\n', file=sys.stderr) |
|
40 | 47 |
include_dirs = [] |
41 | 48 |
else: |
42 | 49 |
include_dirs = [numpy.get_include()] |
... | ... |
@@ -103,10 +110,6 @@ if use_cython: |
103 | 110 |
|
104 | 111 |
distr_root = os.path.dirname(os.path.abspath(__file__)) |
105 | 112 |
|
106 |
-def banner(title=''): |
|
107 |
- starred = title.center(79, '*') |
|
108 |
- return '\n' + starred if title else starred |
|
109 |
- |
|
110 | 113 |
error_msg = """{header} |
111 | 114 |
The compilation of Kwant has failed. Please examine the error message |
112 | 115 |
above and consult the installation instructions in README.rst. |
... | ... |
@@ -236,10 +239,23 @@ source distribution. The old {} was used.""".format(MANIFEST_IN_FILE), |
236 | 239 |
banner(), sep='\n', file=sys.stderr) |
237 | 240 |
|
238 | 241 |
def make_release_tree(self, base_dir, files): |
239 |
- sdist.make_release_tree(self, base_dir, files) |
|
242 |
+ sdist_orig.make_release_tree(self, base_dir, files) |
|
240 | 243 |
write_version(os.path.join(base_dir, *STATIC_VERSION_PATH)) |
241 | 244 |
|
242 | 245 |
|
246 |
+# The only purpose of this class is to provide a better error message when |
|
247 |
+# "nose" is not available. |
|
248 |
+class test(test_orig): |
|
249 |
+ def run(self): |
|
250 |
+ try: |
|
251 |
+ import nose |
|
252 |
+ except ImportError: |
|
253 |
+ print('The Python package "nose" is required to run tests.', |
|
254 |
+ file=sys.stderr) |
|
255 |
+ exit(1) |
|
256 |
+ test_orig.run(self) |
|
257 |
+ |
|
258 |
+ |
|
243 | 259 |
def write_version(fname): |
244 | 260 |
# This could be a hard link, so try to delete it first. Is there any way |
245 | 261 |
# to do this atomically together with opening? |
... | ... |
@@ -484,10 +500,10 @@ def main(): |
484 | 500 |
cmdclass={'build': build, |
485 | 501 |
'sdist': sdist, |
486 | 502 |
'build_ext': build_ext, |
487 |
- 'build_tut': build_tut}, |
|
503 |
+ 'build_tut': build_tut, |
|
504 |
+ 'test': test}, |
|
488 | 505 |
ext_modules=ext_modules(extensions()), |
489 | 506 |
include_dirs=include_dirs, |
490 |
- setup_requires=['numpy > 1.6.1', 'nose >= 1.0'], |
|
491 | 507 |
install_requires=['numpy > 1.6.1', 'scipy >= 0.9', 'tinyarray'], |
492 | 508 |
extras_require={'plotting': 'matplotlib >= 1.2'}, |
493 | 509 |
classifiers=[c.strip() for c in CLASSIFIERS.split('\n')]) |
These prefixes were visible, for example when invoking
"./setup.py --help build".
... | ... |
@@ -30,9 +30,9 @@ from setuptools import setup, find_packages, Extension, Command |
30 | 30 |
from sysconfig import get_platform |
31 | 31 |
from distutils.errors import DistutilsError, DistutilsModuleError, \ |
32 | 32 |
CCompilerError |
33 |
-from distutils.command.build import build |
|
34 |
-from setuptools.command.sdist import sdist |
|
35 |
-from setuptools.command.build_ext import build_ext |
|
33 |
+from distutils.command.build import build as build_orig |
|
34 |
+from setuptools.command.sdist import sdist as sdist_orig |
|
35 |
+from setuptools.command.build_ext import build_ext as build_ext_orig |
|
36 | 36 |
|
37 | 37 |
try: |
38 | 38 |
import numpy |
... | ... |
@@ -120,7 +120,7 @@ Build configuration was: |
120 | 120 |
error_msg = error_msg.format(header=banner(' Error '), sep=banner()) |
121 | 121 |
|
122 | 122 |
|
123 |
-class kwant_build_ext(build_ext): |
|
123 |
+class build_ext(build_ext_orig): |
|
124 | 124 |
def run(self): |
125 | 125 |
if not config_file_present: |
126 | 126 |
# Create an empty config file if none is present so that the |
... | ... |
@@ -131,7 +131,7 @@ class kwant_build_ext(build_ext): |
131 | 131 |
f.write('# Created by setup.py - feel free to modify.\n') |
132 | 132 |
|
133 | 133 |
try: |
134 |
- build_ext.run(self) |
|
134 |
+ build_ext_orig.run(self) |
|
135 | 135 |
except (DistutilsError, CCompilerError): |
136 | 136 |
print(error_msg.format(file=CONFIG_FILE, summary=build_summary), |
137 | 137 |
file=sys.stderr) |
... | ... |
@@ -141,7 +141,7 @@ class kwant_build_ext(build_ext): |
141 | 141 |
print(banner()) |
142 | 142 |
|
143 | 143 |
|
144 |
-class kwant_build_tut(Command): |
|
144 |
+class build_tut(Command): |
|
145 | 145 |
description = "build the tutorial scripts" |
146 | 146 |
user_options = [] |
147 | 147 |
|
... | ... |
@@ -167,11 +167,11 @@ class kwant_build_tut(Command): |
167 | 167 |
# Even though the tutorial is not necessary for installation, and "build" is |
168 | 168 |
# supposed to make everything needed to install, this is a robust way to ensure |
169 | 169 |
# that the tutorial is present. |
170 |
-class kwant_build(build): |
|
171 |
- sub_commands = [('build_tut', None)] + build.sub_commands |
|
170 |
+class build(build_orig): |
|
171 |
+ sub_commands = [('build_tut', None)] + build_orig.sub_commands |
|
172 | 172 |
|
173 | 173 |
def run(self): |
174 |
- build.run(self) |
|
174 |
+ build_orig.run(self) |
|
175 | 175 |
write_version(os.path.join(self.build_lib, *STATIC_VERSION_PATH)) |
176 | 176 |
|
177 | 177 |
|
... | ... |
@@ -194,8 +194,8 @@ def git_lsfiles(): |
194 | 194 |
# distribution in the current state actually builds. It also makes sure that |
195 | 195 |
# the Cython-made C files and the tutorial will be included in the source |
196 | 196 |
# distribution and that they will be up-to-date. |
197 |
-class kwant_sdist(sdist): |
|
198 |
- sub_commands = [('build', None)] + sdist.sub_commands |
|
197 |
+class sdist(sdist_orig): |
|
198 |
+ sub_commands = [('build', None)] + sdist_orig.sub_commands |
|
199 | 199 |
|
200 | 200 |
def run(self): |
201 | 201 |
""" |
... | ... |
@@ -227,7 +227,7 @@ class kwant_sdist(sdist): |
227 | 227 |
f.write(''.join([' ', a, sep, stem, dot, 'c'])) |
228 | 228 |
f.write('\n') |
229 | 229 |
|
230 |
- sdist.run(self) |
|
230 |
+ sdist_orig.run(self) |
|
231 | 231 |
|
232 | 232 |
if names is None: |
233 | 233 |
print(banner(' Caution '), |
... | ... |
@@ -481,10 +481,10 @@ def main(): |
481 | 481 |
license="BSD", |
482 | 482 |
packages=find_packages('.'), |
483 | 483 |
test_suite = 'nose.collector', |
484 |
- cmdclass={'build': kwant_build, |
|
485 |
- 'sdist': kwant_sdist, |
|
486 |
- 'build_ext': kwant_build_ext, |
|
487 |
- 'build_tut': kwant_build_tut}, |
|
484 |
+ cmdclass={'build': build, |
|
485 |
+ 'sdist': sdist, |
|
486 |
+ 'build_ext': build_ext, |
|
487 |
+ 'build_tut': build_tut}, |
|
488 | 488 |
ext_modules=ext_modules(extensions()), |
489 | 489 |
include_dirs=include_dirs, |
490 | 490 |
setup_requires=['numpy > 1.6.1', 'nose >= 1.0'], |
Before we used the include_dir argument to setup(), but this caused problems:
https://gitlab.kwant-project.org/kwant/kwant/issues/48
... | ... |
@@ -541,6 +541,17 @@ def main(): |
541 | 541 |
dict(sources=['kwant/linalg/_mumps.pyx'], |
542 | 542 |
depends=['kwant/linalg/cmumps.pxd']))]) |
543 | 543 |
|
544 |
+ # Add NumPy header path to include_dirs of all the extensions. |
|
545 |
+ try: |
|
546 |
+ import numpy |
|
547 |
+ except ImportError: |
|
548 |
+ print(banner(' Caution '), 'NumPy header directory cannot be determined' |
|
549 |
+ ' ("import numpy" failed).', banner(), sep='\n', file=sys.stderr) |
|
550 |
+ else: |
|
551 |
+ numpy_include = numpy.get_include() |
|
552 |
+ for ext in exts.values(): |
|
553 |
+ ext.setdefault('include_dirs', []).append(numpy_include) |
|
554 |
+ |
|
544 | 555 |
aliases = [('lapack', 'kwant.linalg.lapack'), |
545 | 556 |
('mumps', 'kwant.linalg._mumps')] |
546 | 557 |
|
... | ... |
@@ -553,13 +564,6 @@ def main(): |
553 | 564 |
exts = configure_special_extensions(exts, build_summary) |
554 | 565 |
exts = maybe_cythonize(exts) |
555 | 566 |
|
556 |
- try: |
|
557 |
- import numpy |
|
558 |
- except ImportError: |
|
559 |
- numpy_include_dirs = [] |
|
560 |
- else: |
|
561 |
- numpy_include_dirs = [numpy.get_include()] |
|
562 |
- |
|
563 | 567 |
classifiers = """\ |
564 | 568 |
Development Status :: 5 - Production/Stable |
565 | 569 |
Intended Audience :: Science/Research |
... | ... |
@@ -589,7 +593,6 @@ def main(): |
589 | 593 |
'build_ext': kwant_build_ext, |
590 | 594 |
'build_tut': kwant_build_tut}, |
591 | 595 |
ext_modules=exts, |
592 |
- include_dirs=numpy_include_dirs, |
|
593 | 596 |
setup_requires=['pytest-runner >= 2.7'], |
594 | 597 |
tests_require=['numpy > 1.6.1', 'pytest >= 2.6.3'], |
595 | 598 |
install_requires=['numpy > 1.6.1', 'scipy >= 0.11.0', 'tinyarray'], |
Commit a8b0463e15fa04ef0aa05d98d283a0eecbf08b2c turned out to be a bad
idea: unlike on Debian, on many platforms the numpy headers are not
available in the default include path.
... | ... |
@@ -553,6 +553,13 @@ def main(): |
553 | 553 |
exts = configure_special_extensions(exts, build_summary) |
554 | 554 |
exts = maybe_cythonize(exts) |
555 | 555 |
|
556 |
+ try: |
|
557 |
+ import numpy |
|
558 |
+ except ImportError: |
|
559 |
+ numpy_include_dirs = [] |
|
560 |
+ else: |
|
561 |
+ numpy_include_dirs = [numpy.get_include()] |
|
562 |
+ |
|
556 | 563 |
classifiers = """\ |
557 | 564 |
Development Status :: 5 - Production/Stable |
558 | 565 |
Intended Audience :: Science/Research |
... | ... |
@@ -582,6 +589,7 @@ def main(): |
582 | 589 |
'build_ext': kwant_build_ext, |
583 | 590 |
'build_tut': kwant_build_tut}, |
584 | 591 |
ext_modules=exts, |
592 |
+ include_dirs=numpy_include_dirs, |
|
585 | 593 |
setup_requires=['pytest-runner >= 2.7'], |
586 | 594 |
tests_require=['numpy > 1.6.1', 'pytest >= 2.6.3'], |
587 | 595 |
install_requires=['numpy > 1.6.1', 'scipy >= 0.11.0', 'tinyarray'], |
1. Now can be compiled without MUMPS
(previously exception was thrown)
2. Gives sensible error message for Git install,
but without installed Cython.
... | ... |
@@ -12,6 +12,7 @@ from __future__ import print_function |
12 | 12 |
|
13 | 13 |
import sys |
14 | 14 |
|
15 |
+ |
|
15 | 16 |
def ensure_python(required_version): |
16 | 17 |
v = sys.version_info |
17 | 18 |
if v[:3] < required_version: |
... | ... |
@@ -32,9 +33,7 @@ import subprocess |
32 | 33 |
import configparser |
33 | 34 |
import collections |
34 | 35 |
from setuptools import setup, find_packages, Extension, Command |
35 |
-from sysconfig import get_platform |
|
36 |
-from distutils.errors import DistutilsError, DistutilsModuleError, \ |
|
37 |
- CCompilerError |
|
36 |
+from distutils.errors import DistutilsError, CCompilerError |
|
38 | 37 |
from distutils.command.build import build |
39 | 38 |
from setuptools.command.sdist import sdist |
40 | 39 |
from setuptools.command.build_ext import build_ext |
... | ... |
@@ -163,6 +162,7 @@ def init_cython(): |
163 | 162 |
global cythonize, cython_help |
164 | 163 |
|
165 | 164 |
cython_option = '--cython' |
165 |
+ required_cython_version = (0, 22) |
|
166 | 166 |
try: |
167 | 167 |
sys.argv.remove(cython_option) |
168 | 168 |
cythonize = True |
... | ... |
@@ -186,15 +186,14 @@ def init_cython(): |
186 | 186 |
cython_version[-1] -= 1 |
187 | 187 |
cython_version = tuple(cython_version) |
188 | 188 |
|
189 |
- required_cython_version = (0, 22) |
|
190 | 189 |
if cython_version < required_cython_version: |
191 | 190 |
cythonize = None |
192 | 191 |
|
193 |
- if cythonize is None: |
|
194 |
- msg = ("Install Cython >= {0} or use" |
|
195 |
- " a source distribution (tarball) of Kwant.") |
|
196 |
- ver = '.'.join(str(e) for e in required_cython_version) |
|
197 |
- cython_help = msg.format(ver) |
|
192 |
+ if cythonize is None: |
|
193 |
+ msg = ("Install Cython >= {0} or use" |
|
194 |
+ " a source distribution (tarball) of Kwant.") |
|
195 |
+ ver = '.'.join(str(e) for e in required_cython_version) |
|
196 |
+ cython_help = msg.format(ver) |
|
198 | 197 |
else: |
199 | 198 |
msg = "Run setup.py with the {} option to enable Cython." |
200 | 199 |
cython_help = msg.format(cython_option) |
... | ... |
@@ -411,7 +410,7 @@ def configure_special_extensions(exts, build_summary): |
411 | 410 |
build_summary.append('Auto-configured MUMPS') |
412 | 411 |
else: |
413 | 412 |
mumps = None |
414 |
- del exts['mumps'] |
|
413 |
+ del exts['kwant.linalg._mumps'] |
|
415 | 414 |
build_summary.append('No MUMPS support') |
416 | 415 |
|
417 | 416 |
if mumps: |
... | ... |
@@ -585,7 +585,7 @@ def main(): |
585 | 585 |
ext_modules=exts, |
586 | 586 |
setup_requires=['pytest-runner >= 2.7'], |
587 | 587 |
tests_require=['numpy > 1.6.1', 'pytest >= 2.6.3'], |
588 |
- install_requires=['numpy > 1.6.1', 'scipy >= 0.9', 'tinyarray'], |
|
588 |
+ install_requires=['numpy > 1.6.1', 'scipy >= 0.11.0', 'tinyarray'], |
|
589 | 589 |
extras_require={'plotting': 'matplotlib >= 1.2'}, |
590 | 590 |
classifiers=[c.strip() for c in classifiers.split('\n')]) |
591 | 591 |
|
... | ... |
@@ -40,7 +40,6 @@ from setuptools.command.sdist import sdist |
40 | 40 |
from setuptools.command.build_ext import build_ext |
41 | 41 |
|
42 | 42 |
|
43 |
-CONFIG_FILE = 'build.conf' |
|
44 | 43 |
STATIC_VERSION_PATH = ('kwant', '_kwant_version.py') |
45 | 44 |
|
46 | 45 |
distr_root = os.path.dirname(os.path.abspath(__file__)) |
... | ... |
@@ -51,14 +50,32 @@ def configure_extensions(exts, aliases=(), build_summary=None): |
51 | 50 |
|
52 | 51 |
`exts` must be a dict of (name, kwargs) tuples that can be used like this: |
53 | 52 |
`Extension(name, **kwargs). This function modifies the kwargs according to |
54 |
- the configuration file `CONFIG_FILE`. |
|
53 |
+ the configuration file. |
|
54 |
+ |
|
55 |
+ This function modifies `sys.argv`. |
|
55 | 56 |
""" |
56 |
- global config_file_present |
|
57 |
+ global config_file, config_file_present |
|
58 |
+ |
|
59 |
+ #### Determine the name of the configuration file. |
|
60 |
+ config_file_option = '--configfile' |
|
61 |
+ # Handle command line option |
|
62 |
+ for i, opt in enumerate(sys.argv): |
|
63 |
+ if not opt.startswith(config_file_option): |
|
64 |
+ continue |
|
65 |
+ l, _, config_file = opt.partition('=') |
|
66 |
+ if l != config_file_option or not config_file: |
|
67 |
+ print('error: Expecting {}=PATH'.format(config_file_option), |
|
68 |
+ file=sys.stderr) |
|
69 |
+ exit(1) |
|
70 |
+ sys.argv.pop(i) |
|
71 |
+ break |
|
72 |
+ else: |
|
73 |
+ config_file = 'build.conf' |
|
57 | 74 |
|
58 | 75 |
#### Read build configuration file. |
59 | 76 |
configs = configparser.ConfigParser() |
60 | 77 |
try: |
61 |
- with open(CONFIG_FILE) as f: |
|
78 |
+ with open(config_file) as f: |
|
62 | 79 |
configs.read_file(f) |
63 | 80 |
except IOError: |
64 | 81 |
config_file_present = False |
... | ... |
@@ -70,7 +87,7 @@ def configure_extensions(exts, aliases=(), build_summary=None): |
70 | 87 |
if short in configs: |
71 | 88 |
if long in configs: |
72 | 89 |
print('Error: both {} and {} sections present in {}.'.format( |
73 |
- short, long, CONFIG_FILE)) |
|
90 |
+ short, long, config_file)) |
|
74 | 91 |
exit(1) |
75 | 92 |
configs[long] = configs[short] |
76 | 93 |
del configs[short] |
... | ... |
@@ -98,17 +115,17 @@ def configure_extensions(exts, aliases=(), build_summary=None): |
98 | 115 |
if key in kwargs: |
99 | 116 |
msg = 'Caution: user config in file {} shadows {}.{}.' |
100 | 117 |
if build_summary is not None: |
101 |
- build_summary.append(msg.format(CONFIG_FILE, name, key)) |
|
118 |
+ build_summary.append(msg.format(config_file, name, key)) |
|
102 | 119 |
kwargs[key] = value |
103 | 120 |
|
104 |
- kwargs.setdefault('depends', []).append(CONFIG_FILE) |
|
121 |
+ kwargs.setdefault('depends', []).append(config_file) |
|
105 | 122 |
if config is not defaultconfig: |
106 | 123 |
del configs[name] |
107 | 124 |
|
108 | 125 |
unknown_sections = configs.sections() |
109 | 126 |
if unknown_sections: |
110 | 127 |
print('Error: Unknown sections in file {}: {}'.format( |
111 |
- CONFIG_FILE, ', '.join(unknown_sections))) |
|
128 |
+ config_file, ', '.join(unknown_sections))) |
|
112 | 129 |
exit(1) |
113 | 130 |
|
114 | 131 |
return exts |
... | ... |
@@ -195,15 +212,16 @@ class kwant_build_ext(build_ext): |
195 | 212 |
# extensions will not be rebuilt each time. Only depending on the |
196 | 213 |
# config file if it is present would make it impossible to detect a |
197 | 214 |
# necessary rebuild due to a deleted config file. |
198 |
- with open(CONFIG_FILE, 'w') as f: |
|
199 |
- f.write('# Created by setup.py - feel free to modify.\n') |
|
215 |
+ with open(config_file, 'w') as f: |
|
216 |
+ f.write('# Build configuration created by setup.py ' |
|
217 |
+ '- feel free to modify.\n') |
|
200 | 218 |
|
201 | 219 |
try: |
202 | 220 |
build_ext.run(self) |
203 | 221 |
except (DistutilsError, CCompilerError): |
204 | 222 |
error_msg = self.__error_msg.format( |
205 | 223 |
header=banner(' Error '), sep=banner()) |
206 |
- print(error_msg.format(file=CONFIG_FILE, summary=build_summary), |
|
224 |
+ print(error_msg.format(file=config_file, summary=build_summary), |
|
207 | 225 |
file=sys.stderr) |
208 | 226 |
raise |
209 | 227 |
print(banner(' Build summary '), *build_summary, sep='\n') |
... | ... |
@@ -460,7 +478,7 @@ def maybe_cythonize(exts): |
460 | 478 |
exit(1) |
461 | 479 |
|
462 | 480 |
for f in pyx_files + kwargs.get('depends', []): |
463 |
- if f == CONFIG_FILE: |
|
481 |
+ if f == config_file: |
|
464 | 482 |
# The config file is only a dependency for the compilation |
465 | 483 |
# of the cythonized file, not for the cythonization. |
466 | 484 |
continue |
With the reorganization of setup.py, most constants are now used in a
single place. It is clearer and simpler to have them there.
... | ... |
@@ -41,69 +41,7 @@ from setuptools.command.build_ext import build_ext |
41 | 41 |
|
42 | 42 |
|
43 | 43 |
CONFIG_FILE = 'build.conf' |
44 |
-README_FILE = 'README.rst' |
|
45 |
-MANIFEST_IN_FILE = 'MANIFEST.in' |
|
46 |
-README_END_BEFORE = 'See also in this directory:' |
|
47 | 44 |
STATIC_VERSION_PATH = ('kwant', '_kwant_version.py') |
48 |
-REQUIRED_CYTHON_VERSION = (0, 22) |
|
49 |
-CYTHON_OPTION = '--cython' |
|
50 |
-TUT_DIR = 'tutorial' |
|
51 |
-TUT_GLOB = 'doc/source/tutorial/*.py' |
|
52 |
-TUT_HIDDEN_PREFIX = '#HIDDEN' |
|
53 |
-CLASSIFIERS = """\ |
|
54 |
- Development Status :: 5 - Production/Stable |
|
55 |
- Intended Audience :: Science/Research |
|
56 |
- Intended Audience :: Developers |
|
57 |
- Programming Language :: Python :: 3 :: Only |
|
58 |
- Topic :: Software Development |
|
59 |
- Topic :: Scientific/Engineering |
|
60 |
- Operating System :: POSIX |
|
61 |
- Operating System :: Unix |
|
62 |
- Operating System :: MacOS :: MacOS X |
|
63 |
- Operating System :: Microsoft :: Windows""" |
|
64 |
- |
|
65 |
-EXTENSIONS = [ |
|
66 |
- ('kwant._system', |
|
67 |
- {'sources': ['kwant/_system.pyx'], |
|
68 |
- 'include_dirs': ['kwant/graph']}), |
|
69 |
- |
|
70 |
- ('kwant.operator', |
|
71 |
- {'sources': ['kwant/operator.pyx'], |
|
72 |
- 'include_dirs': ['kwant/graph']}), |
|
73 |
- |
|
74 |
- ('kwant.graph.core', |
|
75 |
- {'sources': ['kwant/graph/core.pyx'], |
|
76 |
- 'depends': ['kwant/graph/core.pxd', 'kwant/graph/defs.h', |
|
77 |
- 'kwant/graph/defs.pxd']}), |
|
78 |
- |
|
79 |
- ('kwant.graph.utils', |
|
80 |
- {'sources': ['kwant/graph/utils.pyx'], |
|
81 |
- 'depends': ['kwant/graph/defs.h', 'kwant/graph/defs.pxd', |
|
82 |
- 'kwant/graph/core.pxd']}), |
|
83 |
- |
|
84 |
- ('kwant.graph.slicer', |
|
85 |
- {'sources': ['kwant/graph/slicer.pyx', |
|
86 |
- 'kwant/graph/c_slicer/partitioner.cc', |
|
87 |
- 'kwant/graph/c_slicer/slicer.cc'], |
|
88 |
- |
|
89 |
- 'depends': ['kwant/graph/defs.h', 'kwant/graph/defs.pxd', |
|
90 |
- 'kwant/graph/core.pxd', |
|
91 |
- 'kwant/graph/c_slicer.pxd', |
|
92 |
- 'kwant/graph/c_slicer/bucket_list.h', |
|
93 |
- 'kwant/graph/c_slicer/graphwrap.h', |
|
94 |
- 'kwant/graph/c_slicer/partitioner.h', |
|
95 |
- 'kwant/graph/c_slicer/slicer.h']}), |
|
96 |
- |
|
97 |
- ('kwant.linalg.lapack', |
|
98 |
- {'sources': ['kwant/linalg/lapack.pyx'], |
|
99 |
- 'depends': ['kwant/linalg/f_lapack.pxd']}), |
|
100 |
- |
|
101 |
- ('kwant.linalg._mumps', |
|
102 |
- {'sources': ['kwant/linalg/_mumps.pyx'], |
|
103 |
- 'depends': ['kwant/linalg/cmumps.pxd']})] |
|
104 |
- |
|
105 |
-EXTENSION_ALIASES = [('lapack', 'kwant.linalg.lapack'), |
|
106 |
- ('mumps', 'kwant.linalg._mumps')] |
|
107 | 45 |
|
108 | 46 |
distr_root = os.path.dirname(os.path.abspath(__file__)) |
109 | 47 |
|
... | ... |
@@ -207,8 +145,9 @@ def init_cython(): |
207 | 145 |
""" |
208 | 146 |
global cythonize, cython_help |
209 | 147 |
|
148 |
+ cython_option = '--cython' |
|
210 | 149 |
try: |
211 |
- sys.argv.remove(CYTHON_OPTION) |
|
150 |
+ sys.argv.remove(cython_option) |
|
212 | 151 |
cythonize = True |
213 | 152 |
except ValueError: |
214 | 153 |
cythonize = version_is_from_git |
... | ... |
@@ -230,17 +169,18 @@ def init_cython(): |
230 | 169 |
cython_version[-1] -= 1 |
231 | 170 |
cython_version = tuple(cython_version) |
232 | 171 |
|
233 |
- if cython_version < REQUIRED_CYTHON_VERSION: |
|
172 |
+ required_cython_version = (0, 22) |
|
173 |
+ if cython_version < required_cython_version: |
|
234 | 174 |
cythonize = None |
235 | 175 |
|
236 | 176 |
if cythonize is None: |
237 | 177 |
msg = ("Install Cython >= {0} or use" |
238 | 178 |
" a source distribution (tarball) of Kwant.") |
239 |
- ver = '.'.join(str(e) for e in REQUIRED_CYTHON_VERSION) |
|
179 |
+ ver = '.'.join(str(e) for e in required_cython_version) |
|
240 | 180 |
cython_help = msg.format(ver) |
241 | 181 |
else: |
242 | 182 |
msg = "Run setup.py with the {} option to enable Cython." |
243 |
- cython_help = msg.format(CYTHON_OPTION) |
|
183 |
+ cython_help = msg.format(cython_option) |
|
244 | 184 |
|
245 | 185 |
|
246 | 186 |
def banner(title=''): |
... | ... |
@@ -292,14 +232,15 @@ class kwant_build_tut(Command): |
292 | 232 |
pass |
293 | 233 |
|
294 | 234 |
def run(self): |
295 |
- if not os.path.exists(TUT_DIR): |
|
296 |
- os.mkdir(TUT_DIR) |
|
297 |
- for in_fname in glob.glob(TUT_GLOB): |
|
298 |
- out_fname = os.path.join(TUT_DIR, os.path.basename(in_fname)) |
|
235 |
+ tut_dir = 'tutorial' |
|
236 |
+ if not os.path.exists(tut_dir): |
|
237 |
+ os.mkdir(tut_dir) |
|
238 |
+ for in_fname in glob.glob('doc/source/tutorial/*.py'): |
|
239 |
+ out_fname = os.path.join(tut_dir, os.path.basename(in_fname)) |
|
299 | 240 |
with open(in_fname) as in_file: |
300 | 241 |
with open(out_fname, 'w') as out_file: |
301 | 242 |
for line in in_file: |
302 |
- if not line.startswith(TUT_HIDDEN_PREFIX): |
|
243 |
+ if not line.startswith('#HIDDEN'): |
|
303 | 244 |
out_file.write(line) |
304 | 245 |
|
305 | 246 |
|
... | ... |
@@ -347,11 +288,12 @@ class kwant_sdist(sdist): |
347 | 288 |
should be there. Setting include_package_data to True makes setuptools |
348 | 289 |
include *.pyx and other source files in the binary distribution. |
349 | 290 |
""" |
350 |
- manifest = os.path.join(distr_root, MANIFEST_IN_FILE) |
|
291 |
+ manifest_in_file = 'MANIFEST.in' |
|
292 |
+ manifest = os.path.join(distr_root, manifest_in_file) |
|
351 | 293 |
names = git_lsfiles() |
352 | 294 |
if names is None: |
353 | 295 |
if not (os.path.isfile(manifest) and os.access(manifest, os.R_OK)): |
354 |
- print("Error:", MANIFEST_IN_FILE, |
|
296 |
+ print("Error:", manifest_in_file, |
|
355 | 297 |
"file is missing and Git is not available" |
356 | 298 |
" to regenerate it.", file=sys.stderr) |
357 | 299 |
exit(1) |
... | ... |
@@ -372,7 +314,7 @@ class kwant_sdist(sdist): |
372 | 314 |
if names is None: |
373 | 315 |
msg = ("Git was not available to generate the list of files to be " |
374 | 316 |
"included in the\nsource distribution. The old {} was used.") |
375 |
- msg = msg.format(MANIFEST_IN_FILE) |
|
317 |
+ msg = msg.format(manifest_in_file) |
|
376 | 318 |
print(banner(' Caution '), msg, banner(), sep='\n', file=sys.stderr) |
377 | 319 |
|
378 | 320 |
def make_release_tree(self, base_dir, files): |
... | ... |
@@ -395,9 +337,9 @@ def write_version(fname): |
395 | 337 |
def long_description(): |
396 | 338 |
text = [] |
397 | 339 |
try: |
398 |
- with open(README_FILE) as f: |
|
340 |
+ with open('README.rst') as f: |
|
399 | 341 |
for line in f: |
400 |
- if line.startswith(README_END_BEFORE): |
|
342 |
+ if line.startswith('See also in this directory:'): |
|
401 | 343 |
break |
402 | 344 |
text.append(line.rstrip()) |
403 | 345 |
while text[-1] == "": |
... | ... |
@@ -550,17 +492,62 @@ def maybe_cythonize(exts): |
550 | 492 |
|
551 | 493 |
|
552 | 494 |
def main(): |
553 |
- global build_summary |
|
495 |
+ exts = collections.OrderedDict([ |
|
496 |
+ ('kwant._system', |
|
497 |
+ dict(sources=['kwant/_system.pyx'], |
|
498 |
+ include_dirs=['kwant/graph'])), |
|
499 |
+ ('kwant.operator', |
|
500 |
+ dict(sources=['kwant/operator.pyx'], |
|
501 |
+ include_dirs=['kwant/graph'])), |
|
502 |
+ ('kwant.graph.core', |
|
503 |
+ dict(sources=['kwant/graph/core.pyx'], |
|
504 |
+ depends=['kwant/graph/core.pxd', 'kwant/graph/defs.h', |
|
505 |
+ 'kwant/graph/defs.pxd'])), |
|
506 |
+ ('kwant.graph.utils', |
|
507 |
+ dict(sources=['kwant/graph/utils.pyx'], |
|
508 |
+ depends=['kwant/graph/defs.h', 'kwant/graph/defs.pxd', |
|
509 |
+ 'kwant/graph/core.pxd'])), |
|
510 |
+ ('kwant.graph.slicer', |
|
511 |
+ dict(sources=['kwant/graph/slicer.pyx', |
|
512 |
+ 'kwant/graph/c_slicer/partitioner.cc', |
|
513 |
+ 'kwant/graph/c_slicer/slicer.cc'], |
|
514 |
+ depends=['kwant/graph/defs.h', 'kwant/graph/defs.pxd', |
|
515 |
+ 'kwant/graph/core.pxd', 'kwant/graph/c_slicer.pxd', |
|
516 |
+ 'kwant/graph/c_slicer/bucket_list.h', |
|
517 |
+ 'kwant/graph/c_slicer/graphwrap.h', |
|
518 |
+ 'kwant/graph/c_slicer/partitioner.h', |
|
519 |
+ 'kwant/graph/c_slicer/slicer.h'])), |
|
520 |
+ ('kwant.linalg.lapack', |
|
521 |
+ dict(sources=['kwant/linalg/lapack.pyx'], |
|
522 |
+ depends=['kwant/linalg/f_lapack.pxd'])), |
|
523 |
+ ('kwant.linalg._mumps', |
|
524 |
+ dict(sources=['kwant/linalg/_mumps.pyx'], |
|
525 |
+ depends=['kwant/linalg/cmumps.pxd']))]) |
|
526 |
+ |
|
527 |
+ aliases = [('lapack', 'kwant.linalg.lapack'), |
|
528 |
+ ('mumps', 'kwant.linalg._mumps')] |
|
554 | 529 |
|
555 | 530 |
get_version() |
556 | 531 |
init_cython() |
557 | 532 |
|
533 |
+ global build_summary |
|
558 | 534 |
build_summary = [] |
559 |
- exts = collections.OrderedDict(EXTENSIONS) |
|
560 |
- exts = configure_extensions(exts, EXTENSION_ALIASES, build_summary) |
|
535 |
+ exts = configure_extensions(exts, aliases, build_summary) |
|
561 | 536 |
exts = configure_special_extensions(exts, build_summary) |
562 | 537 |
exts = maybe_cythonize(exts) |
563 | 538 |
|
539 |
+ classifiers = """\ |
|
540 |
+ Development Status :: 5 - Production/Stable |
|
541 |
+ Intended Audience :: Science/Research |
|
542 |
+ Intended Audience :: Developers |
|
543 |
+ Programming Language :: Python :: 3 :: Only |
|
544 |
+ Topic :: Software Development |
|
545 |
+ Topic :: Scientific/Engineering |
|
546 |
+ Operating System :: POSIX |
|
547 |
+ Operating System :: Unix |
|
548 |
+ Operating System :: MacOS :: MacOS X |
|
549 |
+ Operating System :: Microsoft :: Windows""" |
|
550 |
+ |
|
564 | 551 |
setup(name='kwant', |
565 | 552 |
version=version, |
566 | 553 |
author='C. W. Groth (CEA), M. Wimmer, ' |
... | ... |
@@ -582,7 +569,7 @@ def main(): |
582 | 569 |
tests_require=['numpy > 1.6.1', 'pytest >= 2.6.3'], |
583 | 570 |
install_requires=['numpy > 1.6.1', 'scipy >= 0.9', 'tinyarray'], |
584 | 571 |
extras_require={'plotting': 'matplotlib >= 1.2'}, |
585 |
- classifiers=[c.strip() for c in CLASSIFIERS.split('\n')]) |
|
572 |
+ classifiers=[c.strip() for c in classifiers.split('\n')]) |
|
586 | 573 |
|
587 | 574 |
if __name__ == '__main__': |
588 | 575 |
main() |
The CYTHON_TRACE macro can be now set in the build.conf file.
Christoph Groth authored on 21/09/2016 11:09:27... | ... |
@@ -47,7 +47,6 @@ README_END_BEFORE = 'See also in this directory:' |
47 | 47 |
STATIC_VERSION_PATH = ('kwant', '_kwant_version.py') |
48 | 48 |
REQUIRED_CYTHON_VERSION = (0, 22) |
49 | 49 |
CYTHON_OPTION = '--cython' |
50 |
-CYTHON_TRACE_OPTION = '--cython-trace' |
|
51 | 50 |
TUT_DIR = 'tutorial' |
52 | 51 |
TUT_GLOB = 'doc/source/tutorial/*.py' |
53 | 52 |
TUT_HIDDEN_PREFIX = '#HIDDEN' |
... | ... |
@@ -118,13 +117,6 @@ def configure_extensions(exts, aliases=(), build_summary=None): |
118 | 117 |
""" |
119 | 118 |
global config_file_present |
120 | 119 |
|
121 |
- #### Add cython tracing macro |
|
122 |
- if trace_cython: |
|
123 |
- for name, kwargs in exts.items(): |
|
124 |
- macros = kwargs.get('define_macros', []) |
|
125 |
- macros.append(('CYTHON_TRACE', '1')) |
|
126 |
- kwargs['define_macros'] = macros |
|
127 |
- |
|
128 | 120 |
#### Read build configuration file. |
129 | 121 |
configs = configparser.ConfigParser() |
130 | 122 |
try: |
... | ... |
@@ -213,7 +205,7 @@ def init_cython(): |
213 | 205 |
|
214 | 206 |
This function modifies `sys.argv`. |
215 | 207 |
""" |
216 |
- global cythonize, cython_help, trace_cython |
|
208 |
+ global cythonize, cython_help |
|
217 | 209 |
|
218 | 210 |
try: |
219 | 211 |
sys.argv.remove(CYTHON_OPTION) |
... | ... |
@@ -221,16 +213,6 @@ def init_cython(): |
221 | 213 |
except ValueError: |
222 | 214 |
cythonize = version_is_from_git |
223 | 215 |
|
224 |
- try: |
|
225 |
- sys.argv.remove(CYTHON_TRACE_OPTION) |
|
226 |
- trace_cython = True |
|
227 |
- if not cythonize: |
|
228 |
- print('Error: --cython-trace provided, but Cython will not be run.', |
|
229 |
- file=sys.stderr) |
|
230 |
- exit(1) |
|
231 |
- except ValueError: |
|
232 |
- trace_cython = False |
|
233 |
- |
|
234 | 216 |
if cythonize: |
235 | 217 |
try: |
236 | 218 |
import Cython |
... | ... |
@@ -495,7 +477,7 @@ def maybe_cythonize(exts): |
495 | 477 |
return cythonize([Extension(name, **kwargs) |
496 | 478 |
for name, kwargs in exts.items()], |
497 | 479 |
language_level=3, |
498 |
- compiler_directives={'linetrace': trace_cython}) |
|
480 |
+ compiler_directives={'linetrace': True}) |
|
499 | 481 |
|
500 | 482 |
# Cython is not going to be run: replace pyx extension by that of |
501 | 483 |
# the shipped translated file. |
All C extensions are now treated on equal footing and can be configured
in "build.conf". All the options known by Extension may be set now for
any extension individually and for all of them together (using the
[DEFAULT] section).
... | ... |
@@ -30,6 +30,7 @@ import glob |
30 | 30 |
import imp |
31 | 31 |
import subprocess |
32 | 32 |
import configparser |
33 |
+import collections |
|
33 | 34 |
from setuptools import setup, find_packages, Extension, Command |
34 | 35 |
from sysconfig import get_platform |
35 | 36 |
from distutils.errors import DistutilsError, DistutilsModuleError, \ |
... | ... |
@@ -62,10 +63,127 @@ CLASSIFIERS = """\ |
62 | 63 |
Operating System :: MacOS :: MacOS X |
63 | 64 |
Operating System :: Microsoft :: Windows""" |
64 | 65 |
|
66 |
+EXTENSIONS = [ |
|
67 |
+ ('kwant._system', |
|
68 |
+ {'sources': ['kwant/_system.pyx'], |
|
69 |
+ 'include_dirs': ['kwant/graph']}), |
|
70 |
+ |
|
71 |
+ ('kwant.operator', |
|
72 |
+ {'sources': ['kwant/operator.pyx'], |
|
73 |
+ 'include_dirs': ['kwant/graph']}), |
|
74 |
+ |
|
75 |
+ ('kwant.graph.core', |
|
76 |
+ {'sources': ['kwant/graph/core.pyx'], |
|
77 |
+ 'depends': ['kwant/graph/core.pxd', 'kwant/graph/defs.h', |
|
78 |
+ 'kwant/graph/defs.pxd']}), |
|
79 |
+ |
|
80 |
+ ('kwant.graph.utils', |
|
81 |
+ {'sources': ['kwant/graph/utils.pyx'], |
|
82 |
+ 'depends': ['kwant/graph/defs.h', 'kwant/graph/defs.pxd', |
|
83 |
+ 'kwant/graph/core.pxd']}), |
|
84 |
+ |
|
85 |
+ ('kwant.graph.slicer', |
|
86 |
+ {'sources': ['kwant/graph/slicer.pyx', |
|
87 |
+ 'kwant/graph/c_slicer/partitioner.cc', |
|
88 |
+ 'kwant/graph/c_slicer/slicer.cc'], |
|
89 |
+ |
|
90 |
+ 'depends': ['kwant/graph/defs.h', 'kwant/graph/defs.pxd', |
|
91 |
+ 'kwant/graph/core.pxd', |
|
92 |
+ 'kwant/graph/c_slicer.pxd', |
|
93 |
+ 'kwant/graph/c_slicer/bucket_list.h', |
|
94 |
+ 'kwant/graph/c_slicer/graphwrap.h', |
|
95 |
+ 'kwant/graph/c_slicer/partitioner.h', |
|
96 |
+ 'kwant/graph/c_slicer/slicer.h']}), |
|
97 |
+ |
|
98 |
+ ('kwant.linalg.lapack', |
|
99 |
+ {'sources': ['kwant/linalg/lapack.pyx'], |
|
100 |
+ 'depends': ['kwant/linalg/f_lapack.pxd']}), |
|
101 |
+ |
|
102 |
+ ('kwant.linalg._mumps', |
|
103 |
+ {'sources': ['kwant/linalg/_mumps.pyx'], |
|
104 |
+ 'depends': ['kwant/linalg/cmumps.pxd']})] |
|
105 |
+ |
|
106 |
+EXTENSION_ALIASES = [('lapack', 'kwant.linalg.lapack'), |
|
107 |
+ ('mumps', 'kwant.linalg._mumps')] |
|
65 | 108 |
|
66 | 109 |
distr_root = os.path.dirname(os.path.abspath(__file__)) |
67 | 110 |
|
68 | 111 |
|
112 |
+def configure_extensions(exts, aliases=(), build_summary=None): |
|
113 |
+ """Modify extension configuration according to the configuration file |
|
114 |
+ |
|
115 |
+ `exts` must be a dict of (name, kwargs) tuples that can be used like this: |
|
116 |
+ `Extension(name, **kwargs). This function modifies the kwargs according to |
|
117 |
+ the configuration file `CONFIG_FILE`. |
|
118 |
+ """ |
|
119 |
+ global config_file_present |
|
120 |
+ |
|
121 |
+ #### Add cython tracing macro |
|
122 |
+ if trace_cython: |
|
123 |
+ for name, kwargs in exts.items(): |
|
124 |
+ macros = kwargs.get('define_macros', []) |
|
125 |
+ macros.append(('CYTHON_TRACE', '1')) |
|
126 |
+ kwargs['define_macros'] = macros |
|
127 |
+ |
|
128 |
+ #### Read build configuration file. |
|
129 |
+ configs = configparser.ConfigParser() |
|
130 |
+ try: |
|
131 |
+ with open(CONFIG_FILE) as f: |
|
132 |
+ configs.read_file(f) |
|
133 |
+ except IOError: |
|
134 |
+ config_file_present = False |
|
135 |
+ else: |
|
136 |
+ config_file_present = True |
|
137 |
+ |
|
138 |
+ #### Handle section aliases. |
|
139 |
+ for short, long in aliases: |
|
140 |
+ if short in configs: |
|
141 |
+ if long in configs: |
|
142 |
+ print('Error: both {} and {} sections present in {}.'.format( |
|
143 |
+ short, long, CONFIG_FILE)) |
|
144 |
+ exit(1) |
|
145 |
+ configs[long] = configs[short] |
|
146 |
+ del configs[short] |
|
147 |
+ |
|
148 |
+ #### Apply config from file. Use [DEFAULT] section for missing sections. |
|
149 |
+ defaultconfig = configs.defaults() |
|
150 |
+ for name, kwargs in exts.items(): |
|
151 |
+ config = configs[name] if name in configs else defaultconfig |
|
152 |
+ for key, value in config.items(): |
|
153 |
+ |
|
154 |
+ # Most, but not all, keys are lists of strings |
|
155 |
+ if key == 'language': |
|
156 |
+ pass |
|
157 |
+ elif key == 'optional': |
|
158 |
+ value = bool(int(value)) |
|
159 |
+ else: |
|
160 |
+ value = value.split() |
|
161 |
+ |
|
162 |
+ if key == 'define_macros': |
|
163 |
+ value = [tuple(entry.split('=', maxsplit=1)) |
|
164 |
+ for entry in value] |
|
165 |
+ value = [(entry[0], None) if len(entry) == 1 else entry |
|
166 |
+ for entry in value] |
|
167 |
+ |
|
168 |
+ if key in kwargs: |
|
169 |
+ msg = 'Caution: user config in file {} shadows {}.{}.' |
|
170 |
+ if build_summary is not None: |
|
171 |
+ build_summary.append(msg.format(CONFIG_FILE, name, key)) |
|
172 |
+ kwargs[key] = value |
|
173 |
+ |
|
174 |
+ kwargs.setdefault('depends', []).append(CONFIG_FILE) |
|
175 |
+ if config is not defaultconfig: |
|
176 |
+ del configs[name] |
|
177 |
+ |
|
178 |
+ unknown_sections = configs.sections() |
|
179 |
+ if unknown_sections: |
|
180 |
+ print('Error: Unknown sections in file {}: {}'.format( |
|
181 |
+ CONFIG_FILE, ', '.join(unknown_sections))) |
|
182 |
+ exit(1) |
|
183 |
+ |
|
184 |
+ return exts |
|
185 |
+ |
|
186 |
+ |
|
69 | 187 |
def get_version(): |
70 | 188 |
global version, version_is_from_git |
71 | 189 |
|
... | ... |
@@ -166,8 +284,7 @@ class kwant_build_ext(build_ext): |
166 | 284 |
print(error_msg.format(file=CONFIG_FILE, summary=build_summary), |
167 | 285 |
file=sys.stderr) |
168 | 286 |
raise |
169 |
- print(banner(' Build summary ')) |
|
170 |
- print(build_summary) |
|
287 |
+ print(banner(' Build summary '), *build_summary, sep='\n') |
|
171 | 288 |
print(banner()) |
172 | 289 |
|
173 | 290 |
__error_msg = """{header} |
... | ... |
@@ -331,106 +448,53 @@ def search_mumps(): |
331 | 448 |
return {} |
332 | 449 |
|
333 | 450 |
|
334 |
-def extensions(): |
|
335 |
- """Return a list of tuples (args, kwrds) to be passed to Extension.""" |
|
336 |
- |
|
337 |
- global build_summary, config_file_present |
|
338 |
- build_summary = [] |
|
339 |
- |
|
340 |
- #### Add components of Kwant without external compile-time dependencies. |
|
341 |
- result = [ |
|
342 |
- (['kwant._system', ['kwant/_system.pyx']], |
|
343 |
- {'include_dirs': ['kwant/graph']}), |
|
344 |
- (['kwant.operator', ['kwant/operator.pyx']], |
|
345 |
- {'include_dirs': ['kwant/graph']}), |
|
346 |
- (['kwant.graph.core', ['kwant/graph/core.pyx']], |
|
347 |
- {'depends': ['kwant/graph/core.pxd', 'kwant/graph/defs.h', |
|
348 |
- 'kwant/graph/defs.pxd']}), |
|
349 |
- (['kwant.graph.utils', ['kwant/graph/utils.pyx']], |
|
350 |
- {'depends': ['kwant/graph/defs.h', 'kwant/graph/defs.pxd', |
|
351 |
- 'kwant/graph/core.pxd']}), |
|
352 |
- (['kwant.graph.slicer', ['kwant/graph/slicer.pyx', |
|
353 |
- 'kwant/graph/c_slicer/partitioner.cc', |
|
354 |
- 'kwant/graph/c_slicer/slicer.cc']], |
|
355 |
- {'depends': ['kwant/graph/defs.h', 'kwant/graph/defs.pxd', |
|
356 |
- 'kwant/graph/core.pxd', |
|
357 |
- 'kwant/graph/c_slicer.pxd', |
|
358 |
- 'kwant/graph/c_slicer/bucket_list.h', |
|
359 |
- 'kwant/graph/c_slicer/graphwrap.h', |
|
360 |
- 'kwant/graph/c_slicer/partitioner.h', |
|
361 |
- 'kwant/graph/c_slicer/slicer.h']})] |
|
362 |
- |
|
363 |
- #### Add cython tracing macro |
|
364 |
- if trace_cython: |
|
365 |
- for args, kwargs in result: |
|
366 |
- macros = kwargs.get('define_macros', []) |
|
367 |
- macros.append(('CYTHON_TRACE', '1')) |
|
368 |
- kwargs['define_macros'] = macros |
|
369 |
- |
|
370 |
- #### Add components of Kwant with external compile-time dependencies. |
|
371 |
- config = configparser.ConfigParser() |
|
372 |
- try: |
|
373 |
- with open(CONFIG_FILE) as f: |
|
374 |
- config.read_file(f) |
|
375 |
- except IOError: |
|
376 |
- config_file_present = False |
|
377 |
- else: |
|
378 |
- config_file_present = True |
|
379 |
- |
|
380 |
- kwrds_by_section = {} |
|
381 |
- for section in config.sections(): |
|
382 |
- kwrds_by_section[section] = kwrds = {} |
|
383 |
- for name, value in config.items(section): |
|
384 |
- kwrds[name] = value.split() |
|
385 |
- |
|
386 |
- # Setup LAPACK. |
|
387 |
- lapack = kwrds_by_section.get('lapack') |
|
388 |
- if lapack: |
|
451 |
+def configure_special_extensions(exts, build_summary): |
|
452 |
+ #### Special config for LAPACK. |
|
453 |
+ lapack = exts['kwant.linalg.lapack'] |
|
454 |
+ if 'libraries' in lapack: |
|
389 | 455 |
build_summary.append('User-configured LAPACK and BLAS') |
390 | 456 |
else: |
391 |
- lapack = {'libraries': ['lapack', 'blas']} |
|
457 |
+ lapack['libraries'] = ['lapack', 'blas'] |
|
392 | 458 |
build_summary.append('Default LAPACK and BLAS') |
393 |
- kwrds = lapack.copy() |
|
394 |
- kwrds.setdefault('depends', []).extend( |
|
395 |
- [CONFIG_FILE, 'kwant/linalg/f_lapack.pxd']) |
|
396 |
- result.append((['kwant.linalg.lapack', ['kwant/linalg/lapack.pyx']], |
|
397 |
- kwrds)) |
|
398 |
- |
|
399 |
- # Setup MUMPS. |
|
400 |
- kwrds = kwrds_by_section.get('mumps') |
|
401 |
- if kwrds: |
|
459 |
+ |
|
460 |
+ #### Special config for MUMPS. |
|
461 |
+ mumps = exts['kwant.linalg._mumps'] |
|
462 |
+ if 'libraries' in mumps: |
|
402 | 463 |
build_summary.append('User-configured MUMPS') |
403 | 464 |
else: |
404 |
- kwrds = search_mumps() |
|
405 |
- if kwrds: |
|
465 |
+ kwargs = search_mumps() |
|
466 |
+ if kwargs: |
|
467 |
+ for key, value in kwargs.items(): |
|
468 |
+ mumps.setdefault(key, []).extend(value) |
|
406 | 469 |
build_summary.append('Auto-configured MUMPS') |
407 |
- if kwrds: |
|
408 |
- for name, value in lapack.items(): |
|
409 |
- kwrds.setdefault(name, []).extend(value) |
|
410 |
- kwrds.setdefault('depends', []).extend( |
|
411 |
- [CONFIG_FILE, 'kwant/linalg/cmumps.pxd']) |
|
412 |
- result.append((['kwant.linalg._mumps', ['kwant/linalg/_mumps.pyx']], |
|
413 |
- kwrds)) |
|
414 |
- else: |
|
415 |
- build_summary.append('No MUMPS support') |
|
470 |
+ else: |
|
471 |
+ mumps = None |
|
472 |
+ del exts['mumps'] |
|
473 |
+ build_summary.append('No MUMPS support') |
|
416 | 474 |
|
417 |
- build_summary = '\n'.join(build_summary) |
|
418 |
- return result |
|
475 |
+ if mumps: |
|
476 |
+ # Copy config from LAPACK. |
|
477 |
+ for key, value in lapack.items(): |
|
478 |
+ if key not in ['sources', 'depends']: |
|
479 |
+ mumps.setdefault(key, []).extend(value) |
|
419 | 480 |
|
481 |
+ return exts |
|
420 | 482 |
|
421 |
-def maybe_cythonize(extensions): |
|
483 |
+ |
|
484 |
+def maybe_cythonize(exts): |
|
422 | 485 |
"""Prepare a list of `Extension` instances, ready for `setup()`. |
423 | 486 |
|
424 |
- The argument `extensions` must be a sequence of (args, kwrds) to be passed on |
|
425 |
- to `Extension`. |
|
487 |
+ The argument `exts` must be a mapping of names to kwargs to be passed |
|
488 |
+ on to `Extension`. |
|
426 | 489 |
|
427 | 490 |
If Cython is to be run, create the extensions and calls `cythonize()` on |
428 | 491 |
them. If Cython is not to be run, replace .pyx file with .c or .cpp, |
429 | 492 |
check timestamps, and create the extensions. |
430 | 493 |
""" |
431 | 494 |
if cythonize: |
432 |
- return cythonize([Extension(*args, **kwrds) |
|
433 |
- for args, kwrds in extensions], language_level=3, |
|
495 |
+ return cythonize([Extension(name, **kwargs) |
|
496 |
+ for name, kwargs in exts.items()], |
|
497 |
+ language_level=3, |
|
434 | 498 |
compiler_directives={'linetrace': trace_cython}) |
435 | 499 |
|
436 | 500 |
# Cython is not going to be run: replace pyx extension by that of |
... | ... |
@@ -438,10 +502,8 @@ def maybe_cythonize(extensions): |
438 | 502 |
|
439 | 503 |
result = [] |
440 | 504 |
problematic_files = [] |
441 |
- for args, kwrds in extensions: |
|
442 |
- name, sources = args |
|
443 |
- |
|
444 |
- language = kwrds.get('language') |
|
505 |
+ for name, kwargs in exts.items(): |
|
506 |
+ language = kwargs.get('language') |
|
445 | 507 |
if language is None: |
446 | 508 |
ext = '.c' |
447 | 509 |
elif language == 'c': |
... | ... |
@@ -454,14 +516,14 @@ def maybe_cythonize(extensions): |
454 | 516 |
|
455 | 517 |
pyx_files = [] |
456 | 518 |
cythonized_files = [] |
457 |
- new_sources = [] |
|
458 |
- for f in sources: |
|
519 |
+ sources = [] |
|
520 |
+ for f in kwargs['sources']: |
|
459 | 521 |
if f.endswith('.pyx'): |
460 | 522 |
pyx_files.append(f) |
461 | 523 |
f = f.rstrip('.pyx') + ext |
462 | 524 |
cythonized_files.append(f) |
463 |
- new_sources.append(f) |
|
464 |
- sources = new_sources |
|
525 |
+ sources.append(f) |
|
526 |
+ kwargs['sources'] = sources |
|
465 | 527 |
|
466 | 528 |
# Complain if cythonized files are older than Cython source files. |
467 | 529 |
try: |
... | ... |
@@ -473,7 +535,7 @@ def maybe_cythonize(extensions): |
473 | 535 |
cython_help, banner(), sep="\n", file=sys.stderr) |
474 | 536 |
exit(1) |
475 | 537 |
|
476 |
- for f in pyx_files + kwrds.get('depends', []): |
|
538 |
+ for f in pyx_files + kwargs.get('depends', []): |
|
477 | 539 |
if f == CONFIG_FILE: |
478 | 540 |
# The config file is only a dependency for the compilation |
479 | 541 |
# of the cythonized file, not for the cythonization. |
... | ... |
@@ -481,7 +543,7 @@ def maybe_cythonize(extensions): |
481 | 543 |
if os.stat(f).st_mtime > cythonized_oldest: |
482 | 544 |
problematic_files.append(f) |
483 | 545 |
|
484 |
- result.append(Extension(name, sources, **kwrds)) |
|
546 |
+ result.append(Extension(name, **kwargs)) |
|
485 | 547 |
|
486 | 548 |
if problematic_files: |
487 | 549 |
msg = ("Some Cython source files are newer than files that have " |
... | ... |
@@ -506,9 +568,17 @@ def maybe_cythonize(extensions): |
506 | 568 |
|
507 | 569 |
|
508 | 570 |
def main(): |
571 |
+ global build_summary |
|
572 |
+ |
|
509 | 573 |
get_version() |
510 | 574 |
init_cython() |
511 | 575 |
|
576 |
+ build_summary = [] |
|
577 |
+ exts = collections.OrderedDict(EXTENSIONS) |
|
578 |
+ exts = configure_extensions(exts, EXTENSION_ALIASES, build_summary) |
|
579 |
+ exts = configure_special_extensions(exts, build_summary) |
|
580 |
+ exts = maybe_cythonize(exts) |
|
581 |
+ |
|
512 | 582 |
setup(name='kwant', |
513 | 583 |
version=version, |
514 | 584 |
author='C. W. Groth (CEA), M. Wimmer, ' |
... | ... |
@@ -525,7 +595,7 @@ def main(): |
525 | 595 |
'sdist': kwant_sdist, |
526 | 596 |
'build_ext': kwant_build_ext, |
527 | 597 |
'build_tut': kwant_build_tut}, |
528 |
- ext_modules=maybe_cythonize(extensions()), |
|
598 |
+ ext_modules=exts, |
|
529 | 599 |
setup_requires=['pytest-runner >= 2.7'], |
530 | 600 |
tests_require=['numpy > 1.6.1', 'pytest >= 2.6.3'], |
531 | 601 |
install_requires=['numpy > 1.6.1', 'scipy >= 0.9', 'tinyarray'], |
... | ... |
@@ -12,13 +12,17 @@ from __future__ import print_function |
12 | 12 |
|
13 | 13 |
import sys |
14 | 14 |
|
15 |
-v = sys.version_info |
|
16 |
-if v[:2] < (3, 4): |
|
17 |
- error = "This version of Kwant requires Python 3.4 or above.\n" |
|
18 |
- if v[0] == 2: |
|
19 |
- error += "Kwant 1.1 is the last version to support Python 2." |
|
20 |
- print(error, file=sys.stderr) |
|
21 |
- sys.exit(1) |
|
15 |
+def ensure_python(required_version): |
|
16 |
+ v = sys.version_info |
|
17 |
+ if v[:3] < required_version: |
|
18 |
+ error = "This version of Kwant requires Python {} or above.".format( |
|
19 |
+ ".".join(str(p) for p in required_version)) |
|
20 |
+ if v[0] == 2: |
|
21 |
+ error += "\nKwant 1.1 is the last version to support Python 2." |
|
22 |
+ print(error, file=sys.stderr) |
|
23 |
+ sys.exit(1) |
|
24 |
+ |
|
25 |
+ensure_python((3, 4)) |
|
22 | 26 |
|
23 | 27 |
import re |
24 | 28 |
import os |
... | ... |
@@ -267,10 +267,10 @@ class kwant_sdist(sdist): |
267 | 267 |
sdist.run(self) |
268 | 268 |
|
269 | 269 |
if names is None: |
270 |
- print(banner(' Caution '), |
|
271 |
- """Git was not available to generate the list of files to be included in the |
|
272 |
-source distribution. The old {} was used.""".format(MANIFEST_IN_FILE), |
|
273 |
- banner(), sep='\n', file=sys.stderr) |
|
270 |
+ msg = ("Git was not available to generate the list of files to be " |
|
271 |
+ "included in the\nsource distribution. The old {} was used.") |
|
272 |
+ msg = msg.format(MANIFEST_IN_FILE) |
|
273 |
+ print(banner(' Caution '), msg, banner(), sep='\n', file=sys.stderr) |
|
274 | 274 |
|
275 | 275 |
def make_release_tree(self, base_dir, files): |
276 | 276 |
sdist.make_release_tree(self, base_dir, files) |
... | ... |
@@ -77,31 +77,46 @@ def get_version(): |
77 | 77 |
|
78 | 78 |
|
79 | 79 |
def init_cython(): |
80 |
- global use_cython, cython_version, trace_cython, cythonize |
|
80 |
+ """Set the global variable `cythonize` (and other related globals). |
|
81 |
+ |
|
82 |
+ The variable `cythonize` can be in three states: |
|
83 |
+ |
|
84 |
+ * If Cython should be run and is ready, it contains the `cythonize()` |
|
85 |
+ function. |
|
86 |
+ |
|
87 |
+ * If Cython is not to be run, it contains `False`. |
|
88 |
+ |
|
89 |
+ * If Cython should, but cannot be run it contains `None`. A help message |
|
90 |
+ on how to solve the problem is stored in `cython_help`. |
|
91 |
+ |
|
92 |
+ This function modifies `sys.argv`. |
|
93 |
+ """ |
|
94 |
+ global cythonize, cython_help, trace_cython |
|
81 | 95 |
|
82 | 96 |
try: |
83 | 97 |
sys.argv.remove(CYTHON_OPTION) |
84 |
- use_cython = True |
|
98 |
+ cythonize = True |
|
85 | 99 |
except ValueError: |
86 |
- use_cython = version_is_from_git |
|
100 |
+ cythonize = version_is_from_git |
|
87 | 101 |
|
88 | 102 |
try: |
89 | 103 |
sys.argv.remove(CYTHON_TRACE_OPTION) |
90 | 104 |
trace_cython = True |
91 |
- if not use_cython: |
|
92 |
- print('error: --cython-trace provided, but cython will not be run', |
|
105 |
+ if not cythonize: |
|
106 |
+ print('Error: --cython-trace provided, but Cython will not be run.', |
|
93 | 107 |
file=sys.stderr) |
94 | 108 |
exit(1) |
95 | 109 |
except ValueError: |
96 | 110 |
trace_cython = False |
97 | 111 |
|
98 |
- if use_cython: |
|
112 |
+ if cythonize: |
|
99 | 113 |
try: |
100 | 114 |
import Cython |
101 | 115 |
from Cython.Build import cythonize |
102 | 116 |
except ImportError: |
103 |
- cython_version = () |
|
117 |
+ cythonize = None |
|
104 | 118 |
else: |
119 |
+ #### Get Cython version. |
|
105 | 120 |
match = re.match('([0-9.]*)(.*)', Cython.__version__) |
106 | 121 |
cython_version = [int(n) for n in match.group(1).split('.')] |
107 | 122 |
# Decrease version if the version string contains a suffix. |
... | ... |
@@ -111,6 +126,18 @@ def init_cython(): |
111 | 126 |
cython_version[-1] -= 1 |
112 | 127 |
cython_version = tuple(cython_version) |
113 | 128 |
|
129 |
+ if cython_version < REQUIRED_CYTHON_VERSION: |
|
130 |
+ cythonize = None |
|
131 |
+ |
|
132 |
+ if cythonize is None: |
|
133 |
+ msg = ("Install Cython >= {0} or use" |
|
134 |
+ " a source distribution (tarball) of Kwant.") |
|
135 |
+ ver = '.'.join(str(e) for e in REQUIRED_CYTHON_VERSION) |
|
136 |
+ cython_help = msg.format(ver) |
|
137 |
+ else: |
|
138 |
+ msg = "Run setup.py with the {} option to enable Cython." |
|
139 |
+ cython_help = msg.format(CYTHON_OPTION) |
|
140 |
+ |
|
114 | 141 |
|
115 | 142 |
def banner(title=''): |
116 | 143 |
starred = title.center(79, '*') |
... | ... |
@@ -387,18 +414,6 @@ def extensions(): |
387 | 414 |
return result |
388 | 415 |
|
389 | 416 |
|
390 |
-def complain_cython_unavailable(): |
|
391 |
- assert not use_cython or cython_version < REQUIRED_CYTHON_VERSION |
|
392 |
- if use_cython: |
|
393 |
- msg = ("Install Cython {0} or newer so it can be made\n" |
|
394 |
- "or use a source distribution of Kwant.") |
|
395 |
- ver = '.'.join(str(e) for e in REQUIRED_CYTHON_VERSION) |
|
396 |
- print(msg.format(ver), file=sys.stderr) |
|
397 |
- else: |
|
398 |
- print("Run setup.py with the {} option.".format(CYTHON_OPTION), |
|
399 |
- file=sys.stderr) |
|
400 |
- |
|
401 |
- |
|
402 | 417 |
def maybe_cythonize(extensions): |
403 | 418 |
"""Prepare a list of `Extension` instances, ready for `setup()`. |
404 | 419 |
|
... | ... |
@@ -409,7 +424,7 @@ def maybe_cythonize(extensions): |
409 | 424 |
them. If Cython is not to be run, replace .pyx file with .c or .cpp, |
410 | 425 |
check timestamps, and create the extensions. |
411 | 426 |
""" |
412 |
- if use_cython and cython_version >= REQUIRED_CYTHON_VERSION: |
|
427 |
+ if cythonize: |
|
413 | 428 |
return cythonize([Extension(*args, **kwrds) |
414 | 429 |
for args, kwrds in extensions], language_level=3, |
415 | 430 |
compiler_directives={'linetrace': trace_cython}) |
... | ... |
@@ -449,9 +464,9 @@ def maybe_cythonize(extensions): |
449 | 464 |
cythonized_oldest = min(os.stat(f).st_mtime |
450 | 465 |
for f in cythonized_files) |
451 | 466 |
except OSError: |
452 |
- print("error: Cython-generated file {} is missing.".format(f), |
|
453 |
- file=sys.stderr) |
|
454 |
- complain_cython_unavailable() |
|
467 |
+ msg = "Cython-generated file {} is missing." |
|
468 |
+ print(banner(" Error "), msg.format(f), "", |
|
469 |
+ cython_help, banner(), sep="\n", file=sys.stderr) |
|
455 | 470 |
exit(1) |
456 | 471 |
|
457 | 472 |
for f in pyx_files + kwrds.get('depends', []): |
... | ... |
@@ -465,28 +480,23 @@ def maybe_cythonize(extensions): |
465 | 480 |
result.append(Extension(name, sources, **kwrds)) |
466 | 481 |
|
467 | 482 |
if problematic_files: |
468 |
- problematic_files = ", ".join(problematic_files) |
|
469 |
- msg = ("Some Cython source files are newer than files that should have\n" |
|
470 |
- "been derived from them, but {}.\n" |
|
471 |
- "\n" |
|
472 |
- "Affected files: {}") |
|
473 |
- if use_cython: |
|
474 |
- if not cython_version: |
|
475 |
- reason = "Cython is not installed" |
|
476 |
- else: |
|
477 |
- reason = "the installed Cython is too old" |
|
478 |
- print(banner(" Error "), msg.format(reason, problematic_files), |
|
479 |
- banner(), sep="\n", file=sys.stderr) |
|
480 |
- print() |
|
481 |
- complain_cython_unavailable() |
|
483 |
+ msg = ("Some Cython source files are newer than files that have " |
|
484 |
+ "been derived from them:\n{}") |
|
485 |
+ msg = msg.format(", ".join(problematic_files)) |
|
486 |
+ |
|
487 |
+ # Cython should be run but won't. Signal an error if this is because |
|
488 |
+ # Cython *cannot* be run, warn otherwise. |
|
489 |
+ error = cythonize is None |
|
490 |
+ if cythonize is False: |
|
491 |
+ dontworry = ('(Do not worry about this if you are building Kwant ' |
|
492 |
+ 'from unmodified sources,\n' |
|
493 |
+ 'e.g. with "pip install".)\n\n') |
|
494 |
+ msg = dontworry + msg |
|
495 |
+ |
|
496 |
+ print(banner(" Error " if error else " Caution "), msg, "", |
|
497 |
+ cython_help, banner(), sep="\n", file=sys.stderr) |
|
498 |
+ if error: |
|
482 | 499 |
exit(1) |
483 |
- else: |
|
484 |
- reason = "the option {} has not been given".format(CYTHON_OPTION) |
|
485 |
- dontworry = ('(Do not worry about this if you are building Kwant\n' |
|
486 |
- 'from unmodified sources, e.g. with "pip install".)\n') |
|
487 |
- print(banner(" Caution "), dontworry, |
|
488 |
- msg.format(reason, problematic_files), |
|
489 |
- banner(), sep='\n', file=sys.stderr) |
|
490 | 500 |
|
491 | 501 |
return result |
492 | 502 |
|
This reduces the number of global variables and makes the code easier to
understand.
... | ... |
@@ -59,49 +59,58 @@ CLASSIFIERS = """\ |
59 | 59 |
Operating System :: Microsoft :: Windows""" |
60 | 60 |
|
61 | 61 |
|
62 |
-# Let Kwant itself determine its own version. We cannot simply import kwant, as |
|
63 |
-# it is not built yet. |
|
64 |
-_dont_write_bytecode_saved = sys.dont_write_bytecode |
|
65 |
-sys.dont_write_bytecode = True |
|
66 |
-_common = imp.load_source('_common', 'kwant/_common.py') |
|
67 |
-sys.dont_write_bytecode = _dont_write_bytecode_saved |
|
68 |
- |
|
69 |
-version = _common.version |
|
70 |
-version_is_from_git = _common.version_is_from_git |
|
71 |
- |
|
72 |
-try: |
|
73 |
- sys.argv.remove(CYTHON_OPTION) |
|
74 |
- use_cython = True |
|
75 |
-except ValueError: |
|
76 |
- use_cython = version_is_from_git |
|
77 |
- |
|
78 |
-try: |
|
79 |
- sys.argv.remove(CYTHON_TRACE_OPTION) |
|
80 |
- trace_cython = True |
|
81 |
- if not use_cython: |
|
82 |
- print('error: --cython-trace provided, but cython will not be run', |
|
83 |
- file=sys.stderr) |
|
84 |
- exit(1) |
|
85 |
-except ValueError: |
|
86 |
- trace_cython = False |
|
62 |
+distr_root = os.path.dirname(os.path.abspath(__file__)) |
|
63 |
+ |
|
64 |
+ |
|
65 |
+def get_version(): |
|
66 |
+ global version, version_is_from_git |
|
67 |
+ |
|
68 |
+ # Let Kwant itself determine its own version. We cannot simply import |
|
69 |
+ # kwant, as it is not built yet. |
|
70 |
+ _dont_write_bytecode_saved = sys.dont_write_bytecode |
|
71 |
+ sys.dont_write_bytecode = True |
|
72 |
+ _common = imp.load_source('_common', 'kwant/_common.py') |
|
73 |
+ sys.dont_write_bytecode = _dont_write_bytecode_saved |
|
74 |
+ |
|
75 |
+ version = _common.version |
|
76 |
+ version_is_from_git = _common.version_is_from_git |
|
77 |
+ |
|
78 |
+ |
|
79 |
+def init_cython(): |
|
80 |
+ global use_cython, cython_version, trace_cython, cythonize |
|
87 | 81 |
|
88 |
-if use_cython: |
|
89 | 82 |
try: |
90 |
- import Cython |
|
91 |
- from Cython.Build import cythonize |
|
92 |
- except ImportError: |
|
93 |
- cython_version = () |
|
94 |
- else: |
|
95 |
- match = re.match('([0-9.]*)(.*)', Cython.__version__) |
|
96 |
- cython_version = [int(n) for n in match.group(1).split('.')] |
|
97 |
- # Decrease version if the version string contains a suffix. |
|
98 |
- if match.group(2): |
|
99 |
- while cython_version[-1] == 0: |
|
100 |
- cython_version.pop() |
|
101 |
- cython_version[-1] -= 1 |
|
102 |
- cython_version = tuple(cython_version) |
|
83 |
+ sys.argv.remove(CYTHON_OPTION) |
|
84 |
+ use_cython = True |
|
85 |
+ except ValueError: |
|
86 |
+ use_cython = version_is_from_git |
|
87 |
+ |
|
88 |
+ try: |
|
89 |
+ sys.argv.remove(CYTHON_TRACE_OPTION) |
|
90 |
+ trace_cython = True |
|
91 |
+ if not use_cython: |
|
92 |
+ print('error: --cython-trace provided, but cython will not be run', |
|
93 |
+ file=sys.stderr) |
|
94 |
+ exit(1) |
|
95 |
+ except ValueError: |
|
96 |
+ trace_cython = False |
|
97 |
+ |
|
98 |
+ if use_cython: |
|
99 |
+ try: |
|
100 |
+ import Cython |
|
101 |
+ from Cython.Build import cythonize |
|
102 |
+ except ImportError: |
|
103 |
+ cython_version = () |
|
104 |
+ else: |
|
105 |
+ match = re.match('([0-9.]*)(.*)', Cython.__version__) |
|
106 |
+ cython_version = [int(n) for n in match.group(1).split('.')] |
|
107 |
+ # Decrease version if the version string contains a suffix. |
|
108 |
+ if match.group(2): |
|
109 |
+ while cython_version[-1] == 0: |
|
110 |
+ cython_version.pop() |
|
111 |
+ cython_version[-1] -= 1 |
|
112 |
+ cython_version = tuple(cython_version) |
|
103 | 113 |
|
104 |
-distr_root = os.path.dirname(os.path.abspath(__file__)) |
|
105 | 114 |
|
106 | 115 |
def banner(title=''): |
107 | 116 |
starred = title.center(79, '*') |
... | ... |
@@ -483,6 +492,9 @@ def maybe_cythonize(extensions): |
483 | 492 |
|
484 | 493 |
|
485 | 494 |
def main(): |
495 |
+ get_version() |
|
496 |
+ init_cython() |
|
497 |
+ |
|
486 | 498 |
setup(name='kwant', |
487 | 499 |
version=version, |
488 | 500 |
author='C. W. Groth (CEA), M. Wimmer, ' |
... | ... |
@@ -107,18 +107,6 @@ def banner(title=''): |
107 | 107 |
starred = title.center(79, '*') |
108 | 108 |
return '\n' + starred if title else starred |
109 | 109 |
|
110 |
-error_msg = """{header} |
|
111 |
-The compilation of Kwant has failed. Please examine the error message |
|
112 |
-above and consult the installation instructions in README.rst. |
|
113 |
-You might have to customize {{file}}. |
|
114 |
- |
|
115 |
-Build configuration was: |
|
116 |
- |
|
117 |
-{{summary}} |
|
118 |
-{sep} |
|
119 |
-""" |
|
120 |
-error_msg = error_msg.format(header=banner(' Error '), sep=banner()) |
|
121 |
- |
|
122 | 110 |
|
123 | 111 |
class kwant_build_ext(build_ext): |
124 | 112 |
def run(self): |
... | ... |
@@ -133,6 +121,8 @@ class kwant_build_ext(build_ext): |
133 | 121 |
try: |
134 | 122 |
build_ext.run(self) |
135 | 123 |
except (DistutilsError, CCompilerError): |
124 |
+ error_msg = self.__error_msg.format( |
|
125 |
+ header=banner(' Error '), sep=banner()) |
|
136 | 126 |
print(error_msg.format(file=CONFIG_FILE, summary=build_summary), |
137 | 127 |
file=sys.stderr) |
138 | 128 |
raise |
... | ... |
@@ -140,6 +130,17 @@ class kwant_build_ext(build_ext): |
140 | 130 |
print(build_summary) |
141 | 131 |
print(banner()) |
142 | 132 |
|
133 |
+ __error_msg = """{header} |
|
134 |
+The compilation of Kwant has failed. Please examine the error message |
|
135 |
+above and consult the installation instructions in README.rst. |
|
136 |
+You might have to customize {{file}}. |
|
137 |
+ |
|
138 |
+Build configuration was: |
|
139 |
+ |
|
140 |
+{{summary}} |
|
141 |
+{sep} |
|
142 |
+""" |
|
143 |
+ |
|
143 | 144 |
|
144 | 145 |
class kwant_build_tut(Command): |
145 | 146 |
description = "build the tutorial scripts" |
The removed code predates "build.conf" and should not be necessary on
most (all?) platforms. Should numpy be missing in the include path, it
can be added using "build.conf".
If this change turns out to cause problems, we can always revert it.
... | ... |
@@ -34,12 +34,6 @@ from distutils.command.build import build |
34 | 34 |
from setuptools.command.sdist import sdist |
35 | 35 |
from setuptools.command.build_ext import build_ext |
36 | 36 |
|
37 |
-try: |
|
38 |
- import numpy |
|
39 |
-except ImportError: |
|
40 |
- include_dirs = [] |
|
41 |
-else: |
|
42 |
- include_dirs = [numpy.get_include()] |
|
43 | 37 |
|
44 | 38 |
CONFIG_FILE = 'build.conf' |
45 | 39 |
README_FILE = 'README.rst' |
... | ... |
@@ -505,9 +499,8 @@ def main(): |
505 | 499 |
'build_ext': kwant_build_ext, |
506 | 500 |
'build_tut': kwant_build_tut}, |
507 | 501 |
ext_modules=maybe_cythonize(extensions()), |
508 |
- include_dirs=include_dirs, |
|
509 |
- setup_requires=['numpy > 1.6.1', 'pytest-runner >= 2.7'], |
|
510 |
- tests_require=['pytest >= 2.6.3'], |
|
502 |
+ setup_requires=['pytest-runner >= 2.7'], |
|
503 |
+ tests_require=['numpy > 1.6.1', 'pytest >= 2.6.3'], |
|
511 | 504 |
install_requires=['numpy > 1.6.1', 'scipy >= 0.9', 'tinyarray'], |
512 | 505 |
extras_require={'plotting': 'matplotlib >= 1.2'}, |
513 | 506 |
classifiers=[c.strip() for c in CLASSIFIERS.split('\n')]) |
... | ... |
@@ -1,6 +1,6 @@ |
1 | 1 |
#!/usr/bin/env python3 |
2 | 2 |
|
3 |
-# Copyright 2011-2015 Kwant authors. |
|
3 |
+# Copyright 2011-2016 Kwant authors. |
|
4 | 4 |
# |
5 | 5 |
# This file is part of Kwant. It is subject to the license terms in the file |
6 | 6 |
# LICENSE.rst found in the top-level directory of this distribution and at |
... | ... |
@@ -395,11 +395,15 @@ def complain_cython_unavailable(): |
395 | 395 |
file=sys.stderr) |
396 | 396 |
|
397 | 397 |
|
398 |
-def ext_modules(extensions): |
|
399 |
- """Prepare the ext_modules argument for setuptools. |
|
398 |
+def maybe_cythonize(extensions): |
|
399 |
+ """Prepare a list of `Extension` instances, ready for `setup()`. |
|
400 | 400 |
|
401 |
- If Cython is not to be run, replace .pyx extensions with .c or .cpp, and |
|
402 |
- check timestamps. |
|
401 |
+ The argument `extensions` must be a sequence of (args, kwrds) to be passed on |
|
402 |
+ to `Extension`. |
|
403 |
+ |
|
404 |
+ If Cython is to be run, create the extensions and calls `cythonize()` on |
|
405 |
+ them. If Cython is not to be run, replace .pyx file with .c or .cpp, |
|
406 |
+ check timestamps, and create the extensions. |
|
403 | 407 |
""" |
404 | 408 |
if use_cython and cython_version >= REQUIRED_CYTHON_VERSION: |
405 | 409 |
return cythonize([Extension(*args, **kwrds) |
... | ... |
@@ -500,7 +504,7 @@ def main(): |
500 | 504 |
'sdist': kwant_sdist, |
501 | 505 |
'build_ext': kwant_build_ext, |
502 | 506 |
'build_tut': kwant_build_tut}, |
503 |
- ext_modules=ext_modules(extensions()), |
|
507 |
+ ext_modules=maybe_cythonize(extensions()), |
|
504 | 508 |
include_dirs=include_dirs, |
505 | 509 |
setup_requires=['numpy > 1.6.1', 'pytest-runner >= 2.7'], |
506 | 510 |
tests_require=['pytest >= 2.6.3'], |
... | ... |
@@ -404,8 +404,7 @@ def ext_modules(extensions): |
404 | 404 |
if use_cython and cython_version >= REQUIRED_CYTHON_VERSION: |
405 | 405 |
return cythonize([Extension(*args, **kwrds) |
406 | 406 |
for args, kwrds in extensions], language_level=3, |
407 |
- compiler_directives={'linetrace': trace_cython} |
|
408 |
- ) |
|
407 |
+ compiler_directives={'linetrace': trace_cython}) |
|
409 | 408 |
|
410 | 409 |
# Cython is not going to be run: replace pyx extension by that of |
411 | 410 |
# the shipped translated file. |
... | ... |
@@ -306,6 +306,8 @@ def extensions(): |
306 | 306 |
result = [ |
307 | 307 |
(['kwant._system', ['kwant/_system.pyx']], |
308 | 308 |
{'include_dirs': ['kwant/graph']}), |
309 |
+ (['kwant.operator', ['kwant/operator.pyx']], |
|
310 |
+ {'include_dirs': ['kwant/graph']}), |
|
309 | 311 |
(['kwant.graph.core', ['kwant/graph/core.pyx']], |
310 | 312 |
{'depends': ['kwant/graph/core.pxd', 'kwant/graph/defs.h', |
311 | 313 |
'kwant/graph/defs.pxd']}), |
... | ... |
@@ -48,6 +48,7 @@ README_END_BEFORE = 'See also in this directory:' |
48 | 48 |
STATIC_VERSION_PATH = ('kwant', '_kwant_version.py') |
49 | 49 |
REQUIRED_CYTHON_VERSION = (0, 22) |
50 | 50 |
CYTHON_OPTION = '--cython' |
51 |
+CYTHON_TRACE_OPTION = '--cython-trace' |
|
51 | 52 |
TUT_DIR = 'tutorial' |
52 | 53 |
TUT_GLOB = 'doc/source/tutorial/*.py' |
53 | 54 |
TUT_HIDDEN_PREFIX = '#HIDDEN' |
... | ... |
@@ -80,6 +81,16 @@ try: |
80 | 81 |
except ValueError: |
81 | 82 |
use_cython = version_is_from_git |
82 | 83 |
|
84 |
+try: |
|
85 |
+ sys.argv.remove(CYTHON_TRACE_OPTION) |
|
86 |
+ trace_cython = True |
|
87 |
+ if not use_cython: |
|
88 |
+ print('error: --cython-trace provided, but cython will not be run', |
|
89 |
+ file=sys.stderr) |
|
90 |
+ exit(1) |
|
91 |
+except ValueError: |
|
92 |
+ trace_cython = False |
|
93 |
+ |
|
83 | 94 |
if use_cython: |
84 | 95 |
try: |
85 | 96 |
import Cython |
... | ... |
@@ -312,6 +323,13 @@ def extensions(): |
312 | 323 |
'kwant/graph/c_slicer/partitioner.h', |
313 | 324 |
'kwant/graph/c_slicer/slicer.h']})] |
314 | 325 |
|
326 |
+ #### Add cython tracing macro |
|
327 |
+ if trace_cython: |
|
328 |
+ for args, kwargs in result: |
|
329 |
+ macros = kwargs.get('define_macros', []) |
|
330 |
+ macros.append(('CYTHON_TRACE', '1')) |
|
331 |
+ kwargs['define_macros'] = macros |
|
332 |
+ |
|
315 | 333 |
#### Add components of Kwant with external compile-time dependencies. |
316 | 334 |
config = configparser.ConfigParser() |
317 | 335 |
try: |
... | ... |
@@ -383,7 +401,9 @@ def ext_modules(extensions): |
383 | 401 |
""" |
384 | 402 |
if use_cython and cython_version >= REQUIRED_CYTHON_VERSION: |
385 | 403 |
return cythonize([Extension(*args, **kwrds) |
386 |
- for args, kwrds in extensions], language_level=3) |
|
404 |
+ for args, kwrds in extensions], language_level=3, |
|
405 |
+ compiler_directives={'linetrace': trace_cython} |
|
406 |
+ ) |
|
387 | 407 |
|
388 | 408 |
# Cython is not going to be run: replace pyx extension by that of |
389 | 409 |
# the shipped translated file. |
... | ... |
@@ -475,14 +475,14 @@ def main(): |
475 | 475 |
url="http://kwant-project.org/", |
476 | 476 |
license="BSD", |
477 | 477 |
packages=find_packages('.'), |
478 |
- test_suite = 'nose.collector', |
|
479 | 478 |
cmdclass={'build': kwant_build, |
480 | 479 |
'sdist': kwant_sdist, |
481 | 480 |
'build_ext': kwant_build_ext, |
482 | 481 |
'build_tut': kwant_build_tut}, |
483 | 482 |
ext_modules=ext_modules(extensions()), |
484 | 483 |
include_dirs=include_dirs, |
485 |
- setup_requires=['numpy > 1.6.1', 'nose >= 1.0'], |
|
484 |
+ setup_requires=['numpy > 1.6.1', 'pytest-runner >= 2.7'], |
|
485 |
+ tests_require=['pytest >= 2.6.3'], |
|
486 | 486 |
install_requires=['numpy > 1.6.1', 'scipy >= 0.9', 'tinyarray'], |
487 | 487 |
extras_require={'plotting': 'matplotlib >= 1.2'}, |
488 | 488 |
classifiers=[c.strip() for c in CLASSIFIERS.split('\n')]) |
... | ... |
@@ -473,7 +473,8 @@ def main(): |
473 | 473 |
author='C. W. Groth (CEA), M. Wimmer, ' |
474 | 474 |
'A. R. Akhmerov, X. Waintal (CEA), and others', |
475 | 475 |
author_email='authors@kwant-project.org', |
476 |
- description="Package for numerical quantum transport calculations.", |
|
476 |
+ description=("Package for numerical quantum transport calculations " |
|
477 |
+ "(Python 2 version)"), |
|
477 | 478 |
long_description=long_description(), |
478 | 479 |
platforms=["Unix", "Linux", "Mac OS-X", "Windows"], |
479 | 480 |
url="http://kwant-project.org/", |
... | ... |
@@ -13,10 +13,10 @@ from __future__ import print_function |
13 | 13 |
import sys |
14 | 14 |
|
15 | 15 |
v = sys.version_info |
16 |
-if v[:2] not in [(2, 7), (2, 6)]: |
|
17 |
- error = "This version of Kwant requires Python 2.6 or 2.7.\n" |
|
18 |
- if v[0] >= 2: |
|
19 |
- error += "Please use Kwant 1.2 or above." |
|
16 |
+if v[:2] < (3, 4): |
|
17 |
+ error = "This version of Kwant requires Python 3.4 or above.\n" |
|
18 |
+ if v[0] == 2: |
|
19 |
+ error += "Kwant 1.1 is the last version to support Python 2." |
|
20 | 20 |
print(error, file=sys.stderr) |
21 | 21 |
sys.exit(1) |
22 | 22 |
|
... | ... |
@@ -51,6 +51,18 @@ CYTHON_OPTION = '--cython' |
51 | 51 |
TUT_DIR = 'tutorial' |
52 | 52 |
TUT_GLOB = 'doc/source/tutorial/*.py' |
53 | 53 |
TUT_HIDDEN_PREFIX = '#HIDDEN' |
54 |
+CLASSIFIERS = """\ |
|
55 |
+ Development Status :: 5 - Production/Stable |
|
56 |
+ Intended Audience :: Science/Research |
|
57 |
+ Intended Audience :: Developers |
|
58 |
+ Programming Language :: Python :: 2 |
|
59 |
+ Topic :: Software Development |
|
60 |
+ Topic :: Scientific/Engineering |
|
61 |
+ Operating System :: POSIX |
|
62 |
+ Operating System :: Unix |
|
63 |
+ Operating System :: MacOS :: MacOS X |
|
64 |
+ Operating System :: Microsoft :: Windows""" |
|
65 |
+ |
|
54 | 66 |
|
55 | 67 |
# Let Kwant itself determine its own version. We cannot simply import kwant, as |
56 | 68 |
# it is not built yet. |
... | ... |
@@ -476,7 +488,8 @@ def main(): |
476 | 488 |
include_dirs=include_dirs, |
477 | 489 |
setup_requires=['numpy > 1.6.1', 'nose >= 1.0'], |
478 | 490 |
install_requires=['numpy > 1.6.1', 'scipy >= 0.9', 'tinyarray'], |
479 |
- extras_require={'plotting': 'matplotlib >= 1.2'}) |
|
491 |
+ extras_require={'plotting': 'matplotlib >= 1.2'}, |
|
492 |
+ classifiers=[c.strip() for c in CLASSIFIERS.split('\n')]) |
|
480 | 493 |
|
481 | 494 |
if __name__ == '__main__': |
482 | 495 |
main() |
... | ... |
@@ -11,6 +11,15 @@ |
11 | 11 |
from __future__ import print_function |
12 | 12 |
|
13 | 13 |
import sys |
14 |
+ |
|
15 |
+v = sys.version_info |
|
16 |
+if v[:2] not in [(2, 7), (2, 6)]: |
|
17 |
+ error = "This version of Kwant requires Python 2.6 or 2.7.\n" |
|
18 |
+ if v[0] >= 2: |
|
19 |
+ error += "Please use Kwant 1.2 or above." |
|
20 |
+ print(error, file=sys.stderr) |
|
21 |
+ sys.exit(1) |
|
22 |
+ |
|
14 | 23 |
import re |
15 | 24 |
import os |
16 | 25 |
import glob |
... | ... |
@@ -374,7 +374,7 @@ def ext_modules(extensions): |
374 | 374 |
""" |
375 | 375 |
if use_cython and cython_version >= REQUIRED_CYTHON_VERSION: |
376 | 376 |
return cythonize([Extension(*args, **kwrds) |
377 |
- for args, kwrds in extensions]) |
|
377 |
+ for args, kwrds in extensions], language_level=3) |
|
378 | 378 |
|
379 | 379 |
# Cython is not going to be run: replace pyx extension by that of |
380 | 380 |
# the shipped translated file. |
... | ... |
@@ -235,7 +235,7 @@ def write_version(fname): |
235 | 235 |
pass |
236 | 236 |
with open(fname, 'w') as f: |
237 | 237 |
f.write("# This file has been created by setup.py.\n") |
238 |
- f.write("version = '{}'".format(version)) |
|
238 |
+ f.write("version = '{}'\n".format(version)) |
|
239 | 239 |
|
240 | 240 |
|
241 | 241 |
def long_description(): |
Now we exec _kwant_version.py into a namespace and get
the version from that.
... | ... |
@@ -173,7 +173,7 @@ def git_lsfiles(): |
173 | 173 |
|
174 | 174 |
if p.wait() != 0: |
175 | 175 |
return |
176 |
- return p.communicate()[0].split('\n')[:-1] |
|
176 |
+ return p.communicate()[0].decode().split('\n')[:-1] |
|
177 | 177 |
|
178 | 178 |
|
179 | 179 |
# Make the command "sdist" depend on "build". This verifies that the |
... | ... |
@@ -235,7 +235,7 @@ def write_version(fname): |
235 | 235 |
pass |
236 | 236 |
with open(fname, 'w') as f: |
237 | 237 |
f.write("# This file has been created by setup.py.\n") |
238 |
- f.write(version) |
|
238 |
+ f.write("version = '{}'".format(version)) |
|
239 | 239 |
|
240 | 240 |
|
241 | 241 |
def long_description(): |
... | ... |
@@ -43,7 +43,7 @@ TUT_DIR = 'tutorial' |
43 | 43 |
TUT_GLOB = 'doc/source/tutorial/*.py' |
44 | 44 |
TUT_HIDDEN_PREFIX = '#HIDDEN' |
45 | 45 |
CLASSIFIERS = """\ |
46 |
- Development Status :: 4 - Beta |
|
46 |
+ Development Status :: 5 - Production/Stable |
|
47 | 47 |
Intended Audience :: Science/Research |
48 | 48 |
Intended Audience :: Developers |
49 | 49 |
Programming Language :: Python :: 3 :: Only |
Specify only Python3 support in trove classifiers.
https://www.python.org/dev/peps/pep-0301/#distutils-trove-classification
... | ... |
@@ -42,6 +42,18 @@ CYTHON_OPTION = '--cython' |
42 | 42 |
TUT_DIR = 'tutorial' |
43 | 43 |
TUT_GLOB = 'doc/source/tutorial/*.py' |
44 | 44 |
TUT_HIDDEN_PREFIX = '#HIDDEN' |
45 |
+CLASSIFIERS = """\ |
|
46 |
+ Development Status :: 4 - Beta |
|
47 |
+ Intended Audience :: Science/Research |
|
48 |
+ Intended Audience :: Developers |
|
49 |
+ Programming Language :: Python :: 3 :: Only |
|
50 |
+ Topic :: Software Development |
|
51 |
+ Topic :: Scientific/Engineering |
|
52 |
+ Operating System :: POSIX |
|
53 |
+ Operating System :: Unix |
|
54 |
+ Operating System :: MacOS :: MacOS X |
|
55 |
+ Operating System :: Microsoft :: Windows""" |
|
56 |
+ |
|
45 | 57 |
|
46 | 58 |
# Let Kwant itself determine its own version. We cannot simply import kwant, as |
47 | 59 |
# it is not built yet. |
... | ... |
@@ -462,7 +474,8 @@ def main(): |
462 | 474 |
include_dirs=include_dirs, |
463 | 475 |
setup_requires=['numpy > 1.6.1', 'nose >= 1.0'], |
464 | 476 |
install_requires=['numpy > 1.6.1', 'scipy >= 0.9', 'tinyarray'], |
465 |
- extras_require={'plotting': 'matplotlib >= 1.2'}) |
|
477 |
+ extras_require={'plotting': 'matplotlib >= 1.2'}, |
|
478 |
+ classifiers=[c.strip() for c in CLASSIFIERS.split('\n')]) |
|
466 | 479 |
|
467 | 480 |
if __name__ == '__main__': |
468 | 481 |
main() |
Python 3 no longer allows implicit relative imports:
https://docs.python.org/release/3.0.1/whatsnew/3.0.html#removed-syntax
Instead of importing the version file we just parse it. By keeping
the extension ".py" we make it so that it will be distributed along
with the rest of the package.
... | ... |
@@ -47,11 +47,6 @@ TUT_HIDDEN_PREFIX = '#HIDDEN' |
47 | 47 |
# it is not built yet. |
48 | 48 |
_dont_write_bytecode_saved = sys.dont_write_bytecode |
49 | 49 |
sys.dont_write_bytecode = True |
50 |
-try: |
|
51 |
- imp.load_source(STATIC_VERSION_PATH[-1].split('.')[0], |
|
52 |
- os.path.join(*STATIC_VERSION_PATH)) |
|
53 |
-except IOError: |
|
54 |
- pass |
|
55 | 50 |
_common = imp.load_source('_common', 'kwant/_common.py') |
56 | 51 |
sys.dont_write_bytecode = _dont_write_bytecode_saved |
57 | 52 |
|
... | ... |
@@ -228,7 +223,7 @@ def write_version(fname): |
228 | 223 |
pass |
229 | 224 |
with open(fname, 'w') as f: |
230 | 225 |
f.write("# This file has been created by setup.py.\n") |
231 |
- f.write("version = '{}'\n".format(version)) |
|
226 |
+ f.write(version) |
|
232 | 227 |
|
233 | 228 |
|
234 | 229 |
def long_description(): |
... | ... |
@@ -16,7 +16,7 @@ import os |
16 | 16 |
import glob |
17 | 17 |
import imp |
18 | 18 |
import subprocess |
19 |
-import ConfigParser |
|
19 |
+import configparser |
|
20 | 20 |
from setuptools import setup, find_packages, Extension, Command |
21 | 21 |
from sysconfig import get_platform |
22 | 22 |
from distutils.errors import DistutilsError, DistutilsModuleError, \ |
... | ... |
@@ -263,7 +263,7 @@ def search_mumps(): |
263 | 263 |
except OSError: |
264 | 264 |
pass |
265 | 265 |
else: |
266 |
- p.communicate(input='int main() {}\n') |
|
266 |
+ p.communicate(input=b'int main() {}\n') |
|
267 | 267 |
if p.wait() == 0: |
268 | 268 |
return {'libraries': libs} |
269 | 269 |
return {} |
... | ... |
@@ -297,7 +297,7 @@ def extensions(): |
297 | 297 |
'kwant/graph/c_slicer/slicer.h']})] |
298 | 298 |
|
299 | 299 |
#### Add components of Kwant with external compile-time dependencies. |
300 |
- config = ConfigParser.ConfigParser() |
|
300 |
+ config = configparser.ConfigParser() |
|
301 | 301 |
try: |
302 | 302 |
with open(CONFIG_FILE) as f: |
303 | 303 |
config.readfp(f) |
... | ... |
@@ -334,7 +334,7 @@ def extensions(): |
334 | 334 |
if kwrds: |
335 | 335 |
build_summary.append('Auto-configured MUMPS') |
336 | 336 |
if kwrds: |
337 |
- for name, value in lapack.iteritems(): |
|
337 |
+ for name, value in lapack.items(): |
|
338 | 338 |
kwrds.setdefault(name, []).extend(value) |
339 | 339 |
kwrds.setdefault('depends', []).extend( |
340 | 340 |
[CONFIG_FILE, 'kwant/linalg/cmumps.pxd']) |
... | ... |
@@ -355,7 +355,7 @@ def complain_cython_unavailable(): |
355 | 355 |
ver = '.'.join(str(e) for e in REQUIRED_CYTHON_VERSION) |
356 | 356 |
print(msg.format(ver), file=sys.stderr) |
357 | 357 |
else: |
358 |
- print("Run setup.py without {}.".format(NO_CYTHON_OPTION), |
|
358 |
+ print("Run setup.py with the {} option.".format(CYTHON_OPTION), |
|
359 | 359 |
file=sys.stderr) |
360 | 360 |
|
361 | 361 |
|
... | ... |
@@ -209,12 +209,10 @@ class kwant_sdist(sdist): |
209 | 209 |
sdist.run(self) |
210 | 210 |
|
211 | 211 |
if names is None: |
212 |
- print(banner(' Warning '), |
|
213 |
- |
|
212 |
+ print(banner(' Caution '), |
|
214 | 213 |
"""Git was not available to generate the list of files to be included in the |
215 |
-source distribution. The old MANIFEST.in was used.""", |
|
216 |
- banner(), |
|
217 |
- sep='\n', file=sys.stderr) |
|
214 |
+source distribution. The old {} was used.""".format(MANIFEST_IN_FILE), |
|
215 |
+ banner(), sep='\n', file=sys.stderr) |
|
218 | 216 |
|
219 | 217 |
def make_release_tree(self, base_dir, files): |
220 | 218 |
sdist.make_release_tree(self, base_dir, files) |
The pip tool messes up the timestamps of files, so with our previous strategy
of enabling cython by default the build fails if Cython is not available.
Also, turn the "warning" into a "caution" message that is less frightening and
send it to stdout only, so that it does not appear with pip.
... | ... |
@@ -38,7 +38,7 @@ MANIFEST_IN_FILE = 'MANIFEST.in' |
38 | 38 |
README_END_BEFORE = 'See also in this directory:' |
39 | 39 |
STATIC_VERSION_PATH = ('kwant', '_kwant_version.py') |
40 | 40 |
REQUIRED_CYTHON_VERSION = (0, 22) |
41 |
-NO_CYTHON_OPTION = '--no-cython' |
|
41 |
+CYTHON_OPTION = '--cython' |
|
42 | 42 |
TUT_DIR = 'tutorial' |
43 | 43 |
TUT_GLOB = 'doc/source/tutorial/*.py' |
44 | 44 |
TUT_HIDDEN_PREFIX = '#HIDDEN' |
... | ... |
@@ -59,10 +59,10 @@ version = _common.version |
59 | 59 |
version_is_from_git = _common.version_is_from_git |
60 | 60 |
|
61 | 61 |
try: |
62 |
- sys.argv.remove(NO_CYTHON_OPTION) |
|
63 |
- use_cython = False |
|
64 |
-except ValueError: |
|
62 |
+ sys.argv.remove(CYTHON_OPTION) |
|
65 | 63 |
use_cython = True |
64 |
+except ValueError: |
|
65 |
+ use_cython = False |
|
66 | 66 |
|
67 | 67 |
if use_cython: |
68 | 68 |
try: |
... | ... |
@@ -424,7 +424,7 @@ def ext_modules(extensions): |
424 | 424 |
if problematic_files: |
425 | 425 |
problematic_files = ", ".join(problematic_files) |
426 | 426 |
msg = ("Some Cython source files are newer than files that should have\n" |
427 |
- " been derived from them, but {}.\n" |
|
427 |
+ "been derived from them, but {}.\n" |
|
428 | 428 |
"\n" |
429 | 429 |
"Affected files: {}") |
430 | 430 |
if use_cython: |
... | ... |
@@ -438,8 +438,11 @@ def ext_modules(extensions): |
438 | 438 |
complain_cython_unavailable() |
439 | 439 |
exit(1) |
440 | 440 |
else: |
441 |
- reason = "the option --no-cython has been given" |
|
442 |
- print(banner(" Warning "), msg.format(reason, problematic_files), |
|
441 |
+ reason = "the option {} has not been given".format(CYTHON_OPTION) |
|
442 |
+ dontworry = ('(Do not worry about this if you are building Kwant\n' |
|
443 |
+ 'from unmodified sources, e.g. with "pip install".)\n') |
|
444 |
+ print(banner(" Caution "), dontworry, |
|
445 |
+ msg.format(reason, problematic_files), |
|
443 | 446 |
banner(), sep='\n', file=sys.stderr) |
444 | 447 |
|
445 | 448 |
return result |
This offers better dependency handling (the compilation of some .c files
depends on build.conf, but their cythonization doesn't), and other advantages
like parallel builds.
... | ... |
@@ -60,14 +60,15 @@ version_is_from_git = _common.version_is_from_git |
60 | 60 |
|
61 | 61 |
try: |
62 | 62 |
sys.argv.remove(NO_CYTHON_OPTION) |
63 |
- cythonize = False |
|
63 |
+ use_cython = False |
|
64 | 64 |
except ValueError: |
65 |
- cythonize = True |
|
65 |
+ use_cython = True |
|
66 | 66 |
|
67 |
-if cythonize: |
|
67 |
+if use_cython: |
|
68 | 68 |
try: |
69 | 69 |
import Cython |
70 |
- except: |
|
70 |
+ from Cython.Build import cythonize |
|
71 |
+ except ImportError: |
|
71 | 72 |
cython_version = () |
72 | 73 |
else: |
73 | 74 |
match = re.match('([0-9.]*)(.*)', Cython.__version__) |
... | ... |
@@ -349,8 +350,8 @@ def extensions(): |
349 | 350 |
|
350 | 351 |
|
351 | 352 |
def complain_cython_unavailable(): |
352 |
- assert not cythonize or cython_version < REQUIRED_CYTHON_VERSION |
|
353 |
- if cythonize: |
|
353 |
+ assert not use_cython or cython_version < REQUIRED_CYTHON_VERSION |
|
354 |
+ if use_cython: |
|
354 | 355 |
msg = ("Install Cython {0} or newer so it can be made\n" |
355 | 356 |
"or use a source distribution of Kwant.") |
356 | 357 |
ver = '.'.join(str(e) for e in REQUIRED_CYTHON_VERSION) |
... | ... |
@@ -366,51 +367,57 @@ def ext_modules(extensions): |
366 | 367 |
If Cython is not to be run, replace .pyx extensions with .c or .cpp, and |
367 | 368 |
check timestamps. |
368 | 369 |
""" |
370 |
+ if use_cython and cython_version >= REQUIRED_CYTHON_VERSION: |
|
371 |
+ return cythonize([Extension(*args, **kwrds) |
|
372 |
+ for args, kwrds in extensions]) |
|
373 |
+ |
|
374 |
+ # Cython is not going to be run: replace pyx extension by that of |
|
375 |
+ # the shipped translated file. |
|
376 |
+ |
|
369 | 377 |
result = [] |
370 | 378 |
problematic_files = [] |
371 | 379 |
for args, kwrds in extensions: |
372 | 380 |
name, sources = args |
373 |
- if not cythonize or cython_version < REQUIRED_CYTHON_VERSION: |
|
374 |
- # Cython is not going to be run: replace pyx extension by that of |
|
375 |
- # the shipped translated file. |
|
376 |
- language = kwrds.get('language') |
|
377 |
- if language is None: |
|
378 |
- ext = '.c' |
|
379 |
- elif language == 'c': |
|
380 |
- ext = '.c' |
|
381 |
- elif language == 'c++': |
|
382 |
- ext = '.cpp' |
|
383 |
- else: |
|
384 |
- print('Unknown language: {}'.format(language), file=sys.stderr) |
|
385 |
- exit(1) |
|
386 | 381 |
|
387 |
- pyx_files = [] |
|
388 |
- cythonized_files = [] |
|
389 |
- new_sources = [] |
|
390 |
- for f in sources: |
|
391 |
- if f.endswith('.pyx'): |
|
392 |
- pyx_files.append(f) |
|
393 |
- f = f.rstrip('.pyx') + ext |
|
394 |
- cythonized_files.append(f) |
|
395 |
- new_sources.append(f) |
|
396 |
- sources = new_sources |
|
397 |
- |
|
398 |
- # Complain if cythonized files are older than Cython source files. |
|
399 |
- try: |
|
400 |
- cythonized_oldest = min(os.stat(f).st_mtime |
|
401 |
- for f in cythonized_files) |
|
402 |
- except OSError: |
|
403 |
- print("error: Cython-generated file {} is missing.".format(f), |
|
404 |
- file=sys.stderr) |
|
405 |
- complain_cython_unavailable() |
|
406 |
- exit(1) |
|
407 |
- for f in pyx_files + kwrds.get('depends', []): |
|
408 |
- if f == CONFIG_FILE: |
|
409 |
- # The config file is only a dependency for the compilation |
|
410 |
- # of the cythonized file, not for the cythonization. |
|
411 |
- continue |
|
412 |
- if os.stat(f).st_mtime > cythonized_oldest: |
|
413 |
- problematic_files.append(f) |
|
382 |
+ language = kwrds.get('language') |
|
383 |
+ if language is None: |
|
384 |
+ ext = '.c' |
|
385 |
+ elif language == 'c': |
|
386 |
+ ext = '.c' |
|
387 |
+ elif language == 'c++': |
|
388 |
+ ext = '.cpp' |
|
389 |
+ else: |
|
390 |
+ print('Unknown language: {}'.format(language), file=sys.stderr) |
|
391 |
+ exit(1) |
|
392 |
+ |
|
393 |
+ pyx_files = [] |
|
394 |
+ cythonized_files = [] |
|
395 |
+ new_sources = [] |
|
396 |
+ for f in sources: |
|
397 |
+ if f.endswith('.pyx'): |
|
398 |
+ pyx_files.append(f) |
|
399 |
+ f = f.rstrip('.pyx') + ext |
|
400 |
+ cythonized_files.append(f) |
|
401 |
+ new_sources.append(f) |
|
402 |
+ sources = new_sources |
|
403 |
+ |
|
404 |
+ # Complain if cythonized files are older than Cython source files. |
|
405 |
+ try: |
|
406 |
+ cythonized_oldest = min(os.stat(f).st_mtime |
|
407 |
+ for f in cythonized_files) |
|
408 |
+ except OSError: |
|
409 |
+ print("error: Cython-generated file {} is missing.".format(f), |
|
410 |
+ file=sys.stderr) |
|
411 |
+ complain_cython_unavailable() |
|
412 |
+ exit(1) |
|
413 |
+ |
|
414 |
+ for f in pyx_files + kwrds.get('depends', []): |
|
415 |
+ if f == CONFIG_FILE: |
|
416 |
+ # The config file is only a dependency for the compilation |
|
417 |
+ # of the cythonized file, not for the cythonization. |
|
418 |
+ continue |
|
419 |
+ if os.stat(f).st_mtime > cythonized_oldest: |
|
420 |
+ problematic_files.append(f) |
|
414 | 421 |
|
415 | 422 |
result.append(Extension(name, sources, **kwrds)) |
416 | 423 |
|
... | ... |
@@ -420,7 +427,7 @@ def ext_modules(extensions): |
420 | 427 |
" been derived from them, but {}.\n" |
421 | 428 |
"\n" |
422 | 429 |
"Affected files: {}") |
423 |
- if cythonize: |
|
430 |
+ if use_cython: |
|
424 | 431 |
if not cython_version: |
425 | 432 |
reason = "Cython is not installed" |
426 | 433 |
else: |
... | ... |
@@ -437,6 +444,7 @@ def ext_modules(extensions): |
437 | 444 |
|
438 | 445 |
return result |
439 | 446 |
|
447 |
+ |
|
440 | 448 |
def main(): |
441 | 449 |
setup(name='kwant', |
442 | 450 |
version=version, |
... | ... |
@@ -361,33 +361,39 @@ def complain_cython_unavailable(): |
361 | 361 |
|
362 | 362 |
|
363 | 363 |
def ext_modules(extensions): |
364 |
- """Prepare the ext_modules argument for distutils' setup.""" |
|
364 |
+ """Prepare the ext_modules argument for setuptools. |
|
365 |
+ |
|
366 |
+ If Cython is not to be run, replace .pyx extensions with .c or .cpp, and |
|
367 |
+ check timestamps. |
|
368 |
+ """ |
|
365 | 369 |
result = [] |
366 | 370 |
problematic_files = [] |
367 | 371 |
for args, kwrds in extensions: |
372 |
+ name, sources = args |
|
368 | 373 |
if not cythonize or cython_version < REQUIRED_CYTHON_VERSION: |
369 | 374 |
# Cython is not going to be run: replace pyx extension by that of |
370 | 375 |
# the shipped translated file. |
371 |
- if 'language' in kwrds: |
|
372 |
- if kwrds['language'] == 'c': |
|
373 |
- ext = '.c' |
|
374 |
- elif kwrds['language'] == 'c++': |
|
375 |
- ext = '.cpp' |
|
376 |
- else: |
|
377 |
- print('Unknown language', file=sys.stderr) |
|
378 |
- exit(1) |
|
379 |
- else: |
|
376 |
+ language = kwrds.get('language') |
|
377 |
+ if language is None: |
|
378 |
+ ext = '.c' |
|
379 |
+ elif language == 'c': |
|
380 | 380 |
ext = '.c' |
381 |
+ elif language == 'c++': |
|
382 |
+ ext = '.cpp' |
|
383 |
+ else: |
|
384 |
+ print('Unknown language: {}'.format(language), file=sys.stderr) |
|
385 |
+ exit(1) |
|
386 |
+ |
|
381 | 387 |
pyx_files = [] |
382 | 388 |
cythonized_files = [] |
383 |
- sources = [] |
|
384 |
- for f in args[1]: |
|
385 |
- if f[-4:] == '.pyx': |
|
389 |
+ new_sources = [] |
|
390 |
+ for f in sources: |
|
391 |
+ if f.endswith('.pyx'): |
|
386 | 392 |
pyx_files.append(f) |
387 |
- f = f[:-4] + ext |
|
393 |
+ f = f.rstrip('.pyx') + ext |
|
388 | 394 |
cythonized_files.append(f) |
389 |
- sources.append(f) |
|
390 |
- args[1] = sources |
|
395 |
+ new_sources.append(f) |
|
396 |
+ sources = new_sources |
|
391 | 397 |
|
392 | 398 |
# Complain if cythonized files are older than Cython source files. |
393 | 399 |
try: |
... | ... |
@@ -406,7 +412,7 @@ def ext_modules(extensions): |
406 | 412 |
if os.stat(f).st_mtime > cythonized_oldest: |
407 | 413 |
problematic_files.append(f) |
408 | 414 |
|
409 |
- result.append(Extension(*args, **kwrds)) |
|
415 |
+ result.append(Extension(name, sources, **kwrds)) |
|
410 | 416 |
|
411 | 417 |
if problematic_files: |
412 | 418 |
problematic_files = ", ".join(problematic_files) |
... | ... |
@@ -17,7 +17,7 @@ import glob |
17 | 17 |
import imp |
18 | 18 |
import subprocess |
19 | 19 |
import ConfigParser |
20 |
-from setuptools import setup, Extension, Command |
|
20 |
+from setuptools import setup, find_packages, Extension, Command |
|
21 | 21 |
from sysconfig import get_platform |
22 | 22 |
from distutils.errors import DistutilsError, DistutilsModuleError, \ |
23 | 23 |
CCompilerError |
... | ... |
@@ -247,12 +247,6 @@ def long_description(): |
247 | 247 |
return '\n'.join(text) |
248 | 248 |
|
249 | 249 |
|
250 |
-def packages(): |
|
251 |
- return [root.replace('/', '.') |
|
252 |
- for root, dnames, fnames in os.walk('kwant') |
|
253 |
- if '__init__.py' in fnames or root.endswith('/tests')] |
|
254 |
- |
|
255 |
- |
|
256 | 250 |
def search_mumps(): |
257 | 251 |
"""Return the configuration for MUMPS if it is available in a known way. |
258 | 252 |
|
... | ... |
@@ -448,7 +442,7 @@ def main(): |
448 | 442 |
platforms=["Unix", "Linux", "Mac OS-X", "Windows"], |
449 | 443 |
url="http://kwant-project.org/", |
450 | 444 |
license="BSD", |
451 |
- packages=packages(), |
|
445 |
+ packages=find_packages('.'), |
|
452 | 446 |
test_suite = 'nose.collector', |
453 | 447 |
cmdclass={'build': kwant_build, |
454 | 448 |
'sdist': kwant_sdist, |
... | ... |
@@ -25,7 +25,12 @@ from distutils.command.build import build |
25 | 25 |
from setuptools.command.sdist import sdist |
26 | 26 |
from setuptools.command.build_ext import build_ext |
27 | 27 |
|
28 |
-import numpy |
|
28 |
+try: |
|
29 |
+ import numpy |
|
30 |
+except ImportError: |
|
31 |
+ include_dirs = [] |
|
32 |
+else: |
|
33 |
+ include_dirs = [numpy.get_include()] |
|
29 | 34 |
|
30 | 35 |
CONFIG_FILE = 'build.conf' |
31 | 36 |
README_FILE = 'README.rst' |
... | ... |
@@ -432,7 +437,6 @@ def ext_modules(extensions): |
432 | 437 |
|
433 | 438 |
return result |
434 | 439 |
|
435 |
- |
|
436 | 440 |
def main(): |
437 | 441 |
setup(name='kwant', |
438 | 442 |
version=version, |
... | ... |
@@ -451,7 +455,7 @@ def main(): |
451 | 455 |
'build_ext': kwant_build_ext, |
452 | 456 |
'build_tut': kwant_build_tut}, |
453 | 457 |
ext_modules=ext_modules(extensions()), |
454 |
- include_dirs=[numpy.get_include()], |
|
458 |
+ include_dirs=include_dirs, |
|
455 | 459 |
setup_requires=['numpy > 1.6.1', 'nose >= 1.0'], |
456 | 460 |
install_requires=['numpy > 1.6.1', 'scipy >= 0.9', 'tinyarray'], |
457 | 461 |
extras_require={'plotting': 'matplotlib >= 1.2'}) |
... | ... |
@@ -2,10 +2,10 @@ |
2 | 2 |
|
3 | 3 |
# Copyright 2011-2015 Kwant authors. |
4 | 4 |
# |
5 |
-# This file is part of Kwant. It is subject to the license terms in the |
|
6 |
-# LICENSE file found in the top-level directory of this distribution and at |
|
5 |
+# This file is part of Kwant. It is subject to the license terms in the file |
|
6 |
+# LICENSE.rst found in the top-level directory of this distribution and at |
|
7 | 7 |
# http://kwant-project.org/license. A list of Kwant authors can be found in |
8 |
-# the AUTHORS file at the top-level directory of this distribution and at |
|
8 |
+# the file AUTHORS.rst at the top-level directory of this distribution and at |
|
9 | 9 |
# http://kwant-project.org/authors. |
10 | 10 |
|
11 | 11 |
from __future__ import print_function |
... | ... |
@@ -17,17 +17,19 @@ import glob |
17 | 17 |
import imp |
18 | 18 |
import subprocess |
19 | 19 |
import ConfigParser |
20 |
-from distutils.core import setup, Extension, Command |
|
21 |
-from distutils.util import get_platform |
|
20 |
+from setuptools import setup, Extension, Command |
|
21 |
+from sysconfig import get_platform |
|
22 | 22 |
from distutils.errors import DistutilsError, DistutilsModuleError, \ |
23 | 23 |
CCompilerError |
24 | 24 |
from distutils.command.build import build |
25 |
-from distutils.command.sdist import sdist |
|
25 |
+from setuptools.command.sdist import sdist |
|
26 |
+from setuptools.command.build_ext import build_ext |
|
26 | 27 |
|
27 | 28 |
import numpy |
28 | 29 |
|
29 | 30 |
CONFIG_FILE = 'build.conf' |
30 | 31 |
README_FILE = 'README.rst' |
32 |
+MANIFEST_IN_FILE = 'MANIFEST.in' |
|
31 | 33 |
README_END_BEFORE = 'See also in this directory:' |
32 | 34 |
STATIC_VERSION_PATH = ('kwant', '_kwant_version.py') |
33 | 35 |
REQUIRED_CYTHON_VERSION = (0, 22) |
... | ... |
@@ -72,11 +74,6 @@ if cythonize: |
72 | 74 |
cython_version[-1] -= 1 |
73 | 75 |
cython_version = tuple(cython_version) |
74 | 76 |
|
75 |
-if cythonize and cython_version: |
|
76 |
- from Cython.Distutils import build_ext |
|
77 |
-else: |
|
78 |
- from distutils.command.build_ext import build_ext |
|
79 |
- |
|
80 | 77 |
distr_root = os.path.dirname(os.path.abspath(__file__)) |
81 | 78 |
|
82 | 79 |
def banner(title=''): |
... | ... |
@@ -95,6 +92,7 @@ Build configuration was: |
95 | 92 |
""" |
96 | 93 |
error_msg = error_msg.format(header=banner(' Error '), sep=banner()) |
97 | 94 |
|
95 |
+ |
|
98 | 96 |
class kwant_build_ext(build_ext): |
99 | 97 |
def run(self): |
100 | 98 |
if not config_file_present: |
... | ... |
@@ -150,30 +148,6 @@ class kwant_build(build): |
150 | 148 |
write_version(os.path.join(self.build_lib, *STATIC_VERSION_PATH)) |
151 | 149 |
|
152 | 150 |
|
153 |
-class kwant_test(Command): |
|
154 |
- description = "build, then run the unit tests" |
|
155 |
- user_options = [] |
|
156 |
- |
|
157 |
- def initialize_options(self): |
|
158 |
- pass |
|
159 |
- |
|
160 |
- def finalize_options(self): |
|
161 |
- pass |
|
162 |
- |
|
163 |
- def run(self): |
|
164 |
- try: |
|
165 |
- from nose.core import run |
|
166 |
- except ImportError: |
|
167 |
- raise DistutilsModuleError('nose <http://nose.readthedocs.org/> ' |
|
168 |
- 'is needed to run the tests') |
|
169 |
- self.run_command('build') |
|
170 |
- major, minor = sys.version_info[:2] |
|
171 |
- lib_dir = "build/lib.{0}-{1}.{2}".format(get_platform(), major, minor) |
|
172 |
- print() |
|
173 |
- if not run(argv=[__file__, '-v', lib_dir]): |
|
174 |
- raise DistutilsError('at least one of the tests failed') |
|
175 |
- |
|
176 |
- |
|
177 | 151 |
def git_lsfiles(): |
178 | 152 |
if not version_is_from_git: |
179 | 153 |
return |
... | ... |
@@ -197,45 +171,42 @@ class kwant_sdist(sdist): |
197 | 171 |
sub_commands = [('build', None)] + sdist.sub_commands |
198 | 172 |
|
199 | 173 |
def run(self): |
174 |
+ """ |
|
175 |
+ Create MANIFEST.in from git if possible, otherwise check that MANIFEST.in |
|
176 |
+ is present. |
|
177 |
+ |
|
178 |
+ Right now (2015) generating MANIFEST.in seems to be the only way to |
|
179 |
+ include files in the source distribution that setuptools does not think |
|
180 |
+ should be there. Setting include_package_data to True makes setuptools |
|
181 |
+ include *.pyx and other source files in the binary distribution. |
|
182 |
+ """ |
|
183 |
+ manifest = os.path.join(distr_root, MANIFEST_IN_FILE) |
|
200 | 184 |
names = git_lsfiles() |
201 |
- trustworthy = True |
|
202 | 185 |
if names is None: |
203 |
- # Check that MANIFEST exists and has not been generated by |
|
204 |
- # distutils. |
|
205 |
- try: |
|
206 |
- with open(distr_root + '/MANIFEST', 'r') as f: |
|
207 |
- line = f.read() |
|
208 |
- except IOError: |
|
209 |
- print("Error: MANIFEST file is missing and Git is not" |
|
210 |
- " available to regenerate it.", file=sys.stderr) |
|
186 |
+ if not (os.path.isfile(manifest) and os.access(manifest, os.R_OK)): |
|
187 |
+ print("Error:", MANIFEST_IN_FILE, |
|
188 |
+ "file is missing and Git is not available" |
|
189 |
+ " to regenerate it.", file=sys.stderr) |
|
211 | 190 |
exit(1) |
212 |
- trustworthy = not line.strip().startswith('#') |
|
213 | 191 |
else: |
214 |
- # Generate MANIFEST file. |
|
215 |
- with open(distr_root + '/MANIFEST', 'w') as f: |
|
192 |
+ with open(manifest, 'w') as f: |
|
216 | 193 |
for name in names: |
217 | 194 |
a, sep, b = name.rpartition('/') |
218 | 195 |
if b == '.gitignore': |
219 | 196 |
continue |
220 | 197 |
stem, dot, extension = b.rpartition('.') |
198 |
+ f.write('include {}'.format(name)) |
|
221 | 199 |
if extension == 'pyx': |
222 |
- f.write(''.join([a, sep, stem, dot, 'c', '\n'])) |
|
223 |
- f.write(name + '\n') |
|
224 |
- f.write('MANIFEST\n') |
|
200 |
+ f.write(''.join([' ', a, sep, stem, dot, 'c'])) |
|
201 |
+ f.write('\n') |
|
225 | 202 |
|
226 | 203 |
sdist.run(self) |
227 | 204 |
|
228 | 205 |
if names is None: |
229 | 206 |
print(banner(' Warning '), |
230 |
-"""Git was not available for re-generating the MANIFEST file (the list of file |
|
231 |
-names to be included in the source distribution). The old MANIFEST was used.""", |
|
232 |
- banner(), |
|
233 |
- sep='\n', file=sys.stderr) |
|
234 | 207 |
|
235 |
- if not trustworthy: |
|
236 |
- print(banner(' Warning '), |
|
237 |
-"""The existing MANIFEST file seems to have been generated by distutils (it begins |
|
238 |
-with a comment). It may well be incomplete.""", |
|
208 |
+ """Git was not available to generate the list of files to be included in the |
|
209 |
+source distribution. The old MANIFEST.in was used.""", |
|
239 | 210 |
banner(), |
240 | 211 |
sep='\n', file=sys.stderr) |
241 | 212 |
|
... | ... |
@@ -301,9 +272,7 @@ def search_mumps(): |
301 | 272 |
|
302 | 273 |
|
303 | 274 |
def extensions(): |
304 |
- """Return a list of tuples (args, kwrds) to be passed to |
|
305 |
- Extension. possibly after replacing ".pyx" with ".c" if Cython is not to be |
|
306 |
- used.""" |
|
275 |
+ """Return a list of tuples (args, kwrds) to be passed to Extension.""" |
|
307 | 276 |
|
308 | 277 |
global build_summary, config_file_present |
309 | 278 |
build_summary = [] |
... | ... |
@@ -476,13 +445,16 @@ def main(): |
476 | 445 |
url="http://kwant-project.org/", |
477 | 446 |
license="BSD", |
478 | 447 |
packages=packages(), |
448 |
+ test_suite = 'nose.collector', |
|
479 | 449 |
cmdclass={'build': kwant_build, |
480 | 450 |
'sdist': kwant_sdist, |
481 | 451 |
'build_ext': kwant_build_ext, |
482 |
- 'build_tut': kwant_build_tut, |
|
483 |
- 'test': kwant_test}, |
|
452 |
+ 'build_tut': kwant_build_tut}, |
|
484 | 453 |
ext_modules=ext_modules(extensions()), |
485 |
- include_dirs=[numpy.get_include()]) |
|
454 |
+ include_dirs=[numpy.get_include()], |
|
455 |
+ setup_requires=['numpy > 1.6.1', 'nose >= 1.0'], |
|
456 |
+ install_requires=['numpy > 1.6.1', 'scipy >= 0.9', 'tinyarray'], |
|
457 |
+ extras_require={'plotting': 'matplotlib >= 1.2'}) |
|
486 | 458 |
|
487 | 459 |
if __name__ == '__main__': |
488 | 460 |
main() |
... | ... |
@@ -21,8 +21,8 @@ from distutils.core import setup, Extension, Command |
21 | 21 |
from distutils.util import get_platform |
22 | 22 |
from distutils.errors import DistutilsError, DistutilsModuleError, \ |
23 | 23 |
CCompilerError |
24 |
-from distutils.command.build import build as distutils_build |
|
25 |
-from distutils.command.sdist import sdist as distutils_sdist |
|
24 |
+from distutils.command.build import build |
|
25 |
+from distutils.command.sdist import sdist |
|
26 | 26 |
|
27 | 27 |
import numpy |
28 | 28 |
|
... | ... |
@@ -116,7 +116,7 @@ class kwant_build_ext(build_ext): |
116 | 116 |
print(banner()) |
117 | 117 |
|
118 | 118 |
|
119 |
-class build_tut(Command): |
|
119 |
+class kwant_build_tut(Command): |
|
120 | 120 |
description = "build the tutorial scripts" |
121 | 121 |
user_options = [] |
122 | 122 |
|
... | ... |
@@ -142,15 +142,15 @@ class build_tut(Command): |
142 | 142 |
# Even though the tutorial is not necessary for installation, and "build" is |
143 | 143 |
# supposed to make everything needed to install, this is a robust way to ensure |
144 | 144 |
# that the tutorial is present. |
145 |
-class kwant_build(distutils_build): |
|
146 |
- sub_commands = [('build_tut', None)] + distutils_build.sub_commands |
|
145 |
+class kwant_build(build): |
|
146 |
+ sub_commands = [('build_tut', None)] + build.sub_commands |
|
147 | 147 |
|
148 | 148 |
def run(self): |
149 |
- distutils_build.run(self) |
|
149 |
+ build.run(self) |
|
150 | 150 |
write_version(os.path.join(self.build_lib, *STATIC_VERSION_PATH)) |
151 | 151 |
|
152 | 152 |
|
153 |
-class test(Command): |
|
153 |
+class kwant_test(Command): |
|
154 | 154 |
description = "build, then run the unit tests" |
155 | 155 |
user_options = [] |
156 | 156 |
|
... | ... |
@@ -193,8 +193,8 @@ def git_lsfiles(): |
193 | 193 |
# distribution in the current state actually builds. It also makes sure that |
194 | 194 |
# the Cython-made C files and the tutorial will be included in the source |
195 | 195 |
# distribution and that they will be up-to-date. |
196 |
-class kwant_sdist(distutils_sdist): |
|
197 |
- sub_commands = [('build', None)] + distutils_sdist.sub_commands |
|
196 |
+class kwant_sdist(sdist): |
|
197 |
+ sub_commands = [('build', None)] + sdist.sub_commands |
|
198 | 198 |
|
199 | 199 |
def run(self): |
200 | 200 |
names = git_lsfiles() |
... | ... |
@@ -223,7 +223,7 @@ class kwant_sdist(distutils_sdist): |
223 | 223 |
f.write(name + '\n') |
224 | 224 |
f.write('MANIFEST\n') |
225 | 225 |
|
226 |
- distutils_sdist.run(self) |
|
226 |
+ sdist.run(self) |
|
227 | 227 |
|
228 | 228 |
if names is None: |
229 | 229 |
print(banner(' Warning '), |
... | ... |
@@ -240,7 +240,7 @@ with a comment). It may well be incomplete.""", |
240 | 240 |
sep='\n', file=sys.stderr) |
241 | 241 |
|
242 | 242 |
def make_release_tree(self, base_dir, files): |
243 |
- distutils_sdist.make_release_tree(self, base_dir, files) |
|
243 |
+ sdist.make_release_tree(self, base_dir, files) |
|
244 | 244 |
write_version(os.path.join(base_dir, *STATIC_VERSION_PATH)) |
245 | 245 |
|
246 | 246 |
|
... | ... |
@@ -479,8 +479,8 @@ def main(): |
479 | 479 |
cmdclass={'build': kwant_build, |
480 | 480 |
'sdist': kwant_sdist, |
481 | 481 |
'build_ext': kwant_build_ext, |
482 |
- 'build_tut': build_tut, |
|
483 |
- 'test': test}, |
|
482 |
+ 'build_tut': kwant_build_tut, |
|
483 |
+ 'test': kwant_test}, |
|
484 | 484 |
ext_modules=ext_modules(extensions()), |
485 | 485 |
include_dirs=[numpy.get_include()]) |
486 | 486 |
|
When the --no-cython option is given, it is no longer an error when
derived files are older than source files.
Error messages have been improved.
... | ... |
@@ -51,26 +51,27 @@ sys.dont_write_bytecode = _dont_write_bytecode_saved |
51 | 51 |
version = _common.version |
52 | 52 |
version_is_from_git = _common.version_is_from_git |
53 | 53 |
|
54 |
-try: |
|
55 |
- import Cython |
|
56 |
-except: |
|
57 |
- cython_version = () |
|
58 |
-else: |
|
59 |
- match = re.match('([0-9.]*)(.*)', Cython.__version__) |
|
60 |
- cython_version = [int(n) for n in match.group(1).split('.')] |
|
61 |
- # Decrease version if the version string contains a suffix. |
|
62 |
- if match.group(2): |
|
63 |
- while cython_version[-1] == 0: |
|
64 |
- cython_version.pop() |
|
65 |
- cython_version[-1] -= 1 |
|
66 |
- cython_version = tuple(cython_version) |
|
67 |
- |
|
68 | 54 |
try: |
69 | 55 |
sys.argv.remove(NO_CYTHON_OPTION) |
70 | 56 |
cythonize = False |
71 | 57 |
except ValueError: |
72 | 58 |
cythonize = True |
73 | 59 |
|
60 |
+if cythonize: |
|
61 |
+ try: |
|
62 |
+ import Cython |
|
63 |
+ except: |
|
64 |
+ cython_version = () |
|
65 |
+ else: |
|
66 |
+ match = re.match('([0-9.]*)(.*)', Cython.__version__) |
|
67 |
+ cython_version = [int(n) for n in match.group(1).split('.')] |
|
68 |
+ # Decrease version if the version string contains a suffix. |
|
69 |
+ if match.group(2): |
|
70 |
+ while cython_version[-1] == 0: |
|
71 |
+ cython_version.pop() |
|
72 |
+ cython_version[-1] -= 1 |
|
73 |
+ cython_version = tuple(cython_version) |
|
74 |
+ |
|
74 | 75 |
if cythonize and cython_version: |
75 | 76 |
from Cython.Distutils import build_ext |
76 | 77 |
else: |
... | ... |
@@ -382,19 +383,23 @@ def extensions(): |
382 | 383 |
def complain_cython_unavailable(): |
383 | 384 |
assert not cythonize or cython_version < REQUIRED_CYTHON_VERSION |
384 | 385 |
if cythonize: |
385 |
- msg = "Install Cython {0} or newer so it can be made or use a source " \ |
|
386 |
- "distribution of Kwant." |
|
386 |
+ msg = ("Install Cython {0} or newer so it can be made\n" |
|
387 |
+ "or use a source distribution of Kwant.") |
|
387 | 388 |
ver = '.'.join(str(e) for e in REQUIRED_CYTHON_VERSION) |
388 | 389 |
print(msg.format(ver), file=sys.stderr) |
389 | 390 |
else: |
390 |
- print("Run setup.py without", NO_CYTHON_OPTION, file=sys.stderr) |
|
391 |
+ print("Run setup.py without {}.".format(NO_CYTHON_OPTION), |
|
392 |
+ file=sys.stderr) |
|
391 | 393 |
|
392 | 394 |
|
393 | 395 |
def ext_modules(extensions): |
394 | 396 |
"""Prepare the ext_modules argument for distutils' setup.""" |
395 | 397 |
result = [] |
398 |
+ problematic_files = [] |
|
396 | 399 |
for args, kwrds in extensions: |
397 | 400 |
if not cythonize or cython_version < REQUIRED_CYTHON_VERSION: |
401 |
+ # Cython is not going to be run: replace pyx extension by that of |
|
402 |
+ # the shipped translated file. |
|
398 | 403 |
if 'language' in kwrds: |
399 | 404 |
if kwrds['language'] == 'c': |
400 | 405 |
ext = '.c' |
... | ... |
@@ -416,6 +421,7 @@ def ext_modules(extensions): |
416 | 421 |
sources.append(f) |
417 | 422 |
args[1] = sources |
418 | 423 |
|
424 |
+ # Complain if cythonized files are older than Cython source files. |
|
419 | 425 |
try: |
420 | 426 |
cythonized_oldest = min(os.stat(f).st_mtime |
421 | 427 |
for f in cythonized_files) |
... | ... |
@@ -430,19 +436,31 @@ def ext_modules(extensions): |
430 | 436 |
# of the cythonized file, not for the cythonization. |
431 | 437 |
continue |
432 | 438 |
if os.stat(f).st_mtime > cythonized_oldest: |
433 |
- msg = "error: {} is newer than its source file, but " |
|
434 |
- if cythonize and not cython_version: |
|
435 |
- msg += "Cython is not installed." |
|
436 |
- elif cythonize: |
|
437 |
- msg += "the installed Cython is too old." |
|
438 |
- else: |
|
439 |
- msg += "Cython is not to be run." |
|
440 |
- print(msg.format(f), file=sys.stderr) |
|
441 |
- complain_cython_unavailable() |
|
442 |
- exit(1) |
|
439 |
+ problematic_files.append(f) |
|
443 | 440 |
|
444 | 441 |
result.append(Extension(*args, **kwrds)) |
445 | 442 |
|
443 |
+ if problematic_files: |
|
444 |
+ problematic_files = ", ".join(problematic_files) |
|
445 |
+ msg = ("Some Cython source files are newer than files that should have\n" |
|
446 |
+ " been derived from them, but {}.\n" |
|
447 |
+ "\n" |
|
448 |
+ "Affected files: {}") |
|
449 |
+ if cythonize: |
|
450 |
+ if not cython_version: |
|
451 |
+ reason = "Cython is not installed" |
|
452 |
+ else: |
|
453 |
+ reason = "the installed Cython is too old" |
|
454 |
+ print(banner(" Error "), msg.format(reason, problematic_files), |
|
455 |
+ banner(), sep="\n", file=sys.stderr) |
|
456 |
+ print() |
|
457 |
+ complain_cython_unavailable() |
|
458 |
+ exit(1) |
|
459 |
+ else: |
|
460 |
+ reason = "the option --no-cython has been given" |
|
461 |
+ print(banner(" Warning "), msg.format(reason, problematic_files), |
|
462 |
+ banner(), sep='\n', file=sys.stderr) |
|
463 |
+ |
|
446 | 464 |
return result |
447 | 465 |
|
448 | 466 |
|
The file kwant/_static_version.py is no longer written upon every
invocation of setup.py. Instead, a file kwant/_kwant_version.py is
injected into source and binary distributions.
The static version in kwant/_kwant_version.py now takes precedence
before any version from git. This makes the --no-git option to setup.py
no longer necessary, since the existence of kwant/_kwant_version.py has
the same role. The motivation behind this change is to allow keeping
Kwant distributions in git repositories that have a different layout
from the canonical Kwant git repository. This is useful for example for
packaging.
The name of the static version file was changed to avoid problems with
stale files.
... | ... |
@@ -1,6 +1,6 @@ |
1 | 1 |
#!/usr/bin/env python |
2 | 2 |
|
3 |
-# Copyright 2011-2013 Kwant authors. |
|
3 |
+# Copyright 2011-2015 Kwant authors. |
|
4 | 4 |
# |
5 | 5 |
# This file is part of Kwant. It is subject to the license terms in the |
6 | 6 |
# LICENSE file found in the top-level directory of this distribution and at |
... | ... |
@@ -26,22 +26,31 @@ from distutils.command.sdist import sdist as distutils_sdist |
26 | 26 |
|
27 | 27 |
import numpy |
28 | 28 |
|
29 |
-_dont_write_bytecode_saved = sys.dont_write_bytecode |
|
30 |
-sys.dont_write_bytecode = True |
|
31 |
-kwant_common = imp.load_source('kwant_common', 'kwant/_common.py') |
|
32 |
-sys.dont_write_bytecode = _dont_write_bytecode_saved |
|
33 |
- |
|
34 | 29 |
CONFIG_FILE = 'build.conf' |
35 | 30 |
README_FILE = 'README.rst' |
36 | 31 |
README_END_BEFORE = 'See also in this directory:' |
37 |
-STATIC_VERSION_FILE = 'kwant/_static_version.py' |
|
32 |
+STATIC_VERSION_PATH = ('kwant', '_kwant_version.py') |
|
38 | 33 |
REQUIRED_CYTHON_VERSION = (0, 22) |
39 | 34 |
NO_CYTHON_OPTION = '--no-cython' |
40 |
-NO_GIT_OPTION = '--no-git' |
|
41 | 35 |
TUT_DIR = 'tutorial' |
42 | 36 |
TUT_GLOB = 'doc/source/tutorial/*.py' |
43 | 37 |
TUT_HIDDEN_PREFIX = '#HIDDEN' |
44 | 38 |
|
39 |
+# Let Kwant itself determine its own version. We cannot simply import kwant, as |
|
40 |
+# it is not built yet. |
|
41 |
+_dont_write_bytecode_saved = sys.dont_write_bytecode |
|
42 |
+sys.dont_write_bytecode = True |
|
43 |
+try: |
|
44 |
+ imp.load_source(STATIC_VERSION_PATH[-1].split('.')[0], |
|
45 |
+ os.path.join(*STATIC_VERSION_PATH)) |
|
46 |
+except IOError: |
|
47 |
+ pass |
|
48 |
+_common = imp.load_source('_common', 'kwant/_common.py') |
|
49 |
+sys.dont_write_bytecode = _dont_write_bytecode_saved |
|
50 |
+ |
|
51 |
+version = _common.version |
|
52 |
+version_is_from_git = _common.version_is_from_git |
|
53 |
+ |
|
45 | 54 |
try: |
46 | 55 |
import Cython |
47 | 56 |
except: |
... | ... |
@@ -62,12 +71,6 @@ try: |
62 | 71 |
except ValueError: |
63 | 72 |
cythonize = True |
64 | 73 |
|
65 |
-try: |
|
66 |
- sys.argv.remove(NO_GIT_OPTION) |
|
67 |
- use_git = False |
|
68 |
-except ValueError: |
|
69 |
- use_git = True |
|
70 |
- |
|
71 | 74 |
if cythonize and cython_version: |
72 | 75 |
from Cython.Distutils import build_ext |
73 | 76 |
else: |
... | ... |
@@ -141,6 +144,10 @@ class build_tut(Command): |
141 | 144 |
class kwant_build(distutils_build): |
142 | 145 |
sub_commands = [('build_tut', None)] + distutils_build.sub_commands |
143 | 146 |
|
147 |
+ def run(self): |
|
148 |
+ distutils_build.run(self) |
|
149 |
+ write_version(os.path.join(self.build_lib, *STATIC_VERSION_PATH)) |
|
150 |
+ |
|
144 | 151 |
|
145 | 152 |
class test(Command): |
146 | 153 |
description = "build, then run the unit tests" |
... | ... |
@@ -167,7 +174,7 @@ class test(Command): |
167 | 174 |
|
168 | 175 |
|
169 | 176 |
def git_lsfiles(): |
170 |
- if not use_git: |
|
177 |
+ if not version_is_from_git: |
|
171 | 178 |
return |
172 | 179 |
|
173 | 180 |
try: |
... | ... |
@@ -213,7 +220,6 @@ class kwant_sdist(distutils_sdist): |
213 | 220 |
if extension == 'pyx': |
214 | 221 |
f.write(''.join([a, sep, stem, dot, 'c', '\n'])) |
215 | 222 |
f.write(name + '\n') |
216 |
- f.write(STATIC_VERSION_FILE + '\n') |
|
217 | 223 |
f.write('MANIFEST\n') |
218 | 224 |
|
219 | 225 |
distutils_sdist.run(self) |
... | ... |
@@ -232,42 +238,21 @@ with a comment). It may well be incomplete.""", |
232 | 238 |
banner(), |
233 | 239 |
sep='\n', file=sys.stderr) |
234 | 240 |
|
235 |
-def get_version_from_git(): |
|
236 |
- if use_git: |
|
237 |
- return kwant_common.get_version_from_git() |
|
241 |
+ def make_release_tree(self, base_dir, files): |
|
242 |
+ distutils_sdist.make_release_tree(self, base_dir, files) |
|
243 |
+ write_version(os.path.join(base_dir, *STATIC_VERSION_PATH)) |
|
238 | 244 |
|
239 | 245 |
|
240 |
-def read_static_version(): |
|
241 |
- """Return the version as recorded inside the source code.""" |
|
246 |
+def write_version(fname): |
|
247 |
+ # This could be a hard link, so try to delete it first. Is there any way |
|
248 |
+ # to do this atomically together with opening? |
|
242 | 249 |
try: |
243 |
- with open(STATIC_VERSION_FILE) as f: |
|
244 |
- contents = f.read() |
|
245 |
- assert contents[:11] == "version = '" |
|
246 |
- assert contents[-2:] == "'\n" |
|
247 |
- return contents[11:-2] |
|
248 |
- except: |
|
249 |
- return None |
|
250 |
- |
|
251 |
- |
|
252 |
-def write_static_version(version): |
|
253 |
- """Record the version so that it is available without version control.""" |
|
254 |
- with open(STATIC_VERSION_FILE, 'w') as f: |
|
255 |
- f.write("version = '%s'\n" % version) |
|
256 |
- |
|
257 |
- |
|
258 |
-def version(): |
|
259 |
- """Determine the version of Kwant. Return it and save it in a file.""" |
|
260 |
- git_version = get_version_from_git() |
|
261 |
- static_version = read_static_version() |
|
262 |
- if git_version is not None: |
|
263 |
- version = git_version |
|
264 |
- if static_version != git_version: |
|
265 |
- write_static_version(version) |
|
266 |
- elif static_version is not None: |
|
267 |
- version = static_version |
|
268 |
- else: |
|
269 |
- version = 'unknown' |
|
270 |
- return version |
|
250 |
+ os.remove(fname) |
|
251 |
+ except OSError: |
|
252 |
+ pass |
|
253 |
+ with open(fname, 'w') as f: |
|
254 |
+ f.write("# This file has been created by setup.py.\n") |
|
255 |
+ f.write("version = '{}'\n".format(version)) |
|
271 | 256 |
|
272 | 257 |
|
273 | 258 |
def long_description(): |
... | ... |
@@ -463,7 +448,7 @@ def ext_modules(extensions): |
463 | 448 |
|
464 | 449 |
def main(): |
465 | 450 |
setup(name='kwant', |
466 |
- version=version(), |
|
451 |
+ version=version, |
|
467 | 452 |
author='C. W. Groth (CEA), M. Wimmer, ' |
468 | 453 |
'A. R. Akhmerov, X. Waintal (CEA), and others', |
469 | 454 |
author_email='authors@kwant-project.org', |
... | ... |
@@ -14,6 +14,7 @@ import sys |
14 | 14 |
import re |
15 | 15 |
import os |
16 | 16 |
import glob |
17 |
+import imp |
|
17 | 18 |
import subprocess |
18 | 19 |
import ConfigParser |
19 | 20 |
from distutils.core import setup, Extension, Command |
... | ... |
@@ -25,6 +26,11 @@ from distutils.command.sdist import sdist as distutils_sdist |
25 | 26 |
|
26 | 27 |
import numpy |
27 | 28 |
|
29 |
+_dont_write_bytecode_saved = sys.dont_write_bytecode |
|
30 |
+sys.dont_write_bytecode = True |
|
31 |
+kwant_common = imp.load_source('kwant_common', 'kwant/_common.py') |
|
32 |
+sys.dont_write_bytecode = _dont_write_bytecode_saved |
|
33 |
+ |
|
28 | 34 |
CONFIG_FILE = 'build.conf' |
29 | 35 |
README_FILE = 'README.rst' |
30 | 36 |
README_END_BEFORE = 'See also in this directory:' |
... | ... |
@@ -226,53 +232,9 @@ with a comment). It may well be incomplete.""", |
226 | 232 |
banner(), |
227 | 233 |
sep='\n', file=sys.stderr) |
228 | 234 |
|
229 |
-# Other than the "if not use_git" clause in the beginning, this is an exact copy |
|
230 |
-# of the function from kwant/_common.py. We can't import it here (because Kwant |
|
231 |
-# is not yet built when this scipt is run), so we just include a copy. |
|
232 | 235 |
def get_version_from_git(): |
233 |
- if not use_git: |
|
234 |
- return |
|
235 |
- |
|
236 |
- try: |
|
237 |
- p = subprocess.Popen(['git', 'rev-parse', '--show-toplevel'], |
|
238 |
- cwd=distr_root, |
|
239 |
- stdout=subprocess.PIPE, stderr=subprocess.PIPE) |
|
240 |
- except OSError: |
|
241 |
- return |
|
242 |
- if p.wait() != 0: |
|
243 |
- return |
|
244 |
- # TODO: use os.path.samefile once we depend on Python >= 3.3. |
|
245 |
- if os.path.normpath(p.communicate()[0].rstrip('\n')) != distr_root: |
|
246 |
- # The top-level directory of the current Git repository is not the same |
|
247 |
- # as the root directory of the Kwant distribution: do not extract the |
|
248 |
- # version from Git. |
|
249 |
- return |
|
250 |
- |
|
251 |
- # git describe --first-parent does not take into account tags from branches |
|
252 |
- # that were merged-in. |
|
253 |
- for opts in [['--first-parent'], []]: |
|
254 |
- try: |
|
255 |
- p = subprocess.Popen(['git', 'describe'] + opts, cwd=distr_root, |
|
256 |
- stdout=subprocess.PIPE, stderr=subprocess.PIPE) |
|
257 |
- except OSError: |
|
258 |
- return |
|
259 |
- if p.wait() == 0: |
|
260 |
- break |
|
261 |
- else: |
|
262 |
- return |
|
263 |
- version = p.communicate()[0].rstrip('\n') |
|
264 |
- |
|
265 |
- if version[0] == 'v': |
|
266 |
- version = version[1:] |
|
267 |
- |
|
268 |
- try: |
|
269 |
- p = subprocess.Popen(['git', 'diff', '--quiet'], cwd=distr_root) |
|
270 |
- except OSError: |
|
271 |
- version += '-confused' # This should never happen. |
|
272 |
- else: |
|
273 |
- if p.wait() == 1: |
|
274 |
- version += '-dirty' |
|
275 |
- return version |
|
236 |
+ if use_git: |
|
237 |
+ return kwant_common.get_version_from_git() |
|
276 | 238 |
|
277 | 239 |
|
278 | 240 |
def read_static_version(): |
... | ... |
@@ -69,18 +69,21 @@ else: |
69 | 69 |
|
70 | 70 |
distr_root = os.path.dirname(os.path.abspath(__file__)) |
71 | 71 |
|
72 |
-def header(title=''): |
|
73 |
- return title.center(79, '*') |
|
72 |
+def banner(title=''): |
|
73 |
+ starred = title.center(79, '*') |
|
74 |
+ return '\n' + starred if title else starred |
|
74 | 75 |
|
75 |
-error_msg = """{sep} |
|
76 |
+error_msg = """{header} |
|
76 | 77 |
The compilation of Kwant has failed. Please examine the error message |
77 | 78 |
above and consult the installation instructions in README.rst. |
78 | 79 |
You might have to customize {{file}}. |
79 |
-{sep} |
|
80 |
+ |
|
80 | 81 |
Build configuration was: |
82 |
+ |
|
81 | 83 |
{{summary}} |
82 |
-{sep}""" |
|
83 |
-error_msg = error_msg.format(sep=header()) |
|
84 |
+{sep} |
|
85 |
+""" |
|
86 |
+error_msg = error_msg.format(header=banner(' Error '), sep=banner()) |
|
84 | 87 |
|
85 | 88 |
class kwant_build_ext(build_ext): |
86 | 89 |
def run(self): |
... | ... |
@@ -98,8 +101,9 @@ class kwant_build_ext(build_ext): |
98 | 101 |
print(error_msg.format(file=CONFIG_FILE, summary=build_summary), |
99 | 102 |
file=sys.stderr) |
100 | 103 |
raise |
101 |
- print(header(' Build summary ')) |
|
104 |
+ print(banner(' Build summary ')) |
|
102 | 105 |
print(build_summary) |
106 |
+ print(banner()) |
|
103 | 107 |
|
104 | 108 |
|
105 | 109 |
class build_tut(Command): |
... | ... |
@@ -151,7 +155,7 @@ class test(Command): |
151 | 155 |
self.run_command('build') |
152 | 156 |
major, minor = sys.version_info[:2] |
153 | 157 |
lib_dir = "build/lib.{0}-{1}.{2}".format(get_platform(), major, minor) |
154 |
- print(header(' Tests ')) |
|
158 |
+ print() |
|
155 | 159 |
if not run(argv=[__file__, '-v', lib_dir]): |
156 | 160 |
raise DistutilsError('at least one of the tests failed') |
157 | 161 |
|
... | ... |
@@ -188,7 +192,7 @@ class kwant_sdist(distutils_sdist): |
188 | 192 |
with open(distr_root + '/MANIFEST', 'r') as f: |
189 | 193 |
line = f.read() |
190 | 194 |
except IOError: |
191 |
- print("error: MANIFEST file is missing and Git is not" |
|
195 |
+ print("Error: MANIFEST file is missing and Git is not" |
|
192 | 196 |
" available to regenerate it.", file=sys.stderr) |
193 | 197 |
exit(1) |
194 | 198 |
trustworthy = not line.strip().startswith('#') |
... | ... |
@@ -209,15 +213,17 @@ class kwant_sdist(distutils_sdist): |
209 | 213 |
distutils_sdist.run(self) |
210 | 214 |
|
211 | 215 |
if names is None: |
212 |
- print(header(' Warning '), |
|
216 |
+ print(banner(' Warning '), |
|
213 | 217 |
"""Git was not available for re-generating the MANIFEST file (the list of file |
214 | 218 |
names to be included in the source distribution). The old MANIFEST was used.""", |
219 |
+ banner(), |
|
215 | 220 |
sep='\n', file=sys.stderr) |
216 | 221 |
|
217 | 222 |
if not trustworthy: |
218 |
- print(header(' Warning '), |
|
223 |
+ print(banner(' Warning '), |
|
219 | 224 |
"""The existing MANIFEST file seems to have been generated by distutils (it begins |
220 | 225 |
with a comment). It may well be incomplete.""", |
226 |
+ banner(), |
|
221 | 227 |
sep='\n', file=sys.stderr) |
222 | 228 |
|
223 | 229 |
# Other than the "if not use_git" clause in the beginning, this is an exact copy |
... | ... |
@@ -208,21 +208,17 @@ class kwant_sdist(distutils_sdist): |
208 | 208 |
|
209 | 209 |
distutils_sdist.run(self) |
210 | 210 |
|
211 |
- msg = None |
|
212 | 211 |
if names is None: |
213 |
- msg = ['Git was not available for re-generating ' |
|
214 |
- 'the MANIFEST file (the list of file', |
|
215 |
- 'names to be included in the source' |
|
216 |
- ' distribution). The old MANIFEST was used.'] |
|
217 |
- if not trustworthy: |
|
218 |
- msg = ['-The existing MANIFEST file seems to' |
|
219 |
- ' have been generated by distutils (it begins', |
|
220 |
- '-with a comment). It may well be incomplete.'] |
|
221 |
- |
|
222 |
- if msg is not None: |
|
223 |
- msg.insert(0, header(' Warning ')) |
|
224 |
- print(msg, sep='\n', file=sys.stderr) |
|
212 |
+ print(header(' Warning '), |
|
213 |
+"""Git was not available for re-generating the MANIFEST file (the list of file |
|
214 |
+names to be included in the source distribution). The old MANIFEST was used.""", |
|
215 |
+ sep='\n', file=sys.stderr) |
|
225 | 216 |
|
217 |
+ if not trustworthy: |
|
218 |
+ print(header(' Warning '), |
|
219 |
+"""The existing MANIFEST file seems to have been generated by distutils (it begins |
|
220 |
+with a comment). It may well be incomplete.""", |
|
221 |
+ sep='\n', file=sys.stderr) |
|
226 | 222 |
|
227 | 223 |
# Other than the "if not use_git" clause in the beginning, this is an exact copy |
228 | 224 |
# of the function from kwant/_common.py. We can't import it here (because Kwant |
... | ... |
@@ -224,9 +224,9 @@ class kwant_sdist(distutils_sdist): |
224 | 224 |
print(msg, sep='\n', file=sys.stderr) |
225 | 225 |
|
226 | 226 |
|
227 |
-# This is an exact copy of the function from kwant/_common.py. We can't import |
|
228 |
-# it here (because Kwant is not yet built when this scipt is run), so we just |
|
229 |
-# include a copy. |
|
227 |
+# Other than the "if not use_git" clause in the beginning, this is an exact copy |
|
228 |
+# of the function from kwant/_common.py. We can't import it here (because Kwant |
|
229 |
+# is not yet built when this scipt is run), so we just include a copy. |
|
230 | 230 |
def get_version_from_git(): |
231 | 231 |
if not use_git: |
232 | 232 |
return |
This is useful when the source is held in a git repository but this
repository is not an usual kwant repository.
... | ... |
@@ -31,6 +31,7 @@ README_END_BEFORE = 'See also in this directory:' |
31 | 31 |
STATIC_VERSION_FILE = 'kwant/_static_version.py' |
32 | 32 |
REQUIRED_CYTHON_VERSION = (0, 22) |
33 | 33 |
NO_CYTHON_OPTION = '--no-cython' |
34 |
+NO_GIT_OPTION = '--no-git' |
|
34 | 35 |
TUT_DIR = 'tutorial' |
35 | 36 |
TUT_GLOB = 'doc/source/tutorial/*.py' |
36 | 37 |
TUT_HIDDEN_PREFIX = '#HIDDEN' |
... | ... |
@@ -55,6 +56,12 @@ try: |
55 | 56 |
except ValueError: |
56 | 57 |
cythonize = True |
57 | 58 |
|
59 |
+try: |
|
60 |
+ sys.argv.remove(NO_GIT_OPTION) |
|
61 |
+ use_git = False |
|
62 |
+except ValueError: |
|
63 |
+ use_git = True |
|
64 |
+ |
|
58 | 65 |
if cythonize and cython_version: |
59 | 66 |
from Cython.Distutils import build_ext |
60 | 67 |
else: |
... | ... |
@@ -150,6 +157,9 @@ class test(Command): |
150 | 157 |
|
151 | 158 |
|
152 | 159 |
def git_lsfiles(): |
160 |
+ if not use_git: |
|
161 |
+ return |
|
162 |
+ |
|
153 | 163 |
try: |
154 | 164 |
p = subprocess.Popen(['git', 'ls-files'], cwd=distr_root, |
155 | 165 |
stdout=subprocess.PIPE, stderr=subprocess.PIPE) |
... | ... |
@@ -218,6 +228,9 @@ class kwant_sdist(distutils_sdist): |
218 | 228 |
# it here (because Kwant is not yet built when this scipt is run), so we just |
219 | 229 |
# include a copy. |
220 | 230 |
def get_version_from_git(): |
231 |
+ if not use_git: |
|
232 |
+ return |
|
233 |
+ |
|
221 | 234 |
try: |
222 | 235 |
p = subprocess.Popen(['git', 'rev-parse', '--show-toplevel'], |
223 | 236 |
cwd=distr_root, |
... | ... |
@@ -260,7 +260,7 @@ def get_version_from_git(): |
260 | 260 |
return version |
261 | 261 |
|
262 | 262 |
|
263 |
-def get_static_version(): |
|
263 |
+def read_static_version(): |
|
264 | 264 |
"""Return the version as recorded inside the source code.""" |
265 | 265 |
try: |
266 | 266 |
with open(STATIC_VERSION_FILE) as f: |
... | ... |
@@ -272,15 +272,20 @@ def get_static_version(): |
272 | 272 |
return None |
273 | 273 |
|
274 | 274 |
|
275 |
+def write_static_version(version): |
|
276 |
+ """Record the version so that it is available without version control.""" |
|
277 |
+ with open(STATIC_VERSION_FILE, 'w') as f: |
|
278 |
+ f.write("version = '%s'\n" % version) |
|
279 |
+ |
|
280 |
+ |
|
275 | 281 |
def version(): |
276 | 282 |
"""Determine the version of Kwant. Return it and save it in a file.""" |
277 | 283 |
git_version = get_version_from_git() |
278 |
- static_version = get_static_version() |
|
284 |
+ static_version = read_static_version() |
|
279 | 285 |
if git_version is not None: |
280 | 286 |
version = git_version |
281 | 287 |
if static_version != git_version: |
282 |
- with open(STATIC_VERSION_FILE, 'w') as f: |
|
283 |
- f.write("version = '%s'\n" % version) |
|
288 |
+ write_static_version(version) |
|
284 | 289 |
elif static_version is not None: |
285 | 290 |
version = static_version |
286 | 291 |
else: |
... | ... |
@@ -29,7 +29,7 @@ CONFIG_FILE = 'build.conf' |
29 | 29 |
README_FILE = 'README.rst' |
30 | 30 |
README_END_BEFORE = 'See also in this directory:' |
31 | 31 |
STATIC_VERSION_FILE = 'kwant/_static_version.py' |
32 |
-REQUIRED_CYTHON_VERSION = (0, 17, 1) |
|
32 |
+REQUIRED_CYTHON_VERSION = (0, 22) |
|
33 | 33 |
NO_CYTHON_OPTION = '--no-cython' |
34 | 34 |
TUT_DIR = 'tutorial' |
35 | 35 |
TUT_GLOB = 'doc/source/tutorial/*.py' |
... | ... |
@@ -8,15 +8,7 @@ |
8 | 8 |
# the AUTHORS file at the top-level directory of this distribution and at |
9 | 9 |
# http://kwant-project.org/authors. |
10 | 10 |
|
11 |
-CONFIG_FILE = 'build.conf' |
|
12 |
-README_FILE = 'README.rst' |
|
13 |
-README_END_BEFORE = 'See also in this directory:' |
|
14 |
-STATIC_VERSION_FILE = 'kwant/_static_version.py' |
|
15 |
-REQUIRED_CYTHON_VERSION = (0, 17, 1) |
|
16 |
-NO_CYTHON_OPTION = '--no-cython' |
|
17 |
-TUT_DIR = 'tutorial' |
|
18 |
-TUT_GLOB = 'doc/source/tutorial/*.py' |
|
19 |
-TUT_HIDDEN_PREFIX = '#HIDDEN' |
|
11 |
+from __future__ import print_function |
|
20 | 12 |
|
21 | 13 |
import sys |
22 | 14 |
import re |
... | ... |
@@ -30,8 +22,19 @@ from distutils.errors import DistutilsError, DistutilsModuleError, \ |
30 | 22 |
CCompilerError |
31 | 23 |
from distutils.command.build import build as distutils_build |
32 | 24 |
from distutils.command.sdist import sdist as distutils_sdist |
25 |
+ |
|
33 | 26 |
import numpy |
34 | 27 |
|
28 |
+CONFIG_FILE = 'build.conf' |
|
29 |
+README_FILE = 'README.rst' |
|
30 |
+README_END_BEFORE = 'See also in this directory:' |
|
31 |
+STATIC_VERSION_FILE = 'kwant/_static_version.py' |
|
32 |
+REQUIRED_CYTHON_VERSION = (0, 17, 1) |
|
33 |
+NO_CYTHON_OPTION = '--no-cython' |
|
34 |
+TUT_DIR = 'tutorial' |
|
35 |
+TUT_GLOB = 'doc/source/tutorial/*.py' |
|
36 |
+TUT_HIDDEN_PREFIX = '#HIDDEN' |
|
37 |
+ |
|
35 | 38 |
try: |
36 | 39 |
import Cython |
37 | 40 |
except: |
... | ... |
@@ -59,6 +62,18 @@ else: |
59 | 62 |
|
60 | 63 |
distr_root = os.path.dirname(os.path.abspath(__file__)) |
61 | 64 |
|
65 |
+def header(title=''): |
|
66 |
+ return title.center(79, '*') |
|
67 |
+ |
|
68 |
+error_msg = """{sep} |
|
69 |
+The compilation of Kwant has failed. Please examine the error message |
|
70 |
+above and consult the installation instructions in README.rst. |
|
71 |
+You might have to customize {{file}}. |
|
72 |
+{sep} |
|
73 |
+Build configuration was: |
|
74 |
+{{summary}} |
|
75 |
+{sep}""" |
|
76 |
+error_msg = error_msg.format(sep=header()) |
|
62 | 77 |
|
63 | 78 |
class kwant_build_ext(build_ext): |
64 | 79 |
def run(self): |
... | ... |
@@ -73,18 +88,11 @@ class kwant_build_ext(build_ext): |
73 | 88 |
try: |
74 | 89 |
build_ext.run(self) |
75 | 90 |
except (DistutilsError, CCompilerError): |
76 |
- print >>sys.stderr, \ |
|
77 |
-"""{0} |
|
78 |
-The compilation of Kwant has failed. Please examine the error message |
|
79 |
-above and consult the installation instructions in README.rst. |
|
80 |
-You might have to customize {1}. |
|
81 |
-{0} |
|
82 |
-Build configuration was: |
|
83 |
-{2} |
|
84 |
-{0}""".format('*' * 70, CONFIG_FILE, build_summary) |
|
91 |
+ print(error_msg.format(file=CONFIG_FILE, summary=build_summary), |
|
92 |
+ file=sys.stderr) |
|
85 | 93 |
raise |
86 |
- print '**************** Build summary ****************' |
|
87 |
- print build_summary |
|
94 |
+ print(header(' Build summary ')) |
|
95 |
+ print(build_summary) |
|
88 | 96 |
|
89 | 97 |
|
90 | 98 |
class build_tut(Command): |
... | ... |
@@ -136,7 +144,7 @@ class test(Command): |
136 | 144 |
self.run_command('build') |
137 | 145 |
major, minor = sys.version_info[:2] |
138 | 146 |
lib_dir = "build/lib.{0}-{1}.{2}".format(get_platform(), major, minor) |
139 |
- print '**************** Tests ****************' |
|
147 |
+ print(header(' Tests ')) |
|
140 | 148 |
if not run(argv=[__file__, '-v', lib_dir]): |
141 | 149 |
raise DistutilsError('at least one of the tests failed') |
142 | 150 |
|
... | ... |
@@ -170,8 +178,8 @@ class kwant_sdist(distutils_sdist): |
170 | 178 |
with open(distr_root + '/MANIFEST', 'r') as f: |
171 | 179 |
line = f.read() |
172 | 180 |
except IOError: |
173 |
- print >>sys.stderr, "error: MANIFEST file is missing and " \ |
|
174 |
- "Git is not available to regenerate it." |
|
181 |
+ print("error: MANIFEST file is missing and Git is not" |
|
182 |
+ " available to regenerate it.", file=sys.stderr) |
|
175 | 183 |
exit(1) |
176 | 184 |
trustworthy = not line.strip().startswith('#') |
177 | 185 |
else: |
... | ... |
@@ -190,17 +198,20 @@ class kwant_sdist(distutils_sdist): |
190 | 198 |
|
191 | 199 |
distutils_sdist.run(self) |
192 | 200 |
|
201 |
+ msg = None |
|
193 | 202 |
if names is None: |
194 |
- print >>sys.stderr, \ |
|
195 |
- """**************** Warning **************** |
|
196 |
-Git was not available for re-generating the MANIFEST file (the list of file |
|
197 |
-names to be included in the source distribution). The old MANIFEST was used.""" |
|
198 |
- |
|
203 |
+ msg = ['Git was not available for re-generating ' |
|
204 |
+ 'the MANIFEST file (the list of file', |
|
205 |
+ 'names to be included in the source' |
|
206 |
+ ' distribution). The old MANIFEST was used.'] |
|
199 | 207 |
if not trustworthy: |
200 |
- print >>sys.stderr, \ |
|
201 |
- """**************** Warning **************** |
|
202 |
-The existing MANIFEST file seems to have been generated by distutils (it begins |
|
203 |
-with a comment). It may well be incomplete.""" |
|
208 |
+ msg = ['-The existing MANIFEST file seems to' |
|
209 |
+ ' have been generated by distutils (it begins', |
|
210 |
+ '-with a comment). It may well be incomplete.'] |
|
211 |
+ |
|
212 |
+ if msg is not None: |
|
213 |
+ msg.insert(0, header(' Warning ')) |
|
214 |
+ print(msg, sep='\n', file=sys.stderr) |
|
204 | 215 |
|
205 | 216 |
|
206 | 217 |
# This is an exact copy of the function from kwant/_common.py. We can't import |
... | ... |
@@ -407,10 +418,9 @@ def complain_cython_unavailable(): |
407 | 418 |
msg = "Install Cython {0} or newer so it can be made or use a source " \ |
408 | 419 |
"distribution of Kwant." |
409 | 420 |
ver = '.'.join(str(e) for e in REQUIRED_CYTHON_VERSION) |
410 |
- print >>sys.stderr, msg.format(ver) |
|
421 |
+ print(msg.format(ver), file=sys.stderr) |
|
411 | 422 |
else: |
412 |
- print >>sys.stderr, "Run setup.py without", \ |
|
413 |
- NO_CYTHON_OPTION |
|
423 |
+ print("Run setup.py without", NO_CYTHON_OPTION, file=sys.stderr) |
|
414 | 424 |
|
415 | 425 |
|
416 | 426 |
def ext_modules(extensions): |
... | ... |
@@ -424,7 +434,7 @@ def ext_modules(extensions): |
424 | 434 |
elif kwrds['language'] == 'c++': |
425 | 435 |
ext = '.cpp' |
426 | 436 |
else: |
427 |
- print >>sys.stderr, 'Unknown language' |
|
437 |
+ print('Unknown language', file=sys.stderr) |
|
428 | 438 |
exit(1) |
429 | 439 |
else: |
430 | 440 |
ext = '.c' |
... | ... |
@@ -443,8 +453,8 @@ def ext_modules(extensions): |
443 | 453 |
cythonized_oldest = min(os.stat(f).st_mtime |
444 | 454 |
for f in cythonized_files) |
445 | 455 |
except OSError: |
446 |
- print >>sys.stderr, \ |
|
447 |
- "error: Cython-generated file {0} is missing.".format(f) |
|
456 |
+ print("error: Cython-generated file {} is missing.".format(f), |
|
457 |
+ file=sys.stderr) |
|
448 | 458 |
complain_cython_unavailable() |
449 | 459 |
exit(1) |
450 | 460 |
for f in pyx_files + kwrds.get('depends', []): |
... | ... |
@@ -453,14 +463,14 @@ def ext_modules(extensions): |
453 | 463 |
# of the cythonized file, not for the cythonization. |
454 | 464 |
continue |
455 | 465 |
if os.stat(f).st_mtime > cythonized_oldest: |
456 |
- msg = "error: {0} is newer than its source file, but " |
|
466 |
+ msg = "error: {} is newer than its source file, but " |
|
457 | 467 |
if cythonize and not cython_version: |
458 | 468 |
msg += "Cython is not installed." |
459 | 469 |
elif cythonize: |
460 | 470 |
msg += "the installed Cython is too old." |
461 | 471 |
else: |
462 | 472 |
msg += "Cython is not to be run." |
463 |
- print >>sys.stderr, msg.format(f) |
|
473 |
+ print(msg.format(f), file=sys.stderr) |
|
464 | 474 |
complain_cython_unavailable() |
465 | 475 |
exit(1) |
466 | 476 |
|
... | ... |
@@ -472,7 +482,8 @@ def ext_modules(extensions): |
472 | 482 |
def main(): |
473 | 483 |
setup(name='kwant', |
474 | 484 |
version=version(), |
475 |
- author='C. W. Groth (CEA), M. Wimmer, A. R. Akhmerov, X. Waintal (CEA), and others', |
|
485 |
+ author='C. W. Groth (CEA), M. Wimmer, ' |
|
486 |
+ 'A. R. Akhmerov, X. Waintal (CEA), and others', |
|
476 | 487 |
author_email='authors@kwant-project.org', |
477 | 488 |
description="Package for numerical quantum transport calculations.", |
478 | 489 |
long_description=long_description(), |
... | ... |
@@ -10,7 +10,7 @@ |
10 | 10 |
|
11 | 11 |
CONFIG_FILE = 'build.conf' |
12 | 12 |
README_FILE = 'README.rst' |
13 |
-README_END_BEFORE = 'See also the files' |
|
13 |
+README_END_BEFORE = 'See also in this directory:' |
|
14 | 14 |
STATIC_VERSION_FILE = 'kwant/_static_version.py' |
15 | 15 |
REQUIRED_CYTHON_VERSION = (0, 17, 1) |
16 | 16 |
NO_CYTHON_OPTION = '--no-cython' |
Conflicts:
README
... | ... |
@@ -9,7 +9,8 @@ |
9 | 9 |
# http://kwant-project.org/authors. |
10 | 10 |
|
11 | 11 |
CONFIG_FILE = 'build.conf' |
12 |
-README_FILE = 'README' |
|
12 |
+README_FILE = 'README.rst' |
|
13 |
+README_END_BEFORE = 'See also the files' |
|
13 | 14 |
STATIC_VERSION_FILE = 'kwant/_static_version.py' |
14 | 15 |
REQUIRED_CYTHON_VERSION = (0, 17, 1) |
15 | 16 |
NO_CYTHON_OPTION = '--no-cython' |
... | ... |
@@ -75,7 +76,7 @@ class kwant_build_ext(build_ext): |
75 | 76 |
print >>sys.stderr, \ |
76 | 77 |
"""{0} |
77 | 78 |
The compilation of Kwant has failed. Please examine the error message |
78 |
-above and consult the installation instructions in README. |
|
79 |
+above and consult the installation instructions in README.rst. |
|
79 | 80 |
You might have to customize {1}. |
80 | 81 |
{0} |
81 | 82 |
Build configuration was: |
... | ... |
@@ -281,9 +282,11 @@ def long_description(): |
281 | 282 |
try: |
282 | 283 |
with open(README_FILE) as f: |
283 | 284 |
for line in f: |
284 |
- if line == "\n": |
|
285 |
+ if line.startswith(README_END_BEFORE): |
|
285 | 286 |
break |
286 | 287 |
text.append(line.rstrip()) |
288 |
+ while text[-1] == "": |
|
289 |
+ text.pop() |
|
287 | 290 |
except: |
288 | 291 |
return '' |
289 | 292 |
return '\n'.join(text) |
... | ... |
@@ -202,7 +202,7 @@ The existing MANIFEST file seems to have been generated by distutils (it begins |
202 | 202 |
with a comment). It may well be incomplete.""" |
203 | 203 |
|
204 | 204 |
|
205 |
-# This is an exact copy of the function from kwant/version.py. We can't import |
|
205 |
+# This is an exact copy of the function from kwant/_common.py. We can't import |
|
206 | 206 |
# it here (because Kwant is not yet built when this scipt is run), so we just |
207 | 207 |
# include a copy. |
208 | 208 |
def get_version_from_git(): |
Thanks to Bas Nijholt for reporting this.
Christoph Groth authored on 06/05/2014 11:08:18... | ... |
@@ -18,6 +18,7 @@ TUT_GLOB = 'doc/source/tutorial/*.py' |
18 | 18 |
TUT_HIDDEN_PREFIX = '#HIDDEN' |
19 | 19 |
|
20 | 20 |
import sys |
21 |
+import re |
|
21 | 22 |
import os |
22 | 23 |
import glob |
23 | 24 |
import subprocess |
... | ... |
@@ -35,8 +36,14 @@ try: |
35 | 36 |
except: |
36 | 37 |
cython_version = () |
37 | 38 |
else: |
38 |
- cython_version = tuple( |
|
39 |
- int(n) for n in Cython.__version__.split('-')[0].split('.')) |
|
39 |
+ match = re.match('([0-9.]*)(.*)', Cython.__version__) |
|
40 |
+ cython_version = [int(n) for n in match.group(1).split('.')] |
|
41 |
+ # Decrease version if the version string contains a suffix. |
|
42 |
+ if match.group(2): |
|
43 |
+ while cython_version[-1] == 0: |
|
44 |
+ cython_version.pop() |
|
45 |
+ cython_version[-1] -= 1 |
|
46 |
+ cython_version = tuple(cython_version) |
|
40 | 47 |
|
41 | 48 |
try: |
42 | 49 |
sys.argv.remove(NO_CYTHON_OPTION) |
* Only extract the version from Git when the top level directory of the Git
repository coincides with the root directory of the Kwant distribution
* Disregard tags on branches that were merged-in (with Git >= 1.8.4).
... | ... |
@@ -49,7 +49,7 @@ if cythonize and cython_version: |
49 | 49 |
else: |
50 | 50 |
from distutils.command.build_ext import build_ext |
51 | 51 |
|
52 |
-kwant_dir = os.path.dirname(os.path.abspath(__file__)) |
|
52 |
+distr_root = os.path.dirname(os.path.abspath(__file__)) |
|
53 | 53 |
|
54 | 54 |
|
55 | 55 |
class kwant_build_ext(build_ext): |
... | ... |
@@ -135,7 +135,7 @@ class test(Command): |
135 | 135 |
|
136 | 136 |
def git_lsfiles(): |
137 | 137 |
try: |
138 |
- p = subprocess.Popen(['git', 'ls-files'], cwd=kwant_dir, |
|
138 |
+ p = subprocess.Popen(['git', 'ls-files'], cwd=distr_root, |
|
139 | 139 |
stdout=subprocess.PIPE, stderr=subprocess.PIPE) |
140 | 140 |
except OSError: |
141 | 141 |
return |
... | ... |
@@ -159,7 +159,7 @@ class kwant_sdist(distutils_sdist): |
159 | 159 |
# Check that MANIFEST exists and has not been generated by |
160 | 160 |
# distutils. |
161 | 161 |
try: |
162 |
- with open(kwant_dir + '/MANIFEST', 'r') as f: |
|
162 |
+ with open(distr_root + '/MANIFEST', 'r') as f: |
|
163 | 163 |
line = f.read() |
164 | 164 |
except IOError: |
165 | 165 |
print >>sys.stderr, "error: MANIFEST file is missing and " \ |
... | ... |
@@ -168,7 +168,7 @@ class kwant_sdist(distutils_sdist): |
168 | 168 |
trustworthy = not line.strip().startswith('#') |
169 | 169 |
else: |
170 | 170 |
# Generate MANIFEST file. |
171 |
- with open(kwant_dir + '/MANIFEST', 'w') as f: |
|
171 |
+ with open(distr_root + '/MANIFEST', 'w') as f: |
|
172 | 172 |
for name in names: |
173 | 173 |
a, sep, b = name.rpartition('/') |
174 | 174 |
if b == '.gitignore': |
... | ... |
@@ -200,20 +200,39 @@ with a comment). It may well be incomplete.""" |
200 | 200 |
# include a copy. |
201 | 201 |
def get_version_from_git(): |
202 | 202 |
try: |
203 |
- p = subprocess.Popen(['git', 'describe'], cwd=kwant_dir, |
|
203 |
+ p = subprocess.Popen(['git', 'rev-parse', '--show-toplevel'], |
|
204 |
+ cwd=distr_root, |
|
204 | 205 |
stdout=subprocess.PIPE, stderr=subprocess.PIPE) |
205 | 206 |
except OSError: |
206 | 207 |
return |
207 |
- |
|
208 | 208 |
if p.wait() != 0: |
209 | 209 |
return |
210 |
- version = p.communicate()[0].strip() |
|
210 |
+ # TODO: use os.path.samefile once we depend on Python >= 3.3. |
|
211 |
+ if os.path.normpath(p.communicate()[0].rstrip('\n')) != distr_root: |
|
212 |
+ # The top-level directory of the current Git repository is not the same |
|
213 |
+ # as the root directory of the Kwant distribution: do not extract the |
|
214 |
+ # version from Git. |
|
215 |
+ return |
|
216 |
+ |
|
217 |
+ # git describe --first-parent does not take into account tags from branches |
|
218 |
+ # that were merged-in. |
|
219 |
+ for opts in [['--first-parent'], []]: |
|
220 |
+ try: |
|
221 |
+ p = subprocess.Popen(['git', 'describe'] + opts, cwd=distr_root, |
|
222 |
+ stdout=subprocess.PIPE, stderr=subprocess.PIPE) |
|
223 |
+ except OSError: |
|
224 |
+ return |
|
225 |
+ if p.wait() == 0: |
|
226 |
+ break |
|
227 |
+ else: |
|
228 |
+ return |
|
229 |
+ version = p.communicate()[0].rstrip('\n') |
|
211 | 230 |
|
212 | 231 |
if version[0] == 'v': |
213 | 232 |
version = version[1:] |
214 | 233 |
|
215 | 234 |
try: |
216 |
- p = subprocess.Popen(['git', 'diff', '--quiet'], cwd=kwant_dir) |
|
235 |
+ p = subprocess.Popen(['git', 'diff', '--quiet'], cwd=distr_root) |
|
217 | 236 |
except OSError: |
218 | 237 |
version += '-confused' # This should never happen. |
219 | 238 |
else: |
... | ... |
@@ -12,7 +12,6 @@ CONFIG_FILE = 'build.conf' |
12 | 12 |
README_FILE = 'README' |
13 | 13 |
STATIC_VERSION_FILE = 'kwant/_static_version.py' |
14 | 14 |
REQUIRED_CYTHON_VERSION = (0, 17, 1) |
15 |
-MUMPS_DEBIAN_PACKAGE = 'libmumps-scotch-dev' |
|
16 | 15 |
NO_CYTHON_OPTION = '--no-cython' |
17 | 16 |
TUT_DIR = 'tutorial' |
18 | 17 |
TUT_GLOB = 'doc/source/tutorial/*.py' |
... | ... |
@@ -270,19 +269,26 @@ def packages(): |
270 | 269 |
if '__init__.py' in fnames or root.endswith('/tests')] |
271 | 270 |
|
272 | 271 |
|
273 |
-def debian_mumps(): |
|
274 |
- """Return the configuration for debian-provided MUMPS if it is available, |
|
275 |
- or an empty dictionary otherwise.""" |
|
272 |
+def search_mumps(): |
|
273 |
+ """Return the configuration for MUMPS if it is available in a known way. |
|
274 |
+ |
|
275 |
+ This is known to work with the MUMPS provided by the Debian package |
|
276 |
+ libmumps-scotch-dev.""" |
|
277 |
+ |
|
278 |
+ libs = ['zmumps_scotch', 'mumps_common_scotch', 'pord', 'mpiseq_scotch', |
|
279 |
+ 'gfortran'] |
|
280 |
+ |
|
281 |
+ cmd = ['gcc'] |
|
282 |
+ cmd.extend(['-l' + lib for lib in libs]) |
|
283 |
+ cmd.extend(['-o/dev/null', '-xc', '-']) |
|
276 | 284 |
try: |
277 |
- p = subprocess.Popen( |
|
278 |
- ['dpkg-query', '-W', '-f=${Status}', MUMPS_DEBIAN_PACKAGE], |
|
279 |
- stdout=subprocess.PIPE) |
|
285 |
+ p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stderr=subprocess.PIPE) |
|
280 | 286 |
except OSError: |
281 | 287 |
pass |
282 | 288 |
else: |
283 |
- if p.wait() == 0 and p.communicate()[0] == 'install ok installed': |
|
284 |
- return {'libraries': ['zmumps_scotch', 'mumps_common_scotch', |
|
285 |
- 'pord', 'mpiseq_scotch', 'gfortran']} |
|
289 |
+ p.communicate(input='int main() {}\n') |
|
290 |
+ if p.wait() == 0: |
|
291 |
+ return {'libraries': libs} |
|
286 | 292 |
return {} |
287 | 293 |
|
288 | 294 |
|
... | ... |
@@ -349,10 +355,9 @@ def extensions(): |
349 | 355 |
if kwrds: |
350 | 356 |
build_summary.append('User-configured MUMPS') |
351 | 357 |
else: |
352 |
- kwrds = debian_mumps() |
|
358 |
+ kwrds = search_mumps() |
|
353 | 359 |
if kwrds: |
354 |
- build_summary.append( |
|
355 |
- 'MUMPS from package {0}'.format(MUMPS_DEBIAN_PACKAGE)) |
|
360 |
+ build_summary.append('Auto-configured MUMPS') |
|
356 | 361 |
if kwrds: |
357 | 362 |
for name, value in lapack.iteritems(): |
358 | 363 |
kwrds.setdefault(name, []).extend(value) |
... | ... |
@@ -438,7 +438,7 @@ def ext_modules(extensions): |
438 | 438 |
def main(): |
439 | 439 |
setup(name='kwant', |
440 | 440 |
version=version(), |
441 |
- author='C. W. Groth, M. Wimmer, A. R. Akhmerov, X. Waintal, and others', |
|
441 |
+ author='C. W. Groth (CEA), M. Wimmer, A. R. Akhmerov, X. Waintal (CEA), and others', |
|
442 | 442 |
author_email='authors@kwant-project.org', |
443 | 443 |
description="Package for numerical quantum transport calculations.", |
444 | 444 |
long_description=long_description(), |
... | ... |
@@ -438,7 +438,7 @@ def ext_modules(extensions): |
438 | 438 |
def main(): |
439 | 439 |
setup(name='kwant', |
440 | 440 |
version=version(), |
441 |
- author='C. W. Groth, M. Wimmer, A. R. Akhmerov, X. Waintal, et al.', |
|
441 |
+ author='C. W. Groth, M. Wimmer, A. R. Akhmerov, X. Waintal, and others', |
|
442 | 442 |
author_email='authors@kwant-project.org', |
443 | 443 |
description="Package for numerical quantum transport calculations.", |
444 | 444 |
long_description=long_description(), |
... | ... |
@@ -440,7 +440,7 @@ def main(): |
440 | 440 |
version=version(), |
441 | 441 |
author='C. W. Groth, M. Wimmer, A. R. Akhmerov, X. Waintal, et al.', |
442 | 442 |
author_email='authors@kwant-project.org', |
443 |
- description="A package for numerical quantum transport calculations.", |
|
443 |
+ description="Package for numerical quantum transport calculations.", |
|
444 | 444 |
long_description=long_description(), |
445 | 445 |
platforms=["Unix", "Linux", "Mac OS-X", "Windows"], |
446 | 446 |
url="http://kwant-project.org/", |
... | ... |
@@ -414,6 +414,10 @@ def ext_modules(extensions): |
414 | 414 |
complain_cython_unavailable() |
415 | 415 |
exit(1) |
416 | 416 |
for f in pyx_files + kwrds.get('depends', []): |
417 |
+ if f == CONFIG_FILE: |
|
418 |
+ # The config file is only a dependency for the compilation |
|
419 |
+ # of the cythonized file, not for the cythonization. |
|
420 |
+ continue |
|
417 | 421 |
if os.stat(f).st_mtime > cythonized_oldest: |
418 | 422 |
msg = "error: {0} is newer than its source file, but " |
419 | 423 |
if cythonize and not cython_version: |
... | ... |
@@ -367,11 +367,23 @@ def extensions(): |
367 | 367 |
return result |
368 | 368 |
|
369 | 369 |
|
370 |
+def complain_cython_unavailable(): |
|
371 |
+ assert not cythonize or cython_version < REQUIRED_CYTHON_VERSION |
|
372 |
+ if cythonize: |
|
373 |
+ msg = "Install Cython {0} or newer so it can be made or use a source " \ |
|
374 |
+ "distribution of Kwant." |
|
375 |
+ ver = '.'.join(str(e) for e in REQUIRED_CYTHON_VERSION) |
|
376 |
+ print >>sys.stderr, msg.format(ver) |
|
377 |
+ else: |
|
378 |
+ print >>sys.stderr, "Run setup.py without", \ |
|
379 |
+ NO_CYTHON_OPTION |
|
380 |
+ |
|
381 |
+ |
|
370 | 382 |
def ext_modules(extensions): |
371 | 383 |
"""Prepare the ext_modules argument for distutils' setup.""" |
372 | 384 |
result = [] |
373 | 385 |
for args, kwrds in extensions: |
374 |
- if not cythonize or not cython_version: |
|
386 |
+ if not cythonize or cython_version < REQUIRED_CYTHON_VERSION: |
|
375 | 387 |
if 'language' in kwrds: |
376 | 388 |
if kwrds['language'] == 'c': |
377 | 389 |
ext = '.c' |
... | ... |
@@ -399,21 +411,20 @@ def ext_modules(extensions): |
399 | 411 |
except OSError: |
400 | 412 |
print >>sys.stderr, \ |
401 | 413 |
"error: Cython-generated file {0} is missing.".format(f) |
402 |
- if cythonize: |
|
403 |
- print >>sys.stderr, "Install Cython so it can be made" \ |
|
404 |
- " or use a source distribution of Kwant." |
|
405 |
- else: |
|
406 |
- print >>sys.stderr, "Run setup.py without", \ |
|
407 |
- NO_CYTHON_OPTION |
|
414 |
+ complain_cython_unavailable() |
|
408 | 415 |
exit(1) |
409 | 416 |
for f in pyx_files + kwrds.get('depends', []): |
410 | 417 |
if os.stat(f).st_mtime > cythonized_oldest: |
411 |
- msg = "Warning: {0} is newer than its source file, " |
|
412 |
- if cythonize: |
|
413 |
- msg += "but Cython is not installed." |
|
418 |
+ msg = "error: {0} is newer than its source file, but " |
|
419 |
+ if cythonize and not cython_version: |
|
420 |
+ msg += "Cython is not installed." |
|
421 |
+ elif cythonize: |
|
422 |
+ msg += "the installed Cython is too old." |
|
414 | 423 |
else: |
415 |
- msg += "but Cython is not to be run." |
|
424 |
+ msg += "Cython is not to be run." |
|
416 | 425 |
print >>sys.stderr, msg.format(f) |
426 |
+ complain_cython_unavailable() |
|
427 |
+ exit(1) |
|
417 | 428 |
|
418 | 429 |
result.append(Extension(*args, **kwrds)) |
419 | 430 |
|
... | ... |
@@ -421,16 +432,6 @@ def ext_modules(extensions): |
421 | 432 |
|
422 | 433 |
|
423 | 434 |
def main(): |
424 |
- if cythonize and cython_version < REQUIRED_CYTHON_VERSION: |
|
425 |
- msg = 'Warning: Cython {0} is required but ' |
|
426 |
- if cython_version: |
|
427 |
- msg += 'only {1} is present.' |
|
428 |
- else: |
|
429 |
- msg += 'it is not installed.' |
|
430 |
- print >>sys.stderr, msg.format( |
|
431 |
- '.'.join(str(e) for e in REQUIRED_CYTHON_VERSION), |
|
432 |
- '.'.join(str(e) for e in cython_version)) |
|
433 |
- |
|
434 | 435 |
setup(name='kwant', |
435 | 436 |
version=version(), |
436 | 437 |
author='C. W. Groth, M. Wimmer, A. R. Akhmerov, X. Waintal, et al.', |
... | ... |
@@ -55,6 +55,14 @@ kwant_dir = os.path.dirname(os.path.abspath(__file__)) |
55 | 55 |
|
56 | 56 |
class kwant_build_ext(build_ext): |
57 | 57 |
def run(self): |
58 |
+ if not config_file_present: |
|
59 |
+ # Create an empty config file if none is present so that the |
|
60 |
+ # extensions will not be rebuilt each time. Only depending on the |
|
61 |
+ # config file if it is present would make it impossible to detect a |
|
62 |
+ # necessary rebuild due to a deleted config file. |
|
63 |
+ with open(CONFIG_FILE, 'w') as f: |
|
64 |
+ f.write('# Created by setup.py - feel free to modify.\n') |
|
65 |
+ |
|
58 | 66 |
try: |
59 | 67 |
build_ext.run(self) |
60 | 68 |
except (DistutilsError, CCompilerError): |
... | ... |
@@ -283,7 +291,7 @@ def extensions(): |
283 | 291 |
Extension. possibly after replacing ".pyx" with ".c" if Cython is not to be |
284 | 292 |
used.""" |
285 | 293 |
|
286 |
- global build_summary |
|
294 |
+ global build_summary, config_file_present |
|
287 | 295 |
build_summary = [] |
288 | 296 |
|
289 | 297 |
#### Add components of Kwant without external compile-time dependencies. |
... | ... |
@@ -313,8 +321,9 @@ def extensions(): |
313 | 321 |
with open(CONFIG_FILE) as f: |
314 | 322 |
config.readfp(f) |
315 | 323 |
except IOError: |
316 |
- with open(CONFIG_FILE, 'w') as f: |
|
317 |
- f.write('# Created by setup.py - feel free to modify.\n') |
|
324 |
+ config_file_present = False |
|
325 |
+ else: |
|
326 |
+ config_file_present = True |
|
318 | 327 |
|
319 | 328 |
kwrds_by_section = {} |
320 | 329 |
for section in config.sections(): |
... | ... |
@@ -424,8 +424,8 @@ def main(): |
424 | 424 |
|
425 | 425 |
setup(name='kwant', |
426 | 426 |
version=version(), |
427 |
- author='kwant authors', |
|
428 |
- author_email='christoph.groth@cea.fr', |
|
427 |
+ author='C. W. Groth, M. Wimmer, A. R. Akhmerov, X. Waintal, et al.', |
|
428 |
+ author_email='authors@kwant-project.org', |
|
429 | 429 |
description="A package for numerical quantum transport calculations.", |
430 | 430 |
long_description=long_description(), |
431 | 431 |
platforms=["Unix", "Linux", "Mac OS-X", "Windows"], |
... | ... |
@@ -23,9 +23,10 @@ import os |
23 | 23 |
import glob |
24 | 24 |
import subprocess |
25 | 25 |
import ConfigParser |
26 |
-from distutils.core import setup, Command |
|
27 |
-from distutils.extension import Extension |
|
28 |
-from distutils.errors import DistutilsError, CCompilerError |
|
26 |
+from distutils.core import setup, Extension, Command |
|
27 |
+from distutils.util import get_platform |
|
28 |
+from distutils.errors import DistutilsError, DistutilsModuleError, \ |
|
29 |
+ CCompilerError |
|
29 | 30 |
from distutils.command.build import build as distutils_build |
30 | 31 |
from distutils.command.sdist import sdist as distutils_sdist |
31 | 32 |
import numpy |
... | ... |
@@ -101,6 +102,30 @@ class kwant_build(distutils_build): |
101 | 102 |
sub_commands = [('build_tut', None)] + distutils_build.sub_commands |
102 | 103 |
|
103 | 104 |
|
105 |
+class test(Command): |
|
106 |
+ description = "build, then run the unit tests" |
|
107 |
+ user_options = [] |
|
108 |
+ |
|
109 |
+ def initialize_options(self): |
|
110 |
+ pass |
|
111 |
+ |
|
112 |
+ def finalize_options(self): |
|
113 |
+ pass |
|
114 |
+ |
|
115 |
+ def run(self): |
|
116 |
+ try: |
|
117 |
+ from nose.core import run |
|
118 |
+ except ImportError: |
|
119 |
+ raise DistutilsModuleError('nose <http://nose.readthedocs.org/> ' |
|
120 |
+ 'is needed to run the tests') |
|
121 |
+ self.run_command('build') |
|
122 |
+ major, minor = sys.version_info[:2] |
|
123 |
+ lib_dir = "build/lib.{0}-{1}.{2}".format(get_platform(), major, minor) |
|
124 |
+ print '**************** Tests ****************' |
|
125 |
+ if not run(argv=[__file__, '-v', lib_dir]): |
|
126 |
+ raise DistutilsError('at least one of the tests failed') |
|
127 |
+ |
|
128 |
+ |
|
104 | 129 |
def git_lsfiles(): |
105 | 130 |
try: |
106 | 131 |
p = subprocess.Popen(['git', 'ls-files'], cwd=kwant_dir, |
... | ... |
@@ -410,7 +435,8 @@ def main(): |
410 | 435 |
cmdclass={'build': kwant_build, |
411 | 436 |
'sdist': kwant_sdist, |
412 | 437 |
'build_ext': kwant_build_ext, |
413 |
- 'build_tut': build_tut}, |
|
438 |
+ 'build_tut': build_tut, |
|
439 |
+ 'test': test}, |
|
414 | 440 |
ext_modules=ext_modules(extensions()), |
415 | 441 |
include_dirs=[numpy.get_include()]) |
416 | 442 |
|
... | ... |
@@ -1,10 +1,10 @@ |
1 | 1 |
#!/usr/bin/env python |
2 | 2 |
|
3 |
-# Copyright 2011-2013 kwant authors. |
|
3 |
+# Copyright 2011-2013 Kwant authors. |
|
4 | 4 |
# |
5 |
-# This file is part of kwant. It is subject to the license terms in the |
|
5 |
+# This file is part of Kwant. It is subject to the license terms in the |
|
6 | 6 |
# LICENSE file found in the top-level directory of this distribution and at |
7 |
-# http://kwant-project.org/license. A list of kwant authors can be found in |
|
7 |
+# http://kwant-project.org/license. A list of Kwant authors can be found in |
|
8 | 8 |
# the AUTHORS file at the top-level directory of this distribution and at |
9 | 9 |
# http://kwant-project.org/authors. |
10 | 10 |
|
... | ... |
@@ -59,7 +59,7 @@ class kwant_build_ext(build_ext): |
59 | 59 |
except (DistutilsError, CCompilerError): |
60 | 60 |
print >>sys.stderr, \ |
61 | 61 |
"""{0} |
62 |
-The compilation of kwant has failed. Please examine the error message |
|
62 |
+The compilation of Kwant has failed. Please examine the error message |
|
63 | 63 |
above and consult the installation instructions in README. |
64 | 64 |
You might have to customize {1}. |
65 | 65 |
{0} |
... | ... |
@@ -164,7 +164,7 @@ with a comment). It may well be incomplete.""" |
164 | 164 |
|
165 | 165 |
|
166 | 166 |
# This is an exact copy of the function from kwant/version.py. We can't import |
167 |
-# it here (because kwant is not yet built when this scipt is run), so we just |
|
167 |
+# it here (because Kwant is not yet built when this scipt is run), so we just |
|
168 | 168 |
# include a copy. |
169 | 169 |
def get_version_from_git(): |
170 | 170 |
try: |
... | ... |
@@ -191,7 +191,7 @@ def get_version_from_git(): |
191 | 191 |
|
192 | 192 |
|
193 | 193 |
def get_static_version(): |
194 |
- """Return the version as recorded inside kwant.""" |
|
194 |
+ """Return the version as recorded inside the source code.""" |
|
195 | 195 |
try: |
196 | 196 |
with open(STATIC_VERSION_FILE) as f: |
197 | 197 |
contents = f.read() |
... | ... |
@@ -203,7 +203,7 @@ def get_static_version(): |
203 | 203 |
|
204 | 204 |
|
205 | 205 |
def version(): |
206 |
- """Determine the version of kwant. Return it and save it in a file.""" |
|
206 |
+ """Determine the version of Kwant. Return it and save it in a file.""" |
|
207 | 207 |
git_version = get_version_from_git() |
208 | 208 |
static_version = get_static_version() |
209 | 209 |
if git_version is not None: |
... | ... |
@@ -261,7 +261,7 @@ def extensions(): |
261 | 261 |
global build_summary |
262 | 262 |
build_summary = [] |
263 | 263 |
|
264 |
- #### Add components of kwant without external compile-time dependencies. |
|
264 |
+ #### Add components of Kwant without external compile-time dependencies. |
|
265 | 265 |
result = [ |
266 | 266 |
(['kwant._system', ['kwant/_system.pyx']], |
267 | 267 |
{'include_dirs': ['kwant/graph']}), |
... | ... |
@@ -282,7 +282,7 @@ def extensions(): |
282 | 282 |
'kwant/graph/c_slicer/partitioner.h', |
283 | 283 |
'kwant/graph/c_slicer/slicer.h']})] |
284 | 284 |
|
285 |
- #### Add components of kwant with external compile-time dependencies. |
|
285 |
+ #### Add components of Kwant with external compile-time dependencies. |
|
286 | 286 |
config = ConfigParser.ConfigParser() |
287 | 287 |
try: |
288 | 288 |
with open(CONFIG_FILE) as f: |
... | ... |
@@ -367,7 +367,7 @@ def ext_modules(extensions): |
367 | 367 |
"error: Cython-generated file {0} is missing.".format(f) |
368 | 368 |
if cythonize: |
369 | 369 |
print >>sys.stderr, "Install Cython so it can be made" \ |
370 |
- " or use a source distribution of kwant." |
|
370 |
+ " or use a source distribution of Kwant." |
|
371 | 371 |
else: |
372 | 372 |
print >>sys.stderr, "Run setup.py without", \ |
373 | 373 |
NO_CYTHON_OPTION |
... | ... |
@@ -9,6 +9,7 @@ |
9 | 9 |
# http://kwant-project.org/authors. |
10 | 10 |
|
11 | 11 |
CONFIG_FILE = 'build.conf' |
12 |
+README_FILE = 'README' |
|
12 | 13 |
STATIC_VERSION_FILE = 'kwant/_static_version.py' |
13 | 14 |
REQUIRED_CYTHON_VERSION = (0, 17, 1) |
14 | 15 |
MUMPS_DEBIAN_PACKAGE = 'libmumps-scotch-dev' |
... | ... |
@@ -217,6 +218,19 @@ def version(): |
217 | 218 |
return version |
218 | 219 |
|
219 | 220 |
|
221 |
+def long_description(): |
|
222 |
+ text = [] |
|
223 |
+ try: |
|
224 |
+ with open(README_FILE) as f: |
|
225 |
+ for line in f: |
|
226 |
+ if line == "\n": |
|
227 |
+ break |
|
228 |
+ text.append(line.rstrip()) |
|
229 |
+ except: |
|
230 |
+ return '' |
|
231 |
+ return '\n'.join(text) |
|
232 |
+ |
|
233 |
+ |
|
220 | 234 |
def packages(): |
221 | 235 |
return [root.replace('/', '.') |
222 | 236 |
for root, dnames, fnames in os.walk('kwant') |
... | ... |
@@ -387,8 +401,9 @@ def main(): |
387 | 401 |
version=version(), |
388 | 402 |
author='kwant authors', |
389 | 403 |
author_email='christoph.groth@cea.fr', |
390 |
- description="A package for numerical " |
|
391 |
- "quantum transport calculations.", |
|
404 |
+ description="A package for numerical quantum transport calculations.", |
|
405 |
+ long_description=long_description(), |
|
406 |
+ platforms=["Unix", "Linux", "Mac OS-X", "Windows"], |
|
392 | 407 |
url="http://kwant-project.org/", |
393 | 408 |
license="BSD", |
394 | 409 |
packages=packages(), |
... | ... |
@@ -48,6 +48,8 @@ if cythonize and cython_version: |
48 | 48 |
else: |
49 | 49 |
from distutils.command.build_ext import build_ext |
50 | 50 |
|
51 |
+kwant_dir = os.path.dirname(os.path.abspath(__file__)) |
|
52 |
+ |
|
51 | 53 |
|
52 | 54 |
class kwant_build_ext(build_ext): |
53 | 55 |
def run(self): |
... | ... |
@@ -96,7 +98,18 @@ class build_tut(Command): |
96 | 98 |
# that the tutorial is present. |
97 | 99 |
class kwant_build(distutils_build): |
98 | 100 |
sub_commands = [('build_tut', None)] + distutils_build.sub_commands |
99 |
- pass |
|
101 |
+ |
|
102 |
+ |
|
103 |
+def git_lsfiles(): |
|
104 |
+ try: |
|
105 |
+ p = subprocess.Popen(['git', 'ls-files'], cwd=kwant_dir, |
|
106 |
+ stdout=subprocess.PIPE, stderr=subprocess.PIPE) |
|
107 |
+ except OSError: |
|
108 |
+ return |
|
109 |
+ |
|
110 |
+ if p.wait() != 0: |
|
111 |
+ return |
|
112 |
+ return p.communicate()[0].split('\n')[:-1] |
|
100 | 113 |
|
101 | 114 |
|
102 | 115 |
# Make the command "sdist" depend on "build". This verifies that the |
... | ... |
@@ -105,14 +118,54 @@ class kwant_build(distutils_build): |
105 | 118 |
# distribution and that they will be up-to-date. |
106 | 119 |
class kwant_sdist(distutils_sdist): |
107 | 120 |
sub_commands = [('build', None)] + distutils_sdist.sub_commands |
108 |
- pass |
|
121 |
+ |
|
122 |
+ def run(self): |
|
123 |
+ names = git_lsfiles() |
|
124 |
+ trustworthy = True |
|
125 |
+ if names is None: |
|
126 |
+ # Check that MANIFEST exists and has not been generated by |
|
127 |
+ # distutils. |
|
128 |
+ try: |
|
129 |
+ with open(kwant_dir + '/MANIFEST', 'r') as f: |
|
130 |
+ line = f.read() |
|
131 |
+ except IOError: |
|
132 |
+ print >>sys.stderr, "error: MANIFEST file is missing and " \ |
|
133 |
+ "Git is not available to regenerate it." |
|
134 |
+ exit(1) |
|
135 |
+ trustworthy = not line.strip().startswith('#') |
|
136 |
+ else: |
|
137 |
+ # Generate MANIFEST file. |
|
138 |
+ with open(kwant_dir + '/MANIFEST', 'w') as f: |
|
139 |
+ for name in names: |
|
140 |
+ a, sep, b = name.rpartition('/') |
|
141 |
+ if b == '.gitignore': |
|
142 |
+ continue |
|
143 |
+ stem, dot, extension = b.rpartition('.') |
|
144 |
+ if extension == 'pyx': |
|
145 |
+ f.write(''.join([a, sep, stem, dot, 'c', '\n'])) |
|
146 |
+ f.write(name + '\n') |
|
147 |
+ f.write(STATIC_VERSION_FILE + '\n') |
|
148 |
+ f.write('MANIFEST') |
|
149 |
+ |
|
150 |
+ distutils_sdist.run(self) |
|
151 |
+ |
|
152 |
+ if names is None: |
|
153 |
+ print >>sys.stderr, \ |
|
154 |
+ """**************** Warning **************** |
|
155 |
+Git was not available for re-generating the MANIFEST file (the list of file |
|
156 |
+names to be included in the source distribution). The old MANIFEST was used.""" |
|
157 |
+ |
|
158 |
+ if not trustworthy: |
|
159 |
+ print >>sys.stderr, \ |
|
160 |
+ """**************** Warning **************** |
|
161 |
+The existing MANIFEST file seems to have been generated by distutils (it begins |
|
162 |
+with a comment). It may well be incomplete.""" |
|
109 | 163 |
|
110 | 164 |
|
111 | 165 |
# This is an exact copy of the function from kwant/version.py. We can't import |
112 | 166 |
# it here (because kwant is not yet built when this scipt is run), so we just |
113 | 167 |
# include a copy. |
114 | 168 |
def get_version_from_git(): |
115 |
- kwant_dir = os.path.dirname(os.path.abspath(__file__)) |
|
116 | 169 |
try: |
117 | 170 |
p = subprocess.Popen(['git', 'describe'], cwd=kwant_dir, |
118 | 171 |
stdout=subprocess.PIPE, stderr=subprocess.PIPE) |
... | ... |
@@ -297,7 +350,7 @@ def ext_modules(extensions): |
297 | 350 |
for f in cythonized_files) |
298 | 351 |
except OSError: |
299 | 352 |
print >>sys.stderr, \ |
300 |
- "Error: Cython-generated file {0} is missing.".format(f) |
|
353 |
+ "error: Cython-generated file {0} is missing.".format(f) |
|
301 | 354 |
if cythonize: |
302 | 355 |
print >>sys.stderr, "Install Cython so it can be made" \ |
303 | 356 |
" or use a source distribution of kwant." |
... | ... |
@@ -164,6 +164,12 @@ def version(): |
164 | 164 |
return version |
165 | 165 |
|
166 | 166 |
|
167 |
+def packages(): |
|
168 |
+ return [root.replace('/', '.') |
|
169 |
+ for root, dnames, fnames in os.walk('kwant') |
|
170 |
+ if '__init__.py' in fnames or root.endswith('/tests')] |
|
171 |
+ |
|
172 |
+ |
|
167 | 173 |
def debian_mumps(): |
168 | 174 |
"""Return the configuration for debian-provided MUMPS if it is available, |
169 | 175 |
or an empty dictionary otherwise.""" |
... | ... |
@@ -332,11 +338,7 @@ def main(): |
332 | 338 |
"quantum transport calculations.", |
333 | 339 |
url="http://kwant-project.org/", |
334 | 340 |
license="BSD", |
335 |
- packages=["kwant", "kwant.graph", "kwant.linalg", "kwant.physics", |
|
336 |
- "kwant.solvers", "kwant.contrib", |
|
337 |
- "kwant.tests", "kwant.graph.tests", "kwant.linalg.tests", |
|
338 |
- "kwant.physics.tests", "kwant.solvers.tests", |
|
339 |
- "kwant.contrib.tests"], |
|
341 |
+ packages=packages(), |
|
340 | 342 |
cmdclass={'build': kwant_build, |
341 | 343 |
'sdist': kwant_sdist, |
342 | 344 |
'build_ext': kwant_build_ext, |
... | ... |
@@ -333,9 +333,10 @@ def main(): |
333 | 333 |
url="http://kwant-project.org/", |
334 | 334 |
license="BSD", |
335 | 335 |
packages=["kwant", "kwant.graph", "kwant.linalg", "kwant.physics", |
336 |
- "kwant.solvers", "kwant.tests", "kwant.graph.tests", |
|
337 |
- "kwant.linalg.tests", "kwant.physics.tests", |
|
338 |
- "kwant.solvers.tests"], |
|
336 |
+ "kwant.solvers", "kwant.contrib", |
|
337 |
+ "kwant.tests", "kwant.graph.tests", "kwant.linalg.tests", |
|
338 |
+ "kwant.physics.tests", "kwant.solvers.tests", |
|
339 |
+ "kwant.contrib.tests"], |
|
339 | 340 |
cmdclass={'build': kwant_build, |
340 | 341 |
'sdist': kwant_sdist, |
341 | 342 |
'build_ext': kwant_build_ext, |
... | ... |
@@ -1,5 +1,13 @@ |
1 | 1 |
#!/usr/bin/env python |
2 | 2 |
|
3 |
+# Copyright 2011-2013 kwant authors. |
|
4 |
+# |
|
5 |
+# This file is part of kwant. It is subject to the license terms in the |
|
6 |
+# LICENSE file found in the top-level directory of this distribution and at |
|
7 |
+# http://kwant-project.org/license. A list of kwant authors can be found in |
|
8 |
+# the AUTHORS file at the top-level directory of this distribution and at |
|
9 |
+# http://kwant-project.org/authors. |
|
10 |
+ |
|
3 | 11 |
CONFIG_FILE = 'build.conf' |
4 | 12 |
STATIC_VERSION_FILE = 'kwant/_static_version.py' |
5 | 13 |
REQUIRED_CYTHON_VERSION = (0, 17, 1) |
... | ... |
@@ -318,11 +326,12 @@ def main(): |
318 | 326 |
|
319 | 327 |
setup(name='kwant', |
320 | 328 |
version=version(), |
321 |
- author='A. R. Akhmerov, C. W. Groth, X. Waintal, M. Wimmer', |
|
329 |
+ author='kwant authors', |
|
322 | 330 |
author_email='christoph.groth@cea.fr', |
323 | 331 |
description="A package for numerical " |
324 | 332 |
"quantum transport calculations.", |
325 |
- license="not to be distributed", |
|
333 |
+ url="http://kwant-project.org/", |
|
334 |
+ license="BSD", |
|
326 | 335 |
packages=["kwant", "kwant.graph", "kwant.linalg", "kwant.physics", |
327 | 336 |
"kwant.solvers", "kwant.tests", "kwant.graph.tests", |
328 | 337 |
"kwant.linalg.tests", "kwant.physics.tests", |
... | ... |
@@ -324,7 +324,9 @@ def main(): |
324 | 324 |
"quantum transport calculations.", |
325 | 325 |
license="not to be distributed", |
326 | 326 |
packages=["kwant", "kwant.graph", "kwant.linalg", "kwant.physics", |
327 |
- "kwant.solvers"], |
|
327 |
+ "kwant.solvers", "kwant.tests", "kwant.graph.tests", |
|
328 |
+ "kwant.linalg.tests", "kwant.physics.tests", |
|
329 |
+ "kwant.solvers.tests"], |
|
328 | 330 |
cmdclass={'build': kwant_build, |
329 | 331 |
'sdist': kwant_sdist, |
330 | 332 |
'build_ext': kwant_build_ext, |
... | ... |
@@ -75,10 +75,11 @@ class build_tut(Command): |
75 | 75 |
os.mkdir(TUT_DIR) |
76 | 76 |
for in_fname in glob.glob(TUT_GLOB): |
77 | 77 |
out_fname = os.path.join(TUT_DIR, os.path.basename(in_fname)) |
78 |
- with open(in_fname) as in_file, open(out_fname, 'w') as out_file: |
|
79 |
- for line in in_file: |
|
80 |
- if not line.startswith(TUT_HIDDEN_PREFIX): |
|
81 |
- out_file.write(line) |
|
78 |
+ with open(in_fname) as in_file: |
|
79 |
+ with open(out_fname, 'w') as out_file: |
|
80 |
+ for line in in_file: |
|
81 |
+ if not line.startswith(TUT_HIDDEN_PREFIX): |
|
82 |
+ out_file.write(line) |
|
82 | 83 |
|
83 | 84 |
|
84 | 85 |
# Our version of the "build" command also makes sure the tutorial is made. |
... | ... |
@@ -18,6 +18,7 @@ from distutils.core import setup, Command |
18 | 18 |
from distutils.extension import Extension |
19 | 19 |
from distutils.errors import DistutilsError, CCompilerError |
20 | 20 |
from distutils.command.build import build as distutils_build |
21 |
+from distutils.command.sdist import sdist as distutils_sdist |
|
21 | 22 |
import numpy |
22 | 23 |
|
23 | 24 |
try: |
... | ... |
@@ -89,6 +90,15 @@ class kwant_build(distutils_build): |
89 | 90 |
pass |
90 | 91 |
|
91 | 92 |
|
93 |
+# Make the command "sdist" depend on "build". This verifies that the |
|
94 |
+# distribution in the current state actually builds. It also makes sure that |
|
95 |
+# the Cython-made C files and the tutorial will be included in the source |
|
96 |
+# distribution and that they will be up-to-date. |
|
97 |
+class kwant_sdist(distutils_sdist): |
|
98 |
+ sub_commands = [('build', None)] + distutils_sdist.sub_commands |
|
99 |
+ pass |
|
100 |
+ |
|
101 |
+ |
|
92 | 102 |
# This is an exact copy of the function from kwant/version.py. We can't import |
93 | 103 |
# it here (because kwant is not yet built when this scipt is run), so we just |
94 | 104 |
# include a copy. |
... | ... |
@@ -315,6 +325,7 @@ def main(): |
315 | 325 |
packages=["kwant", "kwant.graph", "kwant.linalg", "kwant.physics", |
316 | 326 |
"kwant.solvers"], |
317 | 327 |
cmdclass={'build': kwant_build, |
328 |
+ 'sdist': kwant_sdist, |
|
318 | 329 |
'build_ext': kwant_build_ext, |
319 | 330 |
'build_tut': build_tut}, |
320 | 331 |
ext_modules=ext_modules(extensions()), |
... | ... |
@@ -5,14 +5,19 @@ STATIC_VERSION_FILE = 'kwant/_static_version.py' |
5 | 5 |
REQUIRED_CYTHON_VERSION = (0, 17, 1) |
6 | 6 |
MUMPS_DEBIAN_PACKAGE = 'libmumps-scotch-dev' |
7 | 7 |
NO_CYTHON_OPTION = '--no-cython' |
8 |
+TUT_DIR = 'tutorial' |
|
9 |
+TUT_GLOB = 'doc/source/tutorial/*.py' |
|
10 |
+TUT_HIDDEN_PREFIX = '#HIDDEN' |
|
8 | 11 |
|
9 | 12 |
import sys |
10 | 13 |
import os |
14 |
+import glob |
|
11 | 15 |
import subprocess |
12 | 16 |
import ConfigParser |
13 |
-from distutils.core import setup |
|
17 |
+from distutils.core import setup, Command |
|
14 | 18 |
from distutils.extension import Extension |
15 | 19 |
from distutils.errors import DistutilsError, CCompilerError |
20 |
+from distutils.command.build import build as distutils_build |
|
16 | 21 |
import numpy |
17 | 22 |
|
18 | 23 |
try: |
... | ... |
@@ -54,6 +59,36 @@ Build configuration was: |
54 | 59 |
print build_summary |
55 | 60 |
|
56 | 61 |
|
62 |
+class build_tut(Command): |
|
63 |
+ description = "build the tutorial scripts" |
|
64 |
+ user_options = [] |
|
65 |
+ |
|
66 |
+ def initialize_options(self): |
|
67 |
+ pass |
|
68 |
+ |
|
69 |
+ def finalize_options(self): |
|
70 |
+ pass |
|
71 |
+ |
|
72 |
+ def run(self): |
|
73 |
+ if not os.path.exists(TUT_DIR): |
|
74 |
+ os.mkdir(TUT_DIR) |
|
75 |
+ for in_fname in glob.glob(TUT_GLOB): |
|
76 |
+ out_fname = os.path.join(TUT_DIR, os.path.basename(in_fname)) |
|
77 |
+ with open(in_fname) as in_file, open(out_fname, 'w') as out_file: |
|
78 |
+ for line in in_file: |
|
79 |
+ if not line.startswith(TUT_HIDDEN_PREFIX): |
|
80 |
+ out_file.write(line) |
|
81 |
+ |
|
82 |
+ |
|
83 |
+# Our version of the "build" command also makes sure the tutorial is made. |
|
84 |
+# Even though the tutorial is not necessary for installation, and "build" is |
|
85 |
+# supposed to make everything needed to install, this is a robust way to ensure |
|
86 |
+# that the tutorial is present. |
|
87 |
+class kwant_build(distutils_build): |
|
88 |
+ sub_commands = [('build_tut', None)] + distutils_build.sub_commands |
|
89 |
+ pass |
|
90 |
+ |
|
91 |
+ |
|
57 | 92 |
# This is an exact copy of the function from kwant/version.py. We can't import |
58 | 93 |
# it here (because kwant is not yet built when this scipt is run), so we just |
59 | 94 |
# include a copy. |
... | ... |
@@ -279,7 +314,9 @@ def main(): |
279 | 314 |
license="not to be distributed", |
280 | 315 |
packages=["kwant", "kwant.graph", "kwant.linalg", "kwant.physics", |
281 | 316 |
"kwant.solvers"], |
282 |
- cmdclass={'build_ext': kwant_build_ext}, |
|
317 |
+ cmdclass={'build': kwant_build, |
|
318 |
+ 'build_ext': kwant_build_ext, |
|
319 |
+ 'build_tut': build_tut}, |
|
283 | 320 |
ext_modules=ext_modules(extensions()), |
284 | 321 |
include_dirs=[numpy.get_include()]) |
285 | 322 |
|
... | ... |
@@ -43,7 +43,7 @@ class kwant_build_ext(build_ext): |
43 | 43 |
print >>sys.stderr, \ |
44 | 44 |
"""{0} |
45 | 45 |
The compilation of kwant has failed. Please examine the error message |
46 |
-above and consult the installation instructions in README.txt. |
|
46 |
+above and consult the installation instructions in README. |
|
47 | 47 |
You might have to customize {1}. |
48 | 48 |
{0} |
49 | 49 |
Build configuration was: |
The code should be easier to understand. Configuration through a site.cfg file
is supported.
... | ... |
@@ -1,17 +1,58 @@ |
1 | 1 |
#!/usr/bin/env python |
2 | 2 |
|
3 |
-import sys, subprocess, os |
|
3 |
+CONFIG_FILE = 'build.conf' |
|
4 |
+STATIC_VERSION_FILE = 'kwant/_static_version.py' |
|
5 |
+REQUIRED_CYTHON_VERSION = (0, 17, 1) |
|
6 |
+MUMPS_DEBIAN_PACKAGE = 'libmumps-scotch-dev' |
|
7 |
+NO_CYTHON_OPTION = '--no-cython' |
|
8 |
+ |
|
9 |
+import sys |
|
10 |
+import os |
|
11 |
+import subprocess |
|
12 |
+import ConfigParser |
|
4 | 13 |
from distutils.core import setup |
5 | 14 |
from distutils.extension import Extension |
6 |
-import numpy as np |
|
15 |
+from distutils.errors import DistutilsError, CCompilerError |
|
16 |
+import numpy |
|
17 |
+ |
|
18 |
+try: |
|
19 |
+ import Cython |
|
20 |
+except: |
|
21 |
+ cython_version = () |
|
22 |
+else: |
|
23 |
+ cython_version = tuple( |
|
24 |
+ int(n) for n in Cython.__version__.split('-')[0].split('.')) |
|
7 | 25 |
|
8 |
-run_cython = '--run-cython' in sys.argv |
|
9 |
-if run_cython: |
|
10 |
- sys.argv.remove('--run-cython') |
|
26 |
+try: |
|
27 |
+ sys.argv.remove(NO_CYTHON_OPTION) |
|
28 |
+ cythonize = False |
|
29 |
+except ValueError: |
|
30 |
+ cythonize = True |
|
31 |
+ |
|
32 |
+if cythonize and cython_version: |
|
11 | 33 |
from Cython.Distutils import build_ext |
12 |
- cmdclass = {'build_ext': build_ext} |
|
13 | 34 |
else: |
14 |
- cmdclass = {} |
|
35 |
+ from distutils.command.build_ext import build_ext |
|
36 |
+ |
|
37 |
+ |
|
38 |
+class kwant_build_ext(build_ext): |
|
39 |
+ def run(self): |
|
40 |
+ try: |
|
41 |
+ build_ext.run(self) |
|
42 |
+ except (DistutilsError, CCompilerError): |
|
43 |
+ print >>sys.stderr, \ |
|
44 |
+"""{0} |
|
45 |
+The compilation of kwant has failed. Please examine the error message |
|
46 |
+above and consult the installation instructions in README.txt. |
|
47 |
+You might have to customize {1}. |
|
48 |
+{0} |
|
49 |
+Build configuration was: |
|
50 |
+{2} |
|
51 |
+{0}""".format('*' * 70, CONFIG_FILE, build_summary) |
|
52 |
+ raise |
|
53 |
+ print '**************** Build summary ****************' |
|
54 |
+ print build_summary |
|
55 |
+ |
|
15 | 56 |
|
16 | 57 |
# This is an exact copy of the function from kwant/version.py. We can't import |
17 | 58 |
# it here (because kwant is not yet built when this scipt is run), so we just |
... | ... |
@@ -40,9 +81,11 @@ def get_version_from_git(): |
40 | 81 |
version += '-dirty' |
41 | 82 |
return version |
42 | 83 |
|
84 |
+ |
|
43 | 85 |
def get_static_version(): |
86 |
+ """Return the version as recorded inside kwant.""" |
|
44 | 87 |
try: |
45 |
- with open('kwant/_static_version.py') as f: |
|
88 |
+ with open(STATIC_VERSION_FILE) as f: |
|
46 | 89 |
contents = f.read() |
47 | 90 |
assert contents[:11] == "version = '" |
48 | 91 |
assert contents[-2:] == "'\n" |
... | ... |
@@ -50,99 +93,195 @@ def get_static_version(): |
50 | 93 |
except: |
51 | 94 |
return None |
52 | 95 |
|
53 |
-git_version = get_version_from_git() |
|
54 |
-static_version = get_static_version() |
|
55 |
-if git_version is not None: |
|
56 |
- version = git_version |
|
57 |
- if static_version != git_version: |
|
58 |
- with open('kwant/_static_version.py', 'w') as f: |
|
59 |
- f.write("version = '%s'\n" % version) |
|
60 |
-elif static_version is not None: |
|
61 |
- version = static_version |
|
62 |
-else: |
|
63 |
- version = 'unknown' |
|
64 |
- |
|
65 |
-# List of tuples (args, keywords) to be passed to Extension, possibly after |
|
66 |
-# replacing ".pyx" with ".c" if Cython is not to be used. |
|
67 |
-extensions = [ # (["kwant.graph.scotch", ["kwant/graph/scotch.pyx"]], |
|
68 |
- # {"libraries" : ["scotch", "scotcherr"]}), |
|
69 |
- (["kwant._system", ["kwant/_system.pyx"]], |
|
70 |
- {"include_dirs" : ["kwant/graph"]}), |
|
71 |
- (["kwant.graph.core", ["kwant/graph/core.pyx"]], |
|
72 |
- {"depends" : ["kwant/graph/core.pxd", "kwant/graph/defs.h", |
|
73 |
- "kwant/graph/defs.pxd"]}), |
|
74 |
- (["kwant.graph.utils", ["kwant/graph/utils.pyx"]], |
|
75 |
- {"depends" : ["kwant/graph/defs.h", "kwant/graph/defs.pxd", |
|
76 |
- "kwant/graph/core.pxd"]}), |
|
77 |
- (["kwant.graph.slicer", ["kwant/graph/slicer.pyx", |
|
78 |
- "kwant/graph/c_slicer/partitioner.cc", |
|
79 |
- "kwant/graph/c_slicer/slicer.cc"]], |
|
80 |
- {"depends" : ["kwant/graph/defs.h", "kwant/graph/defs.pxd", |
|
81 |
- "kwant/graph/core.pxd", |
|
82 |
- "kwant/graph/c_slicer.pxd", |
|
83 |
- "kwant/graph/c_slicer/bucket_list.h", |
|
84 |
- "kwant/graph/c_slicer/graphwrap.h", |
|
85 |
- "kwant/graph/c_slicer/partitioner.h", |
|
86 |
- "kwant/graph/c_slicer/slicer.h"]}), |
|
87 |
- (["kwant.linalg.lapack", ["kwant/linalg/lapack.pyx"]], |
|
88 |
- {"libraries" : ["lapack", "blas"], |
|
89 |
- "depends" : ["kwant/linalg/f_lapack.pxd"]}), |
|
90 |
- (["kwant.linalg._mumps", ["kwant/linalg/_mumps.pyx"]], |
|
91 |
- {"libraries" : ["zmumps", "mumps_common", "pord", |
|
92 |
- "metis", "mpiseq", "lapack", "blas", |
|
93 |
- "gfortran"], |
|
94 |
- "depends" : ["kwant/linalg/cmumps.pxd"]}) ] |
|
95 |
- |
|
96 |
-ext_modules = [] |
|
97 |
-for args, keywords in extensions: |
|
98 |
- if not run_cython: |
|
99 |
- if 'language' in keywords: |
|
100 |
- if keywords['language'] == 'c': |
|
101 |
- ext = '.c' |
|
102 |
- elif keywords['language'] == 'c++': |
|
103 |
- ext = '.cpp' |
|
96 |
+ |
|
97 |
+def version(): |
|
98 |
+ """Determine the version of kwant. Return it and save it in a file.""" |
|
99 |
+ git_version = get_version_from_git() |
|
100 |
+ static_version = get_static_version() |
|
101 |
+ if git_version is not None: |
|
102 |
+ version = git_version |
|
103 |
+ if static_version != git_version: |
|
104 |
+ with open(STATIC_VERSION_FILE, 'w') as f: |
|
105 |
+ f.write("version = '%s'\n" % version) |
|
106 |
+ elif static_version is not None: |
|
107 |
+ version = static_version |
|
108 |
+ else: |
|
109 |
+ version = 'unknown' |
|
110 |
+ return version |
|
111 |
+ |
|
112 |
+ |
|
113 |
+def debian_mumps(): |
|
114 |
+ """Return the configuration for debian-provided MUMPS if it is available, |
|
115 |
+ or an empty dictionary otherwise.""" |
|
116 |
+ try: |
|
117 |
+ p = subprocess.Popen( |
|
118 |
+ ['dpkg-query', '-W', '-f=${Status}', MUMPS_DEBIAN_PACKAGE], |
|
119 |
+ stdout=subprocess.PIPE) |
|
120 |
+ except OSError: |
|
121 |
+ pass |
|
122 |
+ else: |
|
123 |
+ if p.wait() == 0 and p.communicate()[0] == 'install ok installed': |
|
124 |
+ return {'libraries': ['zmumps_scotch', 'mumps_common_scotch', |
|
125 |
+ 'pord', 'mpiseq_scotch', 'gfortran']} |
|
126 |
+ return {} |
|
127 |
+ |
|
128 |
+ |
|
129 |
+def extensions(): |
|
130 |
+ """Return a list of tuples (args, kwrds) to be passed to |
|
131 |
+ Extension. possibly after replacing ".pyx" with ".c" if Cython is not to be |
|
132 |
+ used.""" |
|
133 |
+ |
|
134 |
+ global build_summary |
|
135 |
+ build_summary = [] |
|
136 |
+ |
|
137 |
+ #### Add components of kwant without external compile-time dependencies. |
|
138 |
+ result = [ |
|
139 |
+ (['kwant._system', ['kwant/_system.pyx']], |
|
140 |
+ {'include_dirs': ['kwant/graph']}), |
|
141 |
+ (['kwant.graph.core', ['kwant/graph/core.pyx']], |
|
142 |
+ {'depends': ['kwant/graph/core.pxd', 'kwant/graph/defs.h', |
|
143 |
+ 'kwant/graph/defs.pxd']}), |
|
144 |
+ (['kwant.graph.utils', ['kwant/graph/utils.pyx']], |
|
145 |
+ {'depends': ['kwant/graph/defs.h', 'kwant/graph/defs.pxd', |
|
146 |
+ 'kwant/graph/core.pxd']}), |
|
147 |
+ (['kwant.graph.slicer', ['kwant/graph/slicer.pyx', |
|
148 |
+ 'kwant/graph/c_slicer/partitioner.cc', |
|
149 |
+ 'kwant/graph/c_slicer/slicer.cc']], |
|
150 |
+ {'depends': ['kwant/graph/defs.h', 'kwant/graph/defs.pxd', |
|
151 |
+ 'kwant/graph/core.pxd', |
|
152 |
+ 'kwant/graph/c_slicer.pxd', |
|
153 |
+ 'kwant/graph/c_slicer/bucket_list.h', |
|
154 |
+ 'kwant/graph/c_slicer/graphwrap.h', |
|
155 |
+ 'kwant/graph/c_slicer/partitioner.h', |
|
156 |
+ 'kwant/graph/c_slicer/slicer.h']})] |
|
157 |
+ |
|
158 |
+ #### Add components of kwant with external compile-time dependencies. |
|
159 |
+ config = ConfigParser.ConfigParser() |
|
160 |
+ try: |
|
161 |
+ with open(CONFIG_FILE) as f: |
|
162 |
+ config.readfp(f) |
|
163 |
+ except IOError: |
|
164 |
+ with open(CONFIG_FILE, 'w') as f: |
|
165 |
+ f.write('# Created by setup.py - feel free to modify.\n') |
|
166 |
+ |
|
167 |
+ kwrds_by_section = {} |
|
168 |
+ for section in config.sections(): |
|
169 |
+ kwrds_by_section[section] = kwrds = {} |
|
170 |
+ for name, value in config.items(section): |
|
171 |
+ kwrds[name] = value.split() |
|
172 |
+ |
|
173 |
+ # Setup LAPACK. |
|
174 |
+ lapack = kwrds_by_section.get('lapack') |
|
175 |
+ if lapack: |
|
176 |
+ build_summary.append('User-configured LAPACK and BLAS') |
|
177 |
+ else: |
|
178 |
+ lapack = {'libraries': ['lapack', 'blas']} |
|
179 |
+ build_summary.append('Default LAPACK and BLAS') |
|
180 |
+ kwrds = lapack.copy() |
|
181 |
+ kwrds.setdefault('depends', []).extend( |
|
182 |
+ [CONFIG_FILE, 'kwant/linalg/f_lapack.pxd']) |
|
183 |
+ result.append((['kwant.linalg.lapack', ['kwant/linalg/lapack.pyx']], |
|
184 |
+ kwrds)) |
|
185 |
+ |
|
186 |
+ # Setup MUMPS. |
|
187 |
+ kwrds = kwrds_by_section.get('mumps') |
|
188 |
+ if kwrds: |
|
189 |
+ build_summary.append('User-configured MUMPS') |
|
190 |
+ else: |
|
191 |
+ kwrds = debian_mumps() |
|
192 |
+ if kwrds: |
|
193 |
+ build_summary.append( |
|
194 |
+ 'MUMPS from package {0}'.format(MUMPS_DEBIAN_PACKAGE)) |
|
195 |
+ if kwrds: |
|
196 |
+ for name, value in lapack.iteritems(): |
|
197 |
+ kwrds.setdefault(name, []).extend(value) |
|
198 |
+ kwrds.setdefault('depends', []).extend( |
|
199 |
+ [CONFIG_FILE, 'kwant/linalg/cmumps.pxd']) |
|
200 |
+ result.append((['kwant.linalg._mumps', ['kwant/linalg/_mumps.pyx']], |
|
201 |
+ kwrds)) |
|
202 |
+ else: |
|
203 |
+ build_summary.append('No MUMPS support') |
|
204 |
+ |
|
205 |
+ build_summary = '\n'.join(build_summary) |
|
206 |
+ return result |
|
207 |
+ |
|
208 |
+ |
|
209 |
+def ext_modules(extensions): |
|
210 |
+ """Prepare the ext_modules argument for distutils' setup.""" |
|
211 |
+ result = [] |
|
212 |
+ for args, kwrds in extensions: |
|
213 |
+ if not cythonize or not cython_version: |
|
214 |
+ if 'language' in kwrds: |
|
215 |
+ if kwrds['language'] == 'c': |
|
216 |
+ ext = '.c' |
|
217 |
+ elif kwrds['language'] == 'c++': |
|
218 |
+ ext = '.cpp' |
|
219 |
+ else: |
|
220 |
+ print >>sys.stderr, 'Unknown language' |
|
221 |
+ exit(1) |
|
104 | 222 |
else: |
105 |
- print >>sys.stderr, 'Unknown language' |
|
223 |
+ ext = '.c' |
|
224 |
+ pyx_files = [] |
|
225 |
+ cythonized_files = [] |
|
226 |
+ sources = [] |
|
227 |
+ for f in args[1]: |
|
228 |
+ if f[-4:] == '.pyx': |
|
229 |
+ pyx_files.append(f) |
|
230 |
+ f = f[:-4] + ext |
|
231 |
+ cythonized_files.append(f) |
|
232 |
+ sources.append(f) |
|
233 |
+ args[1] = sources |
|
234 |
+ |
|
235 |
+ try: |
|
236 |
+ cythonized_oldest = min(os.stat(f).st_mtime |
|
237 |
+ for f in cythonized_files) |
|
238 |
+ except OSError: |
|
239 |
+ print >>sys.stderr, \ |
|
240 |
+ "Error: Cython-generated file {0} is missing.".format(f) |
|
241 |
+ if cythonize: |
|
242 |
+ print >>sys.stderr, "Install Cython so it can be made" \ |
|
243 |
+ " or use a source distribution of kwant." |
|
244 |
+ else: |
|
245 |
+ print >>sys.stderr, "Run setup.py without", \ |
|
246 |
+ NO_CYTHON_OPTION |
|
106 | 247 |
exit(1) |
248 |
+ for f in pyx_files + kwrds.get('depends', []): |
|
249 |
+ if os.stat(f).st_mtime > cythonized_oldest: |
|
250 |
+ msg = "Warning: {0} is newer than its source file, " |
|
251 |
+ if cythonize: |
|
252 |
+ msg += "but Cython is not installed." |
|
253 |
+ else: |
|
254 |
+ msg += "but Cython is not to be run." |
|
255 |
+ print >>sys.stderr, msg.format(f) |
|
256 |
+ |
|
257 |
+ result.append(Extension(*args, **kwrds)) |
|
258 |
+ |
|
259 |
+ return result |
|
260 |
+ |
|
261 |
+ |
|
262 |
+def main(): |
|
263 |
+ if cythonize and cython_version < REQUIRED_CYTHON_VERSION: |
|
264 |
+ msg = 'Warning: Cython {0} is required but ' |
|
265 |
+ if cython_version: |
|
266 |
+ msg += 'only {1} is present.' |
|
107 | 267 |
else: |
108 |
- ext = '.c' |
|
109 |
- pyx_files = [] |
|
110 |
- cythonized_files = [] |
|
111 |
- sources = [] |
|
112 |
- for f in args[1]: |
|
113 |
- if f[-4:] == '.pyx': |
|
114 |
- pyx_files.append(f) |
|
115 |
- f = f[:-4] + ext |
|
116 |
- cythonized_files.append(f) |
|
117 |
- sources.append(f) |
|
118 |
- args[1] = sources |
|
268 |
+ msg += 'it is not installed.' |
|
269 |
+ print >>sys.stderr, msg.format( |
|
270 |
+ '.'.join(str(e) for e in REQUIRED_CYTHON_VERSION), |
|
271 |
+ '.'.join(str(e) for e in cython_version)) |
|
119 | 272 |
|
120 |
- try: |
|
121 |
- cythonized_oldest = min(os.stat(f).st_mtime |
|
122 |
- for f in cythonized_files) |
|
123 |
- except OSError: |
|
124 |
- msg = "{0} is missing. Run `./setup.py --run-cython build'." |
|
125 |
- print >>sys.stderr, msg.format(f) |
|
126 |
- exit(1) |
|
127 |
- for f in pyx_files + keywords.get('depends', []): |
|
128 |
- if os.stat(f).st_mtime > cythonized_oldest: |
|
129 |
- msg = "{0} has been modified. " \ |
|
130 |
- "Run `./setup.py --run-cython build'." |
|
131 |
- print >>sys.stderr, msg.format(f) |
|
132 |
- exit(1) |
|
273 |
+ setup(name='kwant', |
|
274 |
+ version=version(), |
|
275 |
+ author='A. R. Akhmerov, C. W. Groth, X. Waintal, M. Wimmer', |
|
276 |
+ author_email='christoph.groth@cea.fr', |
|
277 |
+ description="A package for numerical " |
|
278 |
+ "quantum transport calculations.", |
|
279 |
+ license="not to be distributed", |
|
280 |
+ packages=["kwant", "kwant.graph", "kwant.linalg", "kwant.physics", |
|
281 |
+ "kwant.solvers"], |
|
282 |
+ cmdclass={'build_ext': kwant_build_ext}, |
|
283 |
+ ext_modules=ext_modules(extensions()), |
|
284 |
+ include_dirs=[numpy.get_include()]) |
|
133 | 285 |
|
134 |
- ext_modules.append(Extension(*args, **keywords)) |
|
135 |
- |
|
136 |
-include_dirs = [np.get_include()] |
|
137 |
- |
|
138 |
-setup(name='kwant', |
|
139 |
- version=version, |
|
140 |
- author='A. R. Akhmerov, C. W. Groth, X. Waintal, M. Wimmer', |
|
141 |
- author_email='cwg@falma.de', |
|
142 |
- description="A package for numerical quantum transport calculations.", |
|
143 |
- license="not to be distributed", |
|
144 |
- packages=["kwant", "kwant.graph", "kwant.linalg", "kwant.physics", |
|
145 |
- "kwant.solvers"], |
|
146 |
- cmdclass=cmdclass, |
|
147 |
- ext_modules=ext_modules, |
|
148 |
- include_dirs = include_dirs) |
|
286 |
+if __name__ == '__main__': |
|
287 |
+ main() |
... | ... |
@@ -86,7 +86,12 @@ extensions = [ # (["kwant.graph.scotch", ["kwant/graph/scotch.pyx"]], |
86 | 86 |
"kwant/graph/c_slicer/slicer.h"]}), |
87 | 87 |
(["kwant.linalg.lapack", ["kwant/linalg/lapack.pyx"]], |
88 | 88 |
{"libraries" : ["lapack", "blas"], |
89 |
- "depends" : ["kwant/linalg/f_lapack.pxd"]}) ] |
|
89 |
+ "depends" : ["kwant/linalg/f_lapack.pxd"]}), |
|
90 |
+ (["kwant.linalg._mumps", ["kwant/linalg/_mumps.pyx"]], |
|
91 |
+ {"libraries" : ["zmumps", "mumps_common", "pord", |
|
92 |
+ "metis", "mpiseq", "lapack", "blas", |
|
93 |
+ "gfortran"], |
|
94 |
+ "depends" : ["kwant/linalg/cmumps.pxd"]}) ] |
|
90 | 95 |
|
91 | 96 |
ext_modules = [] |
92 | 97 |
for args, keywords in extensions: |
... | ... |
@@ -66,6 +66,8 @@ else: |
66 | 66 |
# replacing ".pyx" with ".c" if Cython is not to be used. |
67 | 67 |
extensions = [ # (["kwant.graph.scotch", ["kwant/graph/scotch.pyx"]], |
68 | 68 |
# {"libraries" : ["scotch", "scotcherr"]}), |
69 |
+ (["kwant._system", ["kwant/_system.pyx"]], |
|
70 |
+ {"include_dirs" : ["kwant/graph"]}), |
|
69 | 71 |
(["kwant.graph.core", ["kwant/graph/core.pyx"]], |
70 | 72 |
{"depends" : ["kwant/graph/core.pxd", "kwant/graph/defs.h", |
71 | 73 |
"kwant/graph/defs.pxd"]}), |
... | ... |
@@ -5,6 +5,13 @@ from distutils.core import setup |
5 | 5 |
from distutils.extension import Extension |
6 | 6 |
import numpy as np |
7 | 7 |
|
8 |
+run_cython = '--run-cython' in sys.argv |
|
9 |
+if run_cython: |
|
10 |
+ sys.argv.remove('--run-cython') |
|
11 |
+ from Cython.Distutils import build_ext |
|
12 |
+ cmdclass = {'build_ext': build_ext} |
|
13 |
+else: |
|
14 |
+ cmdclass = {} |
|
8 | 15 |
|
9 | 16 |
# This is an exact copy of the function from kwant/version.py. We can't import |
10 | 17 |
# it here (because kwant is not yet built when this scipt is run), so we just |
... | ... |
@@ -33,13 +40,6 @@ def get_version_from_git(): |
33 | 40 |
version += '-dirty' |
34 | 41 |
return version |
35 | 42 |
|
36 |
-try: |
|
37 |
- from Cython.Distutils import build_ext |
|
38 |
-except ImportError: |
|
39 |
- use_cython = False |
|
40 |
-else: |
|
41 |
- use_cython = True |
|
42 |
- |
|
43 | 43 |
def get_static_version(): |
44 | 44 |
try: |
45 | 45 |
with open('kwant/_static_version.py') as f: |
... | ... |
@@ -66,21 +66,29 @@ else: |
66 | 66 |
# replacing ".pyx" with ".c" if Cython is not to be used. |
67 | 67 |
extensions = [ # (["kwant.graph.scotch", ["kwant/graph/scotch.pyx"]], |
68 | 68 |
# {"libraries" : ["scotch", "scotcherr"]}), |
69 |
- (["kwant.graph.core", ["kwant/graph/core.pyx"]], {}), |
|
70 |
- (["kwant.graph.utils", ["kwant/graph/utils.pyx"]], {}), |
|
69 |
+ (["kwant.graph.core", ["kwant/graph/core.pyx"]], |
|
70 |
+ {"depends" : ["kwant/graph/core.pxd", "kwant/graph/defs.h", |
|
71 |
+ "kwant/graph/defs.pxd"]}), |
|
72 |
+ (["kwant.graph.utils", ["kwant/graph/utils.pyx"]], |
|
73 |
+ {"depends" : ["kwant/graph/defs.h", "kwant/graph/defs.pxd", |
|
74 |
+ "kwant/graph/core.pxd"]}), |
|
71 | 75 |
(["kwant.graph.slicer", ["kwant/graph/slicer.pyx", |
72 | 76 |
"kwant/graph/c_slicer/partitioner.cc", |
73 | 77 |
"kwant/graph/c_slicer/slicer.cc"]], |
74 |
- {}), |
|
78 |
+ {"depends" : ["kwant/graph/defs.h", "kwant/graph/defs.pxd", |
|
79 |
+ "kwant/graph/core.pxd", |
|
80 |
+ "kwant/graph/c_slicer.pxd", |
|
81 |
+ "kwant/graph/c_slicer/bucket_list.h", |
|
82 |
+ "kwant/graph/c_slicer/graphwrap.h", |
|
83 |
+ "kwant/graph/c_slicer/partitioner.h", |
|
84 |
+ "kwant/graph/c_slicer/slicer.h"]}), |
|
75 | 85 |
(["kwant.linalg.lapack", ["kwant/linalg/lapack.pyx"]], |
76 |
- {"libraries" : ["lapack", "blas"]}) ] |
|
86 |
+ {"libraries" : ["lapack", "blas"], |
|
87 |
+ "depends" : ["kwant/linalg/f_lapack.pxd"]}) ] |
|
77 | 88 |
|
78 |
-cmdclass = {} |
|
79 | 89 |
ext_modules = [] |
80 |
-include_dirs = [np.get_include()] |
|
81 |
- |
|
82 | 90 |
for args, keywords in extensions: |
83 |
- if not use_cython: |
|
91 |
+ if not run_cython: |
|
84 | 92 |
if 'language' in keywords: |
85 | 93 |
if keywords['language'] == 'c': |
86 | 94 |
ext = '.c' |
... | ... |
@@ -91,10 +99,34 @@ for args, keywords in extensions: |
91 | 99 |
exit(1) |
92 | 100 |
else: |
93 | 101 |
ext = '.c' |
94 |
- args[1] = [s.replace('.pyx', ext) for s in args[1]] |
|
102 |
+ pyx_files = [] |
|
103 |
+ cythonized_files = [] |
|
104 |
+ sources = [] |
|
105 |
+ for f in args[1]: |
|
106 |
+ if f[-4:] == '.pyx': |
|
107 |
+ pyx_files.append(f) |
|
108 |
+ f = f[:-4] + ext |
|
109 |
+ cythonized_files.append(f) |
|
110 |
+ sources.append(f) |
|
111 |
+ args[1] = sources |
|
112 |
+ |
|
113 |
+ try: |
|
114 |
+ cythonized_oldest = min(os.stat(f).st_mtime |
|
115 |
+ for f in cythonized_files) |
|
116 |
+ except OSError: |
|
117 |
+ msg = "{0} is missing. Run `./setup.py --run-cython build'." |
|
118 |
+ print >>sys.stderr, msg.format(f) |
|
119 |
+ exit(1) |
|
120 |
+ for f in pyx_files + keywords.get('depends', []): |
|
121 |
+ if os.stat(f).st_mtime > cythonized_oldest: |
|
122 |
+ msg = "{0} has been modified. " \ |
|
123 |
+ "Run `./setup.py --run-cython build'." |
|
124 |
+ print >>sys.stderr, msg.format(f) |
|
125 |
+ exit(1) |
|
126 |
+ |
|
95 | 127 |
ext_modules.append(Extension(*args, **keywords)) |
96 |
-if use_cython: |
|
97 |
- cmdclass.update({'build_ext': build_ext}) |
|
128 |
+ |
|
129 |
+include_dirs = [np.get_include()] |
|
98 | 130 |
|
99 | 131 |
setup(name='kwant', |
100 | 132 |
version=version, |
1 | 1 |
new file mode 100755 |
... | ... |
@@ -0,0 +1,109 @@ |
1 |
+#!/usr/bin/env python |
|
2 |
+ |
|
3 |
+import sys, subprocess, os |
|
4 |
+from distutils.core import setup |
|
5 |
+from distutils.extension import Extension |
|
6 |
+import numpy as np |
|
7 |
+ |
|
8 |
+ |
|
9 |
+# This is an exact copy of the function from kwant/version.py. We can't import |
|
10 |
+# it here (because kwant is not yet built when this scipt is run), so we just |
|
11 |
+# include a copy. |
|
12 |
+def get_version_from_git(): |
|
13 |
+ kwant_dir = os.path.dirname(os.path.abspath(__file__)) |
|
14 |
+ try: |
|
15 |
+ p = subprocess.Popen(['git', 'describe'], cwd=kwant_dir, |
|
16 |
+ stdout=subprocess.PIPE, stderr=subprocess.PIPE) |
|
17 |
+ except OSError: |
|
18 |
+ return |
|
19 |
+ |
|
20 |
+ if p.wait() != 0: |
|
21 |
+ return |
|
22 |
+ version = p.communicate()[0].strip() |
|
23 |
+ |
|
24 |
+ if version[0] == 'v': |
|
25 |
+ version = version[1:] |
|
26 |
+ |
|
27 |
+ try: |
|
28 |
+ p = subprocess.Popen(['git', 'diff', '--quiet'], cwd=kwant_dir) |
|
29 |
+ except OSError: |
|
30 |
+ version += '-confused' # This should never happen. |
|
31 |
+ else: |
|
32 |
+ if p.wait() == 1: |
|
33 |
+ version += '-dirty' |
|
34 |
+ return version |
|
35 |
+ |
|
36 |
+try: |
|
37 |
+ from Cython.Distutils import build_ext |
|
38 |
+except ImportError: |
|
39 |
+ use_cython = False |
|
40 |
+else: |
|
41 |
+ use_cython = True |
|
42 |
+ |
|
43 |
+def get_static_version(): |
|
44 |
+ try: |
|
45 |
+ with open('kwant/_static_version.py') as f: |
|
46 |
+ contents = f.read() |
|
47 |
+ assert contents[:11] == "version = '" |
|
48 |
+ assert contents[-2:] == "'\n" |
|
49 |
+ return contents[11:-2] |
|
50 |
+ except: |
|
51 |
+ return None |
|
52 |
+ |
|
53 |
+git_version = get_version_from_git() |
|
54 |
+static_version = get_static_version() |
|
55 |
+if git_version is not None: |
|
56 |
+ version = git_version |
|
57 |
+ if static_version != git_version: |
|
58 |
+ with open('kwant/_static_version.py', 'w') as f: |
|
59 |
+ f.write("version = '%s'\n" % version) |
|
60 |
+elif static_version is not None: |
|
61 |
+ version = static_version |
|
62 |
+else: |
|
63 |
+ version = 'unknown' |
|
64 |
+ |
|
65 |
+# List of tuples (args, keywords) to be passed to Extension, possibly after |
|
66 |
+# replacing ".pyx" with ".c" if Cython is not to be used. |
|
67 |
+extensions = [ # (["kwant.graph.scotch", ["kwant/graph/scotch.pyx"]], |
|
68 |
+ # {"libraries" : ["scotch", "scotcherr"]}), |
|
69 |
+ (["kwant.graph.core", ["kwant/graph/core.pyx"]], {}), |
|
70 |
+ (["kwant.graph.utils", ["kwant/graph/utils.pyx"]], {}), |
|
71 |
+ (["kwant.graph.slicer", ["kwant/graph/slicer.pyx", |
|
72 |
+ "kwant/graph/c_slicer/partitioner.cc", |
|
73 |
+ "kwant/graph/c_slicer/slicer.cc"]], |
|
74 |
+ {}), |
|
75 |
+ (["kwant.linalg.lapack", ["kwant/linalg/lapack.pyx"]], |
|
76 |
+ {"libraries" : ["lapack", "blas"]}) ] |
|
77 |
+ |
|
78 |
+cmdclass = {} |
|
79 |
+ext_modules = [] |
|
80 |
+include_dirs = [np.get_include()] |
|
81 |
+ |
|
82 |
+for args, keywords in extensions: |
|
83 |
+ if not use_cython: |
|
84 |
+ if 'language' in keywords: |
|
85 |
+ if keywords['language'] == 'c': |
|
86 |
+ ext = '.c' |
|
87 |
+ elif keywords['language'] == 'c++': |
|
88 |
+ ext = '.cpp' |
|
89 |
+ else: |
|
90 |
+ print >>sys.stderr, 'Unknown language' |
|
91 |
+ exit(1) |
|
92 |
+ else: |
|
93 |
+ ext = '.c' |
|
94 |
+ args[1] = [s.replace('.pyx', ext) for s in args[1]] |
|
95 |
+ ext_modules.append(Extension(*args, **keywords)) |
|
96 |
+if use_cython: |
|
97 |
+ cmdclass.update({'build_ext': build_ext}) |
|
98 |
+ |
|
99 |
+setup(name='kwant', |
|
100 |
+ version=version, |
|
101 |
+ author='A. R. Akhmerov, C. W. Groth, X. Waintal, M. Wimmer', |
|
102 |
+ author_email='cwg@falma.de', |
|
103 |
+ description="A package for numerical quantum transport calculations.", |
|
104 |
+ license="not to be distributed", |
|
105 |
+ packages=["kwant", "kwant.graph", "kwant.linalg", "kwant.physics", |
|
106 |
+ "kwant.solvers"], |
|
107 |
+ cmdclass=cmdclass, |
|
108 |
+ ext_modules=ext_modules, |
|
109 |
+ include_dirs = include_dirs) |