diff --git a/docs/conf.py b/docs/conf.py index 1fed244..f5c2cde 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -27,36 +27,36 @@ # needs_sphinx = '1.0' # Do not warn on external images. -suppress_warnings = ['image.nonlocal_uri'] +suppress_warnings = ["image.nonlocal_uri"] # 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.coverage', - 'sphinx.ext.doctest', - 'sphinx.ext.graphviz', - 'sphinx.ext.intersphinx', - 'sphinx.ext.viewcode', + "sphinx.ext.autodoc", + "sphinx.ext.coverage", + "sphinx.ext.doctest", + "sphinx.ext.graphviz", + "sphinx.ext.intersphinx", + "sphinx.ext.viewcode", ] # Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] +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' +source_suffix = ".rst" # The master toctree document. -master_doc = 'index' +master_doc = "index" # General information about the project. -project = 'reana' -copyright = '2018-2019, info@reana.io' -author = 'info@reana.io' +project = "reana" +copyright = "2018-2019, info@reana.io" +author = "info@reana.io" # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the @@ -66,9 +66,9 @@ # Get the version string. Cannot be done with import! g = {} -with open(os.path.join('..', 'pytest_reana', 'version.py'), 'rt') as fp: +with open(os.path.join("..", "pytest_reana", "version.py"), "rt") as fp: exec(fp.read(), g) - version = g['__version__'] + version = g["__version__"] # The full version, including alpha/beta/rc tags. release = version @@ -83,10 +83,10 @@ # 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'] +exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] # The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' +pygments_style = "sphinx" # If true, `todo` and `todoList` produce output, else they produce nothing. todo_include_todos = False @@ -97,52 +97,52 @@ # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. # -html_theme = 'alabaster' +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 = { - 'logo': 'logo-reana.png', - 'description': """
pytest-REANA is a component of the pytest-REANA is a component of the REANA reusable and reproducible research data analysis platform.
pytest-REANA provides pytest fixtures and test utilities..
""", - 'github_user': 'reanahub', - 'github_repo': 'pytest-reana', - 'github_button': False, - 'github_banner': True, - 'show_powered_by': False, - 'extra_nav_links': { - 'REANA@DockerHub': 'https://hub.docker.com/u/reanahub/', - 'REANA@GitHub': 'https://github.com/reanahub', - 'REANA@Twitter': 'https://twitter.com/reanahub', - 'REANA@Web': 'http://www.reana.io', - } + "github_user": "reanahub", + "github_repo": "pytest-reana", + "github_button": False, + "github_banner": True, + "show_powered_by": False, + "extra_nav_links": { + "REANA@DockerHub": "https://hub.docker.com/u/reanahub/", + "REANA@GitHub": "https://github.com/reanahub", + "REANA@Twitter": "https://twitter.com/reanahub", + "REANA@Web": "http://www.reana.io", + }, } # 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'] +html_static_path = ["_static"] # Custom sidebar templates, maps document names to template names. html_sidebars = { - '**': [ - 'about.html', - 'navigation.html', - 'relations.html', - 'searchbox.html', - 'donate.html', + "**": [ + "about.html", + "navigation.html", + "relations.html", + "searchbox.html", + "donate.html", ] } # -- Options for HTMLHelp output ------------------------------------------ # Output file base name for HTML help builder. -htmlhelp_basename = 'reanadoc' +htmlhelp_basename = "reanadoc" # -- Options for LaTeX output --------------------------------------------- @@ -151,15 +151,12 @@ # 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', @@ -169,8 +166,7 @@ # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ - (master_doc, 'reana.tex', 'reana Documentation', - 'info@reana.io', 'manual'), + (master_doc, "reana.tex", "reana Documentation", "info@reana.io", "manual"), ] @@ -178,10 +174,7 @@ # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). -man_pages = [ - (master_doc, 'reana', 'reana Documentation', - [author], 1) -] +man_pages = [(master_doc, "reana", "reana Documentation", [author], 1)] # -- Options for Texinfo output ------------------------------------------- @@ -190,12 +183,18 @@ # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ - (master_doc, 'reana', 'reana Documentation', - author, 'reana', 'One line description of project.', - 'Miscellaneous'), + ( + master_doc, + "reana", + "reana Documentation", + author, + "reana", + "One line description of project.", + "Miscellaneous", + ), ] # Intersphinx configuration intersphinx_mapping = { - 'kombu': ('http://docs.celeryproject.org/projects/kombu/en/latest/', None), + "kombu": ("http://docs.celeryproject.org/projects/kombu/en/latest/", None), } diff --git a/pytest_reana/__init__.py b/pytest_reana/__init__.py index a5206fd..3851458 100644 --- a/pytest_reana/__init__.py +++ b/pytest_reana/__init__.py @@ -12,4 +12,4 @@ from .version import __version__ -__all__ = ('__version__', ) +__all__ = ("__version__",) diff --git a/pytest_reana/fixtures.py b/pytest_reana/fixtures.py index d00fa69..76d3059 100644 --- a/pytest_reana/fixtures.py +++ b/pytest_reana/fixtures.py @@ -28,7 +28,7 @@ from sqlalchemy_utils import create_database, database_exists, drop_database -@pytest.yield_fixture(scope='module') +@pytest.yield_fixture(scope="module") def tmp_shared_volume_path(tmpdir_factory): """Fixture temporary file system database. @@ -48,7 +48,7 @@ def test_dir_exists(tmp_shared_volume_path): assert os.path.exists(path) """ - temp_path = str(tmpdir_factory.mktemp('reana')) + temp_path = str(tmpdir_factory.mktemp("reana")) yield temp_path shutil.rmtree(temp_path) @@ -72,6 +72,7 @@ def test_create_workflow(session): session.commit() """ from reana_db.database import Session + yield Session Session.close() @@ -97,7 +98,7 @@ def create_ninja_turtle() assert res.status_code == 200 """ - engine = create_engine(base_app.config['SQLALCHEMY_DATABASE_URI']) + engine = create_engine(base_app.config["SQLALCHEMY_DATABASE_URI"]) base_app.session.bind = engine with base_app.app_context(): if not database_exists(engine.url): @@ -128,12 +129,13 @@ def test_default_user_exists(default) """ - default_user_id = '00000000-0000-0000-0000-000000000000' + default_user_id = "00000000-0000-0000-0000-000000000000" user = User.query.filter_by(id_=default_user_id).first() if not user: - with patch('reana_db.database.Session', return_value=session): - user = User(id_=default_user_id, email='info@reana.io', - access_token='secretkey') + with patch("reana_db.database.Session", return_value=session): + user = User( + id_=default_user_id, email="info@reana.io", access_token="secretkey" + ) session.add(user) session.commit() return user @@ -154,9 +156,7 @@ def serial_workflow(): "steps": [ { "environment": "reanahub/reana-env-jupyter", - "commands": [ - "echo 'Hello REANA'" - ] + "commands": ["echo 'Hello REANA'"], } ] }, @@ -178,10 +178,7 @@ def cwl_workflow_with_name(): "reana_specification": { "inputs": {"parameters": {"min_year": "1991", "max_year": "2001"}}, "workflow": { - "specification": { - "first": "do this", - "second": "do that" - }, + "specification": {"first": "do this", "second": "do that"}, "type": "cwl", }, "type": "cwl", @@ -201,10 +198,7 @@ def yadage_workflow_with_name(): return { "reana_specification": { "workflow": { - "specification": { - "first": "do this", - "second": "do that" - }, + "specification": {"first": "do this", "second": "do that"}, "type": "yadage", }, "inputs": {"parameters": {"min_year": "1991", "max_year": "2001"}}, @@ -226,10 +220,7 @@ def cwl_workflow_without_name(): "reana_specification": { "inputs": {"parameters": {"min_year": "1991", "max_year": "2001"}}, "workflow": { - "specification": { - "first": "do this", - "second": "do that" - }, + "specification": {"first": "do this", "second": "do that"}, "type": "cwl", }, "type": "cwl", @@ -249,10 +240,7 @@ def yadage_workflow_without_name(): return { "reana_specification": { "workflow": { - "specification": { - "first": "do this", - "second": "do that" - }, + "specification": {"first": "do this", "second": "do that"}, "type": "yadage", }, "inputs": {"parameters": {"min_year": "1991", "max_year": "2001"}}, @@ -272,8 +260,13 @@ class _BaseConsumerTestIMPL(BaseConsumer): def get_consumers(self, Consumer, channel): """Sample get consumers method.""" - return [Consumer(self.queue, callbacks=[self.on_message], - accept=[self.message_default_format])] + return [ + Consumer( + self.queue, + callbacks=[self.on_message], + accept=[self.message_default_format], + ) + ] def on_message(self, body, message): """Sample on message method.""" @@ -314,7 +307,7 @@ def test_msg(ConsumerBaseOnMessageMock) expected, ANY) """ - with patch.object(ConsumerBase, 'on_message'): + with patch.object(ConsumerBase, "on_message"): yield ConsumerBase @@ -337,6 +330,7 @@ def test_consume_1_msg(ConsumerBase, consume_queue) consume_queue(consumer, limit=1) """ + def _consume_queue(consumer, limit=None): """Consume AMQP queue. @@ -356,7 +350,7 @@ def _consume_queue(consumer, limit=None): return _consume_queue -@pytest.fixture(scope='session') +@pytest.fixture(scope="session") def in_memory_queue_connection(): """In memory message queue. @@ -373,7 +367,7 @@ def test_something(ConsumerBase, in_memory_queue_connection): """ - return Connection('memory:///') + return Connection("memory:///") @pytest.fixture @@ -384,7 +378,7 @@ def default_exchange(): This fixture offers a default :class:`kombu.Exchange`. """ - return Exchange('test-exchange', type='direct') + return Exchange("test-exchange", type="direct") @pytest.fixture @@ -395,8 +389,9 @@ def default_queue(default_exchange): This fixture offers a default :class:`kombu.Queue`. """ - return Queue('test-queue', exchange=default_exchange, - routing_key='test-routing-key') + return Queue( + "test-queue", exchange=default_exchange, routing_key="test-routing-key" + ) @pytest.fixture @@ -417,12 +412,11 @@ def test_publish_hello(default_in_memory_producer, default_queue): """ return in_memory_queue_connection.Producer( - exchange=default_exchange, - routing_key='test-routing-key', - serializer='json') + exchange=default_exchange, routing_key="test-routing-key", serializer="json" + ) -@pytest.fixture(scope='module') +@pytest.fixture(scope="module") def sample_workflow_workspace(tmp_shared_volume_path): """Return the directory path of a sample workspace. @@ -432,18 +426,16 @@ def sample_workflow_workspace(tmp_shared_volume_path): the ``tests/test_workspace`` directory. """ + def _create_sample_workflow_workspace(workflow_id): test_workspace_path = pkg_resources.resource_filename( - 'pytest_reana', - 'test_workspace') - sample_workspace_path = os.path.join(tmp_shared_volume_path, - str(workflow_id)) + "pytest_reana", "test_workspace" + ) + sample_workspace_path = os.path.join(tmp_shared_volume_path, str(workflow_id)) if not os.path.exists(sample_workspace_path): - shutil.copytree(test_workspace_path, - sample_workspace_path) + shutil.copytree(test_workspace_path, sample_workspace_path) yield sample_workspace_path - shutil.rmtree(test_workspace_path, - sample_workspace_path) + shutil.rmtree(test_workspace_path, sample_workspace_path) else: yield sample_workspace_path @@ -451,25 +443,22 @@ def _create_sample_workflow_workspace(workflow_id): @pytest.fixture() -def sample_yadage_workflow_in_db(app, - default_user, - session, - yadage_workflow_with_name): +def sample_yadage_workflow_in_db(app, default_user, session, yadage_workflow_with_name): """Create a sample workflow in the database. Scope: function Adds a sample yadage workflow in the DB. """ - workflow = Workflow(id_=uuid4(), - name='sample_serial_workflow_1', - owner_id=default_user.id_, - reana_specification=yadage_workflow_with_name[ - 'reana_specification'], - operational_options={}, - type_=yadage_workflow_with_name[ - 'reana_specification']['workflow']['type'], - logs='') + workflow = Workflow( + id_=uuid4(), + name="sample_serial_workflow_1", + owner_id=default_user.id_, + reana_specification=yadage_workflow_with_name["reana_specification"], + operational_options={}, + type_=yadage_workflow_with_name["reana_specification"]["workflow"]["type"], + logs="", + ) session.add(workflow) session.commit() yield workflow @@ -487,12 +476,13 @@ def sample_serial_workflow_in_db(app, default_user, session, serial_workflow): """ workflow = Workflow( id_=uuid4(), - name='sample_serial_workflow_1', + name="sample_serial_workflow_1", owner_id=default_user.id_, - reana_specification=serial_workflow['reana_specification'], + reana_specification=serial_workflow["reana_specification"], operational_options={}, - type_=serial_workflow['reana_specification']['workflow']['type'], - logs='') + type_=serial_workflow["reana_specification"]["workflow"]["type"], + logs="", + ) session.add(workflow) session.commit() yield workflow @@ -521,14 +511,11 @@ def no_db_user(): @pytest.fixture def user_secrets(): """Test user secrets dictionary.""" - keytab_file = base64.b64encode(b'keytab file.') + keytab_file = base64.b64encode(b"keytab file.") user_secrets = { - "username": {"value": "reanauser", - "type": "env"}, - "password": {"value": "1232456", - "type": "env"}, - ".keytab": {"value": keytab_file, - "type": "file"} + "username": {"value": "reanauser", "type": "env"}, + "password": {"value": "1232456", "type": "env"}, + ".keytab": {"value": keytab_file, "type": "file"}, } return user_secrets @@ -547,6 +534,7 @@ def corev1_api_client_with_user_secrets(no_db_user): Adds the CoreV1APIClient with example user secrets. """ + def make_corev1_api_client_with_user_secrets(user_secrets): """Callable to return. @@ -554,21 +542,20 @@ def make_corev1_api_client_with_user_secrets(user_secrets): """ corev1_api_client = Mock() metadata = client.V1ObjectMeta(name=str(no_db_user.id_)) - metadata.annotations = {'secrets_types': '{}'} + metadata.annotations = {"secrets_types": "{}"} user_secrets_values = {} secrets_types = {} for secret_name in user_secrets: # Add type metadata to secret store - secrets_types[secret_name] = \ - user_secrets[secret_name]['type'] - user_secrets_values[secret_name] = \ - user_secrets[secret_name]['value'] - metadata.annotations['secrets_types'] = json.dumps(secrets_types) + secrets_types[secret_name] = user_secrets[secret_name]["type"] + user_secrets_values[secret_name] = user_secrets[secret_name]["value"] + metadata.annotations["secrets_types"] = json.dumps(secrets_types) k8s_secrets_store = client.V1Secret( - api_version="v1", - metadata=metadata, - data=user_secrets_values) - corev1_api_client.read_namespaced_secret = \ + api_version="v1", metadata=metadata, data=user_secrets_values + ) + corev1_api_client.read_namespaced_secret = ( lambda name, namespace: k8s_secrets_store + ) return corev1_api_client + return make_corev1_api_client_with_user_secrets diff --git a/pytest_reana/plugin.py b/pytest_reana/plugin.py index 23a73b6..0b38d5f 100644 --- a/pytest_reana/plugin.py +++ b/pytest_reana/plugin.py @@ -9,13 +9,28 @@ """Pytest plugin for REANA.""" -from .fixtures import (ConsumerBase, ConsumerBaseOnMessageMock, app, - consume_queue, corev1_api_client_with_user_secrets, - cwl_workflow_with_name, cwl_workflow_without_name, - default_exchange, default_in_memory_producer, - default_queue, default_user, empty_user_secrets, - in_memory_queue_connection, no_db_user, - sample_serial_workflow_in_db, sample_workflow_workspace, - sample_yadage_workflow_in_db, serial_workflow, session, - tmp_shared_volume_path, user_secrets, - yadage_workflow_with_name, yadage_workflow_without_name) +from .fixtures import ( + ConsumerBase, + ConsumerBaseOnMessageMock, + app, + consume_queue, + corev1_api_client_with_user_secrets, + cwl_workflow_with_name, + cwl_workflow_without_name, + default_exchange, + default_in_memory_producer, + default_queue, + default_user, + empty_user_secrets, + in_memory_queue_connection, + no_db_user, + sample_serial_workflow_in_db, + sample_workflow_workspace, + sample_yadage_workflow_in_db, + serial_workflow, + session, + tmp_shared_volume_path, + user_secrets, + yadage_workflow_with_name, + yadage_workflow_without_name, +) diff --git a/pytest_reana/test_utils.py b/pytest_reana/test_utils.py index cb2f9f9..b24ed5c 100644 --- a/pytest_reana/test_utils.py +++ b/pytest_reana/test_utils.py @@ -17,15 +17,15 @@ def make_mock_api_client(component): mock_response, mock_http_response = Mock(), Mock() mock_response = {} mock_http_response.status_code = 200 - mock_http_response.raw_bytes = b'Sample downloaded data' + mock_http_response.raw_bytes = b"Sample downloaded data" - def mock_api_client(mock_response=mock_response, - mock_http_response=mock_http_response): + def mock_api_client( + mock_response=mock_response, mock_http_response=mock_http_response + ): mock_http_client, mock_result = Mock(), Mock() mock_result.result.return_value = (mock_response, mock_http_response) mock_http_client.request.return_value = mock_result - mock_api_client = BaseAPIClient(component, - http_client=mock_http_client) + mock_api_client = BaseAPIClient(component, http_client=mock_http_client) return mock_api_client._client return mock_api_client diff --git a/setup.py b/setup.py index 354c913..df0a452 100755 --- a/setup.py +++ b/setup.py @@ -15,88 +15,79 @@ from setuptools import find_packages, setup -readme = open('README.rst').read() -history = open('CHANGES.rst').read() +readme = open("README.rst").read() +history = open("CHANGES.rst").read() extras_require = { - 'docs': [ - 'Sphinx>=1.4.4', - 'sphinx-rtd-theme>=0.1.9', - ], + "docs": ["Sphinx>=1.4.4", "sphinx-rtd-theme>=0.1.9",], } -extras_require['all'] = [] +extras_require["all"] = [] for key, reqs in extras_require.items(): - if ':' == key[0]: + if ":" == key[0]: continue - extras_require['all'].extend(reqs) + extras_require["all"].extend(reqs) setup_requires = [ - 'pytest-runner>=2.7', + "pytest-runner>=2.7", ] install_requires = [ - 'apispec>=0.21.0,<0.40', - 'black>=19.10b0', - 'check-manifest>=0.25,<1', - 'checksumdir>=1.1.4,<1.2', - 'click>=7.0', - 'coverage>=5.0,<6.0', - 'jsonschema>=3.2.0,<4.0', - 'mock>=3.0,<4.0', - 'pika>=0.12.0,<0.13', + "apispec>=0.21.0,<0.40", + "black>=19.10b0", + "check-manifest>=0.25,<1", + "checksumdir>=1.1.4,<1.2", + "click>=7.0", + "coverage>=5.0,<6.0", + "jsonschema>=3.2.0,<4.0", + "mock>=3.0,<4.0", + "pika>=0.12.0,<0.13", 'pydocstyle>=5.0.0,<6.0.0 ; python_version>="3"', 'pydocstyle==3.0.0 ; python_version=="2.7"', - 'pytest-cache>=1.0,<2.0', - 'pytest-cov>=2.8.0,<3.0', - 'pytest>=3.8.0,<5.0.0', - 'reana-commons[kubernetes]>=0.7.0.dev20200203', - 'reana-db>=0.7.0.dev20200206', - 'swagger_spec_validator>=2.1.0,<3.0', + "pytest-cache>=1.0,<2.0", + "pytest-cov>=2.8.0,<3.0", + "pytest>=3.8.0,<5.0.0", + "reana-commons[kubernetes]>=0.7.0.dev20200203", + "reana-db>=0.7.0.dev20200206", + "swagger_spec_validator>=2.1.0,<3.0", ] packages = find_packages() # Get the version string. Cannot be done with import! -with open(os.path.join('pytest_reana', - 'version.py'), 'rt') as f: - version = re.search( - '__version__\s*=\s*"(?P