diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 0000000..2b6e1f2 --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,104 @@ + +version: 2 +jobs: + build: + working_directory: /root/project + docker: + + - image: karrlab/wc_env_dependencies:latest + + steps: + # Clone repository + - checkout + + # Load packages from cache + - restore_cache: + keys: + - v1-{{ arch }}-{{ .Branch }}-{{ checksum "/etc/docker-image-tag" }}-{{ checksum "requirements.txt" }} + + # Python 3 installation tasks + - run: + name: Install pkg_utils (Python 3) + command: pip3 install -U git+https://github.com/KarrLab/pkg_utils.git#egg=pkg_utils + - run: + name: Install karr_lab_build_utils (Python 3) + command: | + pip3 install -U git+https://github.com/KarrLab/log.git#egg=log + pip3 install -U git+https://github.com/KarrLab/sphinxcontrib-googleanalytics.git#egg=sphinxcontrib_googleanalytics + pip3 install -U git+https://github.com/KarrLab/wc_utils.git#egg=wc_utils[all] + pip3 install -U git+https://github.com/KarrLab/karr_lab_build_utils.git#egg=karr_lab_build_utils[all] + - run: + name: Install package configuration files including credentials + command: karr_lab_build_utils3 download-install-package-config-files + - run: + name: Setup Python environment + command: | + if [[ -f .circleci/requirements.txt ]]; then + while IFS="" read -r line || [ -n "$line" ]; do + if [[ ! -z "$line" ]] && [[ ! "$line" =~ ^# ]]; then + pip3 install -U "$line" + fi + done < .circleci/requirements.txt + fi + - run: + name: Install package (Python 3) + command: pip3 install -U -e .[all] + + # Save packages to cache + - save_cache: + key: v1-{{ arch }}-{{ .Branch }}-{{ checksum "/etc/docker-image-tag" }}-{{ checksum "requirements.txt" }} + paths: + - /usr/local/lib/python3.6/site-packages + + # Test code + - run: + name: Test code + command: | + set +e + + karr_lab_build_utils3 run-tests --with-xunit --with-coverage + TEST_EXIT_CODE_PY3=$? + + # Calculate exit code and save to file for reading by the next step + if [[ $TEST_EXIT_CODE_PY3 -eq 0 ]]; then + echo "0" > TEST_EXIT_CODE + exit 0 + else + echo "0" > TEST_EXIT_CODE + exit 1 + fi + + # Generate reports, archive results, and send notifications + - run: + name: Generate reports, archive results, and send notifications + when: always + command: | + if [[ -f TEST_EXIT_CODE ]]; then + INSTALLATION_EXIT_CODE=0 + TEST_EXIT_CODE=$( +:Date: 2019-6-25 +:Copyright: 2019, Karr Lab +:License: MIT +""" + +import cement +import bcforms +import bcforms.core + + +class BaseController(cement.Controller): + """ Base controller for command line application """ + + class Meta: + label = 'base' + description = "bcforms" + arguments = [ + (['-v', '--version'], dict(action='version', version=bcforms.__version__)), + ] + + @cement.ex(help='command_1 description') + def cmd1(self): + """ command_1 description """ + print('command_1 output') + + @cement.ex(help='command_2 description') + def cmd2(self): + """ command_2 description """ + print('command_2 output') + + @cement.ex(hide=True) + def _default(self): + self._parser.print_help() + + +class Command3WithArgumentsController(cement.Controller): + """ Command3 description """ + + class Meta: + label = 'command-3' + description = 'Command3 description' + stacked_on = 'base' + stacked_type = 'nested' + arguments = [ + (['arg_1'], dict( + type=str, help='Description of arg_1')), + (['arg_2'], dict( + type=str, help='Description of arg_2')), + (['--opt-arg-3'], dict( + type=str, default='default value of opt-arg-1', help='Description of opt-arg-3')), + (['--opt-arg-4'], dict( + type=float, default=float('nan'), help='Description of opt-arg-4')), + ] + + @cement.ex(hide=True) + def _default(self): + args = self.app.pargs + args.arg_1 + args.arg_2 + args.opt_arg_3 + args.opt_arg_4 + + +class App(cement.App): + """ Command line application """ + class Meta: + label = 'bcforms' + base_controller = 'base' + handlers = [ + BaseController, + Command3WithArgumentsController, + ] + +def main(): + with App() as app: + app.run() \ No newline at end of file diff --git a/bcforms/core.py b/bcforms/core.py new file mode 100644 index 0000000..488fc29 --- /dev/null +++ b/bcforms/core.py @@ -0,0 +1,47 @@ +""" bcforms + +:Author: Name +:Date: 2019-6-25 +:Copyright: 2019, Karr Lab +:License: MIT +""" + + +class ExampleClass(object): + """ Descipton of ExampleClass + + Attributes: + attr_1 (:obj:`type of attr_1`): description of attr_1 + attr_2 (:obj:`type of attr_2`): description of attr_2 + ... + """ + + def __init__(self, arg_1, arg_2, kwarg_1=None, kwarg_2=None): + """ + Args: + arg_1 (:obj:`type of arg_1`): description of arg_1 + arg_2 (:obj:`type of arg_2`): description of arg_2 + kwarg_1 (:obj:`type of kwarg_1`, optional): description of kwarg_1 + kwarg_2 (:obj:`type of kwarg_2`, optional): description of kwarg_2 + ... + """ + self.attr_1 = arg_1 + self.attr_2 = arg_2 + + def method_1(self, arg_1, arg_2, kwarg_1=None, kwarg_2=None): + """ Description of method_1 + + Args: + arg_1 (:obj:`type of arg_1`): description of arg_1 + arg_2 (:obj:`type of arg_2`): description of arg_2 + kwarg_1 (:obj:`type of kwarg_1`, optional): description of kwarg_1 + kwarg_2 (:obj:`type of kwarg_2`, optional): description of kwarg_2 + ... + + Returns: + :obj:`type of return value`: description of return value + + Raises: + :obj:`type of raised exception(s)`: description of raised exceptions + """ + pass \ No newline at end of file diff --git a/docs/about.rst b/docs/about.rst new file mode 100644 index 0000000..933ed11 --- /dev/null +++ b/docs/about.rst @@ -0,0 +1,27 @@ +About +===== + +---------------------- +License +---------------------- + +The software is released under the MIT license + +.. literalinclude:: ../LICENSE + :language: text + +---------------------- +Development team +---------------------- + +This package was developed by the `Karr Lab `_ at the Icahn School of Medicine at Mount Sinai in New York, USA. + +---------------------- +Acknowledgements +---------------------- + +---------------------- +Questions and comments +---------------------- + +Please contact the `Karr Lab `_ with any questions or comments. \ No newline at end of file diff --git a/docs/conf.py b/docs/conf.py new file mode 100644 index 0000000..8943668 --- /dev/null +++ b/docs/conf.py @@ -0,0 +1,398 @@ +# -*- coding: utf-8 -*- +# +# Documentation build configuration file, created by karr_lab_build_utils. +# +import datetime +import os +import sys +sys.path.insert(0, os.path.abspath('..')) + +# -- General configuration ------------------------------------------------ + +# If your documentation needs a minimal Sphinx version, state it here. +# +# needs_sphinx = '1.0' + +# 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.autosectionlabel', + 'sphinx.ext.coverage', + 'sphinx.ext.imgconverter', + 'sphinx.ext.linkcode', + 'sphinx.ext.mathjax', + 'sphinx.ext.napoleon', + 'sphinx.ext.todo', + 'sphinx_fontawesome', + 'sphinxcontrib.addmetahtml', + 'sphinxcontrib.bibtex', + 'sphinxcontrib.googleanalytics', + 'sphinxcontrib.spelling', + 'sphinxprettysearchresults', +] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix(es) of source filenames. +# You can specify multiple suffix as a list of string: +# +# source_suffix = ['.rst', '.md'] +source_suffix = '.rst' + +# The encoding of source files. +# +# source_encoding = 'utf-8-sig' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = u'bcforms' +copyright = u'{}, Karr Lab'.format(datetime.datetime.now().year) +author = u'Karr Lab' + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +filename = os.path.join(os.path.dirname(__file__), '..', 'bcforms', 'VERSION') +with open(filename, 'r') as file: + version = file.read() +# The full version, including alpha/beta/rc tags. +release = version + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +# +# This is also used if you do content translation via gettext catalogs. +# Usually you set "language" from the command line for these cases. +language = None + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +# +# today = '' +# +# Else, today_fmt is used as the format for a strftime call. +# +# today_fmt = '%B %d, %Y' + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This patterns also effect to html_static_path and html_extra_path +exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] + +# The reST default role (used for this markup: `text`) to use for all +# documents. +# +# default_role = None + +# If true, '()' will be appended to :func: etc. cross-reference text. +# +# add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +# +# add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +# +# show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# A list of ignored prefixes for module index sorting. +# modindex_common_prefix = [] + +# If true, keep warnings as "system message" paragraphs in the built documents. +# keep_warnings = False + +# If true, `todo` and `todoList` produce output, else they produce nothing. +todo_include_todos = False + + +# -- section/figure/table numbering options ------------------------------- +numfig = True +numfig_format = { + 'figure': 'Figure %s', + 'table': 'Table %s', + 'code-block': 'Listing %s', + 'section': 'Section %s', +} + + +# -- image converter options ---------------------------------------------- +image_converter_args = [ + '-density', '150', + '-quality', '00', + ] + + +# -- linkcode options ----------------------------------------------------- +def linkcode_resolve(domain, info): + if domain != 'py': + return None + if not info['module']: + return None + rel_filename = info['module'].replace('.', '/') + if os.path.isfile(os.path.join(os.path.dirname(__file__), '..', rel_filename + '.py')): + return "https://github.com/KarrLab/bcforms/blob/master/{}.py".format(rel_filename) + else: + return "https://github.com/KarrLab/bcforms/blob/master/{}/__init__.py".format(rel_filename) + + +# -- napoleon options ----------------------------------------------------- +napoleon_google_docstring = True +napoleon_numpy_docstring = False +napoleon_include_private_with_doc = False +napoleon_include_special_with_doc = True +napoleon_use_admonition_for_examples = False +napoleon_use_admonition_for_notes = False +napoleon_use_admonition_for_references = False +napoleon_use_ivar = False +napoleon_use_param = True +napoleon_use_rtype = True + + +# -- Options for HTML output ---------------------------------------------- + +import sphinx_rtd_theme + +# The theme to use for HTML and HTML Help pages. See the documentation for +# 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. +# +# html_theme_options = {} + +# Add any paths that contain custom themes here, relative to this directory. +html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] + +# The name for this set of Sphinx documents. +# " v documentation" by default. +# +# html_title = u'bcforms v0.0.1' + +# 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 = None + +# The name of an image file (relative to this directory) to use as a 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 None, a 'Last updated on:' timestamp is inserted at every page +# bottom, using the given strftime format. +# The empty string is equivalent to '%b %d, %Y'. +# +# html_last_updated_fmt = None + +# 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 = {} + +# 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 = False + +# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. +# +html_show_sphinx = False + +# 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', 'zh' +# +# html_search_language = 'en' + +# A dictionary with options for the search language support, empty by default. +# 'ja' uses this config value. +# 'zh' user can custom change `jieba` dictionary path. +# +# 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 = 'bcforms-doc' + +# -- Options for LaTeX output --------------------------------------------- + +latex_elements = { + # The paper size ('letterpaper' or 'a4paper'). + # + # 'papersize': 'letterpaper', + + # The font size ('10pt', '11pt' or '12pt'). + # + # 'pointsize': '10pt', + + # Additional stuff for the LaTeX preamble. + # + # 'preamble': '', + + # Latex figure (float) alignment + # + # 'figure_align': 'htbp', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, +# author, documentclass [howto, manual, or own class]). +latex_documents = [ + (master_doc, 'bcforms.tex', u'bcforms documentation', + u'Karr Lab', 'manual'), +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +# +# latex_logo = None + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +# +# latex_use_parts = False + +# If true, show page references after internal links. +# +# latex_show_pagerefs = False + +# If true, show URL addresses after external links. +# +# latex_show_urls = False + +# Documents to append as an appendix to all manuals. +# +# latex_appendices = [] + +# It false, will not define \strong, \code, itleref, \crossref ... but only +# \sphinxstrong, ..., \sphinxtitleref, ... To help avoid clash with user added +# packages. +# +# latex_keep_old_macro_names = True + +# If false, no module index is generated. +# +# latex_domain_indices = True + + +# -- Options for manual page output --------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + (master_doc, 'bcforms', u'bcforms documentation', + [author], 1) +] + +# If true, show URL addresses after external links. +# +# man_show_urls = False + + +# -- Options for Texinfo output ------------------------------------------- + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + (master_doc, 'bcforms', u'bcforms documentation', + author, 'bcforms', 'One line description of project.', + 'Miscellaneous'), +] + +# Documents to append as an appendix to all manuals. +# +# texinfo_appendices = [] + +# If false, no module index is generated. +# +# texinfo_domain_indices = True + +# How to display URL addresses: 'footnote', 'no', or 'inline'. +# +# texinfo_show_urls = 'footnote' + +# If true, do not generate a @detailmenu in the "Top" node's menu. +# +# texinfo_no_detailmenu = False + + +# -- Google analytics ID -------------------------------------------------- + +googleanalytics_id = 'UA-86340737-1' + + +# -- if RTD, redirect to https://docs.karrlab.org ------------------------ + +addmetahtml_content = '' +addmetahtml_enabled = os.getenv('READTHEDOCS', '') == 'True' \ No newline at end of file diff --git a/docs/index.rst b/docs/index.rst new file mode 100644 index 0000000..3445bbf --- /dev/null +++ b/docs/index.rst @@ -0,0 +1,15 @@ +bcforms documentation +===================== + +Contents +-------- + +.. toctree:: + :maxdepth: 3 + :numbered: + + installation.rst + overview.rst + API documentation + about.rst + references.rst \ No newline at end of file diff --git a/docs/installation.rst b/docs/installation.rst new file mode 100644 index 0000000..6bf616d --- /dev/null +++ b/docs/installation.rst @@ -0,0 +1,20 @@ +Installation +============ + +Prerequisites +-------------------------- + +* Python +* Pip + +Latest revision from GitHub +--------------------------- +Run the following command to install the latest version from GitHub:: + + pip install git+https://github.com/KarrLab/bcforms.git#egg=bcforms[all] + +Latest release From PyPI +--------------------------- +Run the following command to install the latest release from PyPI:: + + pip install bcforms[all] \ No newline at end of file diff --git a/docs/overview.rst b/docs/overview.rst new file mode 100644 index 0000000..0f276ed --- /dev/null +++ b/docs/overview.rst @@ -0,0 +1,2 @@ +Overview +======== \ No newline at end of file diff --git a/docs/references.bib b/docs/references.bib new file mode 100644 index 0000000..e69de29 diff --git a/docs/references.rst b/docs/references.rst new file mode 100644 index 0000000..715ff65 --- /dev/null +++ b/docs/references.rst @@ -0,0 +1,6 @@ +References +========== + +.. bibliography:: references.bib + :encoding: latin + :style: unsrt \ No newline at end of file diff --git a/docs/requirements.rtd.txt b/docs/requirements.rtd.txt new file mode 100644 index 0000000..db833d4 --- /dev/null +++ b/docs/requirements.rtd.txt @@ -0,0 +1,8 @@ +sphinx >= 1.8 +sphinx_fontawesome +sphinx_rtd_theme >= 0.4.2 +sphinxcontrib_addmetahtml >= 0.1.1 +sphinxcontrib_bibtex +sphinxcontrib_googleanalytics @ git+https://github.com/karrlab/sphinxcontrib-googleanalytics.git#egg=sphinxcontrib_googleanalytics-0.1.1 +sphinxcontrib_spelling +sphinxprettysearchresults \ No newline at end of file diff --git a/docs/requirements.txt b/docs/requirements.txt new file mode 100644 index 0000000..c5953f3 --- /dev/null +++ b/docs/requirements.txt @@ -0,0 +1,8 @@ +sphinx >= 1.8 +sphinx_fontawesome +sphinx_rtd_theme >= 0.4.2 +sphinxcontrib_addmetahtml >= 0.1.1 +sphinxcontrib_bibtex +sphinxcontrib_googleanalytics >= 0.1.1 +sphinxcontrib_spelling +sphinxprettysearchresults \ No newline at end of file diff --git a/docs/spelling_wordlist.txt b/docs/spelling_wordlist.txt new file mode 100644 index 0000000..e69de29 diff --git a/requirements.optional.txt b/requirements.optional.txt new file mode 100644 index 0000000..e69de29 diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..0a809f9 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,4 @@ +cement >= 3.0.0 # for command line programs +setuptools # for pkg_resources module +bpforms[all] +wc_utils[all] diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..20e9044 --- /dev/null +++ b/setup.cfg @@ -0,0 +1,10 @@ +[bdist_wheel] +universal = 1 + +[coverage:run] +source = + bcforms + +[sphinx-apidocs] +packages = + bcforms \ No newline at end of file diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..f1d0039 --- /dev/null +++ b/setup.py @@ -0,0 +1,48 @@ +import setuptools +try: + import pkg_utils +except ImportError: + import pip._internal + pip._internal.main(['install', 'pkg_utils']) + import pkg_utils +import os + +name = 'bcforms' +dirname = os.path.dirname(__file__) +package_data = { + name: [ + 'VERSION', + ], +} + +# get package metadata +md = pkg_utils.get_package_metadata(dirname, name, package_data_filename_patterns=package_data) + +# install package +setuptools.setup( + name=name, + version=md.version, + description='Toolkit for concretely describing macromolecular complexes', + long_description=md.long_description, + url="https://github.com/KarrLab/" + name, + download_url='https://github.com/KarrLab/' + name, + author="Karr Lab", + author_email="karr@mssm.com", + license="MIT", + keywords='complex post-translational modification crosslinks systems biology', + packages=setuptools.find_packages(exclude=['tests', 'tests.*']), + package_data=md.package_data, + install_requires=md.install_requires, + extras_require=md.extras_require, + tests_require=md.tests_require, + dependency_links=md.dependency_links, + classifiers=[ + 'Development Status :: 3 - Alpha', + 'License :: OSI Approved :: MIT License', + 'Programming Language :: Python', + ], + entry_points={ + 'console_scripts': [ + ], + }, +) \ No newline at end of file diff --git a/tests/requirements.txt b/tests/requirements.txt new file mode 100644 index 0000000..7be10cb --- /dev/null +++ b/tests/requirements.txt @@ -0,0 +1,2 @@ +capturer # to capture standard output in tests +mock # to mock python classes and methods \ No newline at end of file diff --git a/tests/test_core.py b/tests/test_core.py new file mode 100644 index 0000000..b77159b --- /dev/null +++ b/tests/test_core.py @@ -0,0 +1,17 @@ +""" Test of bcforms.core + +:Author: Name +:Date: 2019-6-25 +:Copyright: 2019, Karr Lab +:License: MIT +""" + +from bcforms import core +import unittest + + +class CoreTestCase(unittest.TestCase): + + def test_1(self): + # Example test + self.assertTrue(True) # example assertion \ No newline at end of file diff --git a/tests/test_main.py b/tests/test_main.py new file mode 100644 index 0000000..927d37f --- /dev/null +++ b/tests/test_main.py @@ -0,0 +1,82 @@ +""" Tests of bcforms command line interface (bcforms.__main__) + +:Author: Name +:Date: 2019-6-25 +:Copyright: 2019, Karr Lab +:License: MIT +""" + +from bcforms import __main__ +import bcforms +import capturer +import mock +import unittest + + +class CliTestCase(unittest.TestCase): + + def test_cli(self): + with mock.patch('sys.argv', ['bcforms', '--help']): + with self.assertRaises(SystemExit) as context: + __main__.main() + self.assertRegex(context.Exception, 'usage: bcforms') + + def test_help(self): + with self.assertRaises(SystemExit): + with __main__.App(argv=['--help']) as app: + app.run() + + def test_version(self): + with __main__.App(argv=['-v']) as app: + with capturer.CaptureOutput(merged=False, relay=False) as captured: + with self.assertRaises(SystemExit): + app.run() + self.assertEqual(captured.stdout.get_text(), bcforms.__version__) + self.assertEqual(captured.stderr.get_text(), '') + + with __main__.App(argv=['--version']) as app: + with capturer.CaptureOutput(merged=False, relay=False) as captured: + with self.assertRaises(SystemExit): + app.run() + self.assertEqual(captured.stdout.get_text(), bcforms.__version__) + self.assertEqual(captured.stderr.get_text(), '') + + def test_command_1(self): + with capturer.CaptureOutput(merged=False, relay=False) as captured: + with __main__.App(argv=['command-1']) as app: + # run app + app.run() + + # test that the CLI produced the correct output + self.assertEqual(captured.stdout.get_text(), 'command_1 output') + self.assertEqual(captured.stderr.get_text(), '') + + def test_command_1(self): + with capturer.CaptureOutput(merged=False, relay=False) as captured: + with __main__.App(argv=['command-2']) as app: + # run app + app.run() + + # test that the CLI produced the correct output + self.assertEqual(captured.stdout.get_text(), 'command_2 output') + self.assertEqual(captured.stderr.get_text(), '') + + def test_command_3(self): + with capturer.CaptureOutput(merged=False, relay=False) as captured: + with __main__.App(argv=['command-3', + 'arg-1 value', + 'arg-2 value', + '--opt-arg-3', 'opt-arg-3 value', + '--opt-arg-4', 'opt-arg-4 value']) as app: + # run app + app.run() + + # test that the arguments to the CLI were correctly parsed + self.assertTrue(app.pargs.arg_1) + self.assertTrue(app.pargs.arg_2) + self.assertTrue(app.pargs.opt_arg_3) + self.assertTrue(app.pargs.opt_arg_4) + + # test that the CLI produced the correct output + self.assertEqual(captured.stdout.get_text(), '...') + self.assertEqual(captured.stderr.get_text(), '...') \ No newline at end of file