diff --git a/.gitignore b/.gitignore index 3215c00..5b06af7 100644 --- a/.gitignore +++ b/.gitignore @@ -214,3 +214,7 @@ pip-log.txt #Mr Developer .mr.developer.cfg + +.vscode/ +.pytest_cache/ +__pycache__/ diff --git a/.travis.yml b/.travis.yml index c8c9d1b..7b3453e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,33 +1,10 @@ language: python python: - # We don't actually use the Travis Python, but this keeps it organized. - "2.7" - - "3.5" + - "3.6" install: - - sudo apt-get update - # We do this conditionally because it saves us some downloading if the - # version is the same. - - if [[ "$TRAVIS_PYTHON_VERSION" == "2.7" ]]; then - wget https://repo.continuum.io/miniconda/Miniconda-latest-Linux-x86_64.sh -O miniconda.sh; - else - wget https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda.sh; - fi - - bash miniconda.sh -b -p $HOME/miniconda - - export PATH="$HOME/miniconda/bin:$PATH" - - hash -r - - conda config --set always_yes yes --set changeps1 no - - conda update -q conda - # some required packages - - conda install conda-build jinja2 anaconda-client --quiet - # Useful for debugging any issues with conda - - conda info -a - - # Replace dep1 dep2 ... with your dependencies - - conda env create - - source activate numpy_indexed - + - pip install pipenv --upgrade + - pipenv install --dev --system --skip-lock script: - # Your test script goes here - - invoke test - - invoke build - - python setup.py sdist + - PYTHONPATH=. pytest + - python setup.py bdist_wheel diff --git a/LICENSE.md b/LICENSE.md deleted file mode 100644 index cb564da..0000000 --- a/LICENSE.md +++ /dev/null @@ -1,163 +0,0 @@ -GNU Lesser General Public License -================================= - -_Version 3, 29 June 2007_ -_Copyright © 2007 Free Software Foundation, Inc. <>_ - -Everyone is permitted to copy and distribute verbatim copies -of this license document, but changing it is not allowed. - - -This version of the GNU Lesser General Public License incorporates -the terms and conditions of version 3 of the GNU General Public -License, supplemented by the additional permissions listed below. - -### 0. Additional Definitions - -As used herein, “this License” refers to version 3 of the GNU Lesser -General Public License, and the “GNU GPL” refers to version 3 of the GNU -General Public License. - -“The Library” refers to a covered work governed by this License, -other than an Application or a Combined Work as defined below. - -An “Application” is any work that makes use of an interface provided -by the Library, but which is not otherwise based on the Library. -Defining a subclass of a class defined by the Library is deemed a mode -of using an interface provided by the Library. - -A “Combined Work” is a work produced by combining or linking an -Application with the Library. The particular version of the Library -with which the Combined Work was made is also called the “Linked -Version”. - -The “Minimal Corresponding Source” for a Combined Work means the -Corresponding Source for the Combined Work, excluding any source code -for portions of the Combined Work that, considered in isolation, are -based on the Application, and not on the Linked Version. - -The “Corresponding Application Code” for a Combined Work means the -object code and/or source code for the Application, including any data -and utility programs needed for reproducing the Combined Work from the -Application, but excluding the System Libraries of the Combined Work. - -### 1. Exception to Section 3 of the GNU GPL - -You may convey a covered work under sections 3 and 4 of this License -without being bound by section 3 of the GNU GPL. - -### 2. Conveying Modified Versions - -If you modify a copy of the Library, and, in your modifications, a -facility refers to a function or data to be supplied by an Application -that uses the facility (other than as an argument passed when the -facility is invoked), then you may convey a copy of the modified -version: - -* **a)** under this License, provided that you make a good faith effort to -ensure that, in the event an Application does not supply the -function or data, the facility still operates, and performs -whatever part of its purpose remains meaningful, or - -* **b)** under the GNU GPL, with none of the additional permissions of -this License applicable to that copy. - -### 3. Object Code Incorporating Material from Library Header Files - -The object code form of an Application may incorporate material from -a header file that is part of the Library. You may convey such object -code under terms of your choice, provided that, if the incorporated -material is not limited to numerical parameters, data structure -layouts and accessors, or small macros, inline functions and templates -(ten or fewer lines in length), you do both of the following: - -* **a)** Give prominent notice with each copy of the object code that the -Library is used in it and that the Library and its use are -covered by this License. -* **b)** Accompany the object code with a copy of the GNU GPL and this license -document. - -### 4. Combined Works - -You may convey a Combined Work under terms of your choice that, -taken together, effectively do not restrict modification of the -portions of the Library contained in the Combined Work and reverse -engineering for debugging such modifications, if you also do each of -the following: - -* **a)** Give prominent notice with each copy of the Combined Work that -the Library is used in it and that the Library and its use are -covered by this License. - -* **b)** Accompany the Combined Work with a copy of the GNU GPL and this license -document. - -* **c)** For a Combined Work that displays copyright notices during -execution, include the copyright notice for the Library among -these notices, as well as a reference directing the user to the -copies of the GNU GPL and this license document. - -* **d)** Do one of the following: - - **0)** Convey the Minimal Corresponding Source under the terms of this -License, and the Corresponding Application Code in a form -suitable for, and under terms that permit, the user to -recombine or relink the Application with a modified version of -the Linked Version to produce a modified Combined Work, in the -manner specified by section 6 of the GNU GPL for conveying -Corresponding Source. - - **1)** Use a suitable shared library mechanism for linking with the -Library. A suitable mechanism is one that **(a)** uses at run time -a copy of the Library already present on the user's computer -system, and **(b)** will operate properly with a modified version -of the Library that is interface-compatible with the Linked -Version. - -* **e)** Provide Installation Information, but only if you would otherwise -be required to provide such information under section 6 of the -GNU GPL, and only to the extent that such information is -necessary to install and execute a modified version of the -Combined Work produced by recombining or relinking the -Application with a modified version of the Linked Version. (If -you use option **4d0**, the Installation Information must accompany -the Minimal Corresponding Source and Corresponding Application -Code. If you use option **4d1**, you must provide the Installation -Information in the manner specified by section 6 of the GNU GPL -for conveying Corresponding Source.) - -### 5. Combined Libraries - -You may place library facilities that are a work based on the -Library side by side in a single library together with other library -facilities that are not Applications and are not covered by this -License, and convey such a combined library under terms of your -choice, if you do both of the following: - -* **a)** Accompany the combined library with a copy of the same work based -on the Library, uncombined with any other library facilities, -conveyed under the terms of this License. -* **b)** Give prominent notice with the combined library that part of it -is a work based on the Library, and explaining where to find the -accompanying uncombined form of the same work. - -### 6. Revised Versions of the GNU Lesser General Public License - -The Free Software Foundation may publish revised and/or new versions -of the GNU Lesser General Public License from time to time. Such new -versions will be similar in spirit to the present version, but may -differ in detail to address new problems or concerns. - -Each version is given a distinguishing version number. If the -Library as you received it specifies that a certain numbered version -of the GNU Lesser General Public License “or any later version” -applies to it, you have the option of following the terms and -conditions either of that published version or of any later version -published by the Free Software Foundation. If the Library as you -received it does not specify a version number of the GNU Lesser -General Public License, you may choose any version of the GNU Lesser -General Public License ever published by the Free Software Foundation. - -If the Library as you received it specifies that a proxy can decide -whether future versions of the GNU Lesser General Public License shall -apply, that proxy's public statement of acceptance of any version is -permanent authorization for you to choose that version for the -Library. diff --git a/MANIFEST.in b/MANIFEST.in deleted file mode 100644 index 5702991..0000000 --- a/MANIFEST.in +++ /dev/null @@ -1,3 +0,0 @@ -include pkg_conf.py -include environment.yml -recursive-include conda-recipe *.* diff --git a/Pipfile b/Pipfile new file mode 100644 index 0000000..31b5676 --- /dev/null +++ b/Pipfile @@ -0,0 +1,14 @@ +[[source]] +url = "https://pypi.python.org/simple" +verify_ssl = true +name = "pypi" + +[packages] +numpy = "*" +future = "*" + +[dev-packages] +pytest = "*" +matplotlib = "*" +wheel = "*" +setuptools = "*" diff --git a/Pipfile.lock b/Pipfile.lock new file mode 100644 index 0000000..d95baf0 --- /dev/null +++ b/Pipfile.lock @@ -0,0 +1,322 @@ +{ + "_meta": { + "hash": { + "sha256": "71215e0fcc8f75e02822415acaacb7e497ce441820a291699a1108bf13c8cdb2" + }, + "pipfile-spec": 6, + "requires": {}, + "sources": [ + { + "name": "pypi", + "url": "https://pypi.python.org/simple", + "verify_ssl": true + } + ] + }, + "default": { + "future": { + "hashes": [ + "sha256:e39ced1ab767b5936646cedba8bcce582398233d6a627067d4c6a454c90cfedb" + ], + "index": "pypi", + "version": "==0.16.0" + }, + "numpy": { + "hashes": [ + "sha256:0739146eaf4985962f07c62f7133aca89f3a600faac891ce6c7f3a1e2afe5272", + "sha256:07e21f14490324cc1160db101e9b6c1233c33985af4cb1d301dd02650fea1d7f", + "sha256:0f6a5ed0cd7ab1da11f5c07a8ecada73fc55a70ef7bb6311a4109891341d7277", + "sha256:0fd65cbbfdbf76bbf80c445d923b3accefea0fe2c2082049e0ce947c81fe1d3f", + "sha256:20cac3123d791e4bf8482a580d98d6b5969ba348b9d5364df791ba3a666b660d", + "sha256:528ce59ded2008f9e8543e0146acb3a98a9890da00adf8904b1e18c82099418b", + "sha256:56e392b7c738bd70e6f46cf48c8194d3d1dd4c5a59fae4b30c58bb6ef86e5233", + "sha256:675e0f23967ce71067d12b6944add505d5f0a251f819cfb44bdf8ee7072c090d", + "sha256:6be6b0ca705321c178c9858e5ad5611af664bbdfae1df1541f938a840a103888", + "sha256:719d914f564f35cce4dc103808f8297c807c9f0297ac183ed81ae8b5650e698e", + "sha256:768e777cc1ffdbf97c507f65975c8686ebafe0f3dc8925d02ac117acc4669ce9", + "sha256:7f76d406c6b998d6410198dcb82688dcdaec7d846aa87e263ccf52efdcfeba30", + "sha256:8c18ee4dddd5c6a811930c0a7c7947bf16387da3b394725f6063f1366311187d", + "sha256:99051e03b445117b26028623f1a487112ddf61a09a27e2d25e6bc07d37d94f25", + "sha256:a1413d06abfa942ca0553bf3bccaff5fdb36d55b84f2248e36228db871147dab", + "sha256:a7157c9ac6bddd2908c35ef099e4b643bc0e0ebb4d653deb54891d29258dd329", + "sha256:a958bf9d4834c72dee4f91a0476e7837b8a2966dc6fcfc42c421405f98d0da51", + "sha256:bb370120de6d26004358611441e07acda26840e41dfedc259d7f8cc613f96495", + "sha256:d0928076d9bd8a98de44e79b1abe50c1456e7abbb40af7ef58092086f1a6c729", + "sha256:d858423f5ed444d494b15c4cc90a206e1b8c31354c781ac7584da0d21c09c1c3", + "sha256:e6120d63b50e2248219f53302af7ec6fa2a42ed1f37e9cda2c76dbaca65036a7", + "sha256:f2b1378b63bdb581d5d7af2ec0373c8d40d651941d283a2afd7fc71184b3f570", + "sha256:facc6f925c3099ac01a1f03758100772560a0b020fb9d70f210404be08006bcb" + ], + "index": "pypi", + "version": "==1.14.2" + } + }, + "develop": { + "attrs": { + "hashes": [ + "sha256:1c7960ccfd6a005cd9f7ba884e6316b5e430a3f1a6c37c5f87d8b43f83b54ec9", + "sha256:a17a9573a6f475c99b551c0e0a812707ddda1ec9653bed04c13841404ed6f450" + ], + "version": "==17.4.0" + }, + "backcall": { + "hashes": [ + "sha256:38ecd85be2c1e78f77fd91700c76e14667dc21e2713b63876c0eb901196e01e4", + "sha256:bbbf4b1e5cd2bdb08f915895b51081c041bac22394fdfcfdfbe9f14b77c08bf2" + ], + "version": "==0.1.0" + }, + "colorama": { + "hashes": [ + "sha256:463f8483208e921368c9f306094eb6f725c6ca42b0f97e313cb5d5512459feda", + "sha256:48eb22f4f8461b1df5734a074b57042430fb06e1d61bd1e11b078c0fe6d7a1f1" + ], + "markers": "sys_platform == 'win32'", + "version": "==0.3.9" + }, + "cycler": { + "hashes": [ + "sha256:1d8a5ae1ff6c5cf9b93e8811e581232ad8920aeec647c37316ceac982b08cb2d", + "sha256:cd7b2d1018258d7247a71425e9f26463dfb444d411c39569972f4ce586b0c9d8" + ], + "version": "==0.10.0" + }, + "decorator": { + "hashes": [ + "sha256:2c51dff8ef3c447388fe5e4453d24a2bf128d3a4c32af3fabef1f01c6851ab82", + "sha256:c39efa13fbdeb4506c476c9b3babf6a718da943dab7811c206005a4a956c080c" + ], + "version": "==4.3.0" + }, + "ipdb": { + "hashes": [ + "sha256:7081c65ed7bfe7737f83fa4213ca8afd9617b42ff6b3f1daf9a3419839a2a00a" + ], + "index": "pypi", + "version": "==0.11" + }, + "ipython": { + "hashes": [ + "sha256:85882f97d75122ff8cdfe129215a408085a26039527110c8d4a2b8a5e45b7639", + "sha256:a6ac981381b3f5f604b37a293369963485200e3639fb0404fa76092383c10c41" + ], + "version": "==6.3.1" + }, + "ipython-genutils": { + "hashes": [ + "sha256:72dd37233799e619666c9f639a9da83c34013a73e8bbc79a7a6348d93c61fab8", + "sha256:eb2e116e75ecef9d4d228fdc66af54269afa26ab4463042e33785b887c628ba8" + ], + "version": "==0.2.0" + }, + "jedi": { + "hashes": [ + "sha256:1972f694c6bc66a2fac8718299e2ab73011d653a6d8059790c3476d2353b99ad", + "sha256:5861f6dc0c16e024cbb0044999f9cf8013b292c05f287df06d3d991a87a4eb89" + ], + "version": "==0.12.0" + }, + "kiwisolver": { + "hashes": [ + "sha256:0ee4ed8b3ae8f5f712b0aa9ebd2858b5b232f1b9a96b0943dceb34df2a223bc3", + "sha256:0f7f532f3c94e99545a29f4c3f05637f4d2713e7fd91b4dd8abfc18340b86cd5", + "sha256:1a078f5dd7e99317098f0e0d490257fd0349d79363e8c923d5bb76428f318421", + "sha256:1aa0b55a0eb1bd3fa82e704f44fb8f16e26702af1a073cc5030eea399e617b56", + "sha256:2874060b91e131ceeff00574b7c2140749c9355817a4ed498e82a4ffa308ecbc", + "sha256:379d97783ba8d2934d52221c833407f20ca287b36d949b4bba6c75274bcf6363", + "sha256:3b791ddf2aefc56382aadc26ea5b352e86a2921e4e85c31c1f770f527eb06ce4", + "sha256:4329008a167fac233e398e8a600d1b91539dc33c5a3eadee84c0d4b04d4494fa", + "sha256:45813e0873bbb679334a161b28cb9606d9665e70561fd6caa8863e279b5e464b", + "sha256:53a5b27e6b5717bdc0125338a822605084054c80f382051fb945d2c0e6899a20", + "sha256:66f82819ff47fa67a11540da96966fb9245504b7f496034f534b81cacf333861", + "sha256:79e5fe3ccd5144ae80777e12973027bd2f4f5e3ae8eb286cabe787bed9780138", + "sha256:8b6a7b596ce1d2a6d93c3562f1178ebd3b7bb445b3b0dd33b09f9255e312a965", + "sha256:9576cb63897fbfa69df60f994082c3f4b8e6adb49cccb60efb2a80a208e6f996", + "sha256:95a25d9f3449046ecbe9065be8f8380c03c56081bc5d41fe0fb964aaa30b2195", + "sha256:aaec1cfd94f4f3e9a25e144d5b0ed1eb8a9596ec36d7318a504d813412563a85", + "sha256:acb673eecbae089ea3be3dcf75bfe45fc8d4dcdc951e27d8691887963cf421c7", + "sha256:b15bc8d2c2848a4a7c04f76c9b3dc3561e95d4dabc6b4f24bfabe5fd81a0b14f", + "sha256:b1c240d565e977d80c0083404c01e4d59c5772c977fae2c483f100567f50847b", + "sha256:ce3be5d520b4d2c3e5eeb4cd2ef62b9b9ab8ac6b6fedbaa0e39cdb6f50644278", + "sha256:e0f910f84b35c36a3513b96d816e6442ae138862257ae18a0019d2fc67b041dc", + "sha256:ea36e19ac0a483eea239320aef0bd40702404ff8c7e42179a2d9d36c5afcb55c", + "sha256:f923406e6b32c86309261b8195e24e18b6a8801df0cfc7814ac44017bfcb3939" + ], + "version": "==1.0.1" + }, + "matplotlib": { + "hashes": [ + "sha256:07055eb872fa109bd88f599bdb52065704b2e22d475b67675f345d75d32038a0", + "sha256:0f2f253d6d51f5ed52a819921f8a0a8e054ce0daefcfbc2557e1c433f14dc77d", + "sha256:1ef9fd285334bd6b0495b6de9d56a39dc95081577f27bafabcf28e0d318bed31", + "sha256:3fb2db66ef98246bafc04b4ef4e9b0e73c6369f38a29716844e939d197df816a", + "sha256:3fd90b407d1ab0dae686a4200030ce305526ff20b85a443dc490d194114b2dfa", + "sha256:45dac8589ef1721d7f2ab0f48f986694494dfcc5d13a3e43a5cb6c816276094e", + "sha256:4bb10087e09629ba3f9b25b6c734fd3f99542f93d71c5b9c023f28cb377b43a9", + "sha256:4dc7ef528aad21f22be85e95725234c5178c0f938e2228ca76640e5e84d8cde8", + "sha256:4f6a516d5ef39128bb16af7457e73dde25c30625c4916d8fbd1cc7c14c55e691", + "sha256:70f0e407fbe9e97f16597223269c849597047421af5eb8b60dbaca0382037e78", + "sha256:7b3d03c876684618e2a2be6abeb8d3a033c3a1bb38a786f751199753ef6227e6", + "sha256:8944d311ce37bee1ba0e41a9b58dcf330ffe0cf29d7654c3d07c572215da68ac", + "sha256:8ff08eaa25c66383fe3b6c7eb288da3c22dcedc4b110a0b592b35f68d0e093b2", + "sha256:9d12378d6a236aa38326e27f3a29427b63edce4ce325745785aec1a7535b1f85", + "sha256:abfd3d9390eb4f2d82cbcaa3a5c2834c581329b64eccb7a071ed9d5df27424f7", + "sha256:bc4d7481f0e8ec94cb1afc4a59905d6274b3b4c389aba7a2539e071766671735", + "sha256:dc0ba2080fd0cfdd07b3458ee4324d35806733feb2b080838d7094731d3f73d9", + "sha256:f26fba7fc68994ab2805d77e0695417f9377a00d36ba4248b5d0f1e5adb08d24" + ], + "index": "pypi", + "version": "==2.2.2" + }, + "more-itertools": { + "hashes": [ + "sha256:0dd8f72eeab0d2c3bd489025bb2f6a1b8342f9b198f6fc37b52d15cfa4531fea", + "sha256:11a625025954c20145b37ff6309cd54e39ca94f72f6bb9576d1195db6fa2442e", + "sha256:c9ce7eccdcb901a2c75d326ea134e0886abfbea5f93e91cc95de9507c0816c44" + ], + "version": "==4.1.0" + }, + "numpy": { + "hashes": [ + "sha256:0739146eaf4985962f07c62f7133aca89f3a600faac891ce6c7f3a1e2afe5272", + "sha256:07e21f14490324cc1160db101e9b6c1233c33985af4cb1d301dd02650fea1d7f", + "sha256:0f6a5ed0cd7ab1da11f5c07a8ecada73fc55a70ef7bb6311a4109891341d7277", + "sha256:0fd65cbbfdbf76bbf80c445d923b3accefea0fe2c2082049e0ce947c81fe1d3f", + "sha256:20cac3123d791e4bf8482a580d98d6b5969ba348b9d5364df791ba3a666b660d", + "sha256:528ce59ded2008f9e8543e0146acb3a98a9890da00adf8904b1e18c82099418b", + "sha256:56e392b7c738bd70e6f46cf48c8194d3d1dd4c5a59fae4b30c58bb6ef86e5233", + "sha256:675e0f23967ce71067d12b6944add505d5f0a251f819cfb44bdf8ee7072c090d", + "sha256:6be6b0ca705321c178c9858e5ad5611af664bbdfae1df1541f938a840a103888", + "sha256:719d914f564f35cce4dc103808f8297c807c9f0297ac183ed81ae8b5650e698e", + "sha256:768e777cc1ffdbf97c507f65975c8686ebafe0f3dc8925d02ac117acc4669ce9", + "sha256:7f76d406c6b998d6410198dcb82688dcdaec7d846aa87e263ccf52efdcfeba30", + "sha256:8c18ee4dddd5c6a811930c0a7c7947bf16387da3b394725f6063f1366311187d", + "sha256:99051e03b445117b26028623f1a487112ddf61a09a27e2d25e6bc07d37d94f25", + "sha256:a1413d06abfa942ca0553bf3bccaff5fdb36d55b84f2248e36228db871147dab", + "sha256:a7157c9ac6bddd2908c35ef099e4b643bc0e0ebb4d653deb54891d29258dd329", + "sha256:a958bf9d4834c72dee4f91a0476e7837b8a2966dc6fcfc42c421405f98d0da51", + "sha256:bb370120de6d26004358611441e07acda26840e41dfedc259d7f8cc613f96495", + "sha256:d0928076d9bd8a98de44e79b1abe50c1456e7abbb40af7ef58092086f1a6c729", + "sha256:d858423f5ed444d494b15c4cc90a206e1b8c31354c781ac7584da0d21c09c1c3", + "sha256:e6120d63b50e2248219f53302af7ec6fa2a42ed1f37e9cda2c76dbaca65036a7", + "sha256:f2b1378b63bdb581d5d7af2ec0373c8d40d651941d283a2afd7fc71184b3f570", + "sha256:facc6f925c3099ac01a1f03758100772560a0b020fb9d70f210404be08006bcb" + ], + "index": "pypi", + "version": "==1.14.2" + }, + "parso": { + "hashes": [ + "sha256:62bd6bf7f04ab5c817704ff513ef175328676471bdef3629d4bdd46626f75551", + "sha256:a75a304d7090d2c67bd298091c14ef9d3d560e3c53de1c239617889f61d1d307" + ], + "version": "==0.2.0" + }, + "pickleshare": { + "hashes": [ + "sha256:84a9257227dfdd6fe1b4be1319096c20eb85ff1e82c7932f36efccfe1b09737b", + "sha256:c9a2541f25aeabc070f12f452e1f2a8eae2abd51e1cd19e8430402bdf4c1d8b5" + ], + "version": "==0.7.4" + }, + "pluggy": { + "hashes": [ + "sha256:7f8ae7f5bdf75671a718d2daf0a64b7885f74510bcd98b1a0bb420eb9a9d0cff", + "sha256:d345c8fe681115900d6da8d048ba67c25df42973bda370783cd58826442dcd7c", + "sha256:e160a7fcf25762bb60efc7e171d4497ff1d8d2d75a3d0df7a21b76821ecbf5c5" + ], + "version": "==0.6.0" + }, + "prompt-toolkit": { + "hashes": [ + "sha256:1df952620eccb399c53ebb359cc7d9a8d3a9538cb34c5a1344bdbeb29fbcc381", + "sha256:3f473ae040ddaa52b52f97f6b4a493cfa9f5920c255a12dc56a7d34397a398a4", + "sha256:858588f1983ca497f1cf4ffde01d978a3ea02b01c8a26a8bbc5cd2e66d816917" + ], + "version": "==1.0.15" + }, + "py": { + "hashes": [ + "sha256:29c9fab495d7528e80ba1e343b958684f4ace687327e6f789a94bf3d1915f881", + "sha256:983f77f3331356039fdd792e9220b7b8ee1aa6bd2b25f567a963ff1de5a64f6a" + ], + "version": "==1.5.3" + }, + "pygments": { + "hashes": [ + "sha256:78f3f434bcc5d6ee09020f92ba487f95ba50f1e3ef83ae96b9d5ffa1bab25c5d", + "sha256:dbae1046def0efb574852fab9e90209b23f556367b5a320c0bcb871c77c3e8cc" + ], + "version": "==2.2.0" + }, + "pyparsing": { + "hashes": [ + "sha256:0832bcf47acd283788593e7a0f542407bd9550a55a8a8435214a1960e04bcb04", + "sha256:281683241b25fe9b80ec9d66017485f6deff1af5cde372469134b56ca8447a07", + "sha256:8f1e18d3fd36c6795bb7e02a39fd05c611ffc2596c1e0d995d34d67630426c18", + "sha256:9e8143a3e15c13713506886badd96ca4b579a87fbdf49e550dbfc057d6cb218e", + "sha256:b8b3117ed9bdf45e14dcc89345ce638ec7e0e29b2b579fa1ecf32ce45ebac8a5", + "sha256:e4d45427c6e20a59bf4f88c639dcc03ce30d193112047f94012102f235853a58", + "sha256:fee43f17a9c4087e7ed1605bd6df994c6173c1e977d7ade7b651292fab2bd010" + ], + "version": "==2.2.0" + }, + "pytest": { + "hashes": [ + "sha256:6266f87ab64692112e5477eba395cfedda53b1933ccd29478e671e73b420c19c", + "sha256:fae491d1874f199537fd5872b5e1f0e74a009b979df9d53d1553fd03da1703e1" + ], + "index": "pypi", + "version": "==3.5.0" + }, + "python-dateutil": { + "hashes": [ + "sha256:3220490fb9741e2342e1cf29a503394fdac874bc39568288717ee67047ff29df", + "sha256:9d8074be4c993fbe4947878ce593052f71dac82932a677d49194d8ce9778002e" + ], + "version": "==2.7.2" + }, + "pytz": { + "hashes": [ + "sha256:65ae0c8101309c45772196b21b74c46b2e5d11b6275c45d251b150d5da334555", + "sha256:c06425302f2cf668f1bba7a0a03f3c1d34d4ebeef2c72003da308b3947c7f749" + ], + "version": "==2018.4" + }, + "simplegeneric": { + "hashes": [ + "sha256:dc972e06094b9af5b855b3df4a646395e43d1c9d0d39ed345b7393560d0b9173" + ], + "version": "==0.8.1" + }, + "six": { + "hashes": [ + "sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9", + "sha256:832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb" + ], + "version": "==1.11.0" + }, + "traitlets": { + "hashes": [ + "sha256:9c4bd2d267b7153df9152698efb1050a5d84982d3384a37b2c1f7723ba3e7835", + "sha256:c6cb5e6f57c5a9bdaa40fa71ce7b4af30298fbab9ece9815b5d995ab6217c7d9" + ], + "version": "==4.3.2" + }, + "wcwidth": { + "hashes": [ + "sha256:3df37372226d6e63e1b1e1eda15c594bca98a22d33a23832a90998faa96bc65e", + "sha256:f4ebe71925af7b40a864553f761ed559b43544f8f71746c2d756c7fe788ade7c" + ], + "version": "==0.1.7" + }, + "wheel": { + "hashes": [ + "sha256:1ae8153bed701cb062913b72429bcf854ba824f973735427681882a688cb55ce", + "sha256:9cdc8ab2cc9c3c2e2727a4b67c22881dbb0e1c503d592992594c5e131c867107" + ], + "index": "pypi", + "version": "==0.31.0" + } + } +} diff --git a/README.rst b/README.rst index dba8ea0..72ff708 100644 --- a/README.rst +++ b/README.rst @@ -3,9 +3,7 @@ Numpy indexed operations ======================== -This package contains functionality for indexed operations on numpy -ndarrays, providing efficient vectorized functionality such as grouping -and set operations. +This package contains functionality for indexed operations on numpy ndarrays, providing efficient vectorized functionality such as grouping and set operations. * Rich and efficient grouping functionality: diff --git a/appveyor.yml b/appveyor.yml index d16f68b..bae4e91 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,66 +1,14 @@ -# http://www.appveyor.com/docs/appveyor-yml -os: unstable # Windows Server 2012 -# https://www.appveyor.com/blog/2014/06/04/shallow-clone-for-git-repositories -shallow_clone: true -# Just being explicit and useful if we ever want to refer to it -clone_folder: C:\projects\numpy_indexed - environment: matrix: - # Pre-installed Python versions, which Appveyor may upgrade to a later point release. - # See: http://www.appveyor.com/docs/installed-software#python - - PYTHON: C:\Miniconda-x64 - CONDA_PY: 27 - CONDA_NPY: 110 - - - PYTHON: C:\Miniconda35-x64 - CONDA_PY: 35 - CONDA_NPY: 110 - + - PYTHON: "C:\\Python27-x64" + - PYTHON: "C:\\Python36-x64" platform: - x64 - -# Makes AppVeyor give up all builds as soon as any of the builds fails -matrix: - fast_finish: false - -init: - - ps: iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1')) - install: - # By default, all script lines are interpreter as batch - - set PATH=%PYTHON%;%PYTHON%\Scripts;%SystemRoot%\system32;%SystemRoot%;%SystemRoot%\System32\Wbem; - - set PATH=%PATH%;%SYSTEMROOT%\System32\WindowsPowerShell\v1.0\;C:\Program Files\Mercurial; - - set PATH=%PATH%;C:\Program Files\7-Zip;C:\Program Files\AppVeyor\BuildAgent - - # Check that we have the expected version and architecture (x64) for Python - - "python --version" - - "python -c \"import struct; print(struct.calcsize('P') * 8)\"" - - # Set up our environment - - conda update conda --yes --quiet - # show_channel_urls: http://conda.pydata.org/docs/config.html#show-channel-urls-show-channel-urls - # always_yes: http://conda.pydata.org/docs/config.html#always-yes-always-yes - - conda config --set show_channel_urls True --set always_yes True - - # Install the necessary packages - - conda install conda-build jinja2 anaconda-client --quiet - # Show us the conda configuration we have right now - - conda info -a - # If this needs any private packages, we'll have to be more creative - - conda env create --force --quiet - -# See https://github.com/scikit-learn/scikit-learn/blob/master/appveyor.yml for inspiration + - set PATH=%PYTHON%;%PYTHON%\Scripts;%PATH% + - pip install pipenv --upgrade + - pipenv install --dev --system --skip-lock build_script: - # There are so many dependencies for the invoke commands that it's easier to use the environment - - activate numpy_indexed - - invoke test - # build conda package; no upload - - invoke build - # build egg - - python setup.py sdist - -skip_commits: - # skip commits when creating new branches, closing branches, also see https://www.appveyor.com/docs/how-to/skip-build - # case-insensitive regex flag is not processed!! - message: /([Cc]reated?( new)?|[Cc]losed?) branch.*/ + - set PYTHONPATH=. + - pytest + - python setup.py bdist_wheel diff --git a/conda-recipe/bld.bat b/conda-recipe/bld.bat deleted file mode 100644 index fb9a835..0000000 --- a/conda-recipe/bld.bat +++ /dev/null @@ -1,8 +0,0 @@ -"%PYTHON%" setup.py install -if errorlevel 1 exit 1 - -:: Add more build steps here, if they are necessary. - -:: See -:: http://docs.continuum.io/conda/build.html -:: for a list of environment variables that are set during the build process. \ No newline at end of file diff --git a/conda-recipe/build.sh b/conda-recipe/build.sh deleted file mode 100644 index 4d7fc03..0000000 --- a/conda-recipe/build.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash - -$PYTHON setup.py install - -# Add more build steps here, if they are necessary. - -# See -# http://docs.continuum.io/conda/build.html -# for a list of environment variables that are set during the build process. diff --git a/conda-recipe/meta.yaml b/conda-recipe/meta.yaml index 13bb0b6..bdead3f 100644 --- a/conda-recipe/meta.yaml +++ b/conda-recipe/meta.yaml @@ -1,31 +1,23 @@ -about: - home: https://github.com/EelcoHoogendoorn/Numpy_arraysetops_EP - license: Freely Distributable - summary: Numpy extensions for set operations on nd-arrays, group_by operations, - and related functionality -build: - noarch_python: true - number: 1 package: name: numpy-indexed - version: 0.3.4 + version: 0.3.5 +source: + path: .. +build: + noarch: python + script: python setup.py install --single-version-externally-managed --record=record.txt + number: 0 requirements: build: - python - - numpy - - pyyaml 3.11* - - future 0.15* - - invoke 0.12* run: - python - numpy - future -source: - path: .. test: - commands: - - py.test --pyargs numpy_indexed imports: - numpy_indexed - requires: - - pytest +about: + home: https://github.com/EelcoHoogendoorn/Numpy_arraysetops_EP + license: Freely Distributable + summary: This package contains functionality for indexed operations on numpy ndarrays, providing efficient vectorized functionality such as grouping and set operations. diff --git a/environment.yml b/environment.yml deleted file mode 100644 index caf9312..0000000 --- a/environment.yml +++ /dev/null @@ -1,13 +0,0 @@ -name: numpy_indexed -channels: - - anaconda - - clinicalgraphics -dependencies: - - python - - numpy - - future - # dev - - pyyaml =3.11* - - invoke =0.12* - # tests - - pytest diff --git a/numpy_indexed/examples.py b/examples.py similarity index 100% rename from numpy_indexed/examples.py rename to examples.py diff --git a/numpy_indexed/__init__.py b/numpy_indexed/__init__.py index 68f819c..a6fc30b 100644 --- a/numpy_indexed/__init__.py +++ b/numpy_indexed/__init__.py @@ -14,4 +14,4 @@ pkg_dir = os.path.abspath(os.path.dirname(__file__)) -__version__ = '0.3.4' +__version__ = '0.3.5' diff --git a/numpy_indexed/tests/__init__.py b/numpy_indexed/tests/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/numpy_indexed/tests/test_numpy.py b/numpy_indexed/tests/test_numpy.py deleted file mode 100644 index 165df6a..0000000 --- a/numpy_indexed/tests/test_numpy.py +++ /dev/null @@ -1,71 +0,0 @@ -"""monkey-patch the numpy tests, and see if they still run with their native function replaced -with their equivalents from this package""" - -from __future__ import absolute_import, division, print_function, unicode_literals -from builtins import * - -import os -import numpy -import numpy_indexed -import unittest - - -__author__ = "Eelco Hoogendoorn" -__license__ = "LGPL" -__email__ = "hoogendoorn.eelco@gmail.com" - - -def load_numpy_tests(): - # load numpy arraysetops testing module from the installed numpy distro - numpy_path = os.path.split(numpy.__file__)[0] - module_source = os.path.join(numpy_path, 'lib', 'tests', 'test_arraysetops.py') - module_name = 'numpy_indexed.tests.numpy_tests' - try: - import importlib.util - spec = importlib.util.spec_from_file_location(module_name, module_source) - numpy_tests = importlib.util.module_from_spec(spec) - spec.loader.exec_module(numpy_tests) - except: - import imp - numpy_tests = imp.load_source(module_name, module_source) - return numpy_tests - - -def monkey_patch_tests(numpy_tests): - """ - monkey-patch the numpy tests of: - intersect1d, setxor1d, union1d, setdiff1d, unique, in1d - """ - numpy_tests.intersect1d = numpy_indexed.intersection - - numpy_tests.setxor1d = numpy_indexed.exclusive - - numpy_tests.union1d = numpy_indexed.union - - numpy_tests.setdiff1d = numpy_indexed.difference - - # make sure this is called with axis=0 - def unique(ar, return_index=False, return_inverse=False, return_counts=False): - return numpy_indexed.unique(ar, None, return_index, return_inverse, return_counts) - numpy_tests.unique = unique - - # add silly invert keyword - def in1d(ar1, ar2, assume_unique=False, invert=False): - ret = numpy_indexed.contains(ar2, ar1, axis=None) - return numpy.invert(ret) if invert else ret - - numpy_tests.in1d = in1d - - -def run_tests(numpy_tests): - # run the suite - suite = unittest.TestLoader().loadTestsFromTestCase(numpy_tests.TestSetOps) - unittest.TextTestRunner(verbosity=3).run(suite) - - -class TestNumpy(unittest.TestCase): - def runTest(self): - numpy_tests = load_numpy_tests() - run_tests(numpy_tests) - monkey_patch_tests(numpy_tests) - run_tests(numpy_tests) diff --git a/pkg_conf.py b/pkg_conf.py deleted file mode 100644 index 081fc8d..0000000 --- a/pkg_conf.py +++ /dev/null @@ -1,59 +0,0 @@ -import os -import yaml - -######################### -# Customizable settings # -######################### - -AUTHOR = 'Eelco Hoogendoorn' -AUTHOR_EMAIL = 'hoogendoorn.eelco@gmail.com' -DOC_ROOT = 'docs' -ANACONDA_USER = 'EelcoHoogendoorn' -PKG_ROOT = 'numpy_indexed' -PKG_NAME = 'numpy-indexed' -DATA_FILES = ["*.npz", "*.json"] - -################################ -# End of customizable settings # -################################ - -ABS_REPO_ROOT = os.path.dirname(os.path.realpath(__file__)) -_cache = dict() - - -def get_channels(): - with open(os.path.join(ABS_REPO_ROOT, 'environment.yml'), "r") as infile: - environment = yaml.load(infile) - return environment['channels'] - - -def get_recipe_meta(): - global _cache - if 'recipe_meta' not in _cache: - with open(os.path.join(ABS_REPO_ROOT, 'conda-recipe', 'meta.yaml'), "r") as infile: - _cache['recipe_meta'] = yaml.load(infile) - return _cache['recipe_meta'] - - -def get_version(): - global _cache - if 'version' not in _cache: - with open(os.path.join(ABS_REPO_ROOT, PKG_ROOT, '__init__.py')) as fid: - for line in fid: - if line.startswith('__version__'): - _cache['version'] = line.strip().split()[-1][1:-1] - break - return _cache['version'] - - -def get_readme_rst(): - with open(os.path.join(ABS_REPO_ROOT, 'README.rst'), "r") as infile: - return infile.read() - - -def get_build_number(): - return get_recipe_meta()["build"]["number"] - - -def get_url(): - return get_recipe_meta()["about"]["home"] diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..3c6e79c --- /dev/null +++ b/setup.cfg @@ -0,0 +1,2 @@ +[bdist_wheel] +universal=1 diff --git a/setup.py b/setup.py index 0f57977..34bb91c 100644 --- a/setup.py +++ b/setup.py @@ -1,29 +1,29 @@ -from setuptools import find_packages -from distutils.core import setup +from setuptools import find_packages, setup -import pkg_conf + +from version import __version__ setup( - keywords = "numpy group_by set-operations indexing", - name=pkg_conf.PKG_NAME, - version=pkg_conf.get_version(), + name="numpy-indexed", packages=find_packages(), - install_requires=['pyyaml', 'future'], - description=pkg_conf.get_recipe_meta()['about']['summary'], - long_description=pkg_conf.get_readme_rst(), - author=pkg_conf.AUTHOR, - author_email=pkg_conf.AUTHOR_EMAIL, - url=pkg_conf.get_recipe_meta()['about']['home'], - license=pkg_conf.get_recipe_meta()['about']['license'], - platforms='any', + version=__version__, + install_requires=['numpy', 'future'], + keywords="numpy group_by set-operations indexing", + description=open("README.rst").readlines()[5], + long_description=open("README.rst").read(), + author="Eelco Hoogendoorn", + author_email="hoogendoorn.eelco@gmail.com", + url="https://github.com/EelcoHoogendoorn/Numpy_arraysetops_EP", + license="Freely Distributable", + platforms='Any', classifiers=[ "Development Status :: 4 - Beta", 'Intended Audience :: Science/Research', 'Intended Audience :: Developers', "Topic :: Utilities", 'Topic :: Scientific/Engineering', - 'License :: {}'.format(pkg_conf.get_recipe_meta()['about']['license']), + "License :: {}".format("Freely Distributable"), 'Operating System :: MacOS :: MacOS X', 'Operating System :: Microsoft :: Windows', 'Operating System :: POSIX', @@ -31,4 +31,4 @@ 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3.5', ], -) \ No newline at end of file +) diff --git a/tasks.py b/tasks.py deleted file mode 100644 index 45bbdfd..0000000 --- a/tasks.py +++ /dev/null @@ -1,340 +0,0 @@ -# from __future__ import absolute_import, division, print_function, unicode_literals -from builtins import * - -import os -import shutil -import traceback -import subprocess -import pkg_conf -import sys -import yaml - -from invoke import task, run - - -__author__ = "Ivo Flipse, Eelco Hoogendoorn" -__license__ = "LGPL" -__email__ = "hoogendoorn.eelco@gmail.com" - - -# variables used to build documentation and package according to OS -on_win32 = sys.platform.startswith("win") -on_linux = sys.platform.startswith("linux") -on_osx = sys.platform.startswith("darwin") - - -def _print(message): - print("[INVOKE] {}".format(message)) - - -def _exit(message): - sys.exit("[INVOKE QUITTING] {}".format(message)) - - -def _confirm(prompt='Are you sure?', error='Cancelled.'): - """ - Prompt the user to confirm. - """ - response = input("{} Type 'y' and hit enter to continue. Anything else will cancel.\n".format(prompt)).lower() - - if str(response) != r"y": - _exit(error) - - return True - - -@task -def build(): - """ - Builds the conda package - """ - _print("Building your package now") - - sep = ' && ' - # add all required channels - channels = sep.join('conda config --add channels ' + c for c in pkg_conf.get_channels()) - command = channels + sep + "conda build conda-recipe --no-anaconda-upload --quiet" - if on_win32: - run("deactivate" + sep + command) - elif on_linux: - run("source deactivate" + sep + command, pty=True) - else: - raise NotImplementedError("Building is not supported for this OS") - - -@task -def test(): - """ - Runs the test suite - """ - run("py.test") - - -@task -def lint(): - """ - Lints the source code - """ - run("flake8 --config=flake8.cfg {}".format(pkg_conf.PKG_ROOT)) - # make sure this command is run regularly as well - _environment_and_recipe_consistency() - - -# @task -# def changelog(): -# # TODO: update changelog -# pass - - -def _browse(url): - if on_win32: - run('explorer "{}"'.format(url), hide='stdout') - elif on_linux: - run('xdg-open "{}"'.format(url), hide='stdout') - else: - raise NotImplementedError("Browsing is not supported for this OS") - - -def _environment_and_recipe_consistency(): - """Notify if environment.yml and meta.yml appear to be inconsistent""" - # get recipe yaml - recipe = pkg_conf.get_recipe_meta() - # custom loading of environment.yml - with open(os.path.join(pkg_conf.ABS_REPO_ROOT, 'environment.yml'), "r") as infile: - environment = infile.read() - environment = yaml.load(environment.split('# dev')[0]) # only take the first part of environment file - - reformatted_environment_lines = [] - msg = "dependency '{}' does not appear to be present as such in recipe: requirements: {}:" - for line in environment['dependencies']: - # note; conda build and conda env have subtly different syntax for pinning to a fixed version - reformat_line = line.replace(' =', ' ') - reformatted_environment_lines.append(reformat_line) - if reformat_line not in recipe['requirements']['build']: - _exit(msg.format(line, 'build')) - if reformat_line not in recipe['requirements']['run']: - _exit(msg.format(line, 'run')) - - msg = "{} requirement '{}' does not appear to be present as such in environment file" - for line in recipe['requirements']['run']: - if line not in reformatted_environment_lines: - _exit(msg.format('run', line)) - - -@task(help={'quiet': "Do not open documentation index in browser after building."}) -def docs(quiet=False, clean=False): - """ - Build the documentation. - """ - if not os.path.exists(pkg_conf.DOC_ROOT): - _exit("Documentation root doesn't exist.") - - source_path = os.path.join(pkg_conf.DOC_ROOT, 'source') - build_path = os.path.join(pkg_conf.DOC_ROOT, 'build') - - if clean and os.path.exists(build_path): - _print("Clearing build directory.") - shutil.rmtree(build_path) - - run("sphinx-build -q {} {}".format(source_path, build_path)) - - if not quiet: - _browse("file:///{}/{}/build/index.html".format(os.path.dirname(os.path.realpath(__file__)).replace("\\", "/"), - pkg_conf.DOC_ROOT)) - - -def _get_hg_info(): - """ - Checks if the current directory is under hg version control - - Returns current revision id if current directory is under hg version control, False if not. - """ - id = subprocess.check_output("hg identify --id").strip() - branch = subprocess.check_output("hg branch").strip() - return { - 'branch': branch, - 'id': id, - "dirty": "+" in id, - "default": "default" in branch - } - - -def _get_git_info(): - id = str(subprocess.check_output("git status").strip()) - branch = str(subprocess.check_output("git branch").strip()) - return { - 'branch': branch, - 'id': id, - "dirty": "modified" in id, - "default": "master" in branch - } - - -def _assert_version_ok(): - info = _get_git_info() - if info['dirty']: - _exit("working directory is not clean, release cancelled") - if not info['default']: - _exit("not on default branch, release cancelled") - - -def _assert_release_ok(): - _assert_version_ok() - - current_version = pkg_conf.get_version() - - if 'dev' in current_version: - _exit("dev version detected, release cancelled") - - -def _update_version(new_version_number, build_number): - """ - Updates the version of the package and the conda recipe - """ - # package - with open("{}/__init__.py".format(pkg_conf.PKG_ROOT), "r") as infile: - init_content = infile.readlines() - - version_line = [line.startswith('__version__ = ') for line in init_content].index(True) - init_content[version_line] = "__version__ = '{}'".format(new_version_number) + '\n' - - # Now we write it back to the file - with open("{}/__init__.py".format(pkg_conf.PKG_ROOT), "w") as outfile: - outfile.writelines(init_content) - - # conda recipe - with open("conda-recipe/meta.yaml", "r") as infile: - recipe_meta = yaml.load(infile) - - recipe_meta["package"]["version"] = new_version_number - recipe_meta["build"]["number"] = build_number - - with open("conda-recipe/meta.yaml", "w") as outfile: - outfile.write(yaml.safe_dump(recipe_meta, default_flow_style=False, allow_unicode=True)) - - _print("Updated the version number to {}".format(new_version_number)) - - -@task(name='version', - help={ - "major": "Bump the major version number, e.g. from 0.0.0 to 1.0.0. Use it when you introduce breaking changes.", - "minor": "Bump the minor version number, e.g. from 0.0.0 to 0.1.0. Use it when you introduce new features, and maintain backwards compatibility.", - "patch": "Bump the patch version number, e.g. from 0.0.0 to 0.0.1. Use it when you only release bugfixes, and maintain backwards compatibility.", - "release": "Leave out the dev label from the version number to indicate that this is a production release, e.g. from 0.0.dev0 to 0.0.0."}) -def update_version(major=False, minor=False, patch=False, release=False): - """ - Bump the version of the package - """ - _assert_version_ok() - - current_version = pkg_conf.get_version() - current_build_number = pkg_conf.get_build_number() - _print("Current version {}".format(current_version)) - _print("Current build number {}".format(current_build_number)) - - # We strip out .dev if present, so we can parse the version number itself - major_number, minor_number, patch_number = current_version.replace("dev", "").split(".") - build_number = current_build_number - - if major: - major_number = int(major_number) + 1 - minor_number = 0 - patch_number = 0 - build_number = 0 - elif minor: - minor_number = int(minor_number) + 1 - patch_number = 0 - build_number = 0 - elif patch: - patch_number = int(patch_number) + 1 - build_number = 0 - else: - build_number += 1 - - # By default we add dev to ours builds unless its a release - dev_string = "dev" - if release: - dev_string = "" - - version_number = "{}.{}.{}{}".format(major_number, minor_number, dev_string, patch_number) - - # actually write to the recipe and package - _update_version(version_number, build_number) - - # the version numbers in the package and recipe have been updated, so commit those changes first - # run('hg commit -m "Bumped version to {}_{}."'.format(version_number, build_number)) - run('git add .') - run('git commit -m "Bumped version to {}_{}."'.format(version_number, build_number)) - - -def _tag_hg_revision(revision_tag): - """Tag current revision in mercurial.""" - hg_info = _get_hg_info() - if hg_info['dirty']: - _exit("Can't tag dirty revision.") - - # then tag the current revision - if run("hg tag {}".format(revision_tag), warn=True): - _print("Tag '{}' applied".format(revision_tag)) - else: - # if tagging failed, apparently the tag already exists and someone is being silly - _print("Tagging failed! Rolling back.") - # the tag operation has already been rolled back - # we should rollback the version number commit as well - run('hg rollback') - # and clean up the working dir so the updated files don't get committed accidentally anyway - run('hg update -C') - _exit("Are you sure the version you're going for doesn't already exist?") - - -def _tag_git_revision(revision_tag): - """Tag current revision in mercurial.""" - git_info = _get_git_info() - if git_info['dirty']: - _exit("Can't tag dirty revision.") - - # then tag the current revision - if run('git tag -a {} -m "{}"'.format(revision_tag, 'Tagged version {}'.format(revision_tag)), warn=True): - _print("Tag '{}' applied".format(revision_tag)) - else: - raise NotImplementedError('should do rollback here') - run('git push origin') - - -@task(help={"yes": "Skip confirmation prompt."}) -def release(yes=False, token=None): - """ - Builds package and uploads to Anaconda.org - We only allow releases from the production branch - """ - _assert_release_ok() - - # if token is None: - # token = os.environ['BINSTAR_TOKEN'] - - version = pkg_conf.get_version() - - _print("You are about to build and upload version {}, build {} of package {} to user {}".format( - version, pkg_conf.get_build_number(), pkg_conf.PKG_NAME, run('anaconda whoami').stdout)) - if yes or _confirm(prompt="Do you want to continue?"): - - try: - pkg_path = run("deactivate && conda build conda-recipe --output", hide='stdout').stdout.strip().split()[-1] - # run("deactivate && conda build conda-recipe --no-anaconda-upload --quiet") - print (pkg_path) - build() - run("anaconda upload {}".format(pkg_path)) - except: - traceback.print_exc() - _print("anaconda upload failed.") - return False - - try: - run("python setup.py sdist upload") - except: - traceback.print_exc() - _print("pypi upload failed.") - return False - - _tag_git_revision("v{}".format(version)) - return True diff --git a/numpy_indexed/tests/test_grouping.py b/tests/test_grouping.py similarity index 100% rename from numpy_indexed/tests/test_grouping.py rename to tests/test_grouping.py diff --git a/numpy_indexed/tests/test_indexed.py b/tests/test_indexed.py similarity index 100% rename from numpy_indexed/tests/test_indexed.py rename to tests/test_indexed.py diff --git a/version.py b/version.py new file mode 100644 index 0000000..25cf627 --- /dev/null +++ b/version.py @@ -0,0 +1,16 @@ +import re +from os import path + +__version__ = False # Prevent 'undefined name' warning. + +# Read file that should contain __version__ var, and find it. Though it should be the first line, +# we scan the whole file and exec the version setter to have it available in our context, instead +# of more fragile string parsing and regexing. +with open(path.join(path.dirname(path.abspath(__file__)), 'numpy_indexed', '__init__.py'), 'r') as f: + for line in f: + if re.search('^__version__ =', line): + exec(line) + break + + +print(__version__)