diff --git a/.appveyor.yml b/.appveyor.yml index d1698e1..f787261 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -45,8 +45,8 @@ # respective CI run configuration). -# make repository clone cheap -shallow_clone: true +# do not make repository clone cheap: interfers with versioneer +shallow_clone: false environment: @@ -66,7 +66,7 @@ environment: APPVEYOR_BUILD_WORKER_IMAGE: Ubuntu2004 INSTALL_SYSPKGS: python3-virtualenv # system git-annex is way too old, use better one - INSTALL_GITANNEX: git-annex -m deb-url --url http://snapshot.debian.org/archive/debian/20201228T023115Z/pool/main/g/git-annex/git-annex_8.20201127-1_amd64.deb + INSTALL_GITANNEX: git-annex -m deb-url --url http://snapshot.debian.org/archive/debian/20210906T204127Z/pool/main/g/git-annex/git-annex_8.20210903-1_amd64.deb CODECOV_BINARY: https://uploader.codecov.io/latest/linux/codecov # Windows core tests - ID: WinP39core @@ -155,11 +155,16 @@ install: ) - sh: python -m pip install datalad-installer${DATALAD_INSTALLER_VERSION:-} # Missing system software - - sh: "[ -n \"$INSTALL_SYSPKGS\" ] && ( [ \"x${APPVEYOR_BUILD_WORKER_IMAGE}\" = \"xmacOS\" ] && brew install -q ${INSTALL_SYSPKGS} || sudo apt-get install --no-install-recommends -y ${INSTALL_SYSPKGS} ) || true" + - sh: "[ -n \"$INSTALL_SYSPKGS\" ] && ( [ \"x${APPVEYOR_BUILD_WORKER_IMAGE}\" = \"xmacOS\" ] && brew install -q ${INSTALL_SYSPKGS} || { sudo apt-get update -y && sudo apt-get install --no-install-recommends -y ${INSTALL_SYSPKGS}; } ) || true" # Install git-annex on windows, otherwise INSTALL_SYSPKGS can be used # deploy git-annex, if desired - cmd: IF DEFINED INSTALL_GITANNEX datalad-installer --sudo ok %INSTALL_GITANNEX% - sh: "[ -n \"${INSTALL_GITANNEX}\" ] && datalad-installer --sudo ok ${INSTALL_GITANNEX}" + # in case of a snapshot installation, use the following approach to adjust + # the PATH as necessary + #- sh: "[ -n \"${INSTALL_GITANNEX}\" ] && datalad-installer -E ${HOME}/dlinstaller_env.sh --sudo ok ${INSTALL_GITANNEX}" + # add location of datalad installer results to PATH + #- sh: "[ -f ${HOME}/dlinstaller_env.sh ] && . ${HOME}/dlinstaller_env.sh || true" #before_build: diff --git a/.codeclimate.yml b/.codeclimate.yml new file mode 100644 index 0000000..9ac1b30 --- /dev/null +++ b/.codeclimate.yml @@ -0,0 +1,17 @@ +version: "2" +checks: + file-lines: + config: + threshold: 500 +plugins: + bandit: + enabled: true + checks: + assert_used: + enabled: false +exclude_patterns: +- "_datalad_buildsupport/" +- "versioneer.py" +- "*/_version.py" +- "tools/" +- "**/tests/" diff --git a/.github/workflows/test_crippledfs.yml b/.github/workflows/test_crippledfs.yml index 72e798d..e0d4124 100644 --- a/.github/workflows/test_crippledfs.yml +++ b/.github/workflows/test_crippledfs.yml @@ -52,10 +52,4 @@ jobs: echo "== mount >>" mount echo "<< mount ==" - python -m nose -s -v --with-doctest --with-coverage --cover-package datalad_ebrains datalad_ebrains - - name: Report coverage - run: | - python -m coverage xml - curl -Os "https://uploader.codecov.io/latest/linux/codecov" - chmod +x codecov - ./codecov + python -m nose -s -v --with-doctest --with-coverage --cover-package datalad_helloworld datalad_helloworld diff --git a/MANIFEST.in b/MANIFEST.in index 7e8ea16..a83f85f 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,2 +1,6 @@ -include versioneer.py -include datalad_ebrains/_version.py +include CONTRIBUTORS LICENSE versioneer.py +graft _datalad_buildsupport +graft datalad_helloworld +graft docs +prune docs/build +global-exclude *.py[cod] diff --git a/Makefile b/Makefile index da8f7f1..be524e9 100644 --- a/Makefile +++ b/Makefile @@ -9,8 +9,7 @@ clean: release-pypi: # avoid upload of stale builds test ! -e dist - $(PYTHON) setup.py sdist - python setup.py bdist_wheel --universal + $(PYTHON) setup.py sdist bdist_wheel twine upload dist/* update-buildsupport: diff --git a/_datalad_buildsupport/formatters.py b/_datalad_buildsupport/formatters.py index 015f62a..5ac01de 100644 --- a/_datalad_buildsupport/formatters.py +++ b/_datalad_buildsupport/formatters.py @@ -251,7 +251,7 @@ def _mk_options(self, parser): def _format_action(self, action): # determine the required width and the entry label - action_header = self._format_action_invocation(action, doubledash='-\\\\-') + action_header = self._format_action_invocation(action) if action.help: help_text = self._expand_help(action) diff --git a/_datalad_buildsupport/setup.py b/_datalad_buildsupport/setup.py index b83ccfa..27e0821 100644 --- a/_datalad_buildsupport/setup.py +++ b/_datalad_buildsupport/setup.py @@ -9,12 +9,11 @@ import datetime import os -from distutils.core import Command -from distutils.errors import DistutilsOptionError from os.path import ( dirname, join as opj, ) +from setuptools import Command, DistutilsOptionError from setuptools.config import read_configuration import versioneer @@ -75,7 +74,7 @@ def finalize_options(self): mod_name, suite_name = self.cmdsuite.split(':') mod = __import__(mod_name, fromlist=mod_name.split('.')) suite = getattr(mod, suite_name) - self.cmdlist = [c[2] if len(c) > 2 else c[1].replace('_', '-') + self.cmdlist = [c[2] if len(c) > 2 else c[1].replace('_', '-').lower() for c in suite[1]] self.announce('Writing man page(s) to %s' % self.manpath) @@ -157,40 +156,6 @@ def run(self): f.write(formatted) -class BuildRSTExamplesFromScripts(Command): - description = 'Generate RST variants of example shell scripts.' - - user_options = [ - ('expath=', None, 'path to look for example scripts'), - ('rstpath=', None, 'output path for RST files'), - ] - - def initialize_options(self): - self.expath = opj('docs', 'examples') - self.rstpath = opj('docs', 'source', 'generated', 'examples') - - def finalize_options(self): - if self.expath is None: - raise DistutilsOptionError('\'expath\' option is required') - if self.rstpath is None: - raise DistutilsOptionError('\'rstpath\' option is required') - self.announce('Converting example scripts') - - def run(self): - opath = self.rstpath - if not os.path.exists(opath): - os.makedirs(opath) - - from glob import glob - for example in glob(opj(self.expath, '*.sh')): - exname = os.path.basename(example)[:-3] - with open(opj(opath, '{0}.rst'.format(exname)), 'w') as out: - fmt.cmdline_example_to_rst( - open(example), - out=out, - ref='_example_{0}'.format(exname)) - - class BuildConfigInfo(Command): description = 'Generate RST documentation for all config items.' diff --git a/docs/Makefile b/docs/Makefile index dbfb529..c31cca0 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -87,9 +87,9 @@ qthelp: @echo @echo "Build finished; now you can run "qcollectiongenerator" with the" \ ".qhcp project file in $(BUILDDIR)/qthelp, like this:" - @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/datalad_metalad.qhcp" + @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/datalad_ebrains.qhcp" @echo "To view the help file:" - @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/datalad_metalad.qhc" + @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/datalad_ebrains.qhc" applehelp: $(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp @@ -104,8 +104,8 @@ devhelp: @echo @echo "Build finished." @echo "To view the help file:" - @echo "# mkdir -p $$HOME/.local/share/devhelp/datalad_metalad" - @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/datalad_metalad" + @echo "# mkdir -p $$HOME/.local/share/devhelp/datalad_ebrains" + @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/datalad_ebrains" @echo "# devhelp" epub: diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..a142e52 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,35 @@ +## Editing, building, and publishing extension documentation + + +The `datalad-ebrains` extension uses [Sphinx](https://www.sphinx-doc.org/en/master/index.html#) for document generation +and suggests using [Read the Docs](https://docs.readthedocs.io/en/stable/) for automatic documentation building, versioning, and hosting. + +Once you are ready to document your extension software, take note of the following: + +### Document editing + +Edit your `docs/source/index.rst` file using [reStructuredText](https://www.sphinx-doc.org/en/master/usage/restructuredtext/basics.html), +which is the default plaintext markup language used by Sphinx. Add further documentation as needed. + +### Local testing + +For testing locally whether your documentation builds and renders correctly, first install the developer requirements from the repository's root directory: +``` +pip install -r requirements-devel.txt +``` + +Then build the documentation locally: +``` +make -C docs html +``` + +Navigate to `docs/build/` and open `index.html` in your browser to view your documentation. + +### Remote building and testing + +The GitHub Action workflow located at `.github/workflows/docbuild.yml` will run on a push or pull request to your GitHub repository's master/main branch. This builds the documentation remotely and serves as an automated documentation test. + +### Publishing your documentation + +- If you maintain your extension yourself *outside of the scope of the DataLad GitHub organization*, you can follow [these instructions](https://docs.readthedocs.io/en/stable/integrations.html) for integrating your version control system (such as GitHub) with Read the Docs. +- If your extension is *maintained by the DataLad developer team*, please create an issue asking for help with the setup. diff --git a/docs/source/conf.py b/docs/source/conf.py index a7b5f01..cd7a084 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # -# datalad_metalad documentation build configuration file, created by +# datalad_ebrains documentation build configuration file, created by # sphinx-quickstart on Tue Oct 13 08:41:19 2015. # # This file is execfile()d with the current directory set to its @@ -13,7 +13,7 @@ # serve to show the default. import sys -import os +import subprocess import datetime from os.path import ( @@ -35,17 +35,19 @@ for setup_py_path in (opj(pardir, 'setup.py'), # travis opj(pardir, pardir, 'setup.py')): # RTD if exists(setup_py_path): - sys.path.insert(0, os.path.abspath(dirname(setup_py_path))) + sys.path.insert(0, abspath(dirname(setup_py_path))) + # Build manpage try: - for cmd in 'manpage',: #'examples': - os.system( - '{} build_{} --cmdsuite {} --manpath {} --rstpath {}'.format( - setup_py_path, - cmd, - 'datalad_ebrains:command_suite', - abspath(opj(dirname(setup_py_path), 'build', 'man')), - opj(dirname(__file__), 'generated', 'man'))) - except: + subprocess.run( + args=[setup_py_path, 'build_manpage', + '--cmdsuite', 'datalad_helloworld:command_suite', + '--manpath', abspath(opj( + dirname(setup_py_path), 'build', 'man')), + '--rstpath', opj(dirname(__file__), 'generated', 'man'), + ], + check=True, + ) + except (FileNotFoundError, subprocess.CalledProcessError): # shut up and do your best pass @@ -101,7 +103,7 @@ # # This is also used if you do content translation via gettext catalogs. # Usually you set "language" from the command line for these cases. -language = "en" +language = 'en' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. @@ -136,3 +138,8 @@ # If true, links to the reST sources are added to the pages. html_show_sourcelink = False + +# smart quotes are incompatible with the RST flavor of the generated manpages +# but see `smartquotes_action` for more fine-grained control, in case +# some of this functionality is needed +smartquotes = False diff --git a/pyproject.toml b/pyproject.toml index d25f6e3..f671f35 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,2 +1,2 @@ [build-system] -requires = ["setuptools >= 30.3.0", "wheel"] +requires = ["setuptools >= 43.0.0", "wheel"] diff --git a/setup.cfg b/setup.cfg index 10c94fe..ab7006d 100644 --- a/setup.cfg +++ b/setup.cfg @@ -16,16 +16,25 @@ python_requires = >= 3.6 install_requires = datalad >= 0.16 datalad_next -test_requires = - nose - coverage -packages = find: +packages = find_namespace: include_package_data = True [options.packages.find] -# do not ship the build helpers -exclude= - _datalad_buildsupport +include = datalad_ebrains* + +[options.extras_require] +# this matches the name used by -core and what is expected by some CI setups +devel = + nose + coverage + +[options.entry_points] +# 'datalad.extensions' is THE entrypoint inspected by the datalad API builders +datalad.extensions = + # the label in front of '=' is the command suite label + # the entrypoint can point to any symbol of any name, as long it is + # valid datalad interface specification (see demo in this extensions) + ebrains = datalad_ebrains:command_suite [versioneer] # See the docstring in versioneer.py for instructions. Note that you must diff --git a/setup.py b/setup.py index 77fa791..a534d6a 100755 --- a/setup.py +++ b/setup.py @@ -11,26 +11,8 @@ cmdclass = versioneer.get_cmdclass() cmdclass.update(build_manpage=BuildManPage) -# Give setuptools a hint to complain if it's too old a version -# 30.3.0 allows us to put most metadata in setup.cfg -# Should match pyproject.toml -SETUP_REQUIRES = ['setuptools >= 30.3.0'] -# This enables setuptools to install wheel on-the-fly -SETUP_REQUIRES += ['wheel'] if 'bdist_wheel' in sys.argv else [] - if __name__ == '__main__': - setup(name='datalad_ebrains', + setup(name='datalad_helloworld', version=versioneer.get_version(), cmdclass=cmdclass, - setup_requires=SETUP_REQUIRES, - entry_points={ - # 'datalad.extensions' is THE entrypoint inspected by the datalad API builders - 'datalad.extensions': [ - # the label in front of '=' is the command suite label - # the entrypoint can point to any symbol of any name, as long it is - # valid datalad interface specification (see demo in this extensions - 'ebrains=datalad_ebrains:command_suite', - ], - }, ) - diff --git a/versioneer.py b/versioneer.py index 64fea1c..51ca818 100644 --- a/versioneer.py +++ b/versioneer.py @@ -1500,7 +1500,7 @@ def get_cmdclass(): cmds = {} # we add "version" to both distutils and setuptools - from distutils.core import Command + from setuptools import Command class cmd_version(Command): description = "report generated version string"