diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..5481a0d --- /dev/null +++ b/.travis.yml @@ -0,0 +1,58 @@ +language: generic +os: +- linux +- osx +env: + matrix: + - CONDA_ENV=3.7 + - CONDA_ENV=3.6 +sudo: false +jobs: + include: + - stage: lint + os: linux + script: + - make lint + - stage: docs + os: linux + install: + - conda env create --file docs/source/environment.yml + - conda activate bmipy_docs + script: + - sphinx-apidoc --force -o docs bmipy *tests + - make -C docs clean html + - stage: deploy + if: tag =~ v.*$ + script: skip + os: linux + deploy: + on: + all_branches: true + provider: pypi + user: mcflugen + password: + secure: d0lVWG54WokY88HQJRll0hshZ9apboEHdrjjs9mZKbCu6qVADp4r6xkboUuS9W4nSAVDfKZ4Q7cPdkplfGunjuhPq4McztF7jWqc1zPwVvKfJiHhGK90vqwUJwLC/zyPn2QR3HYCTmainZeGGMcsGNh5IvO5CcZg9IGR3M/EsPm6WTTu+/e1JG6fixO+cUmYsQbQ/Z2/+NSHUiFkiT8oAlLJZqZDHvvURU4jQCBeISnqRzOqR76Sy00W1gniUYXeyr8DUAZy+SHPgxIQ8tUAkB/Qg6mwNVQ2P+VEkm1feuTNUbrUYyi34XZhcjvP6AQfU1sKIsdMQvCtBTfSO1ALNy+5izKUhi1egmoarqcV/HkMho/okSWDDCkrTiYMb1904rYaTH/x6ixcefFT4X1GBLthsF+ZRBvzCQSKxKPWt/Sqn8P9CyAOIVDSJIut/nII/LfkC50fKdIz4DMIb9vtGgyknHlRxj1a2pmAwTlBF7OXV/BKaEafxapaUmAnj/V+OdFsiHn9iA4xLaQ/YgYWjI6fveiWMD+Pl7KPUDt5eK7WtiI1bfsuyuKMlyTwyunkfqJ5Y24R6DTKBksYqNpuYmzAewHTbNcJkesN/ZPvDp1zSgmYQr/IlObTvxt57ebunxn+1rByN/gO48QeUMOr9LWPSaYdHcjQSN5ZHBMKpqI= +before_install: +- | + if [[ $TRAVIS_OS_NAME == "osx" ]]; then + brew remove --force $(brew list) + brew cleanup -s + rm -rf $(brew --cache) + fi +- | + if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then + curl https://repo.continuum.io/miniconda/Miniconda3-latest-MacOSX-x86_64.sh > $HOME/miniconda.sh + else + curl https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh > $HOME/miniconda.sh + fi +- bash $HOME/miniconda.sh -b -p $HOME/anaconda +- export PATH="$HOME/anaconda/bin:$PATH" +- hash -r +- conda config --set always_yes yes --set changeps1 no +- conda create -n test_env python=$CONDA_ENV +- source activate test_env +install: +- pip install . -r requirements.txt +script: +- pytest --cov=bmipy --cov-report=xml:$(pwd)/coverage.xml -vvv +after_success: coveralls diff --git a/MANIFEST.in b/MANIFEST.in index cf15bcd..27d3006 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,2 +1,2 @@ include versioneer.py -include bmi/_version.py +include bmipy/_version.py diff --git a/Makefile b/Makefile index 11a7c71..dbd6bba 100644 --- a/Makefile +++ b/Makefile @@ -51,12 +51,11 @@ clean-test: ## remove test and coverage artifacts rm -fr .pytest_cache lint: ## check style with flake8 - flake8 bmi tests + flake8 bmipy tests pretty: ## reformat files to make them look pretty - find bmi -name '*.py' | xargs isort - find tests -name '*.py' | xargs isort - black setup.py bmi tests + find bmipy -name '*.py' | xargs isort + black setup.py bmipy test: ## run tests quickly with the default Python py.test @@ -65,16 +64,16 @@ test-all: ## run tests on every Python version with tox tox coverage: ## check code coverage quickly with the default Python - pytest --cov=bmi --cov-report= --cov-report=html --cov-config=setup.cfg + pytest --cov=bmipy --cov-report= --cov-report=html --cov-config=setup.cfg $(BROWSER) htmlcov/index.html docs: ## generate Sphinx HTML documentation, including API docs - rm -f docs/api/bmi.rst - rm -f docs/api/modules.rst - sphinx-apidoc --force -o docs/api bmi *tests + rm -f docs/source/bmipy.rst + rm -f docs/source/modules.rst + sphinx-apidoc --force -o docs/source bmipy *tests $(MAKE) -C docs clean $(MAKE) -C docs html - $(BROWSER) docs/_build/html/index.html + $(BROWSER) docs/build/html/index.html servedocs: docs ## compile the docs watching for changes watchmedo shell-command -p '*.rst' -c '$(MAKE) -C docs html' -R -D . diff --git a/README.md b/README.md deleted file mode 100644 index 3f55ad3..0000000 --- a/README.md +++ /dev/null @@ -1,2 +0,0 @@ -# bmi-python -Python bindings for the Basic Model Interface diff --git a/README.rst b/README.rst new file mode 100644 index 0000000..0f2be1c --- /dev/null +++ b/README.rst @@ -0,0 +1,32 @@ +BMI for Python +============== + +Install +------- + +Install *bmipy* with *pip*, + +.. code-block:: bash + + $ pip install bmipy + +If you're using Anaconda, you can also install *bmipy* +with conda from the *conda-forge* channel, + +.. code-block:: bash + + $ conda install bmipy -c conda-forge + + +Usage +----- + +.. code-block:: python + + from bmipy import Bmi + + + class MyBmi(Bmi): + + def initialize(self, config_file): + # Your implementation goes here diff --git a/bmi/__init__.py b/bmipy/__init__.py similarity index 69% rename from bmi/__init__.py rename to bmipy/__init__.py index c381d4f..2eb46d8 100644 --- a/bmi/__init__.py +++ b/bmipy/__init__.py @@ -1,8 +1,7 @@ +from ._version import get_versions from .bmi import Bmi - __all__ = ["Bmi"] -from ._version import get_versions -__version__ = get_versions()['version'] +__version__ = get_versions()["version"] del get_versions diff --git a/bmi/_version.py b/bmipy/_version.py similarity index 83% rename from bmi/_version.py rename to bmipy/_version.py index a33c1cb..4cfe5bf 100644 --- a/bmi/_version.py +++ b/bmipy/_version.py @@ -1,4 +1,3 @@ - # This file helps to compute a version number in source trees obtained from # git-archive tarball (such as those provided by githubs download-from-tag # feature). Distribution tarballs (built by setup.py sdist) and build @@ -42,8 +41,8 @@ def get_config(): cfg.VCS = "git" cfg.style = "pep440" cfg.tag_prefix = "" - cfg.parentdir_prefix = "bmi-" - cfg.versionfile_source = "bmi/_version.py" + cfg.parentdir_prefix = "bmipy-" + cfg.versionfile_source = "bmipy/_version.py" cfg.verbose = False return cfg @@ -58,17 +57,18 @@ class NotThisMethod(Exception): def register_vcs_handler(vcs, method): # decorator """Decorator to mark a method as the handler for a particular VCS.""" + def decorate(f): """Store f in HANDLERS[vcs][method].""" if vcs not in HANDLERS: HANDLERS[vcs] = {} HANDLERS[vcs][method] = f return f + return decorate -def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False, - env=None): +def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False, env=None): """Call the given command(s).""" assert isinstance(commands, list) p = None @@ -76,10 +76,13 @@ def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False, try: dispcmd = str([c] + args) # remember shell=False, so use git.cmd on windows, not just git - p = subprocess.Popen([c] + args, cwd=cwd, env=env, - stdout=subprocess.PIPE, - stderr=(subprocess.PIPE if hide_stderr - else None)) + p = subprocess.Popen( + [c] + args, + cwd=cwd, + env=env, + stdout=subprocess.PIPE, + stderr=(subprocess.PIPE if hide_stderr else None), + ) break except EnvironmentError: e = sys.exc_info()[1] @@ -116,16 +119,22 @@ def versions_from_parentdir(parentdir_prefix, root, verbose): for i in range(3): dirname = os.path.basename(root) if dirname.startswith(parentdir_prefix): - return {"version": dirname[len(parentdir_prefix):], - "full-revisionid": None, - "dirty": False, "error": None, "date": None} + return { + "version": dirname[len(parentdir_prefix) :], + "full-revisionid": None, + "dirty": False, + "error": None, + "date": None, + } else: rootdirs.append(root) root = os.path.dirname(root) # up a level if verbose: - print("Tried directories %s but none started with prefix %s" % - (str(rootdirs), parentdir_prefix)) + print( + "Tried directories %s but none started with prefix %s" + % (str(rootdirs), parentdir_prefix) + ) raise NotThisMethod("rootdir doesn't start with parentdir_prefix") @@ -181,7 +190,7 @@ def git_versions_from_keywords(keywords, tag_prefix, verbose): # starting in git-1.8.3, tags are listed as "tag: foo-1.0" instead of # just "foo-1.0". If we see a "tag: " prefix, prefer those. TAG = "tag: " - tags = set([r[len(TAG):] for r in refs if r.startswith(TAG)]) + tags = set([r[len(TAG) :] for r in refs if r.startswith(TAG)]) if not tags: # Either we're using git < 1.8.3, or there really are no tags. We use # a heuristic: assume all version tags have a digit. The old git %d @@ -190,7 +199,7 @@ def git_versions_from_keywords(keywords, tag_prefix, verbose): # between branches and tags. By ignoring refnames without digits, we # filter out many common branch names like "release" and # "stabilization", as well as "HEAD" and "master". - tags = set([r for r in refs if re.search(r'\d', r)]) + tags = set([r for r in refs if re.search(r"\d", r)]) if verbose: print("discarding '%s', no digits" % ",".join(refs - tags)) if verbose: @@ -198,19 +207,26 @@ def git_versions_from_keywords(keywords, tag_prefix, verbose): for ref in sorted(tags): # sorting will prefer e.g. "2.0" over "2.0rc1" if ref.startswith(tag_prefix): - r = ref[len(tag_prefix):] + r = ref[len(tag_prefix) :] if verbose: print("picking %s" % r) - return {"version": r, - "full-revisionid": keywords["full"].strip(), - "dirty": False, "error": None, - "date": date} + return { + "version": r, + "full-revisionid": keywords["full"].strip(), + "dirty": False, + "error": None, + "date": date, + } # no suitable tags, so version is "0+unknown", but full hex is still there if verbose: print("no suitable tags, using unknown + full revision id") - return {"version": "0+unknown", - "full-revisionid": keywords["full"].strip(), - "dirty": False, "error": "no suitable tags", "date": None} + return { + "version": "0+unknown", + "full-revisionid": keywords["full"].strip(), + "dirty": False, + "error": "no suitable tags", + "date": None, + } @register_vcs_handler("git", "pieces_from_vcs") @@ -225,8 +241,7 @@ def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command): if sys.platform == "win32": GITS = ["git.cmd", "git.exe"] - out, rc = run_command(GITS, ["rev-parse", "--git-dir"], cwd=root, - hide_stderr=True) + out, rc = run_command(GITS, ["rev-parse", "--git-dir"], cwd=root, hide_stderr=True) if rc != 0: if verbose: print("Directory %s not under git control" % root) @@ -234,10 +249,19 @@ def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command): # if there is a tag matching tag_prefix, this yields TAG-NUM-gHEX[-dirty] # if there isn't one, this yields HEX[-dirty] (no NUM) - describe_out, rc = run_command(GITS, ["describe", "--tags", "--dirty", - "--always", "--long", - "--match", "%s*" % tag_prefix], - cwd=root) + describe_out, rc = run_command( + GITS, + [ + "describe", + "--tags", + "--dirty", + "--always", + "--long", + "--match", + "%s*" % tag_prefix, + ], + cwd=root, + ) # --long was added in git-1.5.5 if describe_out is None: raise NotThisMethod("'git describe' failed") @@ -260,17 +284,16 @@ def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command): dirty = git_describe.endswith("-dirty") pieces["dirty"] = dirty if dirty: - git_describe = git_describe[:git_describe.rindex("-dirty")] + git_describe = git_describe[: git_describe.rindex("-dirty")] # now we have TAG-NUM-gHEX or HEX if "-" in git_describe: # TAG-NUM-gHEX - mo = re.search(r'^(.+)-(\d+)-g([0-9a-f]+)$', git_describe) + mo = re.search(r"^(.+)-(\d+)-g([0-9a-f]+)$", git_describe) if not mo: # unparseable. Maybe git-describe is misbehaving? - pieces["error"] = ("unable to parse git-describe output: '%s'" - % describe_out) + pieces["error"] = "unable to parse git-describe output: '%s'" % describe_out return pieces # tag @@ -279,10 +302,12 @@ def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command): if verbose: fmt = "tag '%s' doesn't start with prefix '%s'" print(fmt % (full_tag, tag_prefix)) - pieces["error"] = ("tag '%s' doesn't start with prefix '%s'" - % (full_tag, tag_prefix)) + pieces["error"] = "tag '%s' doesn't start with prefix '%s'" % ( + full_tag, + tag_prefix, + ) return pieces - pieces["closest-tag"] = full_tag[len(tag_prefix):] + pieces["closest-tag"] = full_tag[len(tag_prefix) :] # distance: number of commits since tag pieces["distance"] = int(mo.group(2)) @@ -293,13 +318,13 @@ def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command): else: # HEX: no tags pieces["closest-tag"] = None - count_out, rc = run_command(GITS, ["rev-list", "HEAD", "--count"], - cwd=root) + count_out, rc = run_command(GITS, ["rev-list", "HEAD", "--count"], cwd=root) pieces["distance"] = int(count_out) # total number of commits # commit date: see ISO-8601 comment in git_versions_from_keywords() - date = run_command(GITS, ["show", "-s", "--format=%ci", "HEAD"], - cwd=root)[0].strip() + date = run_command(GITS, ["show", "-s", "--format=%ci", "HEAD"], cwd=root)[ + 0 + ].strip() pieces["date"] = date.strip().replace(" ", "T", 1).replace(" ", "", 1) return pieces @@ -330,8 +355,7 @@ def render_pep440(pieces): rendered += ".dirty" else: # exception #1 - rendered = "0+untagged.%d.g%s" % (pieces["distance"], - pieces["short"]) + rendered = "0+untagged.%d.g%s" % (pieces["distance"], pieces["short"]) if pieces["dirty"]: rendered += ".dirty" return rendered @@ -445,11 +469,13 @@ def render_git_describe_long(pieces): def render(pieces, style): """Render the given version pieces into the requested style.""" if pieces["error"]: - return {"version": "unknown", - "full-revisionid": pieces.get("long"), - "dirty": None, - "error": pieces["error"], - "date": None} + return { + "version": "unknown", + "full-revisionid": pieces.get("long"), + "dirty": None, + "error": pieces["error"], + "date": None, + } if not style or style == "default": style = "pep440" # the default @@ -469,9 +495,13 @@ def render(pieces, style): else: raise ValueError("unknown style '%s'" % style) - return {"version": rendered, "full-revisionid": pieces["long"], - "dirty": pieces["dirty"], "error": None, - "date": pieces.get("date")} + return { + "version": rendered, + "full-revisionid": pieces["long"], + "dirty": pieces["dirty"], + "error": None, + "date": pieces.get("date"), + } def get_versions(): @@ -485,8 +515,7 @@ def get_versions(): verbose = cfg.verbose try: - return git_versions_from_keywords(get_keywords(), cfg.tag_prefix, - verbose) + return git_versions_from_keywords(get_keywords(), cfg.tag_prefix, verbose) except NotThisMethod: pass @@ -495,13 +524,16 @@ def get_versions(): # versionfile_source is the relative path from the top of the source # tree (where the .git directory might live) to this file. Invert # this to find the root from __file__. - for i in cfg.versionfile_source.split('/'): + for i in cfg.versionfile_source.split("/"): root = os.path.dirname(root) except NameError: - return {"version": "0+unknown", "full-revisionid": None, - "dirty": None, - "error": "unable to find root of source tree", - "date": None} + return { + "version": "0+unknown", + "full-revisionid": None, + "dirty": None, + "error": "unable to find root of source tree", + "date": None, + } try: pieces = git_pieces_from_vcs(cfg.tag_prefix, root, verbose) @@ -515,6 +547,10 @@ def get_versions(): except NotThisMethod: pass - return {"version": "0+unknown", "full-revisionid": None, - "dirty": None, - "error": "unable to compute version", "date": None} + return { + "version": "0+unknown", + "full-revisionid": None, + "dirty": None, + "error": "unable to compute version", + "date": None, + } diff --git a/bmi/bmi.py b/bmipy/bmi.py similarity index 99% rename from bmi/bmi.py rename to bmipy/bmi.py index f115a0a..d594a4f 100644 --- a/bmi/bmi.py +++ b/bmipy/bmi.py @@ -226,7 +226,7 @@ def get_var_location(self, name: str) -> str: ----- CSDMS uses the `ugrid conventions`_ to define unstructured grids. - .. _UGRID: http://ugrid-conventions.github.io/ugrid-conventions + .. _ugrid conventions: http://ugrid-conventions.github.io/ugrid-conventions """ ... diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 0000000..69fe55e --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,19 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +SOURCEDIR = source +BUILDDIR = build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) \ No newline at end of file diff --git a/docs/source/_static/powered-by-logo-header.png b/docs/source/_static/powered-by-logo-header.png new file mode 100644 index 0000000..46c82d0 Binary files /dev/null and b/docs/source/_static/powered-by-logo-header.png differ diff --git a/docs/source/_templates/links.html b/docs/source/_templates/links.html new file mode 100644 index 0000000..03f7f56 --- /dev/null +++ b/docs/source/_templates/links.html @@ -0,0 +1,9 @@ +

Useful Links

+ + diff --git a/docs/source/_templates/sidebarintro.html b/docs/source/_templates/sidebarintro.html new file mode 100644 index 0000000..f09d068 --- /dev/null +++ b/docs/source/_templates/sidebarintro.html @@ -0,0 +1,4 @@ +

About bmipy

+

+ Python bindings for the Basic Model Interface. +

diff --git a/docs/source/bmipy.rst b/docs/source/bmipy.rst new file mode 100644 index 0000000..57aec98 --- /dev/null +++ b/docs/source/bmipy.rst @@ -0,0 +1,22 @@ +bmipy package +============= + +Submodules +---------- + +bmipy.bmi module +---------------- + +.. automodule:: bmipy.bmi + :members: + :undoc-members: + :show-inheritance: + + +Module contents +--------------- + +.. automodule:: bmipy + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/conf.py b/docs/source/conf.py new file mode 100644 index 0000000..fbe0538 --- /dev/null +++ b/docs/source/conf.py @@ -0,0 +1,170 @@ +# Configuration file for the Sphinx documentation builder. +# +# This file only contains a selection of the most common options. For a full +# list see the documentation: +# http://www.sphinx-doc.org/en/master/config + +# -- Path setup -------------------------------------------------------------- + +# 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. +# +# import os +# import sys +# sys.path.insert(0, os.path.abspath('.')) + + +# -- Project information ----------------------------------------------------- + +project = 'bmipy' +copyright = '2019, Eric Hutton' +author = 'Eric Hutton' + + +# -- General configuration --------------------------------------------------- + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [ + 'sphinx.ext.autodoc', + 'sphinx.ext.intersphinx', + 'sphinx.ext.todo', + 'sphinx.ext.viewcode', + 'sphinx.ext.githubpages', + 'sphinx.ext.napoleon', +] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This pattern also affects html_static_path and html_extra_path. +exclude_patterns = [] + + +# -- Options for HTML output ---------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +html_theme = 'alabaster' + +# 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. +#html_theme_options = {} + +# Add any paths that contain custom themes here, relative to this directory. +#html_theme_path = [] + +# The name for this set of Sphinx documents. If None, it defaults to +# " v documentation". +#html_title = None + +# A shorter title for the navigation bar. Default is the same as html_title. +#html_short_title = None + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +html_logo = "_static/powered-by-logo-header.png" + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +#html_favicon = None + +# 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 = ['_static'] + +# Add any extra paths that contain custom files (such as robots.txt or +# .htaccess) here, relative to this directory. These files are copied +# directly to the root of the documentation. +#html_extra_path = [] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +#html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +#html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +html_sidebars = { + "index": [ + "sidebarintro.html", + "links.html", + "sourcelink.html", + "searchbox.html", + ], + "**": [ + "sidebarintro.html", + "links.html", + "sourcelink.html", + "searchbox.html", + ] +} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +#html_additional_pages = {} + +# If false, no module index is generated. +#html_domain_indices = True + +# If false, no index is generated. +#html_use_index = True + +# If true, the index is split into individual pages for each letter. +#html_split_index = False + +# If true, links to the reST sources are added to the pages. +#html_show_sourcelink = True + +# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. +#html_show_sphinx = True + +# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. +#html_show_copyright = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +#html_use_opensearch = '' + +# This is the file name suffix for HTML files (e.g. ".xhtml"). +#html_file_suffix = None + +# Language to be used for generating the HTML full-text search index. +# Sphinx supports the following languages: +# 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja' +# 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr' +#html_search_language = 'en' + +# A dictionary with options for the search language support, empty by default. +# Now only 'ja' uses this config value +#html_search_options = {'type': 'default'} + +# The name of a javascript file (relative to the configuration directory) that +# implements a search results scorer. If empty, the default will be used. +#html_search_scorer = 'scorer.js' + +# Output file base name for HTML help builder. +htmlhelp_basename = 'bmidoc' + + +# -- Extension configuration ------------------------------------------------- + +# -- Options for intersphinx extension --------------------------------------- + +# Example configuration for intersphinx: refer to the Python standard library. +intersphinx_mapping = {'https://docs.python.org/': None} + +# -- Options for todo extension ---------------------------------------------- + +# If true, `todo` and `todoList` produce output, else they produce nothing. +todo_include_todos = True diff --git a/docs/source/environment.yml b/docs/source/environment.yml new file mode 100644 index 0000000..6c4e7d4 --- /dev/null +++ b/docs/source/environment.yml @@ -0,0 +1,13 @@ +name: bmipy_docs +channels: + - conda-forge +dependencies: +- python==3.6 +- pandoc +- pip +- sphinx>=1.5.1 +- sphinx_rtd_theme +- tornado +- entrypoints +- pip: + - sphinxcontrib_github_alt diff --git a/docs/source/index.rst b/docs/source/index.rst new file mode 100644 index 0000000..7346d0f --- /dev/null +++ b/docs/source/index.rst @@ -0,0 +1,11 @@ +.. title:: BMIpy + +.. include:: ../../README.rst + + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` diff --git a/docs/source/modules.rst b/docs/source/modules.rst new file mode 100644 index 0000000..8f50db5 --- /dev/null +++ b/docs/source/modules.rst @@ -0,0 +1,7 @@ +bmipy +===== + +.. toctree:: + :maxdepth: 4 + + bmipy diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..84678f7 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,4 @@ +coveralls +flake8 +pytest>=3.6 +pytest-cov diff --git a/setup.cfg b/setup.cfg index 37bfd26..58ff3b5 100644 --- a/setup.cfg +++ b/setup.cfg @@ -2,29 +2,25 @@ disable = line-too-long,bad-continuation [flake8] -exclude = docs -ignore = - E203 - E501 - W503 +exclude = docs bmipy/_version.py max-line-length = 88 [versioneer] VCS = git style = pep440 -versionfile_source = bmi/_version.py -versionfile_build = bmi/_version.py +versionfile_source = bmipy/_version.py +versionfile_build = bmipy/_version.py tag_prefix = -parentdir_prefix = bmi- +parentdir_prefix = bmipy- [tool:pytest] minversion = 3.0 -testpaths = bmi tests +testpaths = bmipy tests norecursedirs = .* *.egg* build dist addopts = --ignore setup.py --ignore versioneer.py - --ignore bmi/_version.py + --ignore bmipy/_version.py --tb native --strict --durations 16 @@ -35,4 +31,4 @@ doctest_optionflags = ALLOW_UNICODE [run] -omit = bmi/_version.py +omit = bmipy/_version.py diff --git a/tests/test_bmipy.py b/tests/test_bmipy.py new file mode 100644 index 0000000..9527458 --- /dev/null +++ b/tests/test_bmipy.py @@ -0,0 +1,134 @@ +import pytest + +from bmipy import Bmi + + +class EmptyBmi(Bmi): + def __init__(self): + pass + + def initialize(self, config_file): + pass + + def update(self): + pass + + def update_until(self, then): + pass + + def finalize(self): + pass + + def get_var_type(self, var_name): + pass + + def get_var_units(self, var_name): + pass + + def get_var_nbytes(self, var_name): + pass + + def get_var_itemsize(self, name): + pass + + def get_var_location(self, name): + pass + + def get_var_grid(self, var_name): + pass + + def get_grid_rank(self, grid_id): + pass + + def get_grid_size(self, grid_id): + pass + + def get_value_ptr(self, var_name): + pass + + def get_value(self, var_name): + pass + + def get_value_at_indices(self, var_name, indices): + pass + + def set_value(self, var_name, src): + pass + + def set_value_at_indices(self, var_name, src, indices): + pass + + def get_component_name(self): + pass + + def get_input_var_names(self): + pass + + def get_output_var_names(self): + pass + + def get_grid_shape(self, grid_id): + pass + + def get_grid_spacing(self, grid_id): + pass + + def get_grid_origin(self, grid_id): + pass + + def get_grid_type(self, grid_id): + pass + + def get_start_time(self): + pass + + def get_end_time(self): + pass + + def get_current_time(self): + pass + + def get_time_step(self): + pass + + def get_time_units(self): + pass + + def get_grid_edge_count(self, grid): + pass + + def get_grid_edge_nodes(self, grid, edge_nodes): + pass + + def get_grid_face_count(self, grid): + pass + + def get_grid_face_nodes(self, grid, face_nodes): + pass + + def get_grid_node_count(self, grid): + pass + + def get_grid_nodes_per_face(self, grid, nodes_per_face): + pass + + def get_grid_x(self, grid, x): + pass + + def get_grid_y(self, grid, y): + pass + + def get_grid_z(self, grid, z): + pass + + +def test_bmi_not_implemented(): + class MyBmi(Bmi): + pass + + with pytest.raises(TypeError): + Bmi() + + +def test_bmi_implemented(): + assert isinstance(EmptyBmi(), Bmi)