Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • paulmc/fslpy
  • ndcn0236/fslpy
  • seanf/fslpy
3 results
Show changes
Showing
with 344 additions and 94 deletions
......@@ -14,42 +14,24 @@ import numpy as np
def pytest_addoption(parser):
parser.addoption('--niters',
type=int,
action='store',
default=150,
help='Number of test iterations for imagewrapper')
parser.addoption('--testdir',
action='store',
help='FSLeyes test data directory')
parser.addoption('--seed',
type=int,
help='Seed for random number generator')
help='Seed for random number generator')
@pytest.fixture
def testdir(request):
"""FSLeyes test data directory."""
return op.expanduser(request.config.getoption('--testdir'))
@pytest.fixture
def niters(request):
"""Number of test iterations."""
return request.config.getoption('--niters')
@pytest.fixture
def seed(request):
seed = request.config.getoption('--seed')
if seed is None:
seed = np.random.randint(2 ** 32)
seed = np.random.randint(2 ** 30)
np.random.seed(seed)
random .seed(seed)
print('Seed for random number generator: {}'.format(seed))
......
/* override table width restrictions */
.wy-table-responsive table td, .wy-table-responsive table th {
white-space: normal;
}
.wy-table-responsive {
margin-bottom: 24px;
max-width: 100%;
overflow: visible;
}
``fslpy`` release history
=========================
.. include:: ../CHANGELOG.rst
......@@ -12,12 +12,70 @@
# All configuration values have a default; values that are commented out
# serve to show the default.
import glob
import itertools as it
import os
import os.path as op
import sys
import datetime
date = datetime.date.today()
def check_for_missing_stubs():
docdir = op.dirname(__file__)
basedir = op.join(docdir, '..')
modules = []
def tomodname(f):
if f.endswith('.py'):
f = f[:-3]
return op.relpath(op.join(dirpath, f), basedir).replace(op.sep, '.')
for dirpath, dirnames, filenames in os.walk(op.join(basedir, 'fsl')):
for d in dirnames:
if d == '__pycache__':
continue
if len(glob.glob(op.join(dirpath, d, '**', '*.py'), recursive=True)) == 0:
continue
modules.append(tomodname(d))
for f in filenames:
if not f.endswith('.py'):
continue
if f in ('__init__.py', '__main__.py'):
continue
modules.append(tomodname(f))
modules = [m for m in modules if not m.startswith('fsl.tests')]
# import fsl
# modules = recurse(fsl)
# modules = [m.name for m in modules]
# print()
# print()
# print()
for mod in modules:
docfile = op.join(docdir, f'{mod}.rst')
if not op.exists(docfile):
print(f'No doc file found for module: {mod}')
for docfile in glob.glob(op.join(docdir, '*.rst')):
docfile = op.relpath(docfile, basedir)
mod = op.splitext(op.basename(docfile))[0]
if mod not in modules:
print(f'No module found for doc file: {docfile}')
if __name__ == '__main__':
check_for_missing_stubs()
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
......@@ -33,7 +91,8 @@ date = datetime.date.today()
# ones.
extensions = [
'sphinx.ext.autodoc',
'sphinx.ext.autosummary',
'sphinx.ext.viewcode',
'sphinx.ext.autosummary',
'sphinx.ext.mathjax',
'sphinx.ext.graphviz',
'sphinx.ext.todo',
......@@ -55,13 +114,13 @@ master_doc = 'index'
# General information about the project.
project = u'fslpy'
copyright = u'{}, Paul McCarthy, FMRIB Centre, University of Oxford'.format(
copyright = u'{}, FMRIB Centre, University of Oxford, Oxford, UK'.format(
date.year)
# Links to other things
rst_epilog = """
.. |fsleyes_apidoc| replace:: FSLeyes
.. _fsleyes_apidoc: http://users.fmrib.ox.ac.uk/~paulmc/fsleyes_apidoc/index.html
.. _fsleyes_apidoc: http://users.fmrib.ox.ac.uk/~paulmc/fsleyes/userdoc/latest/index.html
"""
......@@ -121,6 +180,7 @@ pygments_style = 'sphinx'
# a list of builtin themes.
html_theme = 'sphinx_rtd_theme'
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
......@@ -148,7 +208,11 @@ html_theme = 'sphinx_rtd_theme'
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = []
html_static_path = ['_static']
html_css_files = [
'theme_overrides.css', # overrides for wide tables in RTD theme
]
# Add any extra paths that contain custom files (such as robots.txt or
# .htaccess) here, relative to this directory. These files are copied
......@@ -353,26 +417,12 @@ epub_exclude_files = ['search.html']
# special-members flag)
autoclass_content = 'class'
# Document private members and special members (e.g. __init__)
autodocsourc_default_flags = ['private-members', 'special-members']
# Documentation for python modules is in the same order
# as the source code.
autodoc_member_order = 'bysource'
def autodoc_skip_member(app, what, name, obj, skip, options):
# Do not document the _sync_* properties
# that are added by the props package to
# all SyncableHasProperties classes.
if what == 'class':
attName = name.split('.')[-1]
return skip or attName.startswith('_sync_')
return skip or False
def setup(app):
app.connect('autodoc-skip-member', autodoc_skip_member)
autodoc_default_options = {
'special-members' : True,
'private-members' : True,
'undoc-members' : True,
'member-order' : 'bysource',
}
graphviz_output_format = 'svg'
Contributing to ``fslpy``
=========================
*This document is a work in progress*
Development model
-----------------
- The main branch should always be stable and ready to release. All
development occurs on the main branch.
- All changes to the main branch occur via merge requests. Individual
developers are free to choose their own development workflow in their own
repositories.
- Merge requests will not be accepted unless:
- All existing tests pass (or have been updated as needed).
- New tests have been written to cover newly added features.
- Code coverage is as close to 100% as possible.
- Coding conventions are adhered to (unless there is good reason not to).
Commit messages
---------------
To aid readability, all commit messages should be prefixed with one or more of
the following labels (this convention has been inherited from `nibabel
<https://github.com/nipy/nibabel>`_):
* *BF* : bug fix
* *RF* : refactoring
* *ENH*: enhancement/new feature
* *BW* : addresses backward-compatibility
* *OPT* : optimization
* *BK* : breaks something and/or tests fail
* *PL* : making pylint happier
* *DOC* : for all kinds of documentation related commits
* *TEST*: for adding or changing tests
* *MNT* : for administrative/maintenance changes
* *CI* : for continuous-integration changes
Version number
--------------
The ``fslpy`` version number roughly follows `semantic versioning
<http://semver.org/>`_ rules, so that dependant projects are able to perform
compatibility testing. The full version number string consists of three
numbers::
major.minor.patch
- The ``patch`` number is incremented on bugfixes and minor
(backwards-compatible) changes.
- The ``minor`` number is incremented on feature additions and/or
backwards-compatible changes.
- The ``major`` number is incremented on major feature additions, and
backwards-incompatible changes.
The version number in the ``main`` branch should be of the form
``major.minor.patch.dev0``, to indicate that any releases made from this
branch are development releases (although development releases are not part of
the release model).
Releases
--------
A separate branch is created for each **minor** release. The name of the
branch is ``v[major.minor]``, where ``[major.minor]`` is the first two
components of the release version number (see above). For example, the branch
name for minor release ``1.0`` would be ``v1.0``.
Patches and bugfixes may be added to these release branches as ``patch``
releases. These changes should be made on the main branch like any other
change (i.e. via merge requests), and then cherry-picked onto the relevant
release branch(es).
Every release commit is also tagged with its full version number. For
example, the first release off the ``v1.0`` branch would be tagged with
``1.0.0``. Patch releases to the ``v1.0`` branch would be tagged with
``1.0.1``, ``1.0.2``, etc.
Major/minor releases
^^^^^^^^^^^^^^^^^^^^
Follow this process for major and minor releases. Steps 1 and 2 should be
performed via a merge request onto the main branch, and step 4 via a merge
request onto the relevant minor branch.
1. Update the changelog on the main branch to include the new version number
and release date.
2. On the main branch, update the version number in ``fsl/version.py`` to
a development version of **the next** minor release number. For example,
if you are about to release version ``1.3.0``, the version in the main
branch should be ``1.4.0.dev0``.
3. Create the new minor release branch off the main branch.
4. Update the version number on the release branch. If CI tests fail on the
release branch, postpone the release until they are fixed.
5. Tag the new release on the minor release branch.
Bugfix/patch releases
^^^^^^^^^^^^^^^^^^^^^
Follow this process for patch releases. Step 1 should be performed via
a merge request onto the main branch, and step 2 via a merge request onto
the relevant minor branch.
1. Add the fix to the main branch, along with an updated changelog including
the version number and date for the bugfix release.
2. Cherry-pick the relevant commit(s) from the main branch onto the minor
release branch, and update the version number on the minor release branch.
If CI tests fail on the release branch, go back to step 1.
3. Tag the new release on the minor release branch.
Testing
-------
Unit and integration tests are currently run with ``py.test`` and
``coverage``.
- Aim for 100% code coverage.
- Tests must pass on python 3.5, 3.6, and 3.7.
Coding conventions
------------------
- Clean, readable code is good
- White space and visual alignment is good (where it helps to make the code
more readable)
- Clear and accurate documentation is good
- Document all modules, functions, classes, and methods using
`ReStructuredText <http://www.sphinx-doc.org/en/stable/rest.html>`_.
Configure your text editor to use:
- `flake8 <http://flake8.pycqa.org/en/latest/>`_: This checks your code for
adherence to the `PEP8 <https://www.python.org/dev/peps/pep-0008/>`_ coding
standard.
- `pylint <https://www.pylint.org/>`_: This checks that your code follows
other good conventions.
Because I like whitespace and vertical alignment more than PEP8 does, the
following violations of the PEP8 standard are accepted (see
`here <https://pycodestyle.readthedocs.io/en/latest/intro.html#error-codes>`_
for a list of error codes):
- E127: continuation line over-indented for visual indent
- E201: whitespace after '('
- E203: whitespace before ':'
- E221: multiple spaces before operator
- E222: multiple spaces after operator
- E241: multiple spaces after ','
- E271: multiple spaces after keyword
- E272: multiple spaces before keyword
- E301: expected 1 blank line, found 0
- E302: expected 2 blank lines, found 0
- E303: too many blank lines (3)
- E701: multiple statements on one line (colon)
- W504: line break after binary operator
The ``pylint`` tool can be *very* opinionated about how you write your code,
and also checks many of the same things as ``flake8``. So I disable all
refactoring and convention messages, and a few select warnings (type ``pylint
--list-msgs`` for a full list of codes):
- W0511 (``fixme``): Warn about ``TODO`` and ``FIXME`` comments
- W0703 (``broad-except``): Warn about too-general ``except`` blocks (e.g.
``except Exception:``)
- W1202 (``logging-format-interpolation``): Warn about using ``format``
when calling a log function, instead of using ``%`` string formatting.
To check code with ``flake8`` and ``pylint``, I use the following commands::
flake8 --ignore=E127,E201,E203,E221,E222,E241,E271,E272,E301,E302,E303,E701,W504 fsl
pylint --extension-pkg-whitelist=numpy,wx \
--generated-members=np.int8,np.uint8,np.int16,np.uint16,np.int32,np.uint32,np.int64,np.uint64,np.float32,np.float64,np.float128,wx.PyDeadObjectError \
--disable=R,C,W0511,W0703,W1202 fsl
:orphan:
fsl.data.atlases module
=======================
``fsl.data.atlases``
====================
.. automodule:: fsl.data.atlases
:members:
......
``fsl.data.bitmap``
===================
.. automodule:: fsl.data.bitmap
:members:
:undoc-members:
:show-inheritance:
``fsl.data.cifti``
==================
.. automodule:: fsl.data.cifti
:members:
:undoc-members:
:show-inheritance:
:orphan:
fsl.data.constants module
=========================
``fsl.data.constants``
======================
.. automodule:: fsl.data.constants
:members:
......
``fsl.data.dicom``
==================
.. automodule:: fsl.data.dicom
:members:
:undoc-members:
:show-inheritance:
:orphan:
fsl.data.dtifit module
======================
``fsl.data.dtifit``
===================
.. automodule:: fsl.data.dtifit
:members:
......
:orphan:
fsl.data.featanalysis module
============================
``fsl.data.featanalysis``
=========================
.. automodule:: fsl.data.featanalysis
:members:
......
:orphan:
fsl.data.featdesign module
==========================
``fsl.data.featdesign``
=======================
.. automodule:: fsl.data.featdesign
:members:
......
:orphan:
fsl.data.featimage module
=========================
``fsl.data.featimage``
======================
.. automodule:: fsl.data.featimage
:members:
......
:orphan:
fsl.utils.async module
``fsl.data.fixlabels``
======================
.. automodule:: fsl.utils.async
.. automodule:: fsl.data.fixlabels
:members:
:undoc-members:
:show-inheritance:
:orphan:
fsl.utils.status module
``fsl.data.freesurfer``
=======================
.. automodule:: fsl.utils.status
.. automodule:: fsl.data.freesurfer
:members:
:undoc-members:
:show-inheritance:
:orphan:
fsl.data.gifti module
=====================
``fsl.data.gifti``
==================
.. automodule:: fsl.data.gifti
:members:
......
:orphan:
fsl.data.image module
=====================
``fsl.data.image``
==================
.. automodule:: fsl.data.image
:members:
......
:orphan:
fsl.data.imagewrapper module
============================
``fsl.data.imagewrapper``
=========================
.. automodule:: fsl.data.imagewrapper
:members:
......
:orphan:
fsl.data.melodicanalysis module
===============================
``fsl.data.melodicanalysis``
============================
.. automodule:: fsl.data.melodicanalysis
:members:
......