diff --git a/.travis.yml b/.travis.yml index b0327361..3f0e88d3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -44,16 +44,16 @@ install: - if "$PYSAL_PLUS"; then conda install --yes numba; fi script: - - pwd - - ls -al - python setup.py sdist >/dev/null - - nosetests -v esda; + - python setup.py install + - nosetests --verbose --with-coverage --cover-package=esda; notifications: email: recipients: - levi.john.wolf+travis@gmail.com - sjsrey+travis@gmail.com + - weikang9009@gmail.com on_success: change on_failure: change diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000..5f552f05 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,58 @@ +# Changes + +Version 2.0.0 (2018-08-24) + +We closed a total of 42 issues (enhancements and bug fixes) through 16 pull requests, since our last release on 2017-07-14. + +## Issues Closed + - Changing esda setup to handle version programatically (#33) + - port legacy esda fix for 1013 (#12) + - notebook links broken (#29) + - include /tests in release (#32) + - Add tests to release (#27) + - Accounting for incoming API changes to `libpysal` and adding testing against `libpysal`'s master branch (#26) + - no `varnames` in `Moran_BV_matrix` (#22) + - add `.varnames` attribute to `Moran_BV` objects in `Moran_BV_Matrix` results (#23) + - Inconsistent metadata in setup.py (#28) + - Update license (#30) + - esda has no readme (#14) + - Readme added (#25) + - move api into __init__ and remove api (#24) + - `.z` attribute divided by standard deviation (#21) + - offer standardised and non-standardised `.z`, `.x` and `.y` attributes (#20) + - get sjsrey's changes into a release (#16) + - esda's namespace is broken (#17) + - update api.py (#18) + - Update docstrings to use libpysal not pysal (#13) + - esda needs an api.py module (#9) + - chore: Update setup for 3+ (#15) + - Master (#10) + - infrastructure changes (#8) + - I made #5 against the esda branch instead of master (#7) + - bump version and add maintainer (#6) + - use 2to3 (#5) + +## Pull Requests + - Changing esda setup to handle version programatically (#33) + - include /tests in release (#32) + - Accounting for incoming API changes to `libpysal` and adding testing against `libpysal`'s master branch (#26) + - add `.varnames` attribute to `Moran_BV` objects in `Moran_BV_Matrix` results (#23) + - Update license (#30) + - Readme added (#25) + - move api into __init__ and remove api (#24) + - `.z` attribute divided by standard deviation (#21) + - get sjsrey's changes into a release (#16) + - update api.py (#18) + - Update docstrings to use libpysal not pysal (#13) + - chore: Update setup for 3+ (#15) + - Master (#10) + - infrastructure changes (#8) + - I made #5 against the esda branch instead of master (#7) + - use 2to3 (#5) + +The following individuals contributed to this release: + + - Serge Rey + - Wei Kang + - Levi John Wolf + - Stefanie Lumnitz diff --git a/LICENSE b/LICENSE index 22a51335..109362ca 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -New BSD License +BSD 3-Clause License Copyright 2018 PySAL Developers diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 00000000..3b7623c8 --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,2 @@ +include LICENSE.txt CHANGELOG.md MANIFEST.in requirements_dev.txt requirements.txt + diff --git a/README.md b/README.md index 17816de4..ca579d37 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ If you are having issues, please talk to us in the [gitter room](https://gitter. License ------- -The project is licensed under the [BSD license](https://github.com/pysal/pysal/blob/master/LICENSE.txt). +The project is licensed under the [BSD license](https://github.com/pysal/esda/blob/master/LICENSE). Funding ------- diff --git a/README.rst b/README.rst new file mode 100644 index 00000000..eabb60f2 --- /dev/null +++ b/README.rst @@ -0,0 +1,64 @@ +Exploratory Spatial Data Analysis (esda) in PySAL +================================================= + +.. image:: https://travis-ci.org/pysal/esda.svg + :target: https://travis-ci.org/pysal/esda + +.. image:: https://badges.gitter.im/pysal/pysal.svg + :target: https://gitter.im/pysal/pysal + + +Methods for testing for global and local autocorrelation in areal unit +data. + +************ +Installation +************ + +Install esda by running: + +:: + + $ pip install esda + +************ +Requirements +************ + +- libpysal + +********** +Contribute +********** + +PySAL-esda is under active development and contributors are welcome. + +If you have any suggestion, feature request, or bug report, please open +a new `issue `__ on GitHub. To +submit patches, please follow the PySAL development +`guidelines `__ +and open a `pull request `__. Once your +changes get merged, you’ll automatically be added to the `Contributors +List `__. + +******* +Support +******* + +If you are having issues, please talk to us in the `gitter +room `__. + +******* +License +******* + +The project is licensed under the `BSD +license `__. + +******* +Funding +******* + +NSF Award #1421935 `New Approaches to Spatial Distribution +Dynamics `__ + diff --git a/setup.py b/setup.py index 70353d53..62859855 100644 --- a/setup.py +++ b/setup.py @@ -2,6 +2,9 @@ from distutils.command.build_py import build_py +with open('README.rst', 'r', encoding='utf8') as file: + long_description = file.read() + # Get __version__ from giddy/__init__.py without importing the package # __version__ has to be defined in the first line with open('esda/__init__.py', 'r') as f: @@ -11,9 +14,10 @@ setup(name='esda', # name of package version=__version__, description='Package with statistics for exploratory spatial data analysis', + long_description=long_description, url='https://github.com/pysal/esda', - maintainer='Sergio Rey', - maintainer_email='sjsrey@gmail.com', + maintainer='Sergio Rey, Wei Kang', + maintainer_email='sjsrey@gmail.com, weikang9009@gmail.com', test_suite='nose.collector', py_modules=['esda'], python_requires='>3.4', diff --git a/tools/gitcount.ipynb b/tools/gitcount.ipynb new file mode 100644 index 00000000..22f1c83e --- /dev/null +++ b/tools/gitcount.ipynb @@ -0,0 +1,852 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## PySAL Change Log Statistics\n", + "\n", + "This notebook generates the summary statistics for a package. \n", + "\n", + "It assumes you are running this under the `tools` directory at the toplevel of the package\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Change the values only in the next cell" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "package_name = 'esda'\n", + "release_date = '2018-08-24'\n", + "start_date = '2017-07-14'" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This notebook will generate a file in the current directory with the name \"changelog_VERSION.md\". You can edit and append this on front of the CHANGELOG file for the package release." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "from __future__ import print_function\n", + "import os\n", + "import json\n", + "import re\n", + "import sys\n", + "import pandas\n", + "\n", + "from datetime import datetime, timedelta\n", + "from time import sleep\n", + "from subprocess import check_output\n", + "try:\n", + " from urllib import urlopen\n", + "except:\n", + " from urllib.request import urlopen\n", + "\n", + "import ssl\n", + "import yaml\n", + "\n", + "context = ssl._create_unverified_context()\n" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "CWD = os.path.abspath(os.path.curdir)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'/Users/weikang/Google Drive (weikang@ucr.edu)/python_repos/pysal-refactor/esda/tools'" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "CWD" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "datetime.datetime(2017, 7, 14, 0, 0)" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "since_date = '--since=\"{start}\"'.format(start=start_date)\n", + "since_date\n", + "since = datetime.strptime(start_date+\" 0:0:0\", \"%Y-%m-%d %H:%M:%S\")\n", + "since" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "# get __version__\n", + "f = \"../{package}/__init__.py\".format(package=package_name)\n", + "\n", + "with open(f, 'r') as initfile:\n", + " exec(initfile.readline())\n", + " " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Total commits by subpackage" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "cmd = ['git', 'log', '--oneline', since_date]\n", + "ncommits = len(check_output(cmd).splitlines())" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "48" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "ncommits" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## List Contributors" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Some of our contributors have many aliases for the same identity. So, we've added a mapping to make sure that individuals are listed once (and only once). " + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [], + "source": [ + "identities = {'Levi John Wolf': ('ljwolf', 'Levi John Wolf'),\n", + " 'Serge Rey': ('Serge Rey', 'Sergio Rey', 'sjsrey', 'serge'),\n", + " 'Wei Kang': ('Wei Kang', 'weikang9009'),\n", + " 'Dani Arribas-Bel': ('Dani Arribas-Bel', 'darribas')\n", + "}\n", + "\n", + "def regularize_identity(string):\n", + " string = string.decode()\n", + " for name, aliases in identities.items():\n", + " for alias in aliases:\n", + " if alias in string:\n", + " string = string.replace(alias, name)\n", + " if len(string.split(' '))>1:\n", + " string = string.title()\n", + " return string.lstrip('* ')" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [], + "source": [ + "author_cmd = ['git', 'log', '--format=* %aN', since_date]" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [], + "source": [ + "from collections import Counter" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [], + "source": [ + "\n", + "ncommits = len(check_output(cmd).splitlines())\n", + "all_authors = check_output(author_cmd).splitlines()\n", + "counter = Counter([regularize_identity(author) for author in all_authors])\n", + "# global_counter += counter\n", + "# counters.update({'.'.join((package,subpackage)): counter})\n", + "unique_authors = sorted(set(all_authors))\n" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [], + "source": [ + "unique_authors = counter.keys()" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "dict_keys(['Wei Kang', 'Serge Rey', 'Levi John Wolf', 'Stefanie Lumnitz'])" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "unique_authors" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Disaggregate by PR, Issue" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [], + "source": [ + "from datetime import datetime, timedelta\n", + "ISO8601 = \"%Y-%m-%dT%H:%M:%SZ\"\n", + "PER_PAGE = 100\n", + "element_pat = re.compile(r'<(.+?)>')\n", + "rel_pat = re.compile(r'rel=[\\'\"](\\w+)[\\'\"]')\n" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [], + "source": [ + "\n", + "def parse_link_header(headers):\n", + " link_s = headers.get('link', '')\n", + " urls = element_pat.findall(link_s)\n", + " rels = rel_pat.findall(link_s)\n", + " d = {}\n", + " for rel,url in zip(rels, urls):\n", + " d[rel] = url\n", + " return d\n", + "\n", + "def get_paged_request(url):\n", + " \"\"\"get a full list, handling APIv3's paging\"\"\"\n", + " results = []\n", + " while url:\n", + " #print(\"fetching %s\" % url, file=sys.stderr)\n", + " f = urlopen(url)\n", + " results.extend(json.load(f))\n", + " links = parse_link_header(f.headers)\n", + " url = links.get('next')\n", + " return results\n", + "\n", + "def get_issues(project=\"pysal/pysal\", state=\"closed\", pulls=False):\n", + " \"\"\"Get a list of the issues from the Github API.\"\"\"\n", + " which = 'pulls' if pulls else 'issues'\n", + " url = \"https://api.github.com/repos/%s/%s?state=%s&per_page=%i\" % (project, which, state, PER_PAGE)\n", + " return get_paged_request(url)\n", + "\n", + "\n", + "def _parse_datetime(s):\n", + " \"\"\"Parse dates in the format returned by the Github API.\"\"\"\n", + " if s:\n", + " return datetime.strptime(s, ISO8601)\n", + " else:\n", + " return datetime.fromtimestamp(0)\n", + "\n", + "\n", + "def issues2dict(issues):\n", + " \"\"\"Convert a list of issues to a dict, keyed by issue number.\"\"\"\n", + " idict = {}\n", + " for i in issues:\n", + " idict[i['number']] = i\n", + " return idict\n", + "\n", + "\n", + "def is_pull_request(issue):\n", + " \"\"\"Return True if the given issue is a pull request.\"\"\"\n", + " return 'pull_request_url' in issue\n", + "\n", + "\n", + "def issues_closed_since(period=timedelta(days=365), project=\"pysal/pysal\", pulls=False):\n", + " \"\"\"Get all issues closed since a particular point in time. period\n", + "can either be a datetime object, or a timedelta object. In the\n", + "latter case, it is used as a time before the present.\"\"\"\n", + "\n", + " which = 'pulls' if pulls else 'issues'\n", + "\n", + " if isinstance(period, timedelta):\n", + " period = datetime.now() - period\n", + " url = \"https://api.github.com/repos/%s/%s?state=closed&sort=updated&since=%s&per_page=%i\" % (project, which, period.strftime(ISO8601), PER_PAGE)\n", + " allclosed = get_paged_request(url)\n", + " # allclosed = get_issues(project=project, state='closed', pulls=pulls, since=period)\n", + " filtered = [i for i in allclosed if _parse_datetime(i['closed_at']) > period]\n", + "\n", + " # exclude rejected PRs\n", + " if pulls:\n", + " filtered = [ pr for pr in filtered if pr['merged_at'] ]\n", + "\n", + " return filtered\n", + "\n", + "\n", + "def sorted_by_field(issues, field='closed_at', reverse=False):\n", + " \"\"\"Return a list of issues sorted by closing date date.\"\"\"\n", + " return sorted(issues, key = lambda i:i[field], reverse=reverse)\n", + "\n", + "\n", + "def report(issues, show_urls=False):\n", + " \"\"\"Summary report about a list of issues, printing number and title.\n", + " \"\"\"\n", + " # titles may have unicode in them, so we must encode everything below\n", + " if show_urls:\n", + " for i in issues:\n", + " role = 'ghpull' if 'merged_at' in i else 'ghissue'\n", + " print('* :%s:`%d`: %s' % (role, i['number'],\n", + " i['title'].encode('utf-8')))\n", + " else:\n", + " for i in issues:\n", + " print('* %d: %s' % (i['number'], i['title'].encode('utf-8')))\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [], + "source": [ + "\n", + "all_issues = {}\n", + "all_pulls = {}\n", + "total_commits = 0\n", + "#prj='pysal/libpysal'\n", + "prj = 'pysal/{package}'.format(package=package_name)\n", + "issues = issues_closed_since(since, project=prj,pulls=False)\n", + "pulls = issues_closed_since(since, project=prj,pulls=True)\n", + "issues = sorted_by_field(issues, reverse=True)\n", + "pulls = sorted_by_field(pulls, reverse=True)\n", + "n_issues, n_pulls = map(len, (issues, pulls))\n", + "n_total = n_issues + n_pulls\n" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [], + "source": [ + "issue_listing = []\n", + "for issue in issues:\n", + " entry = \"{title} (#{number})\".format(title=issue['title'],number=issue['number'])\n", + " issue_listing.append(entry)" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [], + "source": [ + "pull_listing = []\n", + "for pull in pulls:\n", + " entry = \"{title} (#{number})\".format(title=pull['title'],number=pull['number'])\n", + " pull_listing.append(entry)" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "['Changing esda setup to handle version programatically (#33)',\n", + " 'include /tests in release (#32)',\n", + " \"Accounting for incoming API changes to `libpysal` and adding testing against `libpysal`'s master branch (#26)\",\n", + " 'add `.varnames` attribute to `Moran_BV` objects in `Moran_BV_Matrix` results (#23)',\n", + " 'Update license (#30)',\n", + " 'Readme added (#25)',\n", + " 'move api into __init__ and remove api (#24)',\n", + " '`.z` attribute divided by standard deviation (#21)',\n", + " \"get sjsrey's changes into a release (#16)\",\n", + " 'update api.py (#18)',\n", + " 'Update docstrings to use libpysal not pysal (#13)',\n", + " 'chore: Update setup for 3+ (#15)',\n", + " 'Master (#10)',\n", + " 'infrastructure changes (#8)',\n", + " 'I made #5 against the esda branch instead of master (#7)',\n", + " 'use 2to3 (#5)']" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "pull_listing" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [], + "source": [ + "message = \"We closed a total of {total} issues (enhancements and bug fixes) through {pr} pull requests\".format(total=n_total, pr=n_pulls)" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [], + "source": [ + "message = \"{msg}, since our last release on {previous}.\".format(msg=message, previous=str(start_date))\n" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'We closed a total of 42 issues (enhancements and bug fixes) through 16 pull requests, since our last release on 2017-07-14.'" + ] + }, + "execution_count": 23, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "message" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [], + "source": [ + "message += \"\\n\\n## Issues Closed\\n\"" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "We closed a total of 42 issues (enhancements and bug fixes) through 16 pull requests, since our last release on 2017-07-14.\n", + "\n", + "## Issues Closed\n", + "\n" + ] + } + ], + "source": [ + "print(message)" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": {}, + "outputs": [], + "source": [ + "issues = \"\\n\".join([\" - \"+issue for issue in issue_listing])\n", + "message += issues\n", + "message += \"\\n\\n## Pull Requests\\n\"\n", + "pulls = \"\\n\".join([\" - \"+pull for pull in pull_listing])\n", + "message += pulls" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "We closed a total of 42 issues (enhancements and bug fixes) through 16 pull requests, since our last release on 2017-07-14.\n", + "\n", + "## Issues Closed\n", + " - Changing esda setup to handle version programatically (#33)\n", + " - port legacy esda fix for 1013 (#12)\n", + " - notebook links broken (#29)\n", + " - include /tests in release (#32)\n", + " - Add tests to release (#27)\n", + " - Accounting for incoming API changes to `libpysal` and adding testing against `libpysal`'s master branch (#26)\n", + " - no `varnames` in `Moran_BV_matrix` (#22)\n", + " - add `.varnames` attribute to `Moran_BV` objects in `Moran_BV_Matrix` results (#23)\n", + " - Inconsistent metadata in setup.py (#28)\n", + " - Update license (#30)\n", + " - esda has no readme (#14)\n", + " - Readme added (#25)\n", + " - move api into __init__ and remove api (#24)\n", + " - `.z` attribute divided by standard deviation (#21)\n", + " - offer standardised and non-standardised `.z`, `.x` and `.y` attributes (#20)\n", + " - get sjsrey's changes into a release (#16)\n", + " - esda's namespace is broken (#17)\n", + " - update api.py (#18)\n", + " - Update docstrings to use libpysal not pysal (#13)\n", + " - esda needs an api.py module (#9)\n", + " - chore: Update setup for 3+ (#15)\n", + " - Master (#10)\n", + " - infrastructure changes (#8)\n", + " - I made #5 against the esda branch instead of master (#7)\n", + " - bump version and add maintainer (#6)\n", + " - use 2to3 (#5)\n", + "\n", + "## Pull Requests\n", + " - Changing esda setup to handle version programatically (#33)\n", + " - include /tests in release (#32)\n", + " - Accounting for incoming API changes to `libpysal` and adding testing against `libpysal`'s master branch (#26)\n", + " - add `.varnames` attribute to `Moran_BV` objects in `Moran_BV_Matrix` results (#23)\n", + " - Update license (#30)\n", + " - Readme added (#25)\n", + " - move api into __init__ and remove api (#24)\n", + " - `.z` attribute divided by standard deviation (#21)\n", + " - get sjsrey's changes into a release (#16)\n", + " - update api.py (#18)\n", + " - Update docstrings to use libpysal not pysal (#13)\n", + " - chore: Update setup for 3+ (#15)\n", + " - Master (#10)\n", + " - infrastructure changes (#8)\n", + " - I made #5 against the esda branch instead of master (#7)\n", + " - use 2to3 (#5)\n" + ] + } + ], + "source": [ + "print(message)" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": {}, + "outputs": [], + "source": [ + "people = \"\\n\".join([\" - \"+person for person in unique_authors])" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " - Wei Kang\n", + " - Serge Rey\n", + " - Levi John Wolf\n", + " - Stefanie Lumnitz\n" + ] + } + ], + "source": [ + "print(people)" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": {}, + "outputs": [], + "source": [ + "message +=\"\\n\\nThe following individuals contributed to this release:\\n\\n{people}\".format(people=people)" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "We closed a total of 42 issues (enhancements and bug fixes) through 16 pull requests, since our last release on 2017-07-14.\n", + "\n", + "## Issues Closed\n", + " - Changing esda setup to handle version programatically (#33)\n", + " - port legacy esda fix for 1013 (#12)\n", + " - notebook links broken (#29)\n", + " - include /tests in release (#32)\n", + " - Add tests to release (#27)\n", + " - Accounting for incoming API changes to `libpysal` and adding testing against `libpysal`'s master branch (#26)\n", + " - no `varnames` in `Moran_BV_matrix` (#22)\n", + " - add `.varnames` attribute to `Moran_BV` objects in `Moran_BV_Matrix` results (#23)\n", + " - Inconsistent metadata in setup.py (#28)\n", + " - Update license (#30)\n", + " - esda has no readme (#14)\n", + " - Readme added (#25)\n", + " - move api into __init__ and remove api (#24)\n", + " - `.z` attribute divided by standard deviation (#21)\n", + " - offer standardised and non-standardised `.z`, `.x` and `.y` attributes (#20)\n", + " - get sjsrey's changes into a release (#16)\n", + " - esda's namespace is broken (#17)\n", + " - update api.py (#18)\n", + " - Update docstrings to use libpysal not pysal (#13)\n", + " - esda needs an api.py module (#9)\n", + " - chore: Update setup for 3+ (#15)\n", + " - Master (#10)\n", + " - infrastructure changes (#8)\n", + " - I made #5 against the esda branch instead of master (#7)\n", + " - bump version and add maintainer (#6)\n", + " - use 2to3 (#5)\n", + "\n", + "## Pull Requests\n", + " - Changing esda setup to handle version programatically (#33)\n", + " - include /tests in release (#32)\n", + " - Accounting for incoming API changes to `libpysal` and adding testing against `libpysal`'s master branch (#26)\n", + " - add `.varnames` attribute to `Moran_BV` objects in `Moran_BV_Matrix` results (#23)\n", + " - Update license (#30)\n", + " - Readme added (#25)\n", + " - move api into __init__ and remove api (#24)\n", + " - `.z` attribute divided by standard deviation (#21)\n", + " - get sjsrey's changes into a release (#16)\n", + " - update api.py (#18)\n", + " - Update docstrings to use libpysal not pysal (#13)\n", + " - chore: Update setup for 3+ (#15)\n", + " - Master (#10)\n", + " - infrastructure changes (#8)\n", + " - I made #5 against the esda branch instead of master (#7)\n", + " - use 2to3 (#5)\n", + "\n", + "The following individuals contributed to this release:\n", + "\n", + " - Wei Kang\n", + " - Serge Rey\n", + " - Levi John Wolf\n", + " - Stefanie Lumnitz\n" + ] + } + ], + "source": [ + "print(message)" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": {}, + "outputs": [], + "source": [ + "head = \"# Changes\\n\\nVersion {version} ({release_date})\\n\\n\".format(version=__version__, release_date=release_date)" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "# Changes\n", + "\n", + "Version 2.0.0 (2018-08-24)\n", + "\n", + "We closed a total of 42 issues (enhancements and bug fixes) through 16 pull requests, since our last release on 2017-07-14.\n", + "\n", + "## Issues Closed\n", + " - Changing esda setup to handle version programatically (#33)\n", + " - port legacy esda fix for 1013 (#12)\n", + " - notebook links broken (#29)\n", + " - include /tests in release (#32)\n", + " - Add tests to release (#27)\n", + " - Accounting for incoming API changes to `libpysal` and adding testing against `libpysal`'s master branch (#26)\n", + " - no `varnames` in `Moran_BV_matrix` (#22)\n", + " - add `.varnames` attribute to `Moran_BV` objects in `Moran_BV_Matrix` results (#23)\n", + " - Inconsistent metadata in setup.py (#28)\n", + " - Update license (#30)\n", + " - esda has no readme (#14)\n", + " - Readme added (#25)\n", + " - move api into __init__ and remove api (#24)\n", + " - `.z` attribute divided by standard deviation (#21)\n", + " - offer standardised and non-standardised `.z`, `.x` and `.y` attributes (#20)\n", + " - get sjsrey's changes into a release (#16)\n", + " - esda's namespace is broken (#17)\n", + " - update api.py (#18)\n", + " - Update docstrings to use libpysal not pysal (#13)\n", + " - esda needs an api.py module (#9)\n", + " - chore: Update setup for 3+ (#15)\n", + " - Master (#10)\n", + " - infrastructure changes (#8)\n", + " - I made #5 against the esda branch instead of master (#7)\n", + " - bump version and add maintainer (#6)\n", + " - use 2to3 (#5)\n", + "\n", + "## Pull Requests\n", + " - Changing esda setup to handle version programatically (#33)\n", + " - include /tests in release (#32)\n", + " - Accounting for incoming API changes to `libpysal` and adding testing against `libpysal`'s master branch (#26)\n", + " - add `.varnames` attribute to `Moran_BV` objects in `Moran_BV_Matrix` results (#23)\n", + " - Update license (#30)\n", + " - Readme added (#25)\n", + " - move api into __init__ and remove api (#24)\n", + " - `.z` attribute divided by standard deviation (#21)\n", + " - get sjsrey's changes into a release (#16)\n", + " - update api.py (#18)\n", + " - Update docstrings to use libpysal not pysal (#13)\n", + " - chore: Update setup for 3+ (#15)\n", + " - Master (#10)\n", + " - infrastructure changes (#8)\n", + " - I made #5 against the esda branch instead of master (#7)\n", + " - use 2to3 (#5)\n", + "\n", + "The following individuals contributed to this release:\n", + "\n", + " - Wei Kang\n", + " - Serge Rey\n", + " - Levi John Wolf\n", + " - Stefanie Lumnitz\n" + ] + } + ], + "source": [ + "print(head+message)" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "metadata": {}, + "outputs": [], + "source": [ + "outfile = 'changelog_{version}.md'.format(version=__version__)\n", + "with open(outfile, 'w') as of:\n", + " of.write(head+message)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.4" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +}