Skip to content
Commits on Source (9)
......@@ -6,10 +6,12 @@ os:
- linux
- osx
env:
- CONDA_PY=3.6 MAKE_DOC=TRUE
- CONDA_PY=3.5 MAKE_DOC=TRUE USE_CYTHON=TRUE
- CONDA_PY=3.7
- CONDA_PY=3.6
- CONDA_PY=3.5 USE_CYTHON=TRUE
before_install:
- export MPLBACKEND='Agg'
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then wget https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda.sh; fi
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then wget https://repo.continuum.io/miniconda/Miniconda3-latest-MacOSX-x86_64.sh -O miniconda.sh; fi
- bash miniconda.sh -b -p $HOME/miniconda
......@@ -30,7 +32,7 @@ install:
script:
- WITH_COVERAGE=TRUE make test
- if [ ${MAKE_DOC} ]; then make -C doc clean html; fi
- make -C doc clean html
after_success:
- coveralls
......
# scikit-bio changelog
## Version 0.5.5 (2018-12-10)
### Features
* `skbio.stats.composition` now has methods to compute additive log-ratio transformation and inverse additive log-ratio transformation (`alr`, `alr_inv`) as well as a method to build a basis from a sequential binary partition (`sbp_basis`).
### Backward-incompatible changes [stable]
### Backward-incompatible changes [experimental]
### Performance enhancements
### Bug fixes
### Deprecated functionality [stable]
### Deprecated functionality [experimental]
### Miscellaneous
* Python 3.6 and 3.7 compatibility is now supported
* A pytest runner is shipped with every installation ([#1633](https://github.com/biocore/scikit-bio/pull/1633))
* The nosetest framework has been replaced in favor of pytest ([#1624](https://github.com/biocore/scikit-bio/pull/1624))
* The numpy docs are deprecated in favor of [Napoleon](http://www.sphinx-doc.org/en/master/usage/extensions/napoleon.html) ([#1629](https://github.com/biocore/scikit-bio/pull/1629))
* This version is now compatible with NumPy >= 1.9.2 and Pandas >= 0.23. ([#1627](https://github.com/biocore/scikit-bio/pull/1627))
## Version 0.5.4 (2018-08-23)
### Features
......
......@@ -184,11 +184,9 @@ The scikit-bio coding guidelines describe our [expectations for unit tests](http
Tests can be executed by running ``make test`` from the base directory of the project or from within a Python or IPython session:
``` python
>>> import skbio
>>> skbio.test()
>>> from skbio.test import pytestrunner
>>> pytestrunner()
# full test suite is executed
>>> skbio.io.test()
# tests for the io module are executed
```
Documentation guidelines
......
......@@ -24,3 +24,4 @@ global-exclude *.pyc
global-exclude *.pyo
global-exclude *.so
global-exclude .*.swp
global-exclude .coverage
......@@ -7,8 +7,7 @@
# ----------------------------------------------------------------------------
ifeq ($(WITH_COVERAGE), TRUE)
TEST_COMMAND = COVERAGE_FILE=../.coverage coverage run \
--rcfile ../.coveragerc -m skbio.test
TEST_COMMAND = coverage run --rcfile ../.coveragerc -m skbio.test; coverage report --rcfile ../.coveragerc
else
TEST_COMMAND = python -m skbio.test
endif
......@@ -20,7 +19,7 @@ endif
# simulate a user's install/test process this way to find package data that did
# not install correctly (for example).
test:
cd ci && $(TEST_COMMAND)
cd ci && $(TEST_COMMAND); cd -
flake8 skbio setup.py checklist.py
./checklist.py
check-manifest
pip
# See note in setup.py install_requires about numpy version pin.
numpy<1.14.0
numpy
scipy
matplotlib
pandas<0.23.0
nose
pandas
pep8
ipython
pyflakes
......@@ -12,3 +10,5 @@ flake8
python-dateutil
decorator
scikit-learn
pytest
coverage
......@@ -5,6 +5,5 @@ lockfile
CacheControl
Sphinx
sphinx-bootstrap-theme
numpydoc < 0.8.0
check-manifest
hdmedians
python-skbio (0.5.4-1) UNRELEASED; urgency=medium
python-skbio (0.5.5-1) unstable; urgency=medium
* New upstream version
Closes: #906156
* Standards-Version: 4.2.1
* Build-Depends: python3-hdmedians
* Secure URI in copyright format
* No override for dh_auto_test
* Test-Depends: python3-pytest
-- Andreas Tille <tille@debian.org> Tue, 28 Aug 2018 18:14:05 +0200
-- Andreas Tille <tille@debian.org> Mon, 17 Dec 2018 12:03:10 +0100
python-skbio (0.5.2-1) unstable; urgency=medium
......
Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: scikit-bio
Upstream-Contact: gregcaporaso@gmail.com
Source: https://github.com/biocore/scikit-bio
......
......@@ -18,9 +18,6 @@ override_dh_auto_build:
http_proxy='127.0.0.1:9' \
python3 `which sphinx-build` -b html -d doc/build/doctrees doc/source doc/build/html
override_dh_auto_test:
dh_auto_test
override_dh_auto_clean:
if [ "`find . -name "*.pyo"`" = "" ] ; then echo no need to clean up ; else dh_auto_clean; fi
......
Tests: import-skbio testsuite
Depends: python3-skbio,
python3-httpretty,
python3-pytest
Restrictions: allow-stderr
......@@ -11,7 +11,11 @@ Building the documentation
--------------------------
To build the documentation, you'll need a scikit-bio development environment
set up. See [CONTRIBUTING.md](../CONTRIBUTING.md) for instructions.
set up. See [CONTRIBUTING.md](../CONTRIBUTING.md) for instructions. In
addition, you will also need to install Sphinx and the theme for the
documentation, you can do that with:
pip install Sphinx sphinx-bootstrap-theme
**Important:** The documentation will be built for whatever version of
scikit-bio is *currently installed* on your system (i.e., the version imported
......
// originally taken from scikit-learn's Sphinx theme
$(document).ready(function() {
/* Add a [>>>] button on the top-right corner of code samples to hide
* the >>> and ... prompts and the output and thus make the code
* copyable.
* Note: This JS snippet was taken from the official python.org
* documentation site.*/
* copyable. */
var div = $('.highlight-python .highlight,' +
'.highlight-python3 .highlight,' +
'.highlight-pycon .highlight')
'.highlight-pycon .highlight,' +
'.highlight-default .highlight')
var pre = div.find('pre');
// get the styles from the current theme
......@@ -22,7 +20,7 @@ $(document).ready(function() {
'border-color': border_color, 'border-style': border_style,
'border-width': border_width, 'color': border_color, 'text-size': '75%',
'font-family': 'monospace', 'padding-left': '0.2em', 'padding-right': '0.2em',
'display': 'inline'
'border-radius': '0 3px 0 0'
}
// create and add the button to all the code blocks that contain >>>
......@@ -32,31 +30,34 @@ $(document).ready(function() {
var button = $('<span class="copybutton">&gt;&gt;&gt;</span>');
button.css(button_styles)
button.attr('title', hide_text);
button.data('hidden', 'false');
jthis.prepend(button);
}
// tracebacks (.gt) contain bare text elements that need to be
// wrapped in a span to work with .nextUntil() (see later)
jthis.find('pre:has(.gt)').contents().filter(function() {
return ((this.nodeType == 3) && (this.data.trim().length > 0));
}).wrap('<span>');
});
var show_output = false;
button.bind('click', function() {
if (show_output) {
var button = $(this);
button.parent().find('.go, .gp, .gt').show();
button.next('pre').find('.gt').nextUntil('.gp, .go').css('visibility', 'visible');
button.css('text-decoration', 'none');
button.attr('title', hide_text);
show_output = false;
} else {
// define the behavior of the button when it's clicked
$('.copybutton').click(function(e){
e.preventDefault();
var button = $(this);
if (button.data('hidden') === 'false') {
// hide the code output
button.parent().find('.go, .gp, .gt').hide();
button.next('pre').find('.gt').nextUntil('.gp, .go').css('visibility', 'hidden');
button.css('text-decoration', 'line-through');
button.attr('title', show_text);
show_output = true;
}
});
button.data('hidden', 'true');
} else {
// show the code output
button.parent().find('.go, .gp, .gt').show();
button.next('pre').find('.gt').nextUntil('.gp, .go').css('visibility', 'visible');
button.css('text-decoration', 'none');
button.attr('title', hide_text);
button.data('hidden', 'false');
}
// tracebacks (.gt) contain bare text elements that need to be
// wrapped in a span to work with .nextUntil() (see later)
jthis.find('pre:has(.gt)').contents().filter(function() {
return ((this.nodeType == 3) && (this.data.trim().length > 0));
}).wrap('<span>');
});
});
{% extends "!autosummary/class.rst" %}
{# This template was modified from autosummaries default format #}
{{ fullname | escape | underline}}
{# Taken from scipy's sphinx documentation setup (https://github.com/scipy/scipy/blob/master/doc/source/_templates/autosummary/class.rst). #}
{% block methods %}
{% if methods %}
.. HACK -- the point here is that we don't want this to appear in the output, but the autosummary should still generate the pages.
.. autosummary::
:toctree:
{# We need a list of the built-ins that we implemented, not the default ones #}
{% set built_in_methods = [] %}
{% for item in all_methods %}
{# We want to build dunder methods if they exist, but not every kind of dunder. These are the dunders provided by default on `object` #}
{%- if not item.startswith('_') or (item not in ['__class__',
{% if (item not in ['__class__',
'__delattr__',
'__getattribute__',
'__init__',
'__dir__',
'__format__',
'__new__',
'__reduce__',
'__reduce_ex__',
......@@ -21,21 +17,41 @@
'__setattr__',
'__sizeof__',
'__subclasshook__'] and item.startswith('__')) %}
{{ name }}.{{ item }}
{%- endif -%}
{%- endfor %}
{{ built_in_methods.append(item) or '' }}
{% endif %}
{% endblock %}
{% endfor %}
.. currentmodule:: {{ module }}
.. autoclass:: {{ objname }}
{% block attributes %}
{% if attributes %}
.. HACK -- the point here is that we don't want this to appear in the output, but the autosummary should still generate the pages.
.. rubric:: Attributes
.. autosummary::
{% for item in attributes %}
~{{ name }}.{{ item }}
{%- endfor %}
{% endif %}
{% if built_in_methods %}
.. rubric:: Built-ins
.. autosummary::
:toctree:
{% for item in built_in_methods %}
~{{ name }}.{{ item }}
{%- endfor %}
{% endif %}
{% if methods %}
.. rubric:: Methods
.. autosummary::
:toctree:
{% for item in all_attributes %}
{%- if not item.startswith('_') %}
{{ name }}.{{ item }}
{%- endif -%}
{% for item in methods %}
{% if item != '__init__' %}
~{{ name }}.{{ item }}
{% endif %}
{%- endfor %}
{% endif %}
{% endblock %}
......@@ -70,27 +70,8 @@ class NewAuto(autosummary.Autosummary):
autosummary.Autosummary = NewAuto
import sphinx_bootstrap_theme
import numpydoc
@property
def _extras(self):
# This will be accessed in a for-loop, so memoize to prevent quadratic
# behavior.
if not hasattr(self, '__memoized_extras'):
# We want every dunder that has a function type (not class slot),
# meaning we created the dunder, not Python.
# We don't ever care about __init__ and the user will see plenty of
# __repr__ calls, so why waste space.
self.__memoized_extras = [
a for a, v in inspect.getmembers(self._cls)
if type(v) == types.FunctionType and a.startswith('__')
and a not in ['__init__', '__repr__']
]
return self.__memoized_extras
# The extra_public_methods depends on what class we are looking at.
numpydoc.docscrape.ClassDoc.extra_public_methods = _extras
import skbio
from skbio.util._decorator import classproperty
......@@ -114,7 +95,8 @@ needs_sphinx = '1.6'
extensions = [
'sphinx.ext.autodoc',
'sphinx.ext.mathjax',
'numpydoc',
'sphinx.ext.napoleon',
'sphinx.ext.linkcode',
'sphinx.ext.coverage',
'sphinx.ext.doctest',
'sphinx.ext.autosummary',
......@@ -388,14 +370,6 @@ texinfo_documents = [
# -- Options for autosummary ----------------------------------------------
autosummary_generate = glob.glob('*.rst')
# -- Options for numpydoc -------------------------------------------------
# Generate plots for example sections
numpydoc_use_plots = True
# If we don't turn numpydoc's toctree generation off, Sphinx will warn about
# the toctree referencing missing document(s). This appears to be related to
# generating docs for classes with a __call__ method.
numpydoc_class_members_toctree = False
#------------------------------------------------------------------------------
# Plot
#------------------------------------------------------------------------------
......@@ -453,16 +427,6 @@ intersphinx_mapping = {
import inspect
from os.path import relpath, dirname
for name in ['sphinx.ext.linkcode', 'linkcode', 'numpydoc.linkcode']:
try:
__import__(name)
extensions.append(name)
break
except ImportError:
pass
else:
print "NOTE: linkcode extension not found -- no links to source generated"
def linkcode_resolve(domain, info):
"""
Determine the URL corresponding to Python object
......@@ -522,24 +486,17 @@ def linkcode_resolve(domain, info):
# Link-checking on Travis sometimes times out.
linkcheck_timeout = 30
# This is so that our docs build.
# You might see the following exception when building the documentation:
# TypeError: 'abstractproperty' object is not iterable
def _closure():
def __get__(self, cls, owner):
return self
classproperty.__get__ = __get__
_closure()
def autodoc_skip_member(app, what, name, obj, skip, options):
if what == "method":
if isinstance(obj, classproperty):
return True
return skip
# Add the 'copybutton' javascript, to hide/show the prompt in code
# examples, originally taken from scikit-learn's doc/conf.py
def setup(app):
app.add_javascript('copybutton.js')
app.add_stylesheet('style.css')
app.connect('autodoc-skip-member', autodoc_skip_member)
[nosetests]
verbosity=0
with-doctest=1
doctest-tests=1
doctest-extension=pyx
ignore-files=DONT_IGNORE_ANYTHING
......@@ -42,6 +42,8 @@ classes = """
Programming Language :: Python :: 3 :: Only
Programming Language :: Python :: 3.4
Programming Language :: Python :: 3.5
Programming Language :: Python :: 3.6
Programming Language :: Python :: 3.7
Operating System :: Unix
Operating System :: POSIX
Operating System :: MacOS :: MacOS X
......@@ -106,7 +108,7 @@ setup(name='scikit-bio',
packages=find_packages(),
ext_modules=extensions,
include_dirs=[np.get_include()],
setup_requires=['nose >= 1.3.7'],
tests_require=['pytest', 'coverage'],
install_requires=[
'lockfile >= 0.10.2', # req'd for our usage of CacheControl
'CacheControl >= 0.11.5',
......@@ -114,19 +116,12 @@ setup(name='scikit-bio',
'IPython >= 3.2.0',
'matplotlib >= 1.4.3',
'natsort >= 4.0.3',
# numpy array repr changed in 1.14.0 to use less whitespace, which
# breaks the doctests. The doctests can't be updated to match the new
# arrray repr because we still support Python 3.4, which doesn't have
# a numpy 1.14.0 conda package on `defaults` or `conda-forge`
# channels.
'numpy >= 1.9.2, < 1.14.0',
'pandas >= 0.19.2, < 0.23.0',
'numpy >= 1.9.2',
'pandas >= 0.23',
'scipy >= 0.15.1',
'nose >= 1.3.7',
'hdmedians >= 0.13',
'scikit-learn >= 0.19.1'
],
test_suite='nose.collector',
classifiers=classifiers,
package_data={
'skbio.diversity.alpha.tests': ['data/qiime-191-tt/*'],
......
......@@ -7,8 +7,6 @@
# ----------------------------------------------------------------------------
from skbio.util import TestRunner
# Add skbio.io to sys.modules to prevent cycles in our imports
import skbio.io # noqa
# imports included for convenience
......@@ -26,7 +24,7 @@ __all__ = ['Sequence', 'DNA', 'RNA', 'Protein', 'GeneticCode',
'TreeNode', 'nj', 'read', 'write', 'OrdinationResults']
__credits__ = "https://github.com/biocore/scikit-bio/graphs/contributors"
__version__ = "0.5.4"
__version__ = "0.5.5"
mottos = [
# 03/15/2014
......@@ -78,8 +76,3 @@ if __doc__ is None:
__doc__ = title + art
else:
__doc__ = title + art + __doc__
test = TestRunner(__file__).test
if __name__ == '__main__':
test()
......@@ -200,8 +200,6 @@ ACGTGCCTA-GGTACGCAAG
# The full license is in the file COPYING.txt, distributed with this software.
# ----------------------------------------------------------------------------
from skbio.util import TestRunner
from ._tabular_msa import TabularMSA
from ._pairwise import (
local_pairwise_align_nucleotide, local_pairwise_align_protein,
......@@ -217,5 +215,3 @@ __all__ = ['TabularMSA', 'StripedSmithWaterman', 'AlignmentStructure',
'global_pairwise_align_nucleotide', 'global_pairwise_align_protein',
'local_pairwise_align', 'local_pairwise_align_nucleotide',
'local_pairwise_align_protein', 'make_identity_substitution_matrix']
test = TestRunner(__file__).test
......@@ -7,6 +7,7 @@
# ----------------------------------------------------------------------------
from abc import ABCMeta, abstractmethod
import collections
import numpy as np
import pandas as pd
......@@ -159,6 +160,8 @@ class TabularMSALoc(_Indexing):
complete_key = False
partial_key = False
duplicated_key = False
if not isinstance(indexable, collections.Hashable):
return False
if axis == 0 and self._has_fancy_index():
try:
if type(indexable) is tuple:
......@@ -168,7 +171,10 @@ class TabularMSALoc(_Indexing):
except TypeError: # Unhashable type, no biggie
pass
if index.has_duplicates:
duplicated_key = indexable in index.get_duplicates()
# for a given Index object index,
# index[index.duplicated()].unique() is pandas' recommended
# replacement for index.get_duplicates(), per the pandas 0.23 docs
duplicated_key = indexable in index[index.duplicated()].unique()
return (not duplicated_key and
((np.isscalar(indexable) and not partial_key) or complete_key))
......