From c9d64e5dc9d41ce9ad0616f92310069a8203e77d Mon Sep 17 00:00:00 2001 From: DW Talton Date: Wed, 28 Aug 2019 18:29:37 -0700 Subject: [PATCH] Add support for Read the Docs API v3 Add support for RTD APIv3, which allows for PUT and POST operations (v2 was read-only). Support added via modular API client with RTD module Issue: RELENG-2239 Signed-off-by: DW Talton Change-Id: Iaad90ed360eaac0de0e7a6c5a4c6fa77ab349f70 --- docs/commands/index.rst | 1 + docs/commands/rtd.rst | 65 +++++++ lftools/api/__init__.py | 10 + lftools/api/client.py | 71 +++++++ lftools/api/endpoints/__init__.py | 10 + lftools/api/endpoints/readthedocs.py | 214 +++++++++++++++++++++ lftools/api/exceptions.py | 18 ++ lftools/cli/__init__.py | 2 + lftools/cli/rtd.py | 134 +++++++++++++ .../notes/readthedocs-1c75ba657986dc40.yaml | 24 +++ tests/fixtures/rtd/project_build_details.json | 3 + tests/fixtures/rtd/project_build_list.json | 8 + tests/fixtures/rtd/project_details.json | 3 + tests/fixtures/rtd/project_list.json | 8 + tests/fixtures/rtd/project_version_details.json | 3 + tests/fixtures/rtd/project_version_list.json | 8 + tests/test_api_client.py | 58 ++++++ tests/test_rtd.py | 140 ++++++++++++++ 18 files changed, 780 insertions(+) create mode 100644 docs/commands/rtd.rst create mode 100644 lftools/api/__init__.py create mode 100644 lftools/api/client.py create mode 100644 lftools/api/endpoints/__init__.py create mode 100644 lftools/api/endpoints/readthedocs.py create mode 100644 lftools/api/exceptions.py create mode 100644 lftools/cli/rtd.py create mode 100644 releasenotes/notes/readthedocs-1c75ba657986dc40.yaml create mode 100644 tests/fixtures/rtd/project_build_details.json create mode 100644 tests/fixtures/rtd/project_build_list.json create mode 100644 tests/fixtures/rtd/project_details.json create mode 100644 tests/fixtures/rtd/project_list.json create mode 100644 tests/fixtures/rtd/project_version_details.json create mode 100644 tests/fixtures/rtd/project_version_list.json create mode 100644 tests/test_api_client.py create mode 100644 tests/test_rtd.py diff --git a/docs/commands/index.rst b/docs/commands/index.rst index a0032c77..3aea343f 100644 --- a/docs/commands/index.rst +++ b/docs/commands/index.rst @@ -20,6 +20,7 @@ It supports the following commands: license nexus openstack + rtd schema sign version diff --git a/docs/commands/rtd.rst b/docs/commands/rtd.rst new file mode 100644 index 00000000..4055e76a --- /dev/null +++ b/docs/commands/rtd.rst @@ -0,0 +1,65 @@ +*********** +ReadTheDocs +*********** + +.. program-output:: lftools rtd --help + +Commands +======== + +project-list +------------ + +.. program-output:: lftools rtd project-list --help + +project-details +--------------- + +.. program-output:: lftools rtd project-details --help + + +project-version-list +-------------------- + +.. program-output:: lftools rtd project-version-list --help + + +project-version-details +----------------------- + +.. program-output:: lftools rtd project-version-details --help + + +project-create +-------------- + +.. program-output:: lftools rtd project-create --help + + +project-build-list +------------------ + +.. program-output:: lftools rtd project-build-list --help + + +project-build-details +--------------------- + +.. program-output:: lftools rtd project-build-details --help + + +project-build-trigger +--------------------- + +.. program-output:: lftools rtd project-build-trigger --help + + + +API requires a [rtd] section in ~/.config/lftools/lftools.ini: + +.. code-block:: bash + + [rtd] + token = REDACTED + endpoint = https://readthedocs.org/api/v3/ + diff --git a/lftools/api/__init__.py b/lftools/api/__init__.py new file mode 100644 index 00000000..3ce3ee72 --- /dev/null +++ b/lftools/api/__init__.py @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: EPL-1.0 +############################################################################## +# Copyright (c) 2019 The Linux Foundation and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +############################################################################## +"""Initializes the REST API client.""" diff --git a/lftools/api/client.py b/lftools/api/client.py new file mode 100644 index 00000000..9677888b --- /dev/null +++ b/lftools/api/client.py @@ -0,0 +1,71 @@ +# SPDX-License-Identifier: EPL-1.0 +############################################################################## +# Copyright (c) 2019 The Linux Foundation and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +############################################################################## +"""REST API interface using Requests.""" + +import json + +import requests + + +class RestApi(object): + """A generic REST API interface.""" + + def __init__(self, **params): + """Initialize the REST API class.""" + self.params = params + self.endpoint = self.params['endpoint'] + self.token = self.params['token'] + + if 'timeout' not in self.params: + self.timeout = None + + self.r = requests.Session() + self.r.headers.update({'Authorization': 'Token {}'.format(self.token)}) + self.r.headers.update({'Content-Type': 'application/json'}) + + def _request(self, url, method, data=None, timeout=10): + """Execute the requested request.""" + resp = self.r.request(method, self.endpoint + url, data=data, + timeout=timeout) + + if resp.text: + try: + if resp.headers['Content-Type'] == 'application/json': + body = json.loads(resp.text) + else: + body = resp.text + except ValueError: + body = None + + else: + body = None + return resp + + return resp, body + + def get(self, url, **kwargs): + """HTTP GET request.""" + return self._request(url, 'GET', **kwargs) + + def patch(self, url, **kwargs): + """HTTP PATCH request.""" + return self._request(url, 'PATCH', **kwargs) + + def post(self, url, **kwargs): + """HTTP POST request.""" + return self._request(url, 'POST', **kwargs) + + def put(self, url, **kwargs): + """HTTP PUT request.""" + return self._request(url, 'PUT', **kwargs) + + def delete(self, url, **kwargs): + """HTTP DELETE request.""" + return self._request(url, 'DELETE', **kwargs) diff --git a/lftools/api/endpoints/__init__.py b/lftools/api/endpoints/__init__.py new file mode 100644 index 00000000..51b4d1f8 --- /dev/null +++ b/lftools/api/endpoints/__init__.py @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: EPL-1.0 +############################################################################## +# Copyright (c) 2019 The Linux Foundation and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +############################################################################## +"""Init for endpoints module.""" diff --git a/lftools/api/endpoints/readthedocs.py b/lftools/api/endpoints/readthedocs.py new file mode 100644 index 00000000..da663254 --- /dev/null +++ b/lftools/api/endpoints/readthedocs.py @@ -0,0 +1,214 @@ +# SPDX-License-Identifier: EPL-1.0 +############################################################################## +# Copyright (c) 2019 The Linux Foundation and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +############################################################################## + +"""Read the Docs REST API interface.""" + +import json + +from lftools import config +import lftools.api.client as client + + +class ReadTheDocs(client.RestApi): + """API endpoint wrapper for readthedocs.org. + + Be sure to always include the trailing "/" when adding + new methods. + """ + + def __init__(self, **params): + """Initialize the class.""" + if 'token' not in params: + params['token'] = config.get_setting('rtd', 'token') + if 'endpoint' not in params: + params['endpoint'] = config.get_setting('rtd', 'endpoint') + super(ReadTheDocs, self).__init__(**params) + + def project_list(self): + """Return a list of projects. + + This returns the list of projects by their slug name ['slug'], + not their pretty name ['name']. Since we use these for getting + details, triggering builds, etc., the pretty name is useless. + + :param kwargs: + :return: [projects] + """ + result = self.get('projects/')[1] # NOQA + more_results = None + data = result['results'] + project_list = [] + + if result['next']: + more_results = result['next'].rsplit('/', 1)[-1] + + if more_results: + while more_results is not None: + get_more_results = self.get('projects/' + more_results)[1] + data.append(get_more_results['results']) + more_results = get_more_results['next'] + + if more_results is not None: + more_results = more_results.rsplit('/', 1)[-1] + + for project in data: + project_list.append(project['slug']) + + return project_list + + def project_details(self, project): + """Retrieve the details of a specific project. + + :param project: The project's slug + :param kwargs: + :return: {result} + """ + result = self.get('projects/{}/'.format(project))[1] + return result + + def project_version_list(self, project): + """Retrieve a list of all ACTIVE versions of a project. + + :param project: The project's slug + :return: {result} + """ + result = self.get('projects/{}/versions/?active=True' + .format(project))[1] + more_results = None + versions = [] + + # I feel like there must be a better way...but, this works. -DWTalton + initial_versions = result['results'] + for version in initial_versions: + versions.append(version['slug']) + + if result['next']: + more_results = result['next'].rsplit('/', 1)[-1] + + if more_results: + while more_results is not None: + get_more_results = self.get('projects/{}/versions/' + .format(project) + more_results)[1] + more_results = get_more_results['next'] + + for version in get_more_results['results']: + versions.append(version['slug']) + + if more_results is not None: + more_results = more_results.rsplit('/', 1)[-1] + + return versions + + def project_version_details(self, project, version): + """Retrieve details of a single version. + + :param project: The project's slug + :param version: The version's slug + :return: {result} + """ + result = self.get('projects/{}/versions/{}/' + .format(project, version))[1] + return result + + # This is implemented per their docs, however they do not appear to have + # it working yet as this always returns a 404 + def project_version_update(self, project, version, active, + privacy_level): + """Edit a version. + + :param project: The project slug + :param version: The version slug + :param active: 'true' or 'false' + :param privacy_level: 'public' or 'private' + :return: {result} + """ + data = { + 'active': active, + 'privacy_level': privacy_level + } + + json_data = json.dumps(data) + result = self.patch('projects/{}/version/{}/'.format(project, version), + data=json_data) + return result + + def project_create(self, name, repository_url, repository_type, homepage, + programming_language, language, **kwargs): + """Create a new Read the Docs project. + + :param name: Project name. Any spaces will convert to dashes for the + project slug + :param repository_url: + :param repository_type: Valid types are git, hg, bzr, and svn + :param homepage: + :param programming_language: valid programming language abbreviations + are py, java, js, cpp, ruby, php, perl, go, c, csharp, + swift, vb, r, objc, css, ts, scala, groovy, coffee, + lua, haskell, other, words + :param language: Most two letter language abbreviations: en, es, etc. + :param kwargs: + :return: {results} + """ + data = { + 'name': name, + 'repository': { + 'url': repository_url, + 'type': repository_type + }, + 'homepage': homepage, + 'programming_language': programming_language, + 'language': language + } + + json_data = json.dumps(data) + result = self.post('projects/', data=json_data, **kwargs) + return result + + def project_build_list(self, project, **kwargs): + """Retrieve the project's running build list. + + For future expansion, the statuses are cloning, + installing, building. + + :param project: The project's slug + :param kwargs: + :return: {result} + """ + result = self.get('projects/{}/builds/?running=True' + .format(project), **kwargs)[1] + + if result['count'] > 0: + return result + else: + return "There are no active builds." + + def project_build_details(self, project, build_id, **kwargs): + """Retrieve the details of a specific build. + + :param project: The project's slug + :param build_id: The build id + :param kwargs: + :return: {result} + """ + result = self.get('projects/{}/builds/{}/' + .format(project, build_id))[1] + return result + + def project_build_trigger(self, project, version): + """Trigger a project build. + + :param project: The project's slug + :param version: The version of the project to build + (must be an active version) + :return: {result} + """ + result = self.post('projects/{}/versions/{}/builds/' + .format(project, version))[1] + return result diff --git a/lftools/api/exceptions.py b/lftools/api/exceptions.py new file mode 100644 index 00000000..cbef4e9a --- /dev/null +++ b/lftools/api/exceptions.py @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: EPL-1.0 +############################################################################## +# Copyright (c) 2019 The Linux Foundation and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +############################################################################## +"""Exceptions for the API client.""" + + +class UnsupportedRequestType(Exception): + """Except on an unknown request.""" + + def __str__(self): + """Except unknown return type.""" + return "Unknown request type" diff --git a/lftools/cli/__init__.py b/lftools/cli/__init__.py index b1fd9343..2b732ef2 100644 --- a/lftools/cli/__init__.py +++ b/lftools/cli/__init__.py @@ -29,6 +29,7 @@ from lftools.cli.jenkins import jenkins_cli from lftools.cli.lfidapi import lfidapi from lftools.cli.license import license from lftools.cli.nexus import nexus +from lftools.cli.rtd import rtd from lftools.cli.schema import schema from lftools.cli.sign import sign from lftools.cli.version import version @@ -86,6 +87,7 @@ cli.add_command(infofile) cli.add_command(jenkins_cli, name='jenkins') cli.add_command(license) cli.add_command(nexus) +cli.add_command(rtd) cli.add_command(schema) cli.add_command(lfidapi) cli.add_command(sign) diff --git a/lftools/cli/rtd.py b/lftools/cli/rtd.py new file mode 100644 index 00000000..e50a9c6f --- /dev/null +++ b/lftools/cli/rtd.py @@ -0,0 +1,134 @@ +# SPDX-License-Identifier: EPL-1.0 +############################################################################## +# Copyright (c) 2019 The Linux Foundation and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +############################################################################## + +"""Read the Docs interface.""" + + +import logging +from pprint import pformat + +import click + +from lftools.api.endpoints import readthedocs + +log = logging.getLogger(__name__) + + +@click.group() +@click.pass_context +def rtd(ctx): + """Read the Docs interface.""" + pass + + +@click.command(name='project-list') +@click.pass_context +def project_list(ctx): + """Get a list of Read the Docs projects. + + Returns a list of RTD projects for the account whose + token is configured in lftools.ini. This returns the + slug name, not the pretty name. + """ + r = readthedocs.ReadTheDocs() + for project in r.project_list(): + log.info(project) + + +@click.command(name='project-details') +@click.argument('project-slug') +@click.pass_context +def project_details(ctx, project_slug): + """Retrieve project details.""" + r = readthedocs.ReadTheDocs() + data = r.project_details(project_slug) + log.info(pformat(data)) + + +@click.command(name='project-version-list') +@click.argument('project-slug') +@click.pass_context +def project_version_list(ctx, project_slug): + """Retrieve project version list.""" + r = readthedocs.ReadTheDocs() + data = r.project_version_list(project_slug) + + for version in data: + log.info(version) + + +@click.command(name='project-version-details') +@click.argument('project-slug') +@click.argument('version-slug') +@click.pass_context +def project_version_details(ctx, project_slug, version_slug): + """Retrieve project version details.""" + r = readthedocs.ReadTheDocs() + data = r.project_version_details(project_slug, version_slug) + log.info(pformat(data)) + + +@click.command(name='project-create') +@click.argument('project-name') +@click.argument('repository-url') +@click.argument('repository-type') +@click.argument('homepage') +@click.argument('programming-language') +@click.argument('language') +@click.pass_context +def project_create(ctx, project_name, repository_url, repository_type, + homepage, programming_language, language): + """Create a new project.""" + r = readthedocs.ReadTheDocs() + data = r.project_create(project_name, repository_url, repository_type, + homepage, programming_language, language) + log.info(pformat(data)) + + +@click.command(name='project-build-list') +@click.argument('project-slug') +@click.pass_context +def project_build_list(ctx, project_slug): + """Retrieve a list of a project's builds.""" + r = readthedocs.ReadTheDocs() + data = r.project_build_list(project_slug) + log.info(pformat(data)) + + +@click.command(name='project-build-details') +@click.argument('project-slug') +@click.argument('build-id') +@click.pass_context +def project_build_details(ctx, project_slug, build_id): + """Retrieve specific project build details.""" + r = readthedocs.ReadTheDocs() + data = r.project_build_details(project_slug, build_id) + log.info(pformat(data)) + + +@click.command(name='project-build-trigger') +@click.argument('project-slug') +@click.argument('version-slug') +@click.pass_context +def project_build_trigger(ctx, project_slug, version_slug): + """Trigger a new build.""" + r = readthedocs.ReadTheDocs() + data = r.project_build_trigger(project_slug, version_slug) + log.info(pformat(data)) + + +rtd.add_command(project_list) +rtd.add_command(project_details) +rtd.add_command(project_version_list) +rtd.add_command(project_version_details) +rtd.add_command(project_create) +rtd.add_command(project_build_list) +rtd.add_command(project_build_details) +rtd.add_command(project_build_trigger) diff --git a/releasenotes/notes/readthedocs-1c75ba657986dc40.yaml b/releasenotes/notes/readthedocs-1c75ba657986dc40.yaml new file mode 100644 index 00000000..7216fe04 --- /dev/null +++ b/releasenotes/notes/readthedocs-1c75ba657986dc40.yaml @@ -0,0 +1,24 @@ +--- +features: + - | + Read the Docs CRUD operations. + + Usage: Usage: lftools rtd [OPTIONS] COMMAND [ARGS] + + + .. code-block:: none + + Commands: + project-list Get a list of Read the Docs projects. + project-details Retrieve project details. + project-version-list Retrieve project version list. + project-version-details Retrieve project version details. + project-create Create a new project. + project-build-list Retrieve a list of a project's builds. + project-build-details Retrieve specific project build details. + project-build-trigger Trigger a new build. + + .. code-block:: none + + Options: + --help Show this message and exit. diff --git a/tests/fixtures/rtd/project_build_details.json b/tests/fixtures/rtd/project_build_details.json new file mode 100644 index 00000000..5acf62d6 --- /dev/null +++ b/tests/fixtures/rtd/project_build_details.json @@ -0,0 +1,3 @@ +{ + "id": 9584913 +} diff --git a/tests/fixtures/rtd/project_build_list.json b/tests/fixtures/rtd/project_build_list.json new file mode 100644 index 00000000..91c1f6f7 --- /dev/null +++ b/tests/fixtures/rtd/project_build_list.json @@ -0,0 +1,8 @@ +{ + "count": 1, + "results": [ + { + "success": true + } + ] +} diff --git a/tests/fixtures/rtd/project_details.json b/tests/fixtures/rtd/project_details.json new file mode 100644 index 00000000..2afccbfd --- /dev/null +++ b/tests/fixtures/rtd/project_details.json @@ -0,0 +1,3 @@ +{ + "slug": "testproject1" +} diff --git a/tests/fixtures/rtd/project_list.json b/tests/fixtures/rtd/project_list.json new file mode 100644 index 00000000..a8d79377 --- /dev/null +++ b/tests/fixtures/rtd/project_list.json @@ -0,0 +1,8 @@ +{ + "next":null, + "results":[ + { + "slug":"TestProject1" + } + ] +} diff --git a/tests/fixtures/rtd/project_version_details.json b/tests/fixtures/rtd/project_version_details.json new file mode 100644 index 00000000..c539c3d3 --- /dev/null +++ b/tests/fixtures/rtd/project_version_details.json @@ -0,0 +1,3 @@ +{ + "slug": "latest" +} diff --git a/tests/fixtures/rtd/project_version_list.json b/tests/fixtures/rtd/project_version_list.json new file mode 100644 index 00000000..7d080926 --- /dev/null +++ b/tests/fixtures/rtd/project_version_list.json @@ -0,0 +1,8 @@ +{ + "next": null, + "results": [ + { + "slug": "test-trigger6" + } + ] +} diff --git a/tests/test_api_client.py b/tests/test_api_client.py new file mode 100644 index 00000000..55d7e2b7 --- /dev/null +++ b/tests/test_api_client.py @@ -0,0 +1,58 @@ +# SPDX-License-Identifier: EPL-1.0 +############################################################################## +# Copyright (c) 2018 The Linux Foundation and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +############################################################################## +"""Test generic REST client.""" + +import responses + +import lftools.api.client as client + +c = client.RestApi(endpoint='', token='xyz') + + +@responses.activate +def test_get(): + responses.add(responses.GET, 'https://fakeurl/', json={'success': 'get'}, + status=200, match_querystring=True) + resp = c.get('https://fakeurl/') + assert resp[1] == {'success': 'get'} + + +@responses.activate +def test_patch(): + responses.add(responses.PATCH, url='https://fakeurl/', + json={'success': 'patch'}, status=204, + match_querystring=True) + resp = c.patch('https://fakeurl/') + assert resp[1] == {'success': 'patch'} + + +@responses.activate +def test_post(): + responses.add(responses.POST, 'https://fakeurl/', json={'success': 'post'}, + status=201, match_querystring=True) + resp = c.post('https://fakeurl/') + assert resp[1] == {'success': 'post'} + + +@responses.activate +def test_put(): + responses.add(responses.PUT, 'https://fakeurl/', json={'success': 'put'}, + status=200, match_querystring=True) + resp = c.put('https://fakeurl/') + assert resp[1] == {'success': 'put'} + + +@responses.activate +def test_delete(): + responses.add(responses.DELETE, 'https://fakeurl/', + json={'success': 'delete'}, status=200, + match_querystring=True) + resp = c.delete('https://fakeurl/') + assert resp[1] == {'success': 'delete'} diff --git a/tests/test_rtd.py b/tests/test_rtd.py new file mode 100644 index 00000000..df04c381 --- /dev/null +++ b/tests/test_rtd.py @@ -0,0 +1,140 @@ +# SPDX-License-Identifier: EPL-1.0 +############################################################################## +# Copyright (c) 2018 The Linux Foundation and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +############################################################################## +"""Test rtd command.""" + +import json +import os +import pytest +import responses + +import lftools.api.endpoints.readthedocs as client + +rtd = client.ReadTheDocs(endpoint='https://readthedocs.org/api/v3/', + token='xyz') + +FIXTURE_DIR = os.path.join(os.path.dirname( + os.path.realpath(__file__)), 'fixtures',) + + +@pytest.mark.datafiles(os.path.join(FIXTURE_DIR, 'rtd'),) +@responses.activate +def test_project_list(datafiles): + os.chdir(str(datafiles)) + json_file = open('project_list.json', 'r') + json_data = json.loads(json_file.read()) + responses.add(responses.GET, + url='https://readthedocs.org/api/v3/projects/', + json=json_data, status=200) + assert 'TestProject1' in rtd.project_list() + + +@pytest.mark.datafiles(os.path.join(FIXTURE_DIR, 'rtd'),) +@responses.activate +def test_project_details(datafiles): + os.chdir(str(datafiles)) + json_file = open('project_details.json', 'r') + json_data = json.loads(json_file.read()) + responses.add(responses.GET, + url='https://readthedocs.org/api/v3/projects/TestProject1/', + json=json_data, status=200) + assert 'slug' in rtd.project_details('TestProject1') + + +@pytest.mark.datafiles(os.path.join(FIXTURE_DIR, 'rtd'),) +@responses.activate +def test_project_version_list(datafiles): + os.chdir(str(datafiles)) + json_file = open('project_version_list.json', 'r') + json_data = json.loads(json_file.read()) + responses.add(responses.GET, + url='https://readthedocs.org/api/v3/projects/TestProject1/versions/?active=True', # noqa + json=json_data, status=200, match_querystring=True) + assert 'test-trigger6' in rtd.project_version_list('TestProject1') + + +@pytest.mark.datafiles(os.path.join(FIXTURE_DIR, 'rtd'),) +@responses.activate +def test_project_version_details(datafiles): + os.chdir(str(datafiles)) + json_file = open('project_version_details.json', 'r') + json_data = json.loads(json_file.read()) + responses.add(responses.GET, + url='https://readthedocs.org/api/v3/projects/TestProject1/versions/latest/', # noqa + json=json_data, status=200) + assert 'slug' in rtd.project_version_details('TestProject1', 'latest') + + +@responses.activate +def test_project_version_update(): + data = { + 'active': 'true', + 'privacy_level': 'public' + } + responses.add(responses.PATCH, + url='https://readthedocs.org/api/v3/projects/TestProject1/version/latest/', # noqa + json=data, status=204) + assert rtd.project_version_update('TestProject1', 'latest', + 'true', 'public') + + +@responses.activate +def test_project_create(): + data = { + 'name': 'TestProject1', + 'repository': { + 'url': 'https://repository_url', + 'type': 'my_repo_type' + }, + 'homepage': 'https://homepageurl', + 'programming_language': 'py', + 'language': 'en' + } + responses.add(responses.POST, + url='https://readthedocs.org/api/v3/projects/', + json=data, status=201) + assert rtd.project_create('TestProject1', 'https://repository_url', + 'my_repo_type', 'https://homepageurl', + 'py', 'en') + + +@pytest.mark.datafiles(os.path.join(FIXTURE_DIR, 'rtd'),) +@responses.activate +def test_project_build_list(datafiles): + os.chdir(str(datafiles)) + json_file = open('project_build_list.json', 'r') + json_data = json.loads(json_file.read()) + responses.add(responses.GET, + url='https://readthedocs.org/api/v3/projects/testproject1/builds/?running=True', # noqa + json=json_data, status=200, match_querystring=True) + assert 'success' in rtd.project_build_list('testproject1')['results'][0] + + +@pytest.mark.datafiles(os.path.join(FIXTURE_DIR, 'rtd'),) +@responses.activate +def test_project_build_details(datafiles): + os.chdir(str(datafiles)) + json_file = open('project_build_details.json', 'r') + json_data = json.loads(json_file.read()) + responses.add(responses.GET, + url='https://readthedocs.org/api/v3/projects/testproject1/builds/9584913/', # noqa + json=json_data, status=200) + assert 'id' in rtd.project_build_details('testproject1', 9584913) + + +@responses.activate +def test_project_build_trigger(): + data = { + 'project': 'testproject1', + 'version': 'latest' + } + responses.add(responses.POST, + url='https://readthedocs.org/api/v3/projects/testproject1/versions/latest/builds/', # noqa + json=data, status=201) + assert rtd.project_build_trigger('testproject1', 'latest') -- 2.16.6