diff --git a/.gitignore b/.gitignore index ba74660..4099dca 100644 --- a/.gitignore +++ b/.gitignore @@ -43,6 +43,9 @@ nosetests.xml coverage.xml *,cover +# Vagrant +.vagrant/ + # Translations *.mo *.pot diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..f3a63e0 --- /dev/null +++ b/Makefile @@ -0,0 +1,28 @@ +.PHONY: clean-pyc test tox-test test-with-vagrant docs vagrant-up vagrant-destroy vagrant-provision test-with-vagrant + +all: clean-pyc test + +test: + py.test tests + +tox-test: + tox + +vagrant-up: + vagrant up + +vagrant-destroy: + vagrant destroy + +vagrant-provision: + vagrant provision + +test-with-vagrant: vagrant-up vagrant-provision tox-test + +clean-pyc: + find . -name '*.pyc' -exec rm -f {} + + find . -name '*.pyo' -exec rm -f {} + + find . -name '*~' -exec rm -f {} + + +docs: + $tox -e docs diff --git a/PythonConfluenceAPI/api.py b/PythonConfluenceAPI/api.py index 9efdc20..a5c5a94 100644 --- a/PythonConfluenceAPI/api.py +++ b/PythonConfluenceAPI/api.py @@ -1,5 +1,6 @@ from __future__ import absolute_import import future.standard_library + future.standard_library.install_aliases() __author__ = "Robert Cope" @@ -10,6 +11,7 @@ from urllib.parse import urljoin import logging + try: import anyjson as json except ImportError: @@ -27,9 +29,9 @@ def all_of(api_call, *args, **kwargs): If the `limit` keyword argument is set, it is used to stop the generator after the given number of result items. - >>> for i, v in enumerate(all_of(api.get_content)): - >>> v = bunchify(v) - >>> print('\t'.join((str(i), v.type, v.id, v.status, v.title))) + for i, v in enumerate(all_of(api.get_content)): + v = bunchify(v) + print('\t'.join((str(i), v.type, v.id, v.status, v.title))) :param api_call: Confluence API call (method). :param args: Positional arguments of the call. @@ -44,7 +46,6 @@ def all_of(api_call, *args, **kwargs): if pos > outer_limit: return yield item - ##print((pos, response['start'], response['limit'])) if response.get('_links', {}).get('next', None): kwargs['start'] = response['start'] + response['size'] kwargs['limit'] = response['limit'] @@ -832,8 +833,8 @@ def create_new_label_by_content_id(self, content_id, label_names, callback=None) assert isinstance(label_names, list) assert all(isinstance(ln, dict) and set(ln.keys()) == {"prefix", "name"} for ln in label_names) return self._service_post_request("rest/api/content/{id}/label".format(id=content_id), - data=json.dumps(label_names), headers={"Content-Type": "application/json"}, - callback=callback) + data=json.dumps(label_names), headers={"Content-Type": "application/json"}, + callback=callback) def create_new_property(self, content_id, property_key, new_property_data, callback=None): """ diff --git a/PythonConfluenceAPI/cfapi.py b/PythonConfluenceAPI/cfapi.py index c548658..f3bab21 100644 --- a/PythonConfluenceAPI/cfapi.py +++ b/PythonConfluenceAPI/cfapi.py @@ -27,6 +27,7 @@ def request_patch(self, *args, **kwargs): def wrap(*args_, **kwargs_): resp = sup(*args_, **kwargs_) # Patch the closure to return the callback. + # noinspection PyCallingNonCallable return background_callback(self, resp) func = wrap diff --git a/README.md b/README.md index 6c04e81..0be6d56 100644 --- a/README.md +++ b/README.md @@ -28,5 +28,56 @@ currently is a rather thin wrapper over top of the Confluence API. Users are adv look at the Atlassian API documentation for further info. Examples are also provided in the Examples directory of the repository. +# Testing + +This project uses tox for testing. These tests have an assumption of a confluence instance living +on localhost port 1990. For conveinence, a Vagrantfile has been provided that provides just that. + +To learn about using HashiCorp Vagrant, see the [getting started](https://www.vagrantup.com/docs/getting-started/) guide. + +You will also need to install tox (`pip install tox`) in order to run the test. Tox will handle creating +test virtualenvs for Python-2.7 and Python-3.4, + +To spin up the vagrant instance and perform tox tests: + + make test-with-vagrant + +_(If you do not have the make command, read the Makefile for commands. Running `vagrant up; tox` will +perform the same steps)._ + +This first run will have to download the atlassian/connect vagrant box, boot it, install and configure +Confluence. This could take around 10 minutes based on your system and Internet connection. Subsequent +test runs will complete in seconds. + +If you have already stood up a confluence instance, or you already have vagrant running, simply run tox: + + tox + +If you want to specifically test a specific version of python (say just py27), you can use tox to +specify that environment: + + tox -e py27 # run tests under Python 2.7 + tox -e py34 # run tests under Python 3.4 + +If you want to test against an alternate Confluence instance, modify tests/test_api.py to +point to that instance. + +If you want to shut down the vagrant instance (but leave it in place for later): + + make vagrant-halt + +To restart that instance, `make test-with-vagrant` will perform the steps. After a reboot, +it will takes 2-3 minutes to recreate an Atlassian instance. You can also run: + + vagrant up + vagrant provision + +To delete the vagrant instance completely: + + vagrant destroy + + + + # License This repository was written for Pushrod Technology by Robert Cope, and is licensed as LGPLv3. diff --git a/Vagrantfile b/Vagrantfile new file mode 100644 index 0000000..2853ca0 --- /dev/null +++ b/Vagrantfile @@ -0,0 +1,28 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# https://developer.atlassian.com/docs/developer-tools/working-with-the-sdk/command-reference/atlas-run-standalone + +VAGRANTFILE_API_VERSION = "2" + +Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| + + # Every Vagrant virtual environment requires a box to build off of. + config.vm.box='atlassiandev/connect' + + config.vm.network "forwarded_port", guest: 1990, host: 1990 + config.vm.provision "shell", path: "tests/start-confluence.sh" + + config.vm.provider "virtualbox" do |v| + host = RbConfig::CONFIG['host_os'] + + cpus = 2 + mem = 2048 + + v.customize ["modifyvm", :id, "--memory", mem] + v.customize ["modifyvm", :id, "--cpus", cpus] + v.customize ["modifyvm", :id, "--natdnshostresolver1", "on"] + v.customize ["modifyvm", :id, "--natdnsproxy1", "on"] + end + +end diff --git a/makedocs.sh b/makedocs.sh index f6e5458..ba60405 100755 --- a/makedocs.sh +++ b/makedocs.sh @@ -1,2 +1,2 @@ #!/bin/sh -epydoc -o doc/html --html --show-imports -n PythonConfluenceAPI -u https://github.com/pushrodtechnology/PythonConfluenceAPI --no-sourcecode PythonConfluenceAPI +tox -e docs diff --git a/tests/start-confluence.sh b/tests/start-confluence.sh new file mode 100755 index 0000000..1d6b7cc --- /dev/null +++ b/tests/start-confluence.sh @@ -0,0 +1,44 @@ +#!/bin/bash + +LS_COLORS="string" +PORT=1990 +PRODUCT=confluence +WAIT1=100 +WAIT2=20 + +sudo apt-get install -y screen + +# First, we are just going to check without doing anything. +(: /dev/null && READY=1 || READY=0 + +if [ "$READY" -eq "1" ]; then + echo "Port ${PORT} is already listening, not proceeding." + exit 0 +fi + +echo "Agreeing to Oracle License" +cd /home/vagrant/scripts +echo yes | sudo node oracle-license.js +cd /home/vagrant + +echo "Starting ${PRODUCT} in screen ${PRODUCT}" +sudo screen -d -m -L -S ${PRODUCT} atlas-run-connect --product ${PRODUCT} + +echo "Will wait ${WAIT1} seconds for port ${PORT} to open. A fresh VM could take around 5 minutes (600 seconds)." +echo "A previously configured instance will still take around 2 minutes (120 seconds)." +sleep ${WAIT1} + +while true; do + (: /dev/null && READY=1 || READY=0 + + now=`date +"%T"` + + if [ "$READY" == "1" ]; then + echo "{$now}: Port ${PORT} is listening." + exit 0 + fi + + echo "${now} Waiting ${WAIT2} seconds for ${PORT} to open". + sleep ${WAIT2} +done + diff --git a/tests/test_api.py b/tests/test_api.py new file mode 100644 index 0000000..9d08334 --- /dev/null +++ b/tests/test_api.py @@ -0,0 +1,88 @@ +from PythonConfluenceAPI import ConfluenceAPI +from requests import HTTPError + +USERNAME = 'admin' +PASSWORD = 'admin' +WIKI_SITE = 'http://localhost:1990/confluence' +API = ConfluenceAPI(USERNAME, PASSWORD, WIKI_SITE) + +def test(): + pass + +def test_get_spaces(): + + spaces = API.get_spaces() + if 'results' in spaces: + assert True + +def test_create_new_space(): + + result = API.create_new_space({ + 'key': 'TEST1', + 'name': 'My testing space', + 'description': { + 'plain': {'value': 'This is my new testing space', 'representation': 'plain'} + } + }) + + if result['name'] == 'My testing space': + assert True + +def test_create_page(): + + title = 'My landing page for TESTSPACE!' + + result = API.create_new_content({ + 'type': 'page', + 'title': title, + 'space': {'key': 'TEST1'}, + 'body': { + 'storage': {'value': '
Lorem Ipsum
', + 'representation': 'storage' + } + } + }) + + if result['title'] == title: + assert True + +def test_get_content(): + + key = 'TEST1' + title = 'My landing page for TESTSPACE!' + result = API.get_content(space_key=key, title=title) + for result in result['results']: + if result['title'] == title: + assert True + +def test_delete_page(): + + key = 'TEST1' + title = 'My landing page for TESTSPACE!' + result = API.get_content(space_key=key, title=title) + for result in result['results']: + if result['title'] == title: + id = result['id'] + + try: + d = API.delete_content_by_id(content_id=id) + assert True + except HTTPError: + assert False + +def test_delete_space(): + """Test space deletion""" + + try: + result = API.delete_space(space_key='TEST1') + except HTTPError: + assert False + + if 'id' in result.keys(): + assert True + else: + assert False + + + + diff --git a/tox.ini b/tox.ini new file mode 100644 index 0000000..98537cb --- /dev/null +++ b/tox.ini @@ -0,0 +1,20 @@ +# content of: tox.ini , put in same dir as setup.py +[tox] +envlist = py27,py34 + +[testenv] +install_command = pip install -U --ignore-installed {opts} {packages} + +deps = -rrequirements.txt + epydoc + flake8 + setuptools + pytest + +commands = pip install -e . + py.test tests + +[testenv:docs] +commands = epydoc -o doc/html --html --show-imports -n PythonConfluenceAPI \ + -u https://github.com/pushrodtechnology/PythonConfluenceAPI \ + --no-sourcecode PythonConfluenceAPI