From b0247d96d681a9833b5b3ac565626aa01fe977a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Szczepanik?= Date: Tue, 30 Aug 2022 13:51:01 +0200 Subject: [PATCH 1/5] Squashed commit of the following: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 6945ff5c1a3bde359028584641541a4a5d1a3e8e Merge: 7e2d6d7 c59df33 Author: Michael Hanke Date: Thu Aug 25 18:42:35 2022 +0200 Merge pull request #34 from datalad/mslw-patch-2 Replace os.system with subprocess.run in doc-build commit 7e2d6d72dfbad198856ee5996738a80211d8679e Merge: 89beb38 d695593 Author: Yaroslav Halchenko Date: Tue Aug 9 09:57:39 2022 -0400 Merge pull request #40 from datalad/data-pkg Include "data packages" in projects commit 89beb3800008d11d2655736ade493c981d2ef197 Merge: 0d19eed 2dab8fc Author: Yaroslav Halchenko Date: Tue Aug 9 09:55:34 2022 -0400 Merge pull request #38 from datalad/doc-lang DOC: Set language in Sphinx config to en commit d695593d0f15e046889f792a5163c85a2765501f Author: John T. Wodder II Date: Thu Jun 9 09:43:05 2022 -0400 Include "data packages" in projects commit 2dab8fc8bfcba4be15dd96af5df673658c77494e Author: Adina Wagner Date: Mon May 30 11:32:39 2022 +0200 DOC: Set language in Sphinx config to en Starting with Sphinx version 5.0, the configuration for the doc's language should not be None anymore and causes docbuild failures otherwise (see datalad/datalad#6715). This change sets the language specification to English (en) commit c59df331377c05668283a0ad91d81247fc34e6de Author: Michał Szczepanik Date: Mon Mar 14 13:59:37 2022 +0100 Remove building examples from the docs build process The removed code was previously unused and lived only as a side note two commits ago. It was suggested in issue #33 that datalad-neuroimaging is probably the only extension using this stage of doc-build, and therefore we may drop it from the template. commit 1fc0ef09942fa803d6b71671fb5c2732eed23451 Author: Michał Szczepanik Date: Mon Mar 14 13:44:24 2022 +0100 Replace os.system with subprocess.run in doc-build commit 0d19eeda18bb83be26564d08af6f91adc9268ad2 Merge: bfeaa45 84d672a Author: Michael Hanke Date: Thu Feb 10 15:29:49 2022 +0100 Merge pull request #32 from datalad/docs-explainer Add documentation explainer commit bfeaa45c1f269210897b91b2cb0ff690867c60a6 Merge: 1929a22 8e9bcbc Author: Michael Hanke Date: Thu Feb 10 15:27:24 2022 +0100 Merge pull request #30 from datalad/mslw-patch-1 Replace _metalad with _helloworld for easier grepping commit 84d672accb103b1a2396181565bb2e2ab6e5d38a Author: Stephan Heunis Date: Thu Feb 10 15:08:57 2022 +0100 add documentation explainer commit 8e9bcbc4b2a64e8bcd48059ed85c5c34321f5dad Author: Michał Szczepanik Date: Wed Feb 9 16:23:38 2022 +0100 Replace _metalad with _helloworld for easier grepping commit 1929a229214945e462f40cdcee6a339dfecc7124 Merge: ec54055 7b77859 Author: Michael Hanke Date: Mon Jan 24 10:29:45 2022 +0100 Merge pull request #29 from datalad/rf-tst Round of fixes and updates commit 7b77859c361ca2ff2ae7183069160fd5b8a329ff Author: Michael Hanke Date: Mon Jan 24 10:12:46 2022 +0100 Minimal codeclimate config commit 37b060672423ec4558c131d966c595b6638787e3 Author: Michael Hanke Date: Mon Jan 24 10:10:59 2022 +0100 More applicable command template With the command being in a dedicated file. Now also include standard logger naming suggestions. Fixes datalad/datalad-extension-template#27 commit 4aa498d49a315a5864393a5373fa64bc026a713a Author: Michael Hanke Date: Mon Jan 24 09:52:49 2022 +0100 Document what needs to be done for installing a git-annex snapshot Fixed datalad/datalad-extension-template#22 commit 7aea7b2c69d778433ffc60db22d5f9075e90fdbf Author: Michael Hanke Date: Mon Jan 24 09:50:18 2022 +0100 Update codecov setup to match datalad-core Fixes datalad/datalad-extension-template#24 commit ec5405566fd756d281f9d1fb73e25243a3d266e4 Merge: f6ef763 a3b022c Author: Michael Hanke Date: Tue Jan 11 17:22:44 2022 +0100 Merge pull request #28 from datalad/bf-version Make version detection robust to GIT_DIR specification commit a3b022cdf62e7637f46fc76b4e02ad2b4fb0735b Author: Chris Markiewicz Date: Tue Jan 11 10:37:27 2022 +0100 Make version detection robust to GIT_DIR specification Analog fix to https://github.com/datalad/datalad/pull/6341 commit f6ef763f94cefa953ef5dc1b037b06155a411933 Merge: b04f268 48addfb Author: Michael Hanke Date: Tue Jan 11 10:35:22 2022 +0100 Merge pull request #26 from datalad/no-setup-requires Stop using `setup_requires` commit b04f2685fea8d9e72cb4f03801b22986e7eecf5e Merge: cb64d9b 99a960f Author: Yaroslav Halchenko Date: Mon Oct 25 11:15:25 2021 -0400 Merge pull request #25 from datalad/no-distutils Stop using distutils commit 48addfbabc1ab65406f76324a329449948cad8b6 Author: John T. Wodder II Date: Mon Oct 25 09:20:18 2021 -0400 Stop using `setup_requires` commit 99a960ff3fa47a2b54412a8fb6c50ca48b447f06 Author: John T. Wodder II Date: Mon Oct 25 08:49:30 2021 -0400 Stop using distutils in _datalad_buildsupport commit c294de886d5de7d7597d97e93ff64dd8ed2909c2 Author: John T. Wodder II Date: Mon Oct 25 08:48:42 2021 -0400 Keep versioneer.py from using distutils commit cb64d9b9762d738c7d34ec3f4fd34c55cd7e184f Merge: 8b6234b f05a10b Author: Michael Hanke Date: Fri Oct 1 11:01:30 2021 +0200 Merge pull request #23 from datalad/bdist-wheel Fix bdist_wheel command in Makefile commit f05a10b38d90ed8e68c59a88cf8f00b2511bc4f4 Author: John T. Wodder II Date: Thu Sep 30 09:19:39 2021 -0400 Fix bdist_wheel command in Makefile commit 8b6234b96aa3be6b54446a280042706585d91ca9 Merge: c4c4f52 88aeff2 Author: Michael Hanke Date: Wed Sep 29 08:08:12 2021 +0200 Merge pull request #21 from datalad/testrequires Discontinue use of tests_require commit 88aeff294ecee8b1536e5f9fcdee217c5a7ed706 Author: Michael Hanke Date: Wed Sep 29 08:02:58 2021 +0200 Discontinue use of tests_require To achieve compatibility with some of datalad's default CI setups. commit c4c4f52bb2750c6576f441ff53b560be0a4ad675 Author: Michael Hanke Date: Thu Apr 15 10:20:40 2021 +0200 Disable smart quoting for valid manpages in HTML docs commit 34aa9b7f58ecc9750d2bee8ecb3dddf9ed02ed4d Merge: 0d4f35f edec51f Author: Michael Hanke Date: Wed Sep 22 14:48:33 2021 +0200 Merge pull request #19 from datalad/buildsupport Buildsupport update commit edec51f420f2203328423787d04f4518f0b27ae4 Merge: 0d4f35f 9975f82 Author: Michael Hanke Date: Wed Sep 22 14:41:40 2021 +0200 Update DataLad build helper commit 0d4f35f6dced6fe593e4924124df83f55e0d2590 Merge: 022720b afc8586 Author: Michael Hanke Date: Wed Sep 22 11:04:42 2021 +0200 Merge pull request #18 from datalad/appveyor-updates Appveyor updates commit afc8586101317359de04375815cfe87aede30bab Author: Michael Hanke Date: Wed Sep 22 10:57:41 2021 +0200 Do apt-get update before apt-get install Analog change to an update necessary in -ukbiobank that makes sense in general. Fixes datalad/datalad-extension-template#13 commit 2b59d6a4a773fd330f01864e9e3cf6eb9417e3b1 Author: Michael Hanke Date: Wed Sep 22 10:55:37 2021 +0200 Bump git-annex version for testing to a recent release Matching the one used in datalad-core commit 022720b6aee5f95fc8c9b57916fffe9c9d3b4563 Merge: 64d185d 3cbd005 Author: Michael Hanke Date: Wed Sep 22 10:49:42 2021 +0200 Merge pull request #14 from datalad/fix-manifest Add missing/necessary files to sdists commit 64d185dd7bebfbf8b513a0b90a3b30b7b4530ef2 Merge: e90593e 448eb72 Author: Michael Hanke Date: Wed Sep 22 10:44:32 2021 +0200 Merge pull request #16 from datalad/mv-entry-points Move entry points declaration to setup.cfg commit e90593e86017f2860526c3d9348c2235a6373857 Merge: ec853dc a6e5add Author: Michael Hanke Date: Wed Sep 22 10:41:27 2021 +0200 Merge pull request #15 from datalad/no-universal Remove `--universal` flag commit ec853dcba03878202e2c2fe4da4c68383275675d Merge: 0098853 200030b Author: Michael Hanke Date: Wed Sep 22 10:38:30 2021 +0200 Merge pull request #17 from datalad/versioneer Versioneer needs more history to do its job commit 200030bfea4e0488edd6efc00324a2e05d3db869 Author: Michael Hanke Date: Wed Sep 22 10:33:54 2021 +0200 Versioneer needs more history to do its job commit 448eb72efb482831ce17a1a5421bb1b0863a46c4 Author: John T. Wodder II Date: Wed Sep 15 12:50:54 2021 -0400 Move entry points declaration to setup.cfg commit a6e5add3f3cdb3192a9c9dde910f9d67a7eebb11 Author: John T. Wodder II Date: Wed Sep 15 12:47:19 2021 -0400 Remove `--universal` flag commit 3cbd00592f20d2554da34ec0a4765c55a9184233 Author: John T. Wodder II Date: Wed Sep 15 12:37:40 2021 -0400 Add necessary files to sdists commit 9975f82bd5b43cc6bd6e0d36fc18ae9382bb40ab Author: Michael Hanke Date: Thu Apr 15 08:15:27 2021 +0200 BF: We only have lower-case command names In a command suite that only defines the class name of a command, and no explicit cmdline name, no manpage would be built, because the test against the parser content would look like `Ls != ls` This change enforces lower-case for autogenerated command names. commit 0098853fee84d0ed6794a291b5056445403a6cd2 Merge: 7078c9d 4d2c049 Author: Michael Hanke Date: Sat Apr 10 12:29:35 2021 +0200 Merge pull request #12 from datalad/rf-36 Update workflow to minimal supported Python version (3.6) commit 4d2c04930c184455a30a1592827a55c979c6a49b Author: Michael Hanke Date: Sat Apr 10 12:23:25 2021 +0200 Update workflow to minimal supported Python version (3.6) commit 7078c9d738102d6e5df6cc59b09b159425e610bf Author: Michael Hanke Date: Tue Mar 23 07:29:08 2021 +0100 Use Debian snapshots as a stable place for packages commit 4827d994939d220194a99b53eb5ed83d0b3e18da Merge: 4ad6769 899e9ba Author: Michael Hanke Date: Thu Mar 11 17:13:11 2021 +0100 Merge pull request #11 from datalad/tst-coverage Working coverage submission across all platforms commit 899e9bae0f39ea479a18a9415c0b978d2d2a6e89 Author: Michael Hanke Date: Thu Mar 11 16:51:09 2021 +0100 Working coverage submission across all platforms commit 4ad67696dde62b01213a7cfb2964cc5a1a104507 Merge: 616ea72 1260e41 Author: Michael Hanke Date: Thu Mar 11 09:08:29 2021 +0100 Merge pull request #10 from datalad/typos Minor fixup of wording for command_suite commit 1260e4175d60a1bd9fad85ed04833b79632d3ac8 Author: Yaroslav Halchenko Date: Tue Mar 2 18:30:12 2021 -0500 Minor fixup of wording for command_suite commit 616ea72d35b04e6ea920ef2abfbd5ca76b0f1592 Merge: a4a5749 7d8c9aa Author: Michael Hanke Date: Tue Mar 2 08:20:57 2021 +0100 Merge pull request #9 from datalad/installer Use released version of datalad-installer commit 7d8c9aa9f796df763bb83485174d35ef4a2ebcc7 Author: Michael Hanke Date: Tue Mar 2 07:40:52 2021 +0100 Use released version of datalad-installer - get rid of custom git-annex installer script on windows, use the official implementation instead - add support for requesting a specific installer version via ENV variable DATALAD_INSTALLER_VERSION, go with "latest" by default. Requesting an unavailable installer version will make the build error. commit a4a574989b1dfc78a4ac0287374e9780208add7d Author: Michael Hanke Date: Mon Jan 25 08:12:45 2021 +0100 TST: Switch default test setup to appveyor Following changes in datalad-core as well as other extensions. commit f304d45b8d1f34dae08d0809c8e87c5047f8e278 Author: Michael Hanke Date: Tue Jun 16 13:46:11 2020 +0200 Fix for consistency commit 1fb2ed6756596ff8e0410dd07314a132f81f1357 Author: Michael Hanke Date: Mon Jun 15 17:42:00 2020 +0200 Prevent inclusion of build helpers into binary packages commit ce8e7f002b0aedfd1c0b77403c16ca511b56eeaf Merge: 0924ab1 cd61512 Author: Michael Hanke Date: Mon Jun 15 13:08:29 2020 +0200 Add DataLad build helper commit cd615129ab5efd800a9c4dcbf752651b6b921740 Author: Michael Hanke Date: Mon Jun 15 13:08:29 2020 +0200 Squashed '_datalad_buildsupport/' content from commit 023a1b7 git-subtree-dir: _datalad_buildsupport git-subtree-split: 023a1b77194508f7aa1d7ec5ec3bb222c1d840aa commit 0924ab1e62b31e647eb6268e28c17edd6c26a77f Author: Michael Hanke Date: Mon Jun 15 13:07:44 2020 +0200 Minor name change Avoids conflict with code in datalad-core and matches source repo name. commit 80bf1979d5c8f9f1770deec687dc8106867c91f9 Author: Michael Hanke Date: Mon Jun 15 09:01:18 2020 +0200 Rename file to get a more obvious label commit 1cfca1d17b7b72f01c67e29affa4168c3baba8c8 Author: Michael Hanke Date: Mon Jun 15 09:00:06 2020 +0200 Extend README with practical info commit 49817c694686d21ceb5aacb22c43fa5e320d9945 Merge: a20b711 73a7485 Author: Michael Hanke Date: Mon Jun 15 08:57:28 2020 +0200 Merge pull request #7 from datalad/readme Community related pointers for the README commit 73a74858b21ca7ba32b4abd32330b97ae3cd84a4 Author: Adina Wagner Date: Wed Jun 10 13:28:40 2020 +0200 add a minimal zenodo.json file commit 28b0f3084e7ba0565e6a720653bcfcc89c58abf4 Author: Adina Wagner Date: Wed Jun 10 13:29:27 2020 +0200 add archival and community related pointers to the README commit a20b71151336982730894b1a534d67831f68c94c Merge: ea1ed84 12a5a2d Author: Michael Hanke Date: Mon Jun 15 08:42:44 2020 +0200 Merge pull request #6 from datalad/build_helpers Build and render manpages -- using common build helpers commit 12a5a2de5ae27ef658c4099a988d6b1fd47ebd1b Author: Michael Hanke Date: Mon Jun 15 08:25:24 2020 +0200 Remove leftover broken devel requirement commit dbd12d14cf4e1f4231b84d02d1f555ea02b242dc Merge: da5b936 023a1b7 Author: Michael Hanke Date: Mon Jun 15 08:19:45 2020 +0200 Add DataLad build helper git-subtree-dir: _datalad_build_support git-subtree-mainline: da5b936048453af66ff9d821920df70eedc87d24 git-subtree-split: 023a1b77194508f7aa1d7ec5ec3bb222c1d840aa commit da5b936048453af66ff9d821920df70eedc87d24 Author: Michael Hanke Date: Fri Jun 12 17:32:04 2020 +0200 Add makefile target for updating the DataLad build helpers commit 023a1b77194508f7aa1d7ec5ec3bb222c1d840aa Author: Michael Hanke Date: Mon Jun 15 08:16:13 2020 +0200 BF: Read package metadata directly from setup.cfg The distribution object does not seem to see it (at least not under all circumstances). commit fd99b4eece55f97514387b31787d15b393a669f9 Author: Michael Hanke Date: Mon Jun 15 08:15:09 2020 +0200 RF: Remove helpers that are not needed for extensions DataLad core can add its own ones again, but it is not worth imposing the code on all extensions. commit ba575108283843f6e9f63c1852c69cc29df08ffd Author: Michael Hanke Date: Fri Jun 12 17:35:46 2020 +0200 Enable building manpages for extensions With the ability to point to a specific command suite. The rest is just about making datalad core not break. commit 343b9a0ba4f72c4da641f6ba74dfbe643b70807a Author: Michael Hanke Date: Fri Jun 12 17:21:01 2020 +0200 Start with a copy from datalad@afa682550ee742d69853f69165c0f37c5f4b5f05 commit 5d64f44cb21adf62b26feaf216f9767ca4b1928a Author: Michael Hanke Date: Thu Jun 11 12:41:43 2020 +0200 Build and render manpages commit ea1ed84757f7f3bbbd172073676883179f770c7e Merge: a836e6b 1a56499 Author: Michael Hanke Date: Wed Jun 10 16:24:09 2020 +0200 Merge pull request #5 from mih/master Modernization commit 1a56499f2ccc9d96bb9936d1a2d8edf3a87a4125 Author: Michael Hanke Date: Wed Jun 10 12:17:29 2020 +0200 Make more datalad-friendly by prevent annex creation on datalad-save commit 915818a1b5988efffc4b6c8f25b1ccc6bdd8f6e1 Author: Michael Hanke Date: Wed Jun 10 12:15:06 2020 +0200 Remove needless setup complication commit 90debfceae21cd4d43521230dd59f7a9586442b7 Author: Michael Hanke Date: Wed Jun 10 12:14:50 2020 +0200 Fix badge name commit ec78dfdf1b3f89bb9f21fff2fa5fd26fe37505b6 Author: Michael Hanke Date: Wed Jun 10 11:30:11 2020 +0200 Added top-level Makefile with release-to-pypi helper commit e8d69fb3cf21eadc344c15bc22bf1ad9fe0ee3d7 Author: Michael Hanke Date: Wed Jun 10 09:33:58 2020 +0200 Update README with more status badges commit c34760b8a562053005556fa835dffc200f1ae430 Author: Michael Hanke Date: Wed Jun 10 10:57:46 2020 +0200 Github action to build the docs commit 24199ea7d06f8aafcda006aeec1edd3721bdec36 Author: Michael Hanke Date: Wed Jun 10 10:34:50 2020 +0200 Sphinx-doc scaffold commit 514d3430bf2e6fdab7e6378105e807372cc46646 Author: Michael Hanke Date: Wed Jun 10 10:30:52 2020 +0200 Add workflow for testing on windows commit 61163c77291dc16f6c877c2bf757e1827cb8a1ad Author: Michael Hanke Date: Wed Jun 10 08:20:01 2020 +0200 Standardize on requirement-devel.txt commit cc7ed24953a06aec135bdf94d4a5b49915dccdfb Author: Michael Hanke Date: Wed Jun 10 07:59:48 2020 +0200 Add github workflow for testing on a crippled filesystem commit f2b2a6c2ac938671aa5fb8c7be99a8811cde3102 Author: Michael Hanke Date: Wed Jun 10 07:56:23 2020 +0200 Ignore pip metadata dumps and other stuff commit 8e0ace0a0b48d7fb5e2dba3ca8242dc85a5af4ac Author: Michael Hanke Date: Wed Jun 10 07:48:54 2020 +0200 [DATALAD RUNCMD] Install/enable versioneer === Do not change lines below === { "chain": [], "cmd": "versioneer install", "exit": 0, "extra_inputs": [], "inputs": [], "outputs": [], "pwd": "." } ^^^ Do not change lines above ^^^ commit f44d7e2c0b83801a53c5238d966a54ab50fabfc0 Author: Michael Hanke Date: Wed Jun 10 09:34:46 2020 +0200 Add missing __init__.py to get tests installed correctly commit d94fb13aa4f037d50945eb69c7565d8d92cf68e4 Author: Michael Hanke Date: Wed Jun 10 07:46:56 2020 +0200 Simplify Travis setup No PY2, more up-to-date PY3 versions commit edfe14a6f4ddeb75801864647400185cd48b8b3f Author: Michael Hanke Date: Wed Jun 10 07:41:07 2020 +0200 Fixup and expand metadata in setup.cfg and for setup.py Sensible default setup for dependencies and testing. Should enable to just drop in some code, rename the package and run. commit d0eec9f9c59915dbe48acec863329d1b112aaa23 Author: Adina Wagner Date: Tue Jun 9 10:52:48 2020 +0200 add initial configuration for versioneer setup commit 63e9a481c87e3301528ce6d5f4d65f91cb3bd4b0 Author: Adina Wagner Date: Tue Jun 9 10:46:34 2020 +0200 modernize setup according to https://github.com/datalad/datalad-ukbiobank commit a836e6ba83b8f17cfc321e0c878157cc96ae7847 Author: Michael Hanke Date: Wed Jun 10 08:05:04 2020 +0200 Dummy workflow commit 78de6c37f4443ca1218a3f75abfa6caee300e686 Author: Michael Hanke Date: Fri Oct 12 07:55:25 2018 +0200 TST: Swap out directmode tests for v6 tests commit 75b6fa4b523267b509e4cd20f6db75c43ef53e1c Author: Michael Hanke Date: Fri Oct 12 06:52:49 2018 +0200 Standard gitignore commit 2bc890edefba106124c678bac6df521783d3b397 Author: Michael Hanke Date: Fri Oct 12 06:52:29 2018 +0200 Improve standard setup commit 8da041aaf1c1c20205f788b87d02d675115adebb Author: Michael Hanke Date: Fri Apr 6 11:20:12 2018 +0200 RF: Extension naming conventions commit c971b18d8083aeb3ab14e09a4ecf6f9e735c5dc2 Author: Michael Hanke Date: Fri Mar 30 16:50:11 2018 +0200 TST: Reenable wtf, after datalad got fixed commit 92f22c333fff6920273c0a718082cacbd6fec0f9 Author: Michael Hanke Date: Fri Mar 30 11:13:05 2018 +0200 RF: Standardize on datalad_ module prefix (fixes gh-1) commit cc63930bb47ba424de4fabb14d512eaa0755da04 Author: Michael Hanke Date: Fri Mar 30 09:39:20 2018 +0200 Deal with Datalad bug commit 839f7280e109ff3ac27aac08847636e21d6c806f Author: Michael Hanke Date: Fri Mar 30 09:31:55 2018 +0200 Install the package commit 486cfa704db5745b19c721f9f5648562e0023f44 Author: Michael Hanke Date: Fri Mar 30 09:25:19 2018 +0200 RF: Comply with datalads current ad-hoc naming conventions commit 9351f9974a9e2853f7107499881865e5936b6b55 Author: Michael Hanke Date: Thu Mar 29 20:45:47 2018 +0200 TST: Basic test of whether datalad can see this extension commit 9bc499db31689b9db828ac842bd649241b8121d6 Author: Michael Hanke Date: Thu Mar 29 20:33:10 2018 +0200 TST: Trimmed travis setup from the mothership commit 4ee24c490709275726e5a4b58cae682f6cb2f564 Author: Michael Hanke Date: Wed Mar 28 16:49:08 2018 +0200 DOC: Basic README commit 831e6c5c76e359855738a89b97f22dacd6a8b902 Author: Michael Hanke Date: Wed Mar 28 16:09:14 2018 +0200 DOC: Annotate setup.py commit 7c5a645904f1f591d30a75d3dfee5b7b55998ba9 Author: Michael Hanke Date: Wed Mar 28 16:04:48 2018 +0200 DOC: more complete basic info commit 82300f6c348e6d54e2673d697ecb3570b65da3b2 Author: Michael Hanke Date: Wed Mar 28 16:00:50 2018 +0200 DOC: Some insight into the command implementation commit 387333b0862cb61c1a8aa40ae8fa5342a99c20ab Author: Michael Hanke Date: Wed Mar 28 15:49:56 2018 +0200 Declare dependency on datalad Should be versioned, but needs to wait for a release. commit 00e17548770bd737925007390fb2321844cc6486 Author: Michael Hanke Date: Wed Mar 28 15:19:01 2018 +0200 Demo of a minimalistic DataLad extension module commit be4df7f645296eff76e5bd5b9e5297186280db08 Author: Michael Hanke Date: Wed Mar 28 14:12:07 2018 +0200 first commit --- .appveyor.yml | 13 ++++++--- .codeclimate.yml | 17 ++++++++++++ .github/workflows/test_crippledfs.yml | 8 +----- MANIFEST.in | 8 ++++-- Makefile | 3 +-- _datalad_buildsupport/formatters.py | 2 +- _datalad_buildsupport/setup.py | 39 ++------------------------- docs/Makefile | 8 +++--- docs/README.md | 35 ++++++++++++++++++++++++ docs/source/conf.py | 33 ++++++++++++++--------- pyproject.toml | 2 +- setup.cfg | 23 +++++++++++----- setup.py | 20 +------------- versioneer.py | 2 +- 14 files changed, 115 insertions(+), 98 deletions(-) create mode 100644 .codeclimate.yml create mode 100644 docs/README.md diff --git a/.appveyor.yml b/.appveyor.yml index d1698e1..f787261 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -45,8 +45,8 @@ # respective CI run configuration). -# make repository clone cheap -shallow_clone: true +# do not make repository clone cheap: interfers with versioneer +shallow_clone: false environment: @@ -66,7 +66,7 @@ environment: APPVEYOR_BUILD_WORKER_IMAGE: Ubuntu2004 INSTALL_SYSPKGS: python3-virtualenv # system git-annex is way too old, use better one - INSTALL_GITANNEX: git-annex -m deb-url --url http://snapshot.debian.org/archive/debian/20201228T023115Z/pool/main/g/git-annex/git-annex_8.20201127-1_amd64.deb + INSTALL_GITANNEX: git-annex -m deb-url --url http://snapshot.debian.org/archive/debian/20210906T204127Z/pool/main/g/git-annex/git-annex_8.20210903-1_amd64.deb CODECOV_BINARY: https://uploader.codecov.io/latest/linux/codecov # Windows core tests - ID: WinP39core @@ -155,11 +155,16 @@ install: ) - sh: python -m pip install datalad-installer${DATALAD_INSTALLER_VERSION:-} # Missing system software - - sh: "[ -n \"$INSTALL_SYSPKGS\" ] && ( [ \"x${APPVEYOR_BUILD_WORKER_IMAGE}\" = \"xmacOS\" ] && brew install -q ${INSTALL_SYSPKGS} || sudo apt-get install --no-install-recommends -y ${INSTALL_SYSPKGS} ) || true" + - sh: "[ -n \"$INSTALL_SYSPKGS\" ] && ( [ \"x${APPVEYOR_BUILD_WORKER_IMAGE}\" = \"xmacOS\" ] && brew install -q ${INSTALL_SYSPKGS} || { sudo apt-get update -y && sudo apt-get install --no-install-recommends -y ${INSTALL_SYSPKGS}; } ) || true" # Install git-annex on windows, otherwise INSTALL_SYSPKGS can be used # deploy git-annex, if desired - cmd: IF DEFINED INSTALL_GITANNEX datalad-installer --sudo ok %INSTALL_GITANNEX% - sh: "[ -n \"${INSTALL_GITANNEX}\" ] && datalad-installer --sudo ok ${INSTALL_GITANNEX}" + # in case of a snapshot installation, use the following approach to adjust + # the PATH as necessary + #- sh: "[ -n \"${INSTALL_GITANNEX}\" ] && datalad-installer -E ${HOME}/dlinstaller_env.sh --sudo ok ${INSTALL_GITANNEX}" + # add location of datalad installer results to PATH + #- sh: "[ -f ${HOME}/dlinstaller_env.sh ] && . ${HOME}/dlinstaller_env.sh || true" #before_build: diff --git a/.codeclimate.yml b/.codeclimate.yml new file mode 100644 index 0000000..9ac1b30 --- /dev/null +++ b/.codeclimate.yml @@ -0,0 +1,17 @@ +version: "2" +checks: + file-lines: + config: + threshold: 500 +plugins: + bandit: + enabled: true + checks: + assert_used: + enabled: false +exclude_patterns: +- "_datalad_buildsupport/" +- "versioneer.py" +- "*/_version.py" +- "tools/" +- "**/tests/" diff --git a/.github/workflows/test_crippledfs.yml b/.github/workflows/test_crippledfs.yml index 72e798d..e0d4124 100644 --- a/.github/workflows/test_crippledfs.yml +++ b/.github/workflows/test_crippledfs.yml @@ -52,10 +52,4 @@ jobs: echo "== mount >>" mount echo "<< mount ==" - python -m nose -s -v --with-doctest --with-coverage --cover-package datalad_ebrains datalad_ebrains - - name: Report coverage - run: | - python -m coverage xml - curl -Os "https://uploader.codecov.io/latest/linux/codecov" - chmod +x codecov - ./codecov + python -m nose -s -v --with-doctest --with-coverage --cover-package datalad_helloworld datalad_helloworld diff --git a/MANIFEST.in b/MANIFEST.in index 7e8ea16..a83f85f 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,2 +1,6 @@ -include versioneer.py -include datalad_ebrains/_version.py +include CONTRIBUTORS LICENSE versioneer.py +graft _datalad_buildsupport +graft datalad_helloworld +graft docs +prune docs/build +global-exclude *.py[cod] diff --git a/Makefile b/Makefile index da8f7f1..be524e9 100644 --- a/Makefile +++ b/Makefile @@ -9,8 +9,7 @@ clean: release-pypi: # avoid upload of stale builds test ! -e dist - $(PYTHON) setup.py sdist - python setup.py bdist_wheel --universal + $(PYTHON) setup.py sdist bdist_wheel twine upload dist/* update-buildsupport: diff --git a/_datalad_buildsupport/formatters.py b/_datalad_buildsupport/formatters.py index 015f62a..5ac01de 100644 --- a/_datalad_buildsupport/formatters.py +++ b/_datalad_buildsupport/formatters.py @@ -251,7 +251,7 @@ def _mk_options(self, parser): def _format_action(self, action): # determine the required width and the entry label - action_header = self._format_action_invocation(action, doubledash='-\\\\-') + action_header = self._format_action_invocation(action) if action.help: help_text = self._expand_help(action) diff --git a/_datalad_buildsupport/setup.py b/_datalad_buildsupport/setup.py index b83ccfa..27e0821 100644 --- a/_datalad_buildsupport/setup.py +++ b/_datalad_buildsupport/setup.py @@ -9,12 +9,11 @@ import datetime import os -from distutils.core import Command -from distutils.errors import DistutilsOptionError from os.path import ( dirname, join as opj, ) +from setuptools import Command, DistutilsOptionError from setuptools.config import read_configuration import versioneer @@ -75,7 +74,7 @@ def finalize_options(self): mod_name, suite_name = self.cmdsuite.split(':') mod = __import__(mod_name, fromlist=mod_name.split('.')) suite = getattr(mod, suite_name) - self.cmdlist = [c[2] if len(c) > 2 else c[1].replace('_', '-') + self.cmdlist = [c[2] if len(c) > 2 else c[1].replace('_', '-').lower() for c in suite[1]] self.announce('Writing man page(s) to %s' % self.manpath) @@ -157,40 +156,6 @@ def run(self): f.write(formatted) -class BuildRSTExamplesFromScripts(Command): - description = 'Generate RST variants of example shell scripts.' - - user_options = [ - ('expath=', None, 'path to look for example scripts'), - ('rstpath=', None, 'output path for RST files'), - ] - - def initialize_options(self): - self.expath = opj('docs', 'examples') - self.rstpath = opj('docs', 'source', 'generated', 'examples') - - def finalize_options(self): - if self.expath is None: - raise DistutilsOptionError('\'expath\' option is required') - if self.rstpath is None: - raise DistutilsOptionError('\'rstpath\' option is required') - self.announce('Converting example scripts') - - def run(self): - opath = self.rstpath - if not os.path.exists(opath): - os.makedirs(opath) - - from glob import glob - for example in glob(opj(self.expath, '*.sh')): - exname = os.path.basename(example)[:-3] - with open(opj(opath, '{0}.rst'.format(exname)), 'w') as out: - fmt.cmdline_example_to_rst( - open(example), - out=out, - ref='_example_{0}'.format(exname)) - - class BuildConfigInfo(Command): description = 'Generate RST documentation for all config items.' diff --git a/docs/Makefile b/docs/Makefile index dbfb529..c31cca0 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -87,9 +87,9 @@ qthelp: @echo @echo "Build finished; now you can run "qcollectiongenerator" with the" \ ".qhcp project file in $(BUILDDIR)/qthelp, like this:" - @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/datalad_metalad.qhcp" + @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/datalad_ebrains.qhcp" @echo "To view the help file:" - @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/datalad_metalad.qhc" + @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/datalad_ebrains.qhc" applehelp: $(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp @@ -104,8 +104,8 @@ devhelp: @echo @echo "Build finished." @echo "To view the help file:" - @echo "# mkdir -p $$HOME/.local/share/devhelp/datalad_metalad" - @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/datalad_metalad" + @echo "# mkdir -p $$HOME/.local/share/devhelp/datalad_ebrains" + @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/datalad_ebrains" @echo "# devhelp" epub: diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..a142e52 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,35 @@ +## Editing, building, and publishing extension documentation + + +The `datalad-ebrains` extension uses [Sphinx](https://www.sphinx-doc.org/en/master/index.html#) for document generation +and suggests using [Read the Docs](https://docs.readthedocs.io/en/stable/) for automatic documentation building, versioning, and hosting. + +Once you are ready to document your extension software, take note of the following: + +### Document editing + +Edit your `docs/source/index.rst` file using [reStructuredText](https://www.sphinx-doc.org/en/master/usage/restructuredtext/basics.html), +which is the default plaintext markup language used by Sphinx. Add further documentation as needed. + +### Local testing + +For testing locally whether your documentation builds and renders correctly, first install the developer requirements from the repository's root directory: +``` +pip install -r requirements-devel.txt +``` + +Then build the documentation locally: +``` +make -C docs html +``` + +Navigate to `docs/build/` and open `index.html` in your browser to view your documentation. + +### Remote building and testing + +The GitHub Action workflow located at `.github/workflows/docbuild.yml` will run on a push or pull request to your GitHub repository's master/main branch. This builds the documentation remotely and serves as an automated documentation test. + +### Publishing your documentation + +- If you maintain your extension yourself *outside of the scope of the DataLad GitHub organization*, you can follow [these instructions](https://docs.readthedocs.io/en/stable/integrations.html) for integrating your version control system (such as GitHub) with Read the Docs. +- If your extension is *maintained by the DataLad developer team*, please create an issue asking for help with the setup. diff --git a/docs/source/conf.py b/docs/source/conf.py index a7b5f01..cd7a084 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # -# datalad_metalad documentation build configuration file, created by +# datalad_ebrains documentation build configuration file, created by # sphinx-quickstart on Tue Oct 13 08:41:19 2015. # # This file is execfile()d with the current directory set to its @@ -13,7 +13,7 @@ # serve to show the default. import sys -import os +import subprocess import datetime from os.path import ( @@ -35,17 +35,19 @@ for setup_py_path in (opj(pardir, 'setup.py'), # travis opj(pardir, pardir, 'setup.py')): # RTD if exists(setup_py_path): - sys.path.insert(0, os.path.abspath(dirname(setup_py_path))) + sys.path.insert(0, abspath(dirname(setup_py_path))) + # Build manpage try: - for cmd in 'manpage',: #'examples': - os.system( - '{} build_{} --cmdsuite {} --manpath {} --rstpath {}'.format( - setup_py_path, - cmd, - 'datalad_ebrains:command_suite', - abspath(opj(dirname(setup_py_path), 'build', 'man')), - opj(dirname(__file__), 'generated', 'man'))) - except: + subprocess.run( + args=[setup_py_path, 'build_manpage', + '--cmdsuite', 'datalad_helloworld:command_suite', + '--manpath', abspath(opj( + dirname(setup_py_path), 'build', 'man')), + '--rstpath', opj(dirname(__file__), 'generated', 'man'), + ], + check=True, + ) + except (FileNotFoundError, subprocess.CalledProcessError): # shut up and do your best pass @@ -101,7 +103,7 @@ # # This is also used if you do content translation via gettext catalogs. # Usually you set "language" from the command line for these cases. -language = "en" +language = 'en' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. @@ -136,3 +138,8 @@ # If true, links to the reST sources are added to the pages. html_show_sourcelink = False + +# smart quotes are incompatible with the RST flavor of the generated manpages +# but see `smartquotes_action` for more fine-grained control, in case +# some of this functionality is needed +smartquotes = False diff --git a/pyproject.toml b/pyproject.toml index d25f6e3..f671f35 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,2 +1,2 @@ [build-system] -requires = ["setuptools >= 30.3.0", "wheel"] +requires = ["setuptools >= 43.0.0", "wheel"] diff --git a/setup.cfg b/setup.cfg index 10c94fe..ab7006d 100644 --- a/setup.cfg +++ b/setup.cfg @@ -16,16 +16,25 @@ python_requires = >= 3.6 install_requires = datalad >= 0.16 datalad_next -test_requires = - nose - coverage -packages = find: +packages = find_namespace: include_package_data = True [options.packages.find] -# do not ship the build helpers -exclude= - _datalad_buildsupport +include = datalad_ebrains* + +[options.extras_require] +# this matches the name used by -core and what is expected by some CI setups +devel = + nose + coverage + +[options.entry_points] +# 'datalad.extensions' is THE entrypoint inspected by the datalad API builders +datalad.extensions = + # the label in front of '=' is the command suite label + # the entrypoint can point to any symbol of any name, as long it is + # valid datalad interface specification (see demo in this extensions) + ebrains = datalad_ebrains:command_suite [versioneer] # See the docstring in versioneer.py for instructions. Note that you must diff --git a/setup.py b/setup.py index 77fa791..a534d6a 100755 --- a/setup.py +++ b/setup.py @@ -11,26 +11,8 @@ cmdclass = versioneer.get_cmdclass() cmdclass.update(build_manpage=BuildManPage) -# Give setuptools a hint to complain if it's too old a version -# 30.3.0 allows us to put most metadata in setup.cfg -# Should match pyproject.toml -SETUP_REQUIRES = ['setuptools >= 30.3.0'] -# This enables setuptools to install wheel on-the-fly -SETUP_REQUIRES += ['wheel'] if 'bdist_wheel' in sys.argv else [] - if __name__ == '__main__': - setup(name='datalad_ebrains', + setup(name='datalad_helloworld', version=versioneer.get_version(), cmdclass=cmdclass, - setup_requires=SETUP_REQUIRES, - entry_points={ - # 'datalad.extensions' is THE entrypoint inspected by the datalad API builders - 'datalad.extensions': [ - # the label in front of '=' is the command suite label - # the entrypoint can point to any symbol of any name, as long it is - # valid datalad interface specification (see demo in this extensions - 'ebrains=datalad_ebrains:command_suite', - ], - }, ) - diff --git a/versioneer.py b/versioneer.py index 64fea1c..51ca818 100644 --- a/versioneer.py +++ b/versioneer.py @@ -1500,7 +1500,7 @@ def get_cmdclass(): cmds = {} # we add "version" to both distutils and setuptools - from distutils.core import Command + from setuptools import Command class cmd_version(Command): description = "report generated version string" From 46358b7aba798ea13a8241910774c8ec8b26d857 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Szczepanik?= Date: Tue, 30 Aug 2022 15:04:01 +0200 Subject: [PATCH 2/5] Bring in testing-related updates from the extension template MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This includes two important changes: - Move from nose to pytest - Update minimal requirements to Python 3.7 and DataLad 0.17 Squashed commit of the following: commit aec81056ef6b66566f6126eed0ed83916e92f797 Author: Michael Hanke Date: Thu Aug 25 19:19:11 2022 +0200 Update README (different branch names, some steps missing) commit 7cfac48bfb9d27b4af0d718006631b74fd772637 Merge: ef81d8e 091419c Author: Michael Hanke Date: Thu Aug 25 18:51:20 2022 +0200 Merge pull request #41 from datalad/appv Skip appveyor builds on doc-only changes commit 091419ccf47071e45fc55ba29b00bcc8b62b32b9 Author: Michael Hanke Date: Thu Aug 25 18:47:41 2022 +0200 Skip appveyor builds on doc-only changes Done in -core and elsewhere. Closes datalad/datalad-extension-template#37 commit ef81d8ef0390824ecf632c8b3c515c023ac99f66 Merge: 6945ff5 4652a27 Author: Michael Hanke Date: Thu Aug 25 18:43:46 2022 +0200 Merge pull request #35 from datalad/rf-pytest RF: migrate to use pytest instead of nose, drop PY 3.6, require datalad >= 0.17.0 commit 6945ff5c1a3bde359028584641541a4a5d1a3e8e Merge: 7e2d6d7 c59df33 Author: Michael Hanke Date: Thu Aug 25 18:42:35 2022 +0200 Merge pull request #34 from datalad/mslw-patch-2 Replace os.system with subprocess.run in doc-build commit 4652a2797233d4af83b42b871de051d8556ce536 Author: Yaroslav Halchenko Date: Tue Aug 9 10:19:35 2022 -0400 BF: fix import to use utils_pytest instead of utils commit 4bce17dece9b6b2dae5ad9fd8aef1b1144cb63e3 Author: Yaroslav Halchenko Date: Tue Aug 9 10:14:04 2022 -0400 BF: require python 3.7 and datalad 0.17.0 because we moved to pytest in 0.17.0 and even though 0.16.0 would already be good for python 3.7 I decided just to boost minimal datalad version because prior one is no longer maintained. commit c6e951a72dd25bd49a489628747fdb213b51ee40 Author: Yaroslav Halchenko Date: Mon Apr 25 11:10:22 2022 -0400 RF: migrate to use pytest instead of nose This is contingent on completion and release of migration over to pytest in datalad core which is ongoing in https://github.com/datalad/datalad/pull/6273 which I think should happen in 0.17. We should strive to make that PR **not** break runtime (but can break testing) of extensions. commit 7e2d6d72dfbad198856ee5996738a80211d8679e Merge: 89beb38 d695593 Author: Yaroslav Halchenko Date: Tue Aug 9 09:57:39 2022 -0400 Merge pull request #40 from datalad/data-pkg Include "data packages" in projects commit 89beb3800008d11d2655736ade493c981d2ef197 Merge: 0d19eed 2dab8fc Author: Yaroslav Halchenko Date: Tue Aug 9 09:55:34 2022 -0400 Merge pull request #38 from datalad/doc-lang DOC: Set language in Sphinx config to en commit d695593d0f15e046889f792a5163c85a2765501f Author: John T. Wodder II Date: Thu Jun 9 09:43:05 2022 -0400 Include "data packages" in projects commit 2dab8fc8bfcba4be15dd96af5df673658c77494e Author: Adina Wagner Date: Mon May 30 11:32:39 2022 +0200 DOC: Set language in Sphinx config to en Starting with Sphinx version 5.0, the configuration for the doc's language should not be None anymore and causes docbuild failures otherwise (see datalad/datalad#6715). This change sets the language specification to English (en) commit c59df331377c05668283a0ad91d81247fc34e6de Author: Michał Szczepanik Date: Mon Mar 14 13:59:37 2022 +0100 Remove building examples from the docs build process The removed code was previously unused and lived only as a side note two commits ago. It was suggested in issue #33 that datalad-neuroimaging is probably the only extension using this stage of doc-build, and therefore we may drop it from the template. commit 1fc0ef09942fa803d6b71671fb5c2732eed23451 Author: Michał Szczepanik Date: Mon Mar 14 13:44:24 2022 +0100 Replace os.system with subprocess.run in doc-build commit 0d19eeda18bb83be26564d08af6f91adc9268ad2 Merge: bfeaa45 84d672a Author: Michael Hanke Date: Thu Feb 10 15:29:49 2022 +0100 Merge pull request #32 from datalad/docs-explainer Add documentation explainer commit bfeaa45c1f269210897b91b2cb0ff690867c60a6 Merge: 1929a22 8e9bcbc Author: Michael Hanke Date: Thu Feb 10 15:27:24 2022 +0100 Merge pull request #30 from datalad/mslw-patch-1 Replace _metalad with _helloworld for easier grepping commit 84d672accb103b1a2396181565bb2e2ab6e5d38a Author: Stephan Heunis Date: Thu Feb 10 15:08:57 2022 +0100 add documentation explainer commit 8e9bcbc4b2a64e8bcd48059ed85c5c34321f5dad Author: Michał Szczepanik Date: Wed Feb 9 16:23:38 2022 +0100 Replace _metalad with _helloworld for easier grepping commit 1929a229214945e462f40cdcee6a339dfecc7124 Merge: ec54055 7b77859 Author: Michael Hanke Date: Mon Jan 24 10:29:45 2022 +0100 Merge pull request #29 from datalad/rf-tst Round of fixes and updates commit 7b77859c361ca2ff2ae7183069160fd5b8a329ff Author: Michael Hanke Date: Mon Jan 24 10:12:46 2022 +0100 Minimal codeclimate config commit 37b060672423ec4558c131d966c595b6638787e3 Author: Michael Hanke Date: Mon Jan 24 10:10:59 2022 +0100 More applicable command template With the command being in a dedicated file. Now also include standard logger naming suggestions. Fixes datalad/datalad-extension-template#27 commit 4aa498d49a315a5864393a5373fa64bc026a713a Author: Michael Hanke Date: Mon Jan 24 09:52:49 2022 +0100 Document what needs to be done for installing a git-annex snapshot Fixed datalad/datalad-extension-template#22 commit 7aea7b2c69d778433ffc60db22d5f9075e90fdbf Author: Michael Hanke Date: Mon Jan 24 09:50:18 2022 +0100 Update codecov setup to match datalad-core Fixes datalad/datalad-extension-template#24 commit ec5405566fd756d281f9d1fb73e25243a3d266e4 Merge: f6ef763 a3b022c Author: Michael Hanke Date: Tue Jan 11 17:22:44 2022 +0100 Merge pull request #28 from datalad/bf-version Make version detection robust to GIT_DIR specification commit a3b022cdf62e7637f46fc76b4e02ad2b4fb0735b Author: Chris Markiewicz Date: Tue Jan 11 10:37:27 2022 +0100 Make version detection robust to GIT_DIR specification Analog fix to https://github.com/datalad/datalad/pull/6341 commit f6ef763f94cefa953ef5dc1b037b06155a411933 Merge: b04f268 48addfb Author: Michael Hanke Date: Tue Jan 11 10:35:22 2022 +0100 Merge pull request #26 from datalad/no-setup-requires Stop using `setup_requires` commit b04f2685fea8d9e72cb4f03801b22986e7eecf5e Merge: cb64d9b 99a960f Author: Yaroslav Halchenko Date: Mon Oct 25 11:15:25 2021 -0400 Merge pull request #25 from datalad/no-distutils Stop using distutils commit 48addfbabc1ab65406f76324a329449948cad8b6 Author: John T. Wodder II Date: Mon Oct 25 09:20:18 2021 -0400 Stop using `setup_requires` commit 99a960ff3fa47a2b54412a8fb6c50ca48b447f06 Author: John T. Wodder II Date: Mon Oct 25 08:49:30 2021 -0400 Stop using distutils in _datalad_buildsupport commit c294de886d5de7d7597d97e93ff64dd8ed2909c2 Author: John T. Wodder II Date: Mon Oct 25 08:48:42 2021 -0400 Keep versioneer.py from using distutils commit cb64d9b9762d738c7d34ec3f4fd34c55cd7e184f Merge: 8b6234b f05a10b Author: Michael Hanke Date: Fri Oct 1 11:01:30 2021 +0200 Merge pull request #23 from datalad/bdist-wheel Fix bdist_wheel command in Makefile commit f05a10b38d90ed8e68c59a88cf8f00b2511bc4f4 Author: John T. Wodder II Date: Thu Sep 30 09:19:39 2021 -0400 Fix bdist_wheel command in Makefile commit 8b6234b96aa3be6b54446a280042706585d91ca9 Merge: c4c4f52 88aeff2 Author: Michael Hanke Date: Wed Sep 29 08:08:12 2021 +0200 Merge pull request #21 from datalad/testrequires Discontinue use of tests_require commit 88aeff294ecee8b1536e5f9fcdee217c5a7ed706 Author: Michael Hanke Date: Wed Sep 29 08:02:58 2021 +0200 Discontinue use of tests_require To achieve compatibility with some of datalad's default CI setups. commit c4c4f52bb2750c6576f441ff53b560be0a4ad675 Author: Michael Hanke Date: Thu Apr 15 10:20:40 2021 +0200 Disable smart quoting for valid manpages in HTML docs commit 34aa9b7f58ecc9750d2bee8ecb3dddf9ed02ed4d Merge: 0d4f35f edec51f Author: Michael Hanke Date: Wed Sep 22 14:48:33 2021 +0200 Merge pull request #19 from datalad/buildsupport Buildsupport update commit edec51f420f2203328423787d04f4518f0b27ae4 Merge: 0d4f35f 9975f82 Author: Michael Hanke Date: Wed Sep 22 14:41:40 2021 +0200 Update DataLad build helper commit 0d4f35f6dced6fe593e4924124df83f55e0d2590 Merge: 022720b afc8586 Author: Michael Hanke Date: Wed Sep 22 11:04:42 2021 +0200 Merge pull request #18 from datalad/appveyor-updates Appveyor updates commit afc8586101317359de04375815cfe87aede30bab Author: Michael Hanke Date: Wed Sep 22 10:57:41 2021 +0200 Do apt-get update before apt-get install Analog change to an update necessary in -ukbiobank that makes sense in general. Fixes datalad/datalad-extension-template#13 commit 2b59d6a4a773fd330f01864e9e3cf6eb9417e3b1 Author: Michael Hanke Date: Wed Sep 22 10:55:37 2021 +0200 Bump git-annex version for testing to a recent release Matching the one used in datalad-core commit 022720b6aee5f95fc8c9b57916fffe9c9d3b4563 Merge: 64d185d 3cbd005 Author: Michael Hanke Date: Wed Sep 22 10:49:42 2021 +0200 Merge pull request #14 from datalad/fix-manifest Add missing/necessary files to sdists commit 64d185dd7bebfbf8b513a0b90a3b30b7b4530ef2 Merge: e90593e 448eb72 Author: Michael Hanke Date: Wed Sep 22 10:44:32 2021 +0200 Merge pull request #16 from datalad/mv-entry-points Move entry points declaration to setup.cfg commit e90593e86017f2860526c3d9348c2235a6373857 Merge: ec853dc a6e5add Author: Michael Hanke Date: Wed Sep 22 10:41:27 2021 +0200 Merge pull request #15 from datalad/no-universal Remove `--universal` flag commit ec853dcba03878202e2c2fe4da4c68383275675d Merge: 0098853 200030b Author: Michael Hanke Date: Wed Sep 22 10:38:30 2021 +0200 Merge pull request #17 from datalad/versioneer Versioneer needs more history to do its job commit 200030bfea4e0488edd6efc00324a2e05d3db869 Author: Michael Hanke Date: Wed Sep 22 10:33:54 2021 +0200 Versioneer needs more history to do its job commit 448eb72efb482831ce17a1a5421bb1b0863a46c4 Author: John T. Wodder II Date: Wed Sep 15 12:50:54 2021 -0400 Move entry points declaration to setup.cfg commit a6e5add3f3cdb3192a9c9dde910f9d67a7eebb11 Author: John T. Wodder II Date: Wed Sep 15 12:47:19 2021 -0400 Remove `--universal` flag commit 3cbd00592f20d2554da34ec0a4765c55a9184233 Author: John T. Wodder II Date: Wed Sep 15 12:37:40 2021 -0400 Add necessary files to sdists commit 9975f82bd5b43cc6bd6e0d36fc18ae9382bb40ab Author: Michael Hanke Date: Thu Apr 15 08:15:27 2021 +0200 BF: We only have lower-case command names In a command suite that only defines the class name of a command, and no explicit cmdline name, no manpage would be built, because the test against the parser content would look like `Ls != ls` This change enforces lower-case for autogenerated command names. commit 0098853fee84d0ed6794a291b5056445403a6cd2 Merge: 7078c9d 4d2c049 Author: Michael Hanke Date: Sat Apr 10 12:29:35 2021 +0200 Merge pull request #12 from datalad/rf-36 Update workflow to minimal supported Python version (3.6) commit 4d2c04930c184455a30a1592827a55c979c6a49b Author: Michael Hanke Date: Sat Apr 10 12:23:25 2021 +0200 Update workflow to minimal supported Python version (3.6) commit 7078c9d738102d6e5df6cc59b09b159425e610bf Author: Michael Hanke Date: Tue Mar 23 07:29:08 2021 +0100 Use Debian snapshots as a stable place for packages commit 4827d994939d220194a99b53eb5ed83d0b3e18da Merge: 4ad6769 899e9ba Author: Michael Hanke Date: Thu Mar 11 17:13:11 2021 +0100 Merge pull request #11 from datalad/tst-coverage Working coverage submission across all platforms commit 899e9bae0f39ea479a18a9415c0b978d2d2a6e89 Author: Michael Hanke Date: Thu Mar 11 16:51:09 2021 +0100 Working coverage submission across all platforms commit 4ad67696dde62b01213a7cfb2964cc5a1a104507 Merge: 616ea72 1260e41 Author: Michael Hanke Date: Thu Mar 11 09:08:29 2021 +0100 Merge pull request #10 from datalad/typos Minor fixup of wording for command_suite commit 1260e4175d60a1bd9fad85ed04833b79632d3ac8 Author: Yaroslav Halchenko Date: Tue Mar 2 18:30:12 2021 -0500 Minor fixup of wording for command_suite commit 616ea72d35b04e6ea920ef2abfbd5ca76b0f1592 Merge: a4a5749 7d8c9aa Author: Michael Hanke Date: Tue Mar 2 08:20:57 2021 +0100 Merge pull request #9 from datalad/installer Use released version of datalad-installer commit 7d8c9aa9f796df763bb83485174d35ef4a2ebcc7 Author: Michael Hanke Date: Tue Mar 2 07:40:52 2021 +0100 Use released version of datalad-installer - get rid of custom git-annex installer script on windows, use the official implementation instead - add support for requesting a specific installer version via ENV variable DATALAD_INSTALLER_VERSION, go with "latest" by default. Requesting an unavailable installer version will make the build error. commit a4a574989b1dfc78a4ac0287374e9780208add7d Author: Michael Hanke Date: Mon Jan 25 08:12:45 2021 +0100 TST: Switch default test setup to appveyor Following changes in datalad-core as well as other extensions. commit f304d45b8d1f34dae08d0809c8e87c5047f8e278 Author: Michael Hanke Date: Tue Jun 16 13:46:11 2020 +0200 Fix for consistency commit 1fb2ed6756596ff8e0410dd07314a132f81f1357 Author: Michael Hanke Date: Mon Jun 15 17:42:00 2020 +0200 Prevent inclusion of build helpers into binary packages commit ce8e7f002b0aedfd1c0b77403c16ca511b56eeaf Merge: 0924ab1 cd61512 Author: Michael Hanke Date: Mon Jun 15 13:08:29 2020 +0200 Add DataLad build helper commit cd615129ab5efd800a9c4dcbf752651b6b921740 Author: Michael Hanke Date: Mon Jun 15 13:08:29 2020 +0200 Squashed '_datalad_buildsupport/' content from commit 023a1b7 git-subtree-dir: _datalad_buildsupport git-subtree-split: 023a1b77194508f7aa1d7ec5ec3bb222c1d840aa commit 0924ab1e62b31e647eb6268e28c17edd6c26a77f Author: Michael Hanke Date: Mon Jun 15 13:07:44 2020 +0200 Minor name change Avoids conflict with code in datalad-core and matches source repo name. commit 80bf1979d5c8f9f1770deec687dc8106867c91f9 Author: Michael Hanke Date: Mon Jun 15 09:01:18 2020 +0200 Rename file to get a more obvious label commit 1cfca1d17b7b72f01c67e29affa4168c3baba8c8 Author: Michael Hanke Date: Mon Jun 15 09:00:06 2020 +0200 Extend README with practical info commit 49817c694686d21ceb5aacb22c43fa5e320d9945 Merge: a20b711 73a7485 Author: Michael Hanke Date: Mon Jun 15 08:57:28 2020 +0200 Merge pull request #7 from datalad/readme Community related pointers for the README commit 73a74858b21ca7ba32b4abd32330b97ae3cd84a4 Author: Adina Wagner Date: Wed Jun 10 13:28:40 2020 +0200 add a minimal zenodo.json file commit 28b0f3084e7ba0565e6a720653bcfcc89c58abf4 Author: Adina Wagner Date: Wed Jun 10 13:29:27 2020 +0200 add archival and community related pointers to the README commit a20b71151336982730894b1a534d67831f68c94c Merge: ea1ed84 12a5a2d Author: Michael Hanke Date: Mon Jun 15 08:42:44 2020 +0200 Merge pull request #6 from datalad/build_helpers Build and render manpages -- using common build helpers commit 12a5a2de5ae27ef658c4099a988d6b1fd47ebd1b Author: Michael Hanke Date: Mon Jun 15 08:25:24 2020 +0200 Remove leftover broken devel requirement commit dbd12d14cf4e1f4231b84d02d1f555ea02b242dc Merge: da5b936 023a1b7 Author: Michael Hanke Date: Mon Jun 15 08:19:45 2020 +0200 Add DataLad build helper git-subtree-dir: _datalad_build_support git-subtree-mainline: da5b936048453af66ff9d821920df70eedc87d24 git-subtree-split: 023a1b77194508f7aa1d7ec5ec3bb222c1d840aa commit da5b936048453af66ff9d821920df70eedc87d24 Author: Michael Hanke Date: Fri Jun 12 17:32:04 2020 +0200 Add makefile target for updating the DataLad build helpers commit 023a1b77194508f7aa1d7ec5ec3bb222c1d840aa Author: Michael Hanke Date: Mon Jun 15 08:16:13 2020 +0200 BF: Read package metadata directly from setup.cfg The distribution object does not seem to see it (at least not under all circumstances). commit fd99b4eece55f97514387b31787d15b393a669f9 Author: Michael Hanke Date: Mon Jun 15 08:15:09 2020 +0200 RF: Remove helpers that are not needed for extensions DataLad core can add its own ones again, but it is not worth imposing the code on all extensions. commit ba575108283843f6e9f63c1852c69cc29df08ffd Author: Michael Hanke Date: Fri Jun 12 17:35:46 2020 +0200 Enable building manpages for extensions With the ability to point to a specific command suite. The rest is just about making datalad core not break. commit 343b9a0ba4f72c4da641f6ba74dfbe643b70807a Author: Michael Hanke Date: Fri Jun 12 17:21:01 2020 +0200 Start with a copy from datalad@afa682550ee742d69853f69165c0f37c5f4b5f05 commit 5d64f44cb21adf62b26feaf216f9767ca4b1928a Author: Michael Hanke Date: Thu Jun 11 12:41:43 2020 +0200 Build and render manpages commit ea1ed84757f7f3bbbd172073676883179f770c7e Merge: a836e6b 1a56499 Author: Michael Hanke Date: Wed Jun 10 16:24:09 2020 +0200 Merge pull request #5 from mih/master Modernization commit 1a56499f2ccc9d96bb9936d1a2d8edf3a87a4125 Author: Michael Hanke Date: Wed Jun 10 12:17:29 2020 +0200 Make more datalad-friendly by prevent annex creation on datalad-save commit 915818a1b5988efffc4b6c8f25b1ccc6bdd8f6e1 Author: Michael Hanke Date: Wed Jun 10 12:15:06 2020 +0200 Remove needless setup complication commit 90debfceae21cd4d43521230dd59f7a9586442b7 Author: Michael Hanke Date: Wed Jun 10 12:14:50 2020 +0200 Fix badge name commit ec78dfdf1b3f89bb9f21fff2fa5fd26fe37505b6 Author: Michael Hanke Date: Wed Jun 10 11:30:11 2020 +0200 Added top-level Makefile with release-to-pypi helper commit e8d69fb3cf21eadc344c15bc22bf1ad9fe0ee3d7 Author: Michael Hanke Date: Wed Jun 10 09:33:58 2020 +0200 Update README with more status badges commit c34760b8a562053005556fa835dffc200f1ae430 Author: Michael Hanke Date: Wed Jun 10 10:57:46 2020 +0200 Github action to build the docs commit 24199ea7d06f8aafcda006aeec1edd3721bdec36 Author: Michael Hanke Date: Wed Jun 10 10:34:50 2020 +0200 Sphinx-doc scaffold commit 514d3430bf2e6fdab7e6378105e807372cc46646 Author: Michael Hanke Date: Wed Jun 10 10:30:52 2020 +0200 Add workflow for testing on windows commit 61163c77291dc16f6c877c2bf757e1827cb8a1ad Author: Michael Hanke Date: Wed Jun 10 08:20:01 2020 +0200 Standardize on requirement-devel.txt commit cc7ed24953a06aec135bdf94d4a5b49915dccdfb Author: Michael Hanke Date: Wed Jun 10 07:59:48 2020 +0200 Add github workflow for testing on a crippled filesystem commit f2b2a6c2ac938671aa5fb8c7be99a8811cde3102 Author: Michael Hanke Date: Wed Jun 10 07:56:23 2020 +0200 Ignore pip metadata dumps and other stuff commit 8e0ace0a0b48d7fb5e2dba3ca8242dc85a5af4ac Author: Michael Hanke Date: Wed Jun 10 07:48:54 2020 +0200 [DATALAD RUNCMD] Install/enable versioneer === Do not change lines below === { "chain": [], "cmd": "versioneer install", "exit": 0, "extra_inputs": [], "inputs": [], "outputs": [], "pwd": "." } ^^^ Do not change lines above ^^^ commit f44d7e2c0b83801a53c5238d966a54ab50fabfc0 Author: Michael Hanke Date: Wed Jun 10 09:34:46 2020 +0200 Add missing __init__.py to get tests installed correctly commit d94fb13aa4f037d50945eb69c7565d8d92cf68e4 Author: Michael Hanke Date: Wed Jun 10 07:46:56 2020 +0200 Simplify Travis setup No PY2, more up-to-date PY3 versions commit edfe14a6f4ddeb75801864647400185cd48b8b3f Author: Michael Hanke Date: Wed Jun 10 07:41:07 2020 +0200 Fixup and expand metadata in setup.cfg and for setup.py Sensible default setup for dependencies and testing. Should enable to just drop in some code, rename the package and run. commit d0eec9f9c59915dbe48acec863329d1b112aaa23 Author: Adina Wagner Date: Tue Jun 9 10:52:48 2020 +0200 add initial configuration for versioneer setup commit 63e9a481c87e3301528ce6d5f4d65f91cb3bd4b0 Author: Adina Wagner Date: Tue Jun 9 10:46:34 2020 +0200 modernize setup according to https://github.com/datalad/datalad-ukbiobank commit a836e6ba83b8f17cfc321e0c878157cc96ae7847 Author: Michael Hanke Date: Wed Jun 10 08:05:04 2020 +0200 Dummy workflow commit 78de6c37f4443ca1218a3f75abfa6caee300e686 Author: Michael Hanke Date: Fri Oct 12 07:55:25 2018 +0200 TST: Swap out directmode tests for v6 tests commit 75b6fa4b523267b509e4cd20f6db75c43ef53e1c Author: Michael Hanke Date: Fri Oct 12 06:52:49 2018 +0200 Standard gitignore commit 2bc890edefba106124c678bac6df521783d3b397 Author: Michael Hanke Date: Fri Oct 12 06:52:29 2018 +0200 Improve standard setup commit 8da041aaf1c1c20205f788b87d02d675115adebb Author: Michael Hanke Date: Fri Apr 6 11:20:12 2018 +0200 RF: Extension naming conventions commit c971b18d8083aeb3ab14e09a4ecf6f9e735c5dc2 Author: Michael Hanke Date: Fri Mar 30 16:50:11 2018 +0200 TST: Reenable wtf, after datalad got fixed commit 92f22c333fff6920273c0a718082cacbd6fec0f9 Author: Michael Hanke Date: Fri Mar 30 11:13:05 2018 +0200 RF: Standardize on datalad_ module prefix (fixes gh-1) commit cc63930bb47ba424de4fabb14d512eaa0755da04 Author: Michael Hanke Date: Fri Mar 30 09:39:20 2018 +0200 Deal with Datalad bug commit 839f7280e109ff3ac27aac08847636e21d6c806f Author: Michael Hanke Date: Fri Mar 30 09:31:55 2018 +0200 Install the package commit 486cfa704db5745b19c721f9f5648562e0023f44 Author: Michael Hanke Date: Fri Mar 30 09:25:19 2018 +0200 RF: Comply with datalads current ad-hoc naming conventions commit 9351f9974a9e2853f7107499881865e5936b6b55 Author: Michael Hanke Date: Thu Mar 29 20:45:47 2018 +0200 TST: Basic test of whether datalad can see this extension commit 9bc499db31689b9db828ac842bd649241b8121d6 Author: Michael Hanke Date: Thu Mar 29 20:33:10 2018 +0200 TST: Trimmed travis setup from the mothership commit 4ee24c490709275726e5a4b58cae682f6cb2f564 Author: Michael Hanke Date: Wed Mar 28 16:49:08 2018 +0200 DOC: Basic README commit 831e6c5c76e359855738a89b97f22dacd6a8b902 Author: Michael Hanke Date: Wed Mar 28 16:09:14 2018 +0200 DOC: Annotate setup.py commit 7c5a645904f1f591d30a75d3dfee5b7b55998ba9 Author: Michael Hanke Date: Wed Mar 28 16:04:48 2018 +0200 DOC: more complete basic info commit 82300f6c348e6d54e2673d697ecb3570b65da3b2 Author: Michael Hanke Date: Wed Mar 28 16:00:50 2018 +0200 DOC: Some insight into the command implementation commit 387333b0862cb61c1a8aa40ae8fa5342a99c20ab Author: Michael Hanke Date: Wed Mar 28 15:49:56 2018 +0200 Declare dependency on datalad Should be versioned, but needs to wait for a release. commit 00e17548770bd737925007390fb2321844cc6486 Author: Michael Hanke Date: Wed Mar 28 15:19:01 2018 +0200 Demo of a minimalistic DataLad extension module commit be4df7f645296eff76e5bd5b9e5297186280db08 Author: Michael Hanke Date: Wed Mar 28 14:12:07 2018 +0200 first commit --- .appveyor.yml | 12 +++++++++--- .github/workflows/test_crippledfs.yml | 2 +- requirements-devel.txt | 3 ++- setup.cfg | 6 +++--- 4 files changed, 15 insertions(+), 8 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index f787261..4de52e4 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -90,6 +90,13 @@ matrix: - KNOWN2FAIL: 1 +# do not run the CI if only documentation changes were made +# documentation builds are tested elsewhere and cheaper +skip_commits: + files: + - docs/ + + # it is OK to specify paths that may not exist for a particular test run cache: # pip cache @@ -190,9 +197,8 @@ test_script: - cmd: md __testhome__ - sh: mkdir __testhome__ - cd __testhome__ - # run test selecion (--traverse-namespace needed from Python 3.8 onwards) - - cmd: python -m nose --traverse-namespace -s -v -A "not (turtle)" --with-cov --cover-package datalad_ebrains %DTS% - - sh: python -m nose --traverse-namespace -s -v -A "not (turtle)" --with-cov --cover-package datalad_ebrains ${DTS} + - cmd: python -m pytest -s -v -m "not (turtle)" --doctest-modules --cov=datalad_ebrains --pyargs %DTS% + - sh: python -m pytest -s -v -m "not (turtle)" --doctest-modules --cov=datalad_ebrains --pyargs ${DTS} after_test: diff --git a/.github/workflows/test_crippledfs.yml b/.github/workflows/test_crippledfs.yml index e0d4124..c2c1ff5 100644 --- a/.github/workflows/test_crippledfs.yml +++ b/.github/workflows/test_crippledfs.yml @@ -52,4 +52,4 @@ jobs: echo "== mount >>" mount echo "<< mount ==" - python -m nose -s -v --with-doctest --with-coverage --cover-package datalad_helloworld datalad_helloworld + python -m pytest -s -v --doctest-modules --cov=datalad_ebrains --pyargs datalad_ebrains diff --git a/requirements-devel.txt b/requirements-devel.txt index 5db3241..364f811 100644 --- a/requirements-devel.txt +++ b/requirements-devel.txt @@ -1,5 +1,6 @@ # requirements for a development environment -nose +pytest +pytest-cov coverage sphinx sphinx_rtd_theme diff --git a/setup.cfg b/setup.cfg index ab7006d..5f8e04b 100644 --- a/setup.cfg +++ b/setup.cfg @@ -12,9 +12,9 @@ classifiers = Programming Language :: Python :: 3 [options] -python_requires = >= 3.6 +python_requires = >= 3.7 install_requires = - datalad >= 0.16 + datalad >= 0.17 datalad_next packages = find_namespace: include_package_data = True @@ -25,7 +25,7 @@ include = datalad_ebrains* [options.extras_require] # this matches the name used by -core and what is expected by some CI setups devel = - nose + pytest coverage [options.entry_points] From 0e4399b7f3c5f523f08f99830292681f33e2dce8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Szczepanik?= Date: Tue, 30 Aug 2022 15:08:31 +0200 Subject: [PATCH 3/5] [DATALAD RUNCMD] Update versioneer This updates versioneer from 0.18 to 0.23, which supports Python 3.7 to 3.10. Done automatically by running versioneer install. === Do not change lines below === { "chain": [], "cmd": "versioneer install", "exit": 0, "extra_inputs": [], "inputs": [], "outputs": [], "pwd": "." } ^^^ Do not change lines above ^^^ --- datalad_ebrains/__init__.py | 5 +- datalad_ebrains/_version.py | 265 +++++++++--- versioneer.py | 842 +++++++++++++++++++++++++----------- 3 files changed, 786 insertions(+), 326 deletions(-) diff --git a/datalad_ebrains/__init__.py b/datalad_ebrains/__init__.py index 0d556ce..45e0b09 100644 --- a/datalad_ebrains/__init__.py +++ b/datalad_ebrains/__init__.py @@ -27,6 +27,5 @@ from datalad import setup_package from datalad import teardown_package -from ._version import get_versions -__version__ = get_versions()['version'] -del get_versions +from . import _version +__version__ = _version.get_versions()['version'] diff --git a/datalad_ebrains/_version.py b/datalad_ebrains/_version.py index b997fb8..2bcca9d 100644 --- a/datalad_ebrains/_version.py +++ b/datalad_ebrains/_version.py @@ -6,7 +6,7 @@ # that just contains the computed version number. # This file is released into the public domain. Generated by -# versioneer-0.18 (https://github.com/warner/python-versioneer) +# versioneer-0.23 (https://github.com/python-versioneer/python-versioneer) """Git implementation of _version.py.""" @@ -15,6 +15,8 @@ import re import subprocess import sys +from typing import Callable, Dict +import functools def get_keywords(): @@ -52,12 +54,12 @@ class NotThisMethod(Exception): """Exception raised if a method is not valid for the current scenario.""" -LONG_VERSION_PY = {} -HANDLERS = {} +LONG_VERSION_PY: Dict[str, str] = {} +HANDLERS: Dict[str, Dict[str, Callable]] = {} def register_vcs_handler(vcs, method): # decorator - """Decorator to mark a method as the handler for a particular VCS.""" + """Create decorator to mark a method as the handler of a VCS.""" def decorate(f): """Store f in HANDLERS[vcs][method].""" if vcs not in HANDLERS: @@ -71,17 +73,25 @@ def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False, env=None): """Call the given command(s).""" assert isinstance(commands, list) - p = None - for c in commands: + process = None + + popen_kwargs = {} + if sys.platform == "win32": + # This hides the console window if pythonw.exe is used + startupinfo = subprocess.STARTUPINFO() + startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW + popen_kwargs["startupinfo"] = startupinfo + + for command in commands: try: - dispcmd = str([c] + args) + dispcmd = str([command] + args) # remember shell=False, so use git.cmd on windows, not just git - p = subprocess.Popen([c] + args, cwd=cwd, env=env, - stdout=subprocess.PIPE, - stderr=(subprocess.PIPE if hide_stderr - else None)) + process = subprocess.Popen([command] + args, cwd=cwd, env=env, + stdout=subprocess.PIPE, + stderr=(subprocess.PIPE if hide_stderr + else None), **popen_kwargs) break - except EnvironmentError: + except OSError: e = sys.exc_info()[1] if e.errno == errno.ENOENT: continue @@ -93,15 +103,13 @@ def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False, if verbose: print("unable to find command, tried %s" % (commands,)) return None, None - stdout = p.communicate()[0].strip() - if sys.version_info[0] >= 3: - stdout = stdout.decode() - if p.returncode != 0: + stdout = process.communicate()[0].strip().decode() + if process.returncode != 0: if verbose: print("unable to run %s (error)" % dispcmd) print("stdout was %s" % stdout) - return None, p.returncode - return stdout, p.returncode + return None, process.returncode + return stdout, process.returncode def versions_from_parentdir(parentdir_prefix, root, verbose): @@ -113,15 +121,14 @@ def versions_from_parentdir(parentdir_prefix, root, verbose): """ rootdirs = [] - for i in range(3): + for _ in range(3): dirname = os.path.basename(root) if dirname.startswith(parentdir_prefix): return {"version": dirname[len(parentdir_prefix):], "full-revisionid": None, "dirty": False, "error": None, "date": None} - else: - rootdirs.append(root) - root = os.path.dirname(root) # up a level + rootdirs.append(root) + root = os.path.dirname(root) # up a level if verbose: print("Tried directories %s but none started with prefix %s" % @@ -138,22 +145,21 @@ def git_get_keywords(versionfile_abs): # _version.py. keywords = {} try: - f = open(versionfile_abs, "r") - for line in f.readlines(): - if line.strip().startswith("git_refnames ="): - mo = re.search(r'=\s*"(.*)"', line) - if mo: - keywords["refnames"] = mo.group(1) - if line.strip().startswith("git_full ="): - mo = re.search(r'=\s*"(.*)"', line) - if mo: - keywords["full"] = mo.group(1) - if line.strip().startswith("git_date ="): - mo = re.search(r'=\s*"(.*)"', line) - if mo: - keywords["date"] = mo.group(1) - f.close() - except EnvironmentError: + with open(versionfile_abs, "r") as fobj: + for line in fobj: + if line.strip().startswith("git_refnames ="): + mo = re.search(r'=\s*"(.*)"', line) + if mo: + keywords["refnames"] = mo.group(1) + if line.strip().startswith("git_full ="): + mo = re.search(r'=\s*"(.*)"', line) + if mo: + keywords["full"] = mo.group(1) + if line.strip().startswith("git_date ="): + mo = re.search(r'=\s*"(.*)"', line) + if mo: + keywords["date"] = mo.group(1) + except OSError: pass return keywords @@ -161,10 +167,14 @@ def git_get_keywords(versionfile_abs): @register_vcs_handler("git", "keywords") def git_versions_from_keywords(keywords, tag_prefix, verbose): """Get version information from git keywords.""" - if not keywords: - raise NotThisMethod("no keywords at all, weird") + if "refnames" not in keywords: + raise NotThisMethod("Short version file found") date = keywords.get("date") if date is not None: + # Use only the last line. Previous lines may contain GPG signature + # information. + date = date.splitlines()[-1] + # git-2.2.0 added "%cI", which expands to an ISO-8601 -compliant # datestamp. However we prefer "%ci" (which expands to an "ISO-8601 # -like" string, which we must then edit to make compliant), because @@ -177,11 +187,11 @@ def git_versions_from_keywords(keywords, tag_prefix, verbose): if verbose: print("keywords are unexpanded, not using") raise NotThisMethod("unexpanded keywords, not a git-archive tarball") - refs = set([r.strip() for r in refnames.strip("()").split(",")]) + refs = {r.strip() for r in refnames.strip("()").split(",")} # starting in git-1.8.3, tags are listed as "tag: foo-1.0" instead of # just "foo-1.0". If we see a "tag: " prefix, prefer those. TAG = "tag: " - tags = set([r[len(TAG):] for r in refs if r.startswith(TAG)]) + tags = {r[len(TAG):] for r in refs if r.startswith(TAG)} if not tags: # Either we're using git < 1.8.3, or there really are no tags. We use # a heuristic: assume all version tags have a digit. The old git %d @@ -190,7 +200,7 @@ def git_versions_from_keywords(keywords, tag_prefix, verbose): # between branches and tags. By ignoring refnames without digits, we # filter out many common branch names like "release" and # "stabilization", as well as "HEAD" and "master". - tags = set([r for r in refs if re.search(r'\d', r)]) + tags = {r for r in refs if re.search(r'\d', r)} if verbose: print("discarding '%s', no digits" % ",".join(refs - tags)) if verbose: @@ -199,6 +209,11 @@ def git_versions_from_keywords(keywords, tag_prefix, verbose): # sorting will prefer e.g. "2.0" over "2.0rc1" if ref.startswith(tag_prefix): r = ref[len(tag_prefix):] + # Filter out refs that exactly match prefix or that don't start + # with a number once the prefix is stripped (mostly a concern + # when prefix is '') + if not re.match(r'\d', r): + continue if verbose: print("picking %s" % r) return {"version": r, @@ -214,7 +229,7 @@ def git_versions_from_keywords(keywords, tag_prefix, verbose): @register_vcs_handler("git", "pieces_from_vcs") -def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command): +def git_pieces_from_vcs(tag_prefix, root, verbose, runner=run_command): """Get version from 'git describe' in the root of the source tree. This only gets called if the git-archive 'subst' keywords were *not* @@ -225,8 +240,15 @@ def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command): if sys.platform == "win32": GITS = ["git.cmd", "git.exe"] - out, rc = run_command(GITS, ["rev-parse", "--git-dir"], cwd=root, - hide_stderr=True) + # GIT_DIR can interfere with correct operation of Versioneer. + # It may be intended to be passed to the Versioneer-versioned project, + # but that should not change where we get our version from. + env = os.environ.copy() + env.pop("GIT_DIR", None) + runner = functools.partial(runner, env=env) + + _, rc = runner(GITS, ["rev-parse", "--git-dir"], cwd=root, + hide_stderr=True) if rc != 0: if verbose: print("Directory %s not under git control" % root) @@ -234,15 +256,15 @@ def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command): # if there is a tag matching tag_prefix, this yields TAG-NUM-gHEX[-dirty] # if there isn't one, this yields HEX[-dirty] (no NUM) - describe_out, rc = run_command(GITS, ["describe", "--tags", "--dirty", - "--always", "--long", - "--match", "%s*" % tag_prefix], - cwd=root) + describe_out, rc = runner(GITS, [ + "describe", "--tags", "--dirty", "--always", "--long", + "--match", f"{tag_prefix}[[:digit:]]*" + ], cwd=root) # --long was added in git-1.5.5 if describe_out is None: raise NotThisMethod("'git describe' failed") describe_out = describe_out.strip() - full_out, rc = run_command(GITS, ["rev-parse", "HEAD"], cwd=root) + full_out, rc = runner(GITS, ["rev-parse", "HEAD"], cwd=root) if full_out is None: raise NotThisMethod("'git rev-parse' failed") full_out = full_out.strip() @@ -252,6 +274,39 @@ def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command): pieces["short"] = full_out[:7] # maybe improved later pieces["error"] = None + branch_name, rc = runner(GITS, ["rev-parse", "--abbrev-ref", "HEAD"], + cwd=root) + # --abbrev-ref was added in git-1.6.3 + if rc != 0 or branch_name is None: + raise NotThisMethod("'git rev-parse --abbrev-ref' returned error") + branch_name = branch_name.strip() + + if branch_name == "HEAD": + # If we aren't exactly on a branch, pick a branch which represents + # the current commit. If all else fails, we are on a branchless + # commit. + branches, rc = runner(GITS, ["branch", "--contains"], cwd=root) + # --contains was added in git-1.5.4 + if rc != 0 or branches is None: + raise NotThisMethod("'git branch --contains' returned error") + branches = branches.split("\n") + + # Remove the first line if we're running detached + if "(" in branches[0]: + branches.pop(0) + + # Strip off the leading "* " from the list of branches. + branches = [branch[2:] for branch in branches] + if "master" in branches: + branch_name = "master" + elif not branches: + branch_name = None + else: + # Pick the first branch that is returned. Good or bad. + branch_name = branches[0] + + pieces["branch"] = branch_name + # parse describe_out. It will be like TAG-NUM-gHEX[-dirty] or HEX[-dirty] # TAG might have hyphens. git_describe = describe_out @@ -268,7 +323,7 @@ def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command): # TAG-NUM-gHEX mo = re.search(r'^(.+)-(\d+)-g([0-9a-f]+)$', git_describe) if not mo: - # unparseable. Maybe git-describe is misbehaving? + # unparsable. Maybe git-describe is misbehaving? pieces["error"] = ("unable to parse git-describe output: '%s'" % describe_out) return pieces @@ -293,13 +348,14 @@ def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command): else: # HEX: no tags pieces["closest-tag"] = None - count_out, rc = run_command(GITS, ["rev-list", "HEAD", "--count"], - cwd=root) - pieces["distance"] = int(count_out) # total number of commits + out, rc = runner(GITS, ["rev-list", "HEAD", "--left-right"], cwd=root) + pieces["distance"] = len(out.split()) # total number of commits # commit date: see ISO-8601 comment in git_versions_from_keywords() - date = run_command(GITS, ["show", "-s", "--format=%ci", "HEAD"], - cwd=root)[0].strip() + date = runner(GITS, ["show", "-s", "--format=%ci", "HEAD"], cwd=root)[0].strip() + # Use only the last line. Previous lines may contain GPG signature + # information. + date = date.splitlines()[-1] pieces["date"] = date.strip().replace(" ", "T", 1).replace(" ", "", 1) return pieces @@ -337,19 +393,67 @@ def render_pep440(pieces): return rendered -def render_pep440_pre(pieces): - """TAG[.post.devDISTANCE] -- No -dirty. +def render_pep440_branch(pieces): + """TAG[[.dev0]+DISTANCE.gHEX[.dirty]] . + + The ".dev0" means not master branch. Note that .dev0 sorts backwards + (a feature branch will appear "older" than the master branch). Exceptions: - 1: no tags. 0.post.devDISTANCE + 1: no tags. 0[.dev0]+untagged.DISTANCE.gHEX[.dirty] """ if pieces["closest-tag"]: rendered = pieces["closest-tag"] + if pieces["distance"] or pieces["dirty"]: + if pieces["branch"] != "master": + rendered += ".dev0" + rendered += plus_or_dot(pieces) + rendered += "%d.g%s" % (pieces["distance"], pieces["short"]) + if pieces["dirty"]: + rendered += ".dirty" + else: + # exception #1 + rendered = "0" + if pieces["branch"] != "master": + rendered += ".dev0" + rendered += "+untagged.%d.g%s" % (pieces["distance"], + pieces["short"]) + if pieces["dirty"]: + rendered += ".dirty" + return rendered + + +def pep440_split_post(ver): + """Split pep440 version string at the post-release segment. + + Returns the release segments before the post-release and the + post-release version number (or -1 if no post-release segment is present). + """ + vc = str.split(ver, ".post") + return vc[0], int(vc[1] or 0) if len(vc) == 2 else None + + +def render_pep440_pre(pieces): + """TAG[.postN.devDISTANCE] -- No -dirty. + + Exceptions: + 1: no tags. 0.post0.devDISTANCE + """ + if pieces["closest-tag"]: if pieces["distance"]: - rendered += ".post.dev%d" % pieces["distance"] + # update the post release segment + tag_version, post_version = pep440_split_post(pieces["closest-tag"]) + rendered = tag_version + if post_version is not None: + rendered += ".post%d.dev%d" % (post_version + 1, pieces["distance"]) + else: + rendered += ".post0.dev%d" % (pieces["distance"]) + else: + # no commits, use the tag as the version + rendered = pieces["closest-tag"] else: # exception #1 - rendered = "0.post.dev%d" % pieces["distance"] + rendered = "0.post0.dev%d" % pieces["distance"] return rendered @@ -380,12 +484,41 @@ def render_pep440_post(pieces): return rendered +def render_pep440_post_branch(pieces): + """TAG[.postDISTANCE[.dev0]+gHEX[.dirty]] . + + The ".dev0" means not master branch. + + Exceptions: + 1: no tags. 0.postDISTANCE[.dev0]+gHEX[.dirty] + """ + if pieces["closest-tag"]: + rendered = pieces["closest-tag"] + if pieces["distance"] or pieces["dirty"]: + rendered += ".post%d" % pieces["distance"] + if pieces["branch"] != "master": + rendered += ".dev0" + rendered += plus_or_dot(pieces) + rendered += "g%s" % pieces["short"] + if pieces["dirty"]: + rendered += ".dirty" + else: + # exception #1 + rendered = "0.post%d" % pieces["distance"] + if pieces["branch"] != "master": + rendered += ".dev0" + rendered += "+g%s" % pieces["short"] + if pieces["dirty"]: + rendered += ".dirty" + return rendered + + def render_pep440_old(pieces): """TAG[.postDISTANCE[.dev0]] . The ".dev0" means dirty. - Eexceptions: + Exceptions: 1: no tags. 0.postDISTANCE[.dev0] """ if pieces["closest-tag"]: @@ -456,10 +589,14 @@ def render(pieces, style): if style == "pep440": rendered = render_pep440(pieces) + elif style == "pep440-branch": + rendered = render_pep440_branch(pieces) elif style == "pep440-pre": rendered = render_pep440_pre(pieces) elif style == "pep440-post": rendered = render_pep440_post(pieces) + elif style == "pep440-post-branch": + rendered = render_pep440_post_branch(pieces) elif style == "pep440-old": rendered = render_pep440_old(pieces) elif style == "git-describe": @@ -495,7 +632,7 @@ def get_versions(): # versionfile_source is the relative path from the top of the source # tree (where the .git directory might live) to this file. Invert # this to find the root from __file__. - for i in cfg.versionfile_source.split('/'): + for _ in cfg.versionfile_source.split('/'): root = os.path.dirname(root) except NameError: return {"version": "0+unknown", "full-revisionid": None, diff --git a/versioneer.py b/versioneer.py index 51ca818..2156245 100644 --- a/versioneer.py +++ b/versioneer.py @@ -1,5 +1,5 @@ -# Version: 0.18 +# Version: 0.23 """The Versioneer - like a rocketeer, but for versions. @@ -7,18 +7,14 @@ ============== * like a rocketeer, but for versions! -* https://github.com/warner/python-versioneer +* https://github.com/python-versioneer/python-versioneer * Brian Warner -* License: Public Domain -* Compatible With: python2.6, 2.7, 3.2, 3.3, 3.4, 3.5, 3.6, and pypy -* [![Latest Version] -(https://pypip.in/version/versioneer/badge.svg?style=flat) -](https://pypi.python.org/pypi/versioneer/) -* [![Build Status] -(https://travis-ci.org/warner/python-versioneer.png?branch=master) -](https://travis-ci.org/warner/python-versioneer) - -This is a tool for managing a recorded version number in distutils-based +* License: Public Domain (CC0-1.0) +* Compatible with: Python 3.7, 3.8, 3.9, 3.10 and pypy3 +* [![Latest Version][pypi-image]][pypi-url] +* [![Build Status][travis-image]][travis-url] + +This is a tool for managing a recorded version number in distutils/setuptools-based python projects. The goal is to remove the tedious and error-prone "update the embedded version string" step from your release process. Making a new release should be as easy as recording a new tag in your version-control @@ -27,9 +23,10 @@ ## Quick Install -* `pip install versioneer` to somewhere to your $PATH -* add a `[versioneer]` section to your setup.cfg (see below) +* `pip install versioneer` to somewhere in your $PATH +* add a `[versioneer]` section to your setup.cfg (see [Install](INSTALL.md)) * run `versioneer install` in your source tree, commit the results +* Verify version information with `python setup.py version` ## Version Identifiers @@ -61,7 +58,7 @@ for example `git describe --tags --dirty --always` reports things like "0.7-1-g574ab98-dirty" to indicate that the checkout is one revision past the 0.7 tag, has a unique revision id of "574ab98", and is "dirty" (it has -uncommitted changes. +uncommitted changes). The version identifier is used for multiple purposes: @@ -166,7 +163,7 @@ Some situations are known to cause problems for Versioneer. This details the most significant ones. More can be found on Github -[issues page](https://github.com/warner/python-versioneer/issues). +[issues page](https://github.com/python-versioneer/python-versioneer/issues). ### Subprojects @@ -180,7 +177,7 @@ `setup.cfg`, and `tox.ini`. Projects like these produce multiple PyPI distributions (and upload multiple independently-installable tarballs). * Source trees whose main purpose is to contain a C library, but which also - provide bindings to Python (and perhaps other langauges) in subdirectories. + provide bindings to Python (and perhaps other languages) in subdirectories. Versioneer will look for `.git` in parent directories, and most operations should get the right version string. However `pip` and `setuptools` have bugs @@ -194,9 +191,9 @@ Pip-8.1.1 is known to have this problem, but hopefully it will get fixed in some later version. -[Bug #38](https://github.com/warner/python-versioneer/issues/38) is tracking +[Bug #38](https://github.com/python-versioneer/python-versioneer/issues/38) is tracking this issue. The discussion in -[PR #61](https://github.com/warner/python-versioneer/pull/61) describes the +[PR #61](https://github.com/python-versioneer/python-versioneer/pull/61) describes the issue from the Versioneer side in more detail. [pip PR#3176](https://github.com/pypa/pip/pull/3176) and [pip PR#3615](https://github.com/pypa/pip/pull/3615) contain work to improve @@ -224,22 +221,10 @@ cause egg_info to be rebuilt (including `sdist`, `wheel`, and installing into a different virtualenv), so this can be surprising. -[Bug #83](https://github.com/warner/python-versioneer/issues/83) describes +[Bug #83](https://github.com/python-versioneer/python-versioneer/issues/83) describes this one, but upgrading to a newer version of setuptools should probably resolve it. -### Unicode version strings - -While Versioneer works (and is continually tested) with both Python 2 and -Python 3, it is not entirely consistent with bytes-vs-unicode distinctions. -Newer releases probably generate unicode version strings on py2. It's not -clear that this is wrong, but it may be surprising for applications when then -write these strings to a network connection or include them in bytes-oriented -APIs like cryptographic checksums. - -[Bug #71](https://github.com/warner/python-versioneer/issues/71) investigates -this question. - ## Updating Versioneer @@ -265,6 +250,14 @@ direction and include code from all supported VCS systems, reducing the number of intermediate scripts. +## Similar projects + +* [setuptools_scm](https://github.com/pypa/setuptools_scm/) - a non-vendored build-time + dependency +* [minver](https://github.com/jbweston/miniver) - a lightweight reimplementation of + versioneer +* [versioningit](https://github.com/jwodder/versioningit) - a PEP 518-based setuptools + plugin ## License @@ -274,19 +267,28 @@ Dedication" license (CC0-1.0), as described in https://creativecommons.org/publicdomain/zero/1.0/ . +[pypi-image]: https://img.shields.io/pypi/v/versioneer.svg +[pypi-url]: https://pypi.python.org/pypi/versioneer/ +[travis-image]: +https://img.shields.io/travis/com/python-versioneer/python-versioneer.svg +[travis-url]: https://travis-ci.com/github/python-versioneer/python-versioneer + """ +# pylint:disable=invalid-name,import-outside-toplevel,missing-function-docstring +# pylint:disable=missing-class-docstring,too-many-branches,too-many-statements +# pylint:disable=raise-missing-from,too-many-lines,too-many-locals,import-error +# pylint:disable=too-few-public-methods,redefined-outer-name,consider-using-with +# pylint:disable=attribute-defined-outside-init,too-many-arguments -from __future__ import print_function -try: - import configparser -except ImportError: - import ConfigParser as configparser +import configparser import errno import json import os import re import subprocess import sys +from typing import Callable, Dict +import functools class VersioneerConfig: @@ -321,12 +323,12 @@ def get_root(): # module-import table will cache the first one. So we can't use # os.path.dirname(__file__), as that will find whichever # versioneer.py was first imported, even in later projects. - me = os.path.realpath(os.path.abspath(__file__)) - me_dir = os.path.normcase(os.path.splitext(me)[0]) + my_path = os.path.realpath(os.path.abspath(__file__)) + me_dir = os.path.normcase(os.path.splitext(my_path)[0]) vsr_dir = os.path.normcase(os.path.splitext(versioneer_py)[0]) if me_dir != vsr_dir: print("Warning: build in %s is using versioneer.py from %s" - % (os.path.dirname(me), versioneer_py)) + % (os.path.dirname(my_path), versioneer_py)) except NameError: pass return root @@ -334,30 +336,29 @@ def get_root(): def get_config_from_root(root): """Read the project setup.cfg file to determine Versioneer config.""" - # This might raise EnvironmentError (if setup.cfg is missing), or + # This might raise OSError (if setup.cfg is missing), or # configparser.NoSectionError (if it lacks a [versioneer] section), or # configparser.NoOptionError (if it lacks "VCS="). See the docstring at # the top of versioneer.py for instructions on writing your setup.cfg . setup_cfg = os.path.join(root, "setup.cfg") - parser = configparser.SafeConfigParser() - with open(setup_cfg, "r") as f: - parser.readfp(f) + parser = configparser.ConfigParser() + with open(setup_cfg, "r") as cfg_file: + parser.read_file(cfg_file) VCS = parser.get("versioneer", "VCS") # mandatory - def get(parser, name): - if parser.has_option("versioneer", name): - return parser.get("versioneer", name) - return None + # Dict-like interface for non-mandatory entries + section = parser["versioneer"] + cfg = VersioneerConfig() cfg.VCS = VCS - cfg.style = get(parser, "style") or "" - cfg.versionfile_source = get(parser, "versionfile_source") - cfg.versionfile_build = get(parser, "versionfile_build") - cfg.tag_prefix = get(parser, "tag_prefix") - if cfg.tag_prefix in ("''", '""'): + cfg.style = section.get("style", "") + cfg.versionfile_source = section.get("versionfile_source") + cfg.versionfile_build = section.get("versionfile_build") + cfg.tag_prefix = section.get("tag_prefix") + if cfg.tag_prefix in ("''", '""', None): cfg.tag_prefix = "" - cfg.parentdir_prefix = get(parser, "parentdir_prefix") - cfg.verbose = get(parser, "verbose") + cfg.parentdir_prefix = section.get("parentdir_prefix") + cfg.verbose = section.get("verbose") return cfg @@ -366,17 +367,15 @@ class NotThisMethod(Exception): # these dictionaries contain VCS-specific tools -LONG_VERSION_PY = {} -HANDLERS = {} +LONG_VERSION_PY: Dict[str, str] = {} +HANDLERS: Dict[str, Dict[str, Callable]] = {} def register_vcs_handler(vcs, method): # decorator - """Decorator to mark a method as the handler for a particular VCS.""" + """Create decorator to mark a method as the handler of a VCS.""" def decorate(f): """Store f in HANDLERS[vcs][method].""" - if vcs not in HANDLERS: - HANDLERS[vcs] = {} - HANDLERS[vcs][method] = f + HANDLERS.setdefault(vcs, {})[method] = f return f return decorate @@ -385,17 +384,25 @@ def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False, env=None): """Call the given command(s).""" assert isinstance(commands, list) - p = None - for c in commands: + process = None + + popen_kwargs = {} + if sys.platform == "win32": + # This hides the console window if pythonw.exe is used + startupinfo = subprocess.STARTUPINFO() + startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW + popen_kwargs["startupinfo"] = startupinfo + + for command in commands: try: - dispcmd = str([c] + args) + dispcmd = str([command] + args) # remember shell=False, so use git.cmd on windows, not just git - p = subprocess.Popen([c] + args, cwd=cwd, env=env, - stdout=subprocess.PIPE, - stderr=(subprocess.PIPE if hide_stderr - else None)) + process = subprocess.Popen([command] + args, cwd=cwd, env=env, + stdout=subprocess.PIPE, + stderr=(subprocess.PIPE if hide_stderr + else None), **popen_kwargs) break - except EnvironmentError: + except OSError: e = sys.exc_info()[1] if e.errno == errno.ENOENT: continue @@ -407,18 +414,16 @@ def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False, if verbose: print("unable to find command, tried %s" % (commands,)) return None, None - stdout = p.communicate()[0].strip() - if sys.version_info[0] >= 3: - stdout = stdout.decode() - if p.returncode != 0: + stdout = process.communicate()[0].strip().decode() + if process.returncode != 0: if verbose: print("unable to run %s (error)" % dispcmd) print("stdout was %s" % stdout) - return None, p.returncode - return stdout, p.returncode + return None, process.returncode + return stdout, process.returncode -LONG_VERSION_PY['git'] = ''' +LONG_VERSION_PY['git'] = r''' # This file helps to compute a version number in source trees obtained from # git-archive tarball (such as those provided by githubs download-from-tag # feature). Distribution tarballs (built by setup.py sdist) and build @@ -426,7 +431,7 @@ def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False, # that just contains the computed version number. # This file is released into the public domain. Generated by -# versioneer-0.18 (https://github.com/warner/python-versioneer) +# versioneer-0.23 (https://github.com/python-versioneer/python-versioneer) """Git implementation of _version.py.""" @@ -435,6 +440,8 @@ def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False, import re import subprocess import sys +from typing import Callable, Dict +import functools def get_keywords(): @@ -472,12 +479,12 @@ class NotThisMethod(Exception): """Exception raised if a method is not valid for the current scenario.""" -LONG_VERSION_PY = {} -HANDLERS = {} +LONG_VERSION_PY: Dict[str, str] = {} +HANDLERS: Dict[str, Dict[str, Callable]] = {} def register_vcs_handler(vcs, method): # decorator - """Decorator to mark a method as the handler for a particular VCS.""" + """Create decorator to mark a method as the handler of a VCS.""" def decorate(f): """Store f in HANDLERS[vcs][method].""" if vcs not in HANDLERS: @@ -491,17 +498,25 @@ def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False, env=None): """Call the given command(s).""" assert isinstance(commands, list) - p = None - for c in commands: + process = None + + popen_kwargs = {} + if sys.platform == "win32": + # This hides the console window if pythonw.exe is used + startupinfo = subprocess.STARTUPINFO() + startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW + popen_kwargs["startupinfo"] = startupinfo + + for command in commands: try: - dispcmd = str([c] + args) + dispcmd = str([command] + args) # remember shell=False, so use git.cmd on windows, not just git - p = subprocess.Popen([c] + args, cwd=cwd, env=env, - stdout=subprocess.PIPE, - stderr=(subprocess.PIPE if hide_stderr - else None)) + process = subprocess.Popen([command] + args, cwd=cwd, env=env, + stdout=subprocess.PIPE, + stderr=(subprocess.PIPE if hide_stderr + else None), **popen_kwargs) break - except EnvironmentError: + except OSError: e = sys.exc_info()[1] if e.errno == errno.ENOENT: continue @@ -513,15 +528,13 @@ def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False, if verbose: print("unable to find command, tried %%s" %% (commands,)) return None, None - stdout = p.communicate()[0].strip() - if sys.version_info[0] >= 3: - stdout = stdout.decode() - if p.returncode != 0: + stdout = process.communicate()[0].strip().decode() + if process.returncode != 0: if verbose: print("unable to run %%s (error)" %% dispcmd) print("stdout was %%s" %% stdout) - return None, p.returncode - return stdout, p.returncode + return None, process.returncode + return stdout, process.returncode def versions_from_parentdir(parentdir_prefix, root, verbose): @@ -533,15 +546,14 @@ def versions_from_parentdir(parentdir_prefix, root, verbose): """ rootdirs = [] - for i in range(3): + for _ in range(3): dirname = os.path.basename(root) if dirname.startswith(parentdir_prefix): return {"version": dirname[len(parentdir_prefix):], "full-revisionid": None, "dirty": False, "error": None, "date": None} - else: - rootdirs.append(root) - root = os.path.dirname(root) # up a level + rootdirs.append(root) + root = os.path.dirname(root) # up a level if verbose: print("Tried directories %%s but none started with prefix %%s" %% @@ -558,22 +570,21 @@ def git_get_keywords(versionfile_abs): # _version.py. keywords = {} try: - f = open(versionfile_abs, "r") - for line in f.readlines(): - if line.strip().startswith("git_refnames ="): - mo = re.search(r'=\s*"(.*)"', line) - if mo: - keywords["refnames"] = mo.group(1) - if line.strip().startswith("git_full ="): - mo = re.search(r'=\s*"(.*)"', line) - if mo: - keywords["full"] = mo.group(1) - if line.strip().startswith("git_date ="): - mo = re.search(r'=\s*"(.*)"', line) - if mo: - keywords["date"] = mo.group(1) - f.close() - except EnvironmentError: + with open(versionfile_abs, "r") as fobj: + for line in fobj: + if line.strip().startswith("git_refnames ="): + mo = re.search(r'=\s*"(.*)"', line) + if mo: + keywords["refnames"] = mo.group(1) + if line.strip().startswith("git_full ="): + mo = re.search(r'=\s*"(.*)"', line) + if mo: + keywords["full"] = mo.group(1) + if line.strip().startswith("git_date ="): + mo = re.search(r'=\s*"(.*)"', line) + if mo: + keywords["date"] = mo.group(1) + except OSError: pass return keywords @@ -581,10 +592,14 @@ def git_get_keywords(versionfile_abs): @register_vcs_handler("git", "keywords") def git_versions_from_keywords(keywords, tag_prefix, verbose): """Get version information from git keywords.""" - if not keywords: - raise NotThisMethod("no keywords at all, weird") + if "refnames" not in keywords: + raise NotThisMethod("Short version file found") date = keywords.get("date") if date is not None: + # Use only the last line. Previous lines may contain GPG signature + # information. + date = date.splitlines()[-1] + # git-2.2.0 added "%%cI", which expands to an ISO-8601 -compliant # datestamp. However we prefer "%%ci" (which expands to an "ISO-8601 # -like" string, which we must then edit to make compliant), because @@ -597,11 +612,11 @@ def git_versions_from_keywords(keywords, tag_prefix, verbose): if verbose: print("keywords are unexpanded, not using") raise NotThisMethod("unexpanded keywords, not a git-archive tarball") - refs = set([r.strip() for r in refnames.strip("()").split(",")]) + refs = {r.strip() for r in refnames.strip("()").split(",")} # starting in git-1.8.3, tags are listed as "tag: foo-1.0" instead of # just "foo-1.0". If we see a "tag: " prefix, prefer those. TAG = "tag: " - tags = set([r[len(TAG):] for r in refs if r.startswith(TAG)]) + tags = {r[len(TAG):] for r in refs if r.startswith(TAG)} if not tags: # Either we're using git < 1.8.3, or there really are no tags. We use # a heuristic: assume all version tags have a digit. The old git %%d @@ -610,7 +625,7 @@ def git_versions_from_keywords(keywords, tag_prefix, verbose): # between branches and tags. By ignoring refnames without digits, we # filter out many common branch names like "release" and # "stabilization", as well as "HEAD" and "master". - tags = set([r for r in refs if re.search(r'\d', r)]) + tags = {r for r in refs if re.search(r'\d', r)} if verbose: print("discarding '%%s', no digits" %% ",".join(refs - tags)) if verbose: @@ -619,6 +634,11 @@ def git_versions_from_keywords(keywords, tag_prefix, verbose): # sorting will prefer e.g. "2.0" over "2.0rc1" if ref.startswith(tag_prefix): r = ref[len(tag_prefix):] + # Filter out refs that exactly match prefix or that don't start + # with a number once the prefix is stripped (mostly a concern + # when prefix is '') + if not re.match(r'\d', r): + continue if verbose: print("picking %%s" %% r) return {"version": r, @@ -634,7 +654,7 @@ def git_versions_from_keywords(keywords, tag_prefix, verbose): @register_vcs_handler("git", "pieces_from_vcs") -def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command): +def git_pieces_from_vcs(tag_prefix, root, verbose, runner=run_command): """Get version from 'git describe' in the root of the source tree. This only gets called if the git-archive 'subst' keywords were *not* @@ -645,8 +665,15 @@ def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command): if sys.platform == "win32": GITS = ["git.cmd", "git.exe"] - out, rc = run_command(GITS, ["rev-parse", "--git-dir"], cwd=root, - hide_stderr=True) + # GIT_DIR can interfere with correct operation of Versioneer. + # It may be intended to be passed to the Versioneer-versioned project, + # but that should not change where we get our version from. + env = os.environ.copy() + env.pop("GIT_DIR", None) + runner = functools.partial(runner, env=env) + + _, rc = runner(GITS, ["rev-parse", "--git-dir"], cwd=root, + hide_stderr=True) if rc != 0: if verbose: print("Directory %%s not under git control" %% root) @@ -654,15 +681,15 @@ def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command): # if there is a tag matching tag_prefix, this yields TAG-NUM-gHEX[-dirty] # if there isn't one, this yields HEX[-dirty] (no NUM) - describe_out, rc = run_command(GITS, ["describe", "--tags", "--dirty", - "--always", "--long", - "--match", "%%s*" %% tag_prefix], - cwd=root) + describe_out, rc = runner(GITS, [ + "describe", "--tags", "--dirty", "--always", "--long", + "--match", f"{tag_prefix}[[:digit:]]*" + ], cwd=root) # --long was added in git-1.5.5 if describe_out is None: raise NotThisMethod("'git describe' failed") describe_out = describe_out.strip() - full_out, rc = run_command(GITS, ["rev-parse", "HEAD"], cwd=root) + full_out, rc = runner(GITS, ["rev-parse", "HEAD"], cwd=root) if full_out is None: raise NotThisMethod("'git rev-parse' failed") full_out = full_out.strip() @@ -672,6 +699,39 @@ def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command): pieces["short"] = full_out[:7] # maybe improved later pieces["error"] = None + branch_name, rc = runner(GITS, ["rev-parse", "--abbrev-ref", "HEAD"], + cwd=root) + # --abbrev-ref was added in git-1.6.3 + if rc != 0 or branch_name is None: + raise NotThisMethod("'git rev-parse --abbrev-ref' returned error") + branch_name = branch_name.strip() + + if branch_name == "HEAD": + # If we aren't exactly on a branch, pick a branch which represents + # the current commit. If all else fails, we are on a branchless + # commit. + branches, rc = runner(GITS, ["branch", "--contains"], cwd=root) + # --contains was added in git-1.5.4 + if rc != 0 or branches is None: + raise NotThisMethod("'git branch --contains' returned error") + branches = branches.split("\n") + + # Remove the first line if we're running detached + if "(" in branches[0]: + branches.pop(0) + + # Strip off the leading "* " from the list of branches. + branches = [branch[2:] for branch in branches] + if "master" in branches: + branch_name = "master" + elif not branches: + branch_name = None + else: + # Pick the first branch that is returned. Good or bad. + branch_name = branches[0] + + pieces["branch"] = branch_name + # parse describe_out. It will be like TAG-NUM-gHEX[-dirty] or HEX[-dirty] # TAG might have hyphens. git_describe = describe_out @@ -688,7 +748,7 @@ def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command): # TAG-NUM-gHEX mo = re.search(r'^(.+)-(\d+)-g([0-9a-f]+)$', git_describe) if not mo: - # unparseable. Maybe git-describe is misbehaving? + # unparsable. Maybe git-describe is misbehaving? pieces["error"] = ("unable to parse git-describe output: '%%s'" %% describe_out) return pieces @@ -713,13 +773,14 @@ def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command): else: # HEX: no tags pieces["closest-tag"] = None - count_out, rc = run_command(GITS, ["rev-list", "HEAD", "--count"], - cwd=root) - pieces["distance"] = int(count_out) # total number of commits + out, rc = runner(GITS, ["rev-list", "HEAD", "--left-right"], cwd=root) + pieces["distance"] = len(out.split()) # total number of commits # commit date: see ISO-8601 comment in git_versions_from_keywords() - date = run_command(GITS, ["show", "-s", "--format=%%ci", "HEAD"], - cwd=root)[0].strip() + date = runner(GITS, ["show", "-s", "--format=%%ci", "HEAD"], cwd=root)[0].strip() + # Use only the last line. Previous lines may contain GPG signature + # information. + date = date.splitlines()[-1] pieces["date"] = date.strip().replace(" ", "T", 1).replace(" ", "", 1) return pieces @@ -757,19 +818,67 @@ def render_pep440(pieces): return rendered -def render_pep440_pre(pieces): - """TAG[.post.devDISTANCE] -- No -dirty. +def render_pep440_branch(pieces): + """TAG[[.dev0]+DISTANCE.gHEX[.dirty]] . + + The ".dev0" means not master branch. Note that .dev0 sorts backwards + (a feature branch will appear "older" than the master branch). Exceptions: - 1: no tags. 0.post.devDISTANCE + 1: no tags. 0[.dev0]+untagged.DISTANCE.gHEX[.dirty] """ if pieces["closest-tag"]: rendered = pieces["closest-tag"] + if pieces["distance"] or pieces["dirty"]: + if pieces["branch"] != "master": + rendered += ".dev0" + rendered += plus_or_dot(pieces) + rendered += "%%d.g%%s" %% (pieces["distance"], pieces["short"]) + if pieces["dirty"]: + rendered += ".dirty" + else: + # exception #1 + rendered = "0" + if pieces["branch"] != "master": + rendered += ".dev0" + rendered += "+untagged.%%d.g%%s" %% (pieces["distance"], + pieces["short"]) + if pieces["dirty"]: + rendered += ".dirty" + return rendered + + +def pep440_split_post(ver): + """Split pep440 version string at the post-release segment. + + Returns the release segments before the post-release and the + post-release version number (or -1 if no post-release segment is present). + """ + vc = str.split(ver, ".post") + return vc[0], int(vc[1] or 0) if len(vc) == 2 else None + + +def render_pep440_pre(pieces): + """TAG[.postN.devDISTANCE] -- No -dirty. + + Exceptions: + 1: no tags. 0.post0.devDISTANCE + """ + if pieces["closest-tag"]: if pieces["distance"]: - rendered += ".post.dev%%d" %% pieces["distance"] + # update the post release segment + tag_version, post_version = pep440_split_post(pieces["closest-tag"]) + rendered = tag_version + if post_version is not None: + rendered += ".post%%d.dev%%d" %% (post_version + 1, pieces["distance"]) + else: + rendered += ".post0.dev%%d" %% (pieces["distance"]) + else: + # no commits, use the tag as the version + rendered = pieces["closest-tag"] else: # exception #1 - rendered = "0.post.dev%%d" %% pieces["distance"] + rendered = "0.post0.dev%%d" %% pieces["distance"] return rendered @@ -800,12 +909,41 @@ def render_pep440_post(pieces): return rendered +def render_pep440_post_branch(pieces): + """TAG[.postDISTANCE[.dev0]+gHEX[.dirty]] . + + The ".dev0" means not master branch. + + Exceptions: + 1: no tags. 0.postDISTANCE[.dev0]+gHEX[.dirty] + """ + if pieces["closest-tag"]: + rendered = pieces["closest-tag"] + if pieces["distance"] or pieces["dirty"]: + rendered += ".post%%d" %% pieces["distance"] + if pieces["branch"] != "master": + rendered += ".dev0" + rendered += plus_or_dot(pieces) + rendered += "g%%s" %% pieces["short"] + if pieces["dirty"]: + rendered += ".dirty" + else: + # exception #1 + rendered = "0.post%%d" %% pieces["distance"] + if pieces["branch"] != "master": + rendered += ".dev0" + rendered += "+g%%s" %% pieces["short"] + if pieces["dirty"]: + rendered += ".dirty" + return rendered + + def render_pep440_old(pieces): """TAG[.postDISTANCE[.dev0]] . The ".dev0" means dirty. - Eexceptions: + Exceptions: 1: no tags. 0.postDISTANCE[.dev0] """ if pieces["closest-tag"]: @@ -876,10 +1014,14 @@ def render(pieces, style): if style == "pep440": rendered = render_pep440(pieces) + elif style == "pep440-branch": + rendered = render_pep440_branch(pieces) elif style == "pep440-pre": rendered = render_pep440_pre(pieces) elif style == "pep440-post": rendered = render_pep440_post(pieces) + elif style == "pep440-post-branch": + rendered = render_pep440_post_branch(pieces) elif style == "pep440-old": rendered = render_pep440_old(pieces) elif style == "git-describe": @@ -915,7 +1057,7 @@ def get_versions(): # versionfile_source is the relative path from the top of the source # tree (where the .git directory might live) to this file. Invert # this to find the root from __file__. - for i in cfg.versionfile_source.split('/'): + for _ in cfg.versionfile_source.split('/'): root = os.path.dirname(root) except NameError: return {"version": "0+unknown", "full-revisionid": None, @@ -950,22 +1092,21 @@ def git_get_keywords(versionfile_abs): # _version.py. keywords = {} try: - f = open(versionfile_abs, "r") - for line in f.readlines(): - if line.strip().startswith("git_refnames ="): - mo = re.search(r'=\s*"(.*)"', line) - if mo: - keywords["refnames"] = mo.group(1) - if line.strip().startswith("git_full ="): - mo = re.search(r'=\s*"(.*)"', line) - if mo: - keywords["full"] = mo.group(1) - if line.strip().startswith("git_date ="): - mo = re.search(r'=\s*"(.*)"', line) - if mo: - keywords["date"] = mo.group(1) - f.close() - except EnvironmentError: + with open(versionfile_abs, "r") as fobj: + for line in fobj: + if line.strip().startswith("git_refnames ="): + mo = re.search(r'=\s*"(.*)"', line) + if mo: + keywords["refnames"] = mo.group(1) + if line.strip().startswith("git_full ="): + mo = re.search(r'=\s*"(.*)"', line) + if mo: + keywords["full"] = mo.group(1) + if line.strip().startswith("git_date ="): + mo = re.search(r'=\s*"(.*)"', line) + if mo: + keywords["date"] = mo.group(1) + except OSError: pass return keywords @@ -973,10 +1114,14 @@ def git_get_keywords(versionfile_abs): @register_vcs_handler("git", "keywords") def git_versions_from_keywords(keywords, tag_prefix, verbose): """Get version information from git keywords.""" - if not keywords: - raise NotThisMethod("no keywords at all, weird") + if "refnames" not in keywords: + raise NotThisMethod("Short version file found") date = keywords.get("date") if date is not None: + # Use only the last line. Previous lines may contain GPG signature + # information. + date = date.splitlines()[-1] + # git-2.2.0 added "%cI", which expands to an ISO-8601 -compliant # datestamp. However we prefer "%ci" (which expands to an "ISO-8601 # -like" string, which we must then edit to make compliant), because @@ -989,11 +1134,11 @@ def git_versions_from_keywords(keywords, tag_prefix, verbose): if verbose: print("keywords are unexpanded, not using") raise NotThisMethod("unexpanded keywords, not a git-archive tarball") - refs = set([r.strip() for r in refnames.strip("()").split(",")]) + refs = {r.strip() for r in refnames.strip("()").split(",")} # starting in git-1.8.3, tags are listed as "tag: foo-1.0" instead of # just "foo-1.0". If we see a "tag: " prefix, prefer those. TAG = "tag: " - tags = set([r[len(TAG):] for r in refs if r.startswith(TAG)]) + tags = {r[len(TAG):] for r in refs if r.startswith(TAG)} if not tags: # Either we're using git < 1.8.3, or there really are no tags. We use # a heuristic: assume all version tags have a digit. The old git %d @@ -1002,7 +1147,7 @@ def git_versions_from_keywords(keywords, tag_prefix, verbose): # between branches and tags. By ignoring refnames without digits, we # filter out many common branch names like "release" and # "stabilization", as well as "HEAD" and "master". - tags = set([r for r in refs if re.search(r'\d', r)]) + tags = {r for r in refs if re.search(r'\d', r)} if verbose: print("discarding '%s', no digits" % ",".join(refs - tags)) if verbose: @@ -1011,6 +1156,11 @@ def git_versions_from_keywords(keywords, tag_prefix, verbose): # sorting will prefer e.g. "2.0" over "2.0rc1" if ref.startswith(tag_prefix): r = ref[len(tag_prefix):] + # Filter out refs that exactly match prefix or that don't start + # with a number once the prefix is stripped (mostly a concern + # when prefix is '') + if not re.match(r'\d', r): + continue if verbose: print("picking %s" % r) return {"version": r, @@ -1026,7 +1176,7 @@ def git_versions_from_keywords(keywords, tag_prefix, verbose): @register_vcs_handler("git", "pieces_from_vcs") -def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command): +def git_pieces_from_vcs(tag_prefix, root, verbose, runner=run_command): """Get version from 'git describe' in the root of the source tree. This only gets called if the git-archive 'subst' keywords were *not* @@ -1037,8 +1187,15 @@ def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command): if sys.platform == "win32": GITS = ["git.cmd", "git.exe"] - out, rc = run_command(GITS, ["rev-parse", "--git-dir"], cwd=root, - hide_stderr=True) + # GIT_DIR can interfere with correct operation of Versioneer. + # It may be intended to be passed to the Versioneer-versioned project, + # but that should not change where we get our version from. + env = os.environ.copy() + env.pop("GIT_DIR", None) + runner = functools.partial(runner, env=env) + + _, rc = runner(GITS, ["rev-parse", "--git-dir"], cwd=root, + hide_stderr=True) if rc != 0: if verbose: print("Directory %s not under git control" % root) @@ -1046,15 +1203,15 @@ def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command): # if there is a tag matching tag_prefix, this yields TAG-NUM-gHEX[-dirty] # if there isn't one, this yields HEX[-dirty] (no NUM) - describe_out, rc = run_command(GITS, ["describe", "--tags", "--dirty", - "--always", "--long", - "--match", "%s*" % tag_prefix], - cwd=root) + describe_out, rc = runner(GITS, [ + "describe", "--tags", "--dirty", "--always", "--long", + "--match", f"{tag_prefix}[[:digit:]]*" + ], cwd=root) # --long was added in git-1.5.5 if describe_out is None: raise NotThisMethod("'git describe' failed") describe_out = describe_out.strip() - full_out, rc = run_command(GITS, ["rev-parse", "HEAD"], cwd=root) + full_out, rc = runner(GITS, ["rev-parse", "HEAD"], cwd=root) if full_out is None: raise NotThisMethod("'git rev-parse' failed") full_out = full_out.strip() @@ -1064,6 +1221,39 @@ def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command): pieces["short"] = full_out[:7] # maybe improved later pieces["error"] = None + branch_name, rc = runner(GITS, ["rev-parse", "--abbrev-ref", "HEAD"], + cwd=root) + # --abbrev-ref was added in git-1.6.3 + if rc != 0 or branch_name is None: + raise NotThisMethod("'git rev-parse --abbrev-ref' returned error") + branch_name = branch_name.strip() + + if branch_name == "HEAD": + # If we aren't exactly on a branch, pick a branch which represents + # the current commit. If all else fails, we are on a branchless + # commit. + branches, rc = runner(GITS, ["branch", "--contains"], cwd=root) + # --contains was added in git-1.5.4 + if rc != 0 or branches is None: + raise NotThisMethod("'git branch --contains' returned error") + branches = branches.split("\n") + + # Remove the first line if we're running detached + if "(" in branches[0]: + branches.pop(0) + + # Strip off the leading "* " from the list of branches. + branches = [branch[2:] for branch in branches] + if "master" in branches: + branch_name = "master" + elif not branches: + branch_name = None + else: + # Pick the first branch that is returned. Good or bad. + branch_name = branches[0] + + pieces["branch"] = branch_name + # parse describe_out. It will be like TAG-NUM-gHEX[-dirty] or HEX[-dirty] # TAG might have hyphens. git_describe = describe_out @@ -1080,7 +1270,7 @@ def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command): # TAG-NUM-gHEX mo = re.search(r'^(.+)-(\d+)-g([0-9a-f]+)$', git_describe) if not mo: - # unparseable. Maybe git-describe is misbehaving? + # unparsable. Maybe git-describe is misbehaving? pieces["error"] = ("unable to parse git-describe output: '%s'" % describe_out) return pieces @@ -1105,19 +1295,20 @@ def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command): else: # HEX: no tags pieces["closest-tag"] = None - count_out, rc = run_command(GITS, ["rev-list", "HEAD", "--count"], - cwd=root) - pieces["distance"] = int(count_out) # total number of commits + out, rc = runner(GITS, ["rev-list", "HEAD", "--left-right"], cwd=root) + pieces["distance"] = len(out.split()) # total number of commits # commit date: see ISO-8601 comment in git_versions_from_keywords() - date = run_command(GITS, ["show", "-s", "--format=%ci", "HEAD"], - cwd=root)[0].strip() + date = runner(GITS, ["show", "-s", "--format=%ci", "HEAD"], cwd=root)[0].strip() + # Use only the last line. Previous lines may contain GPG signature + # information. + date = date.splitlines()[-1] pieces["date"] = date.strip().replace(" ", "T", 1).replace(" ", "", 1) return pieces -def do_vcs_install(manifest_in, versionfile_source, ipy): +def do_vcs_install(versionfile_source, ipy): """Git-specific installation logic for Versioneer. For Git, this means creating/changing .gitattributes to mark _version.py @@ -1126,31 +1317,30 @@ def do_vcs_install(manifest_in, versionfile_source, ipy): GITS = ["git"] if sys.platform == "win32": GITS = ["git.cmd", "git.exe"] - files = [manifest_in, versionfile_source] + files = [versionfile_source] if ipy: files.append(ipy) try: - me = __file__ - if me.endswith(".pyc") or me.endswith(".pyo"): - me = os.path.splitext(me)[0] + ".py" - versioneer_file = os.path.relpath(me) + my_path = __file__ + if my_path.endswith(".pyc") or my_path.endswith(".pyo"): + my_path = os.path.splitext(my_path)[0] + ".py" + versioneer_file = os.path.relpath(my_path) except NameError: versioneer_file = "versioneer.py" files.append(versioneer_file) present = False try: - f = open(".gitattributes", "r") - for line in f.readlines(): - if line.strip().startswith(versionfile_source): - if "export-subst" in line.strip().split()[1:]: - present = True - f.close() - except EnvironmentError: + with open(".gitattributes", "r") as fobj: + for line in fobj: + if line.strip().startswith(versionfile_source): + if "export-subst" in line.strip().split()[1:]: + present = True + break + except OSError: pass if not present: - f = open(".gitattributes", "a+") - f.write("%s export-subst\n" % versionfile_source) - f.close() + with open(".gitattributes", "a+") as fobj: + fobj.write(f"{versionfile_source} export-subst\n") files.append(".gitattributes") run_command(GITS, ["add", "--"] + files) @@ -1164,15 +1354,14 @@ def versions_from_parentdir(parentdir_prefix, root, verbose): """ rootdirs = [] - for i in range(3): + for _ in range(3): dirname = os.path.basename(root) if dirname.startswith(parentdir_prefix): return {"version": dirname[len(parentdir_prefix):], "full-revisionid": None, "dirty": False, "error": None, "date": None} - else: - rootdirs.append(root) - root = os.path.dirname(root) # up a level + rootdirs.append(root) + root = os.path.dirname(root) # up a level if verbose: print("Tried directories %s but none started with prefix %s" % @@ -1181,7 +1370,7 @@ def versions_from_parentdir(parentdir_prefix, root, verbose): SHORT_VERSION_PY = """ -# This file was generated by 'versioneer.py' (0.18) from +# This file was generated by 'versioneer.py' (0.23) from # revision-control system data, or from the parent directory name of an # unpacked source archive. Distribution tarballs contain a pre-generated copy # of this file. @@ -1203,7 +1392,7 @@ def versions_from_file(filename): try: with open(filename) as f: contents = f.read() - except EnvironmentError: + except OSError: raise NotThisMethod("unable to read _version.py") mo = re.search(r"version_json = '''\n(.*)''' # END VERSION_JSON", contents, re.M | re.S) @@ -1258,19 +1447,67 @@ def render_pep440(pieces): return rendered -def render_pep440_pre(pieces): - """TAG[.post.devDISTANCE] -- No -dirty. +def render_pep440_branch(pieces): + """TAG[[.dev0]+DISTANCE.gHEX[.dirty]] . + + The ".dev0" means not master branch. Note that .dev0 sorts backwards + (a feature branch will appear "older" than the master branch). Exceptions: - 1: no tags. 0.post.devDISTANCE + 1: no tags. 0[.dev0]+untagged.DISTANCE.gHEX[.dirty] """ if pieces["closest-tag"]: rendered = pieces["closest-tag"] + if pieces["distance"] or pieces["dirty"]: + if pieces["branch"] != "master": + rendered += ".dev0" + rendered += plus_or_dot(pieces) + rendered += "%d.g%s" % (pieces["distance"], pieces["short"]) + if pieces["dirty"]: + rendered += ".dirty" + else: + # exception #1 + rendered = "0" + if pieces["branch"] != "master": + rendered += ".dev0" + rendered += "+untagged.%d.g%s" % (pieces["distance"], + pieces["short"]) + if pieces["dirty"]: + rendered += ".dirty" + return rendered + + +def pep440_split_post(ver): + """Split pep440 version string at the post-release segment. + + Returns the release segments before the post-release and the + post-release version number (or -1 if no post-release segment is present). + """ + vc = str.split(ver, ".post") + return vc[0], int(vc[1] or 0) if len(vc) == 2 else None + + +def render_pep440_pre(pieces): + """TAG[.postN.devDISTANCE] -- No -dirty. + + Exceptions: + 1: no tags. 0.post0.devDISTANCE + """ + if pieces["closest-tag"]: if pieces["distance"]: - rendered += ".post.dev%d" % pieces["distance"] + # update the post release segment + tag_version, post_version = pep440_split_post(pieces["closest-tag"]) + rendered = tag_version + if post_version is not None: + rendered += ".post%d.dev%d" % (post_version + 1, pieces["distance"]) + else: + rendered += ".post0.dev%d" % (pieces["distance"]) + else: + # no commits, use the tag as the version + rendered = pieces["closest-tag"] else: # exception #1 - rendered = "0.post.dev%d" % pieces["distance"] + rendered = "0.post0.dev%d" % pieces["distance"] return rendered @@ -1301,12 +1538,41 @@ def render_pep440_post(pieces): return rendered +def render_pep440_post_branch(pieces): + """TAG[.postDISTANCE[.dev0]+gHEX[.dirty]] . + + The ".dev0" means not master branch. + + Exceptions: + 1: no tags. 0.postDISTANCE[.dev0]+gHEX[.dirty] + """ + if pieces["closest-tag"]: + rendered = pieces["closest-tag"] + if pieces["distance"] or pieces["dirty"]: + rendered += ".post%d" % pieces["distance"] + if pieces["branch"] != "master": + rendered += ".dev0" + rendered += plus_or_dot(pieces) + rendered += "g%s" % pieces["short"] + if pieces["dirty"]: + rendered += ".dirty" + else: + # exception #1 + rendered = "0.post%d" % pieces["distance"] + if pieces["branch"] != "master": + rendered += ".dev0" + rendered += "+g%s" % pieces["short"] + if pieces["dirty"]: + rendered += ".dirty" + return rendered + + def render_pep440_old(pieces): """TAG[.postDISTANCE[.dev0]] . The ".dev0" means dirty. - Eexceptions: + Exceptions: 1: no tags. 0.postDISTANCE[.dev0] """ if pieces["closest-tag"]: @@ -1377,10 +1643,14 @@ def render(pieces, style): if style == "pep440": rendered = render_pep440(pieces) + elif style == "pep440-branch": + rendered = render_pep440_branch(pieces) elif style == "pep440-pre": rendered = render_pep440_pre(pieces) elif style == "pep440-post": rendered = render_pep440_post(pieces) + elif style == "pep440-post-branch": + rendered = render_pep440_post_branch(pieces) elif style == "pep440-old": rendered = render_pep440_old(pieces) elif style == "git-describe": @@ -1480,8 +1750,12 @@ def get_version(): return get_versions()["version"] -def get_cmdclass(): - """Get the custom setuptools/distutils subclasses used by Versioneer.""" +def get_cmdclass(cmdclass=None): + """Get the custom setuptools subclasses used by Versioneer. + + If the package uses a different cmdclass (e.g. one from numpy), it + should be provide as an argument. + """ if "versioneer" in sys.modules: del sys.modules["versioneer"] # this fixes the "python setup.py develop" case (also 'install' and @@ -1495,11 +1769,11 @@ def get_cmdclass(): # parent is protected against the child's "import versioneer". By # removing ourselves from sys.modules here, before the child build # happens, we protect the child from the parent's versioneer too. - # Also see https://github.com/warner/python-versioneer/issues/52 + # Also see https://github.com/python-versioneer/python-versioneer/issues/52 - cmds = {} + cmds = {} if cmdclass is None else cmdclass.copy() - # we add "version" to both distutils and setuptools + # we add "version" to setuptools from setuptools import Command class cmd_version(Command): @@ -1523,7 +1797,7 @@ def run(self): print(" error: %s" % vers["error"]) cmds["version"] = cmd_version - # we override "build_py" in both distutils and setuptools + # we override "build_py" in setuptools # # most invocation pathways end up running build_py: # distutils/build -> build_py @@ -1538,11 +1812,14 @@ def run(self): # then does setup.py bdist_wheel, or sometimes setup.py install # setup.py egg_info -> ? + # pip install -e . and setuptool/editable_wheel will invoke build_py + # but the build_py command is not expected to copy any files. + # we override different "build_py" commands for both environments - if "setuptools" in sys.modules: - from setuptools.command.build_py import build_py as _build_py + if 'build_py' in cmds: + _build_py = cmds['build_py'] else: - from distutils.command.build_py import build_py as _build_py + from setuptools.command.build_py import build_py as _build_py class cmd_build_py(_build_py): def run(self): @@ -1550,6 +1827,10 @@ def run(self): cfg = get_config_from_root(root) versions = get_versions() _build_py.run(self) + if getattr(self, "editable_mode", False): + # During editable installs `.py` and data files are + # not copied to build_lib + return # now locate _version.py in the new build/ directory and replace # it with an updated value if cfg.versionfile_build: @@ -1559,6 +1840,36 @@ def run(self): write_to_version_file(target_versionfile, versions) cmds["build_py"] = cmd_build_py + if 'build_ext' in cmds: + _build_ext = cmds['build_ext'] + else: + from setuptools.command.build_ext import build_ext as _build_ext + + class cmd_build_ext(_build_ext): + def run(self): + root = get_root() + cfg = get_config_from_root(root) + versions = get_versions() + _build_ext.run(self) + if self.inplace: + # build_ext --inplace will only build extensions in + # build/lib<..> dir with no _version.py to write to. + # As in place builds will already have a _version.py + # in the module dir, we do not need to write one. + return + # now locate _version.py in the new build/ directory and replace + # it with an updated value + target_versionfile = os.path.join(self.build_lib, + cfg.versionfile_build) + if not os.path.exists(target_versionfile): + print(f"Warning: {target_versionfile} does not exist, skipping " + "version update. This can happen if you are running build_ext " + "without first running build_py.") + return + print("UPDATING %s" % target_versionfile) + write_to_version_file(target_versionfile, versions) + cmds["build_ext"] = cmd_build_ext + if "cx_Freeze" in sys.modules: # cx_freeze enabled? from cx_Freeze.dist import build_exe as _build_exe # nczeczulin reports that py2exe won't like the pep440-style string @@ -1592,10 +1903,7 @@ def run(self): del cmds["build_py"] if 'py2exe' in sys.modules: # py2exe enabled? - try: - from py2exe.distutils_buildexe import py2exe as _py2exe # py3 - except ImportError: - from py2exe.build_exe import py2exe as _py2exe # py2 + from py2exe.distutils_buildexe import py2exe as _py2exe class cmd_py2exe(_py2exe): def run(self): @@ -1619,11 +1927,48 @@ def run(self): }) cmds["py2exe"] = cmd_py2exe + # sdist farms its file list building out to egg_info + if 'egg_info' in cmds: + _sdist = cmds['egg_info'] + else: + from setuptools.command.egg_info import egg_info as _egg_info + + class cmd_egg_info(_egg_info): + def find_sources(self): + # egg_info.find_sources builds the manifest list and writes it + # in one shot + super().find_sources() + + # Modify the filelist and normalize it + root = get_root() + cfg = get_config_from_root(root) + self.filelist.append('versioneer.py') + if cfg.versionfile_source: + # There are rare cases where versionfile_source might not be + # included by default, so we must be explicit + self.filelist.append(cfg.versionfile_source) + self.filelist.sort() + self.filelist.remove_duplicates() + + # The write method is hidden in the manifest_maker instance that + # generated the filelist and was thrown away + # We will instead replicate their final normalization (to unicode, + # and POSIX-style paths) + from setuptools import unicode_utils + normalized = [unicode_utils.filesys_decode(f).replace(os.sep, '/') + for f in self.filelist.files] + + manifest_filename = os.path.join(self.egg_info, 'SOURCES.txt') + with open(manifest_filename, 'w') as fobj: + fobj.write('\n'.join(normalized)) + + cmds['egg_info'] = cmd_egg_info + # we override different "sdist" commands for both environments - if "setuptools" in sys.modules: - from setuptools.command.sdist import sdist as _sdist + if 'sdist' in cmds: + _sdist = cmds['sdist'] else: - from distutils.command.sdist import sdist as _sdist + from setuptools.command.sdist import sdist as _sdist class cmd_sdist(_sdist): def run(self): @@ -1687,21 +2032,26 @@ def make_release_tree(self, base_dir, files): """ -INIT_PY_SNIPPET = """ +OLD_SNIPPET = """ from ._version import get_versions __version__ = get_versions()['version'] del get_versions """ +INIT_PY_SNIPPET = """ +from . import {0} +__version__ = {0}.get_versions()['version'] +""" + def do_setup(): - """Main VCS-independent setup function for installing Versioneer.""" + """Do main VCS-independent setup function for installing Versioneer.""" root = get_root() try: cfg = get_config_from_root(root) - except (EnvironmentError, configparser.NoSectionError, + except (OSError, configparser.NoSectionError, configparser.NoOptionError) as e: - if isinstance(e, (EnvironmentError, configparser.NoSectionError)): + if isinstance(e, (OSError, configparser.NoSectionError)): print("Adding sample versioneer config to setup.cfg", file=sys.stderr) with open(os.path.join(root, "setup.cfg"), "a") as f: @@ -1725,54 +2075,28 @@ def do_setup(): try: with open(ipy, "r") as f: old = f.read() - except EnvironmentError: + except OSError: old = "" - if INIT_PY_SNIPPET not in old: + module = os.path.splitext(os.path.basename(cfg.versionfile_source))[0] + snippet = INIT_PY_SNIPPET.format(module) + if OLD_SNIPPET in old: + print(" replacing boilerplate in %s" % ipy) + with open(ipy, "w") as f: + f.write(old.replace(OLD_SNIPPET, snippet)) + elif snippet not in old: print(" appending to %s" % ipy) with open(ipy, "a") as f: - f.write(INIT_PY_SNIPPET) + f.write(snippet) else: print(" %s unmodified" % ipy) else: print(" %s doesn't exist, ok" % ipy) ipy = None - # Make sure both the top-level "versioneer.py" and versionfile_source - # (PKG/_version.py, used by runtime code) are in MANIFEST.in, so - # they'll be copied into source distributions. Pip won't be able to - # install the package without this. - manifest_in = os.path.join(root, "MANIFEST.in") - simple_includes = set() - try: - with open(manifest_in, "r") as f: - for line in f: - if line.startswith("include "): - for include in line.split()[1:]: - simple_includes.add(include) - except EnvironmentError: - pass - # That doesn't cover everything MANIFEST.in can do - # (http://docs.python.org/2/distutils/sourcedist.html#commands), so - # it might give some false negatives. Appending redundant 'include' - # lines is safe, though. - if "versioneer.py" not in simple_includes: - print(" appending 'versioneer.py' to MANIFEST.in") - with open(manifest_in, "a") as f: - f.write("include versioneer.py\n") - else: - print(" 'versioneer.py' already in MANIFEST.in") - if cfg.versionfile_source not in simple_includes: - print(" appending versionfile_source ('%s') to MANIFEST.in" % - cfg.versionfile_source) - with open(manifest_in, "a") as f: - f.write("include %s\n" % cfg.versionfile_source) - else: - print(" versionfile_source already in MANIFEST.in") - # Make VCS-specific changes. For git, this means creating/changing # .gitattributes to mark _version.py for export-subst keyword # substitution. - do_vcs_install(manifest_in, cfg.versionfile_source, ipy) + do_vcs_install(cfg.versionfile_source, ipy) return 0 From f990facc5048379d7abb21614ce0aeff7a70a19f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Szczepanik?= Date: Tue, 30 Aug 2022 15:42:40 +0200 Subject: [PATCH 4/5] Remove accidentally introduced mentions of helloworld The merge of template updates accidentally kept the datalad_helloworld placeholder. This is rectified in this commit. --- MANIFEST.in | 2 +- docs/source/conf.py | 2 +- setup.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/MANIFEST.in b/MANIFEST.in index a83f85f..ba46c19 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,6 +1,6 @@ include CONTRIBUTORS LICENSE versioneer.py graft _datalad_buildsupport -graft datalad_helloworld +graft datalad_ebrains graft docs prune docs/build global-exclude *.py[cod] diff --git a/docs/source/conf.py b/docs/source/conf.py index cd7a084..cb1db17 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -40,7 +40,7 @@ try: subprocess.run( args=[setup_py_path, 'build_manpage', - '--cmdsuite', 'datalad_helloworld:command_suite', + '--cmdsuite', 'datalad_ebrains:command_suite', '--manpath', abspath(opj( dirname(setup_py_path), 'build', 'man')), '--rstpath', opj(dirname(__file__), 'generated', 'man'), diff --git a/setup.py b/setup.py index a534d6a..eb88887 100755 --- a/setup.py +++ b/setup.py @@ -12,7 +12,7 @@ cmdclass.update(build_manpage=BuildManPage) if __name__ == '__main__': - setup(name='datalad_helloworld', + setup(name='datalad_ebrains', version=versioneer.get_version(), cmdclass=cmdclass, ) From 01184373cbea1f167caf7e2ad83b2dae618a8aa6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Szczepanik?= Date: Tue, 30 Aug 2022 16:29:23 +0200 Subject: [PATCH 5/5] From datalad.tests import utils_pytest instead of utils Importing from `datalad.tests.utils` causes a failure when running tests in an environment without `nose` (e.g. appveyor in current setup), because `datalad.tests.utils` keep the `nose` dependency. In accordance with DataLad's CONTRIBUTING guide (section on moving to pytest), this import is now replaced with `datalad.tests.utils_pytest`. Note: The use of this particular import had been commented out. I am leaving the comment, although IMO the `ebrains_kg2ds` function looks a bit heavy for checking results just to see if the extension registers. --- datalad_ebrains/tests/test_register.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/datalad_ebrains/tests/test_register.py b/datalad_ebrains/tests/test_register.py index 60e9dc1..cc3c640 100644 --- a/datalad_ebrains/tests/test_register.py +++ b/datalad_ebrains/tests/test_register.py @@ -1,4 +1,4 @@ -from datalad.tests.utils import assert_result_count +from datalad.tests.utils_pytest import assert_result_count def test_register(): @@ -9,4 +9,3 @@ def test_register(): # da.ebrains_kg2ds(), # 1, # action='demo') -