From f03758ba27deff781c739d602fced9f05c372c7a Mon Sep 17 00:00:00 2001 From: Python3pkg Date: Wed, 17 May 2017 23:12:47 -0700 Subject: [PATCH] Convert to python3 --- bitbucket/bitbucket.py | 14 +- bitbucket/bitbucket.py.bak | 292 +++++++++++++++++++ bitbucket/repository.py | 2 +- bitbucket/repository.py.bak | 114 ++++++++ bitbucket/tests/private/issue.py | 12 +- bitbucket/tests/private/issue.py.bak | 62 ++++ bitbucket/tests/private/issue_comment.py | 18 +- bitbucket/tests/private/issue_comment.py.bak | 78 +++++ bitbucket/tests/private/private.py | 4 +- bitbucket/tests/private/private.py.bak | 89 ++++++ bitbucket/tests/private/repository.py | 2 +- bitbucket/tests/private/repository.py.bak | 116 ++++++++ bitbucket/tests/private/service.py | 6 +- bitbucket/tests/private/service.py.bak | 62 ++++ bitbucket/tests/private/ssh.py | 4 +- bitbucket/tests/private/ssh.py.bak | 50 ++++ bitbucket/tests/public.py | 4 +- bitbucket/tests/public.py.bak | 140 +++++++++ docs/conf.py | 16 +- docs/conf.py.bak | 248 ++++++++++++++++ 20 files changed, 1292 insertions(+), 41 deletions(-) create mode 100644 bitbucket/bitbucket.py.bak create mode 100644 bitbucket/repository.py.bak create mode 100644 bitbucket/tests/private/issue.py.bak create mode 100644 bitbucket/tests/private/issue_comment.py.bak create mode 100644 bitbucket/tests/private/private.py.bak create mode 100644 bitbucket/tests/private/repository.py.bak create mode 100644 bitbucket/tests/private/service.py.bak create mode 100644 bitbucket/tests/private/ssh.py.bak create mode 100755 bitbucket/tests/public.py.bak create mode 100644 docs/conf.py.bak diff --git a/bitbucket/bitbucket.py b/bitbucket/bitbucket.py index e7d7b2b..70f4e98 100644 --- a/bitbucket/bitbucket.py +++ b/bitbucket/bitbucket.py @@ -4,7 +4,7 @@ __all__ = ['Bitbucket', ] try: - from urlparse import parse_qs + from urllib.parse import parse_qs except ImportError: from urllib.parse import parse_qs @@ -82,8 +82,8 @@ def username(self): @username.setter def username(self, value): try: - if isinstance(value, basestring): - self._username = unicode(value) + if isinstance(value, str): + self._username = str(value) except NameError: self._username = value @@ -102,8 +102,8 @@ def password(self): @password.setter def password(self, value): try: - if isinstance(value, basestring): - self._password = unicode(value) + if isinstance(value, str): + self._password = str(value) except NameError: self._password = value @@ -125,8 +125,8 @@ def repo_slug(self, value): self._repo_slug = None else: try: - if isinstance(value, basestring): - value = unicode(value) + if isinstance(value, str): + value = str(value) except NameError: pass value = value.lower() diff --git a/bitbucket/bitbucket.py.bak b/bitbucket/bitbucket.py.bak new file mode 100644 index 0000000..e7d7b2b --- /dev/null +++ b/bitbucket/bitbucket.py.bak @@ -0,0 +1,292 @@ +# -*- coding: utf-8 -*- +# git+git://github.com/Sheeprider/BitBucket-api.git + +__all__ = ['Bitbucket', ] + +try: + from urlparse import parse_qs +except ImportError: + from urllib.parse import parse_qs + +import json +import re + +from requests import Request, Session +from requests_oauthlib import OAuth1 +import requests + +from .issue import Issue +from .repository import Repository +from .service import Service +from .ssh import SSH +from .deploy_key import DeployKey + + +# ======== +# = URLs = +# ======== +URLS = { + 'BASE': 'https://bitbucket.org/!api/1.0/%s', + # Get user profile and repos + 'GET_USER': 'users/%(username)s/', + 'GET_USER_PRIVILEGES': 'user/privileges', + # Search repo + # 'SEARCH_REPO': 'repositories/?name=%(search)s', + # Get tags & branches + 'GET_TAGS': 'repositories/%(username)s/%(repo_slug)s/tags/', + 'GET_BRANCHES': 'repositories/%(username)s/%(repo_slug)s/branches/', + + 'REQUEST_TOKEN': 'oauth/request_token/', + 'AUTHENTICATE': 'oauth/authenticate?oauth_token=%(token)s', + 'ACCESS_TOKEN': 'oauth/access_token/' +} + + +class Bitbucket(object): + """ This class lets you interact with the bitbucket public API. """ + def __init__(self, username='', password='', repo_name_or_slug=''): + self.username = username + self.password = password + self.repo_slug = repo_name_or_slug + self.repo_tree = {} + self.URLS = URLS + + self.repository = Repository(self) + self.service = Service(self) + self.ssh = SSH(self) + self.issue = Issue(self) + self.deploy_key = DeployKey(self) + + self.access_token = None + self.access_token_secret = None + self.consumer_key = None + self.consumer_secret = None + self.oauth = None + + # =================== + # = Getters/Setters = + # =================== + + @property + def auth(self): + """ Return credentials for current Bitbucket user. """ + if self.oauth: + return self.oauth + return (self.username, self.password) + + @property + def username(self): + """Return your repository's username.""" + return self._username + + @username.setter + def username(self, value): + try: + if isinstance(value, basestring): + self._username = unicode(value) + except NameError: + self._username = value + + if value is None: + self._username = None + + @username.deleter + def username(self): + del self._username + + @property + def password(self): + """Return your repository's password.""" + return self._password + + @password.setter + def password(self, value): + try: + if isinstance(value, basestring): + self._password = unicode(value) + except NameError: + self._password = value + + if value is None: + self._password = None + + @password.deleter + def password(self): + del self._password + + @property + def repo_slug(self): + """Return your repository's slug name.""" + return self._repo_slug + + @repo_slug.setter + def repo_slug(self, value): + if value is None: + self._repo_slug = None + else: + try: + if isinstance(value, basestring): + value = unicode(value) + except NameError: + pass + value = value.lower() + self._repo_slug = re.sub(r'[^a-z0-9_-]+', '-', value) + + @repo_slug.deleter + def repo_slug(self): + del self._repo_slug + + # ======================== + # = Oauth authentication = + # ======================== + + def authorize(self, consumer_key, consumer_secret, callback_url=None, + access_token=None, access_token_secret=None): + """ + Call this with your consumer key, secret and callback URL, to + generate a token for verification. + """ + self.consumer_key = consumer_key + self.consumer_secret = consumer_secret + + if not access_token and not access_token_secret: + if not callback_url: + return (False, "Callback URL required") + oauth = OAuth1( + consumer_key, + client_secret=consumer_secret, + callback_uri=callback_url) + r = requests.post(self.url('REQUEST_TOKEN'), auth=oauth) + if r.status_code == 200: + creds = parse_qs(r.content) + + self.access_token = creds.get('oauth_token')[0] + self.access_token_secret = creds.get('oauth_token_secret')[0] + else: + return (False, r.content) + else: + self.finalize_oauth(access_token, access_token_secret) + + return (True, None) + + def verify(self, verifier, consumer_key=None, consumer_secret=None, + access_token=None, access_token_secret=None): + """ + After converting the token into verifier, call this to finalize the + authorization. + """ + # Stored values can be supplied to verify + self.consumer_key = consumer_key or self.consumer_key + self.consumer_secret = consumer_secret or self.consumer_secret + self.access_token = access_token or self.access_token + self.access_token_secret = access_token_secret or self.access_token_secret + + oauth = OAuth1( + self.consumer_key, + client_secret=self.consumer_secret, + resource_owner_key=self.access_token, + resource_owner_secret=self.access_token_secret, + verifier=verifier) + r = requests.post(self.url('ACCESS_TOKEN'), auth=oauth) + if r.status_code == 200: + creds = parse_qs(r.content) + else: + return (False, r.content) + + self.finalize_oauth(creds.get('oauth_token')[0], + creds.get('oauth_token_secret')[0]) + return (True, None) + + def finalize_oauth(self, access_token, access_token_secret): + """ Called internally once auth process is complete. """ + self.access_token = access_token + self.access_token_secret = access_token_secret + + # Final OAuth object + self.oauth = OAuth1( + self.consumer_key, + client_secret=self.consumer_secret, + resource_owner_key=self.access_token, + resource_owner_secret=self.access_token_secret) + + # ====================== + # = High lvl functions = + # ====================== + + def dispatch(self, method, url, auth=None, params=None, **kwargs): + """ Send HTTP request, with given method, + credentials and data to the given URL, + and return the success and the result on success. + """ + r = Request( + method=method, + url=url, + auth=auth, + params=params, + data=kwargs) + s = Session() + resp = s.send(r.prepare()) + status = resp.status_code + text = resp.text + error = resp.reason + if status >= 200 and status < 300: + if text: + try: + return (True, json.loads(text)) + except TypeError: + pass + except ValueError: + pass + return (True, text) + elif status >= 300 and status < 400: + return ( + False, + 'Unauthorized access, ' + 'please check your credentials.') + elif status >= 400 and status < 500: + return (False, 'Service not found.') + elif status >= 500 and status < 600: + return (False, 'Server error.') + else: + return (False, error) + + def url(self, action, **kwargs): + """ Construct and return the URL for a specific API service. """ + # TODO : should be static method ? + return self.URLS['BASE'] % self.URLS[action] % kwargs + + # ===================== + # = General functions = + # ===================== + + def get_user(self, username=None): + """ Returns user informations. + If username is not defined, tries to return own informations. + """ + username = username or self.username or '' + url = self.url('GET_USER', username=username) + response = self.dispatch('GET', url) + try: + return (response[0], response[1]['user']) + except TypeError: + pass + return response + + def get_tags(self, repo_slug=None): + """ Get a single repository on Bitbucket and return its tags.""" + repo_slug = repo_slug or self.repo_slug or '' + url = self.url('GET_TAGS', username=self.username, repo_slug=repo_slug) + return self.dispatch('GET', url, auth=self.auth) + + def get_branches(self, repo_slug=None): + """ Get a single repository on Bitbucket and return its branches.""" + repo_slug = repo_slug or self.repo_slug or '' + url = self.url('GET_BRANCHES', + username=self.username, + repo_slug=repo_slug) + return self.dispatch('GET', url, auth=self.auth) + + def get_privileges(self): + """ Get privledges for this user. """ + url = self.url('GET_USER_PRIVILEGES') + return self.dispatch('GET', url, auth=self.auth) diff --git a/bitbucket/repository.py b/bitbucket/repository.py index b900b9b..5d5f99a 100644 --- a/bitbucket/repository.py +++ b/bitbucket/repository.py @@ -106,7 +106,7 @@ def archive(self, repo_slug=None, format='zip', prefix=''): if self.bitbucket.repo_tree: with NamedTemporaryFile(delete=False) as archive: with ZipFile(archive, 'w') as zip_archive: - for name, file in self.bitbucket.repo_tree.items(): + for name, file in list(self.bitbucket.repo_tree.items()): with NamedTemporaryFile(delete=False) as temp_file: temp_file.write(file.encode('utf-8')) zip_archive.write(temp_file.name, prefix + name) diff --git a/bitbucket/repository.py.bak b/bitbucket/repository.py.bak new file mode 100644 index 0000000..b900b9b --- /dev/null +++ b/bitbucket/repository.py.bak @@ -0,0 +1,114 @@ +# -*- coding: utf-8 -*- +from tempfile import NamedTemporaryFile +from zipfile import ZipFile + + +URLS = { + 'CREATE_REPO': 'repositories/', + 'GET_REPO': 'repositories/%(username)s/%(repo_slug)s/', + 'UPDATE_REPO': 'repositories/%(username)s/%(repo_slug)s/', + 'DELETE_REPO': 'repositories/%(username)s/%(repo_slug)s/', + # Get archive + 'GET_ARCHIVE': 'repositories/%(username)s/%(repo_slug)s/%(format)s/master/', +} + + +class Repository(object): + """ This class provide repository-related methods to Bitbucket objects.""" + + def __init__(self, bitbucket): + self.bitbucket = bitbucket + self.bitbucket.URLS.update(URLS) + + def _get_files_in_dir(self, repo_slug=None, dir='/'): + repo_slug = repo_slug or self.bitbucket.repo_slug or '' + dir = dir.lstrip('/') + url = self.bitbucket.url( + 'GET_ARCHIVE', + username=self.bitbucket.username, + repo_slug=repo_slug, + format='src') + dir_url = url + dir + response = self.bitbucket.dispatch('GET', dir_url, auth=self.bitbucket.auth) + if response[0] and isinstance(response[1], dict): + repo_tree = response[1] + url = self.bitbucket.url( + 'GET_ARCHIVE', + username=self.bitbucket.username, + repo_slug=repo_slug, + format='raw') + # Download all files in dir + for file in repo_tree['files']: + file_url = url + '/'.join((file['path'],)) + response = self.bitbucket.dispatch('GET', file_url, auth=self.bitbucket.auth) + self.bitbucket.repo_tree[file['path']] = response[1] + # recursively download in dirs + for directory in repo_tree['directories']: + dir_path = '/'.join((dir, directory)) + self._get_files_in_dir(repo_slug=repo_slug, dir=dir_path) + + def public(self, username=None): + """ Returns all public repositories from an user. + If username is not defined, tries to return own public repos. + """ + username = username or self.bitbucket.username or '' + url = self.bitbucket.url('GET_USER', username=username) + response = self.bitbucket.dispatch('GET', url) + try: + return (response[0], response[1]['repositories']) + except TypeError: + pass + return response + + def all(self): + """ Return own repositories.""" + url = self.bitbucket.url('GET_USER', username=self.bitbucket.username) + response = self.bitbucket.dispatch('GET', url, auth=self.bitbucket.auth) + try: + return (response[0], response[1]['repositories']) + except TypeError: + pass + return response + + def get(self, repo_slug=None): + """ Get a single repository on Bitbucket and return it.""" + repo_slug = repo_slug or self.bitbucket.repo_slug or '' + url = self.bitbucket.url('GET_REPO', username=self.bitbucket.username, repo_slug=repo_slug) + return self.bitbucket.dispatch('GET', url, auth=self.bitbucket.auth) + + def create(self, repo_name, scm='git', private=True, **kwargs): + """ Creates a new repository on own Bitbucket account and return it.""" + url = self.bitbucket.url('CREATE_REPO') + return self.bitbucket.dispatch('POST', url, auth=self.bitbucket.auth, name=repo_name, scm=scm, is_private=private, **kwargs) + + def update(self, repo_slug=None, **kwargs): + """ Updates repository on own Bitbucket account and return it.""" + repo_slug = repo_slug or self.bitbucket.repo_slug or '' + url = self.bitbucket.url('UPDATE_REPO', username=self.bitbucket.username, repo_slug=repo_slug) + return self.bitbucket.dispatch('PUT', url, auth=self.bitbucket.auth, **kwargs) + + def delete(self, repo_slug=None): + """ Delete a repository on own Bitbucket account. + Please use with caution as there is NO confimation and NO undo. + """ + repo_slug = repo_slug or self.bitbucket.repo_slug or '' + url = self.bitbucket.url('DELETE_REPO', username=self.bitbucket.username, repo_slug=repo_slug) + return self.bitbucket.dispatch('DELETE', url, auth=self.bitbucket.auth) + + def archive(self, repo_slug=None, format='zip', prefix=''): + """ Get one of your repositories and compress it as an archive. + Return the path of the archive. + + format parameter is curently not supported. + """ + prefix = '%s'.lstrip('/') % prefix + self._get_files_in_dir(repo_slug=repo_slug, dir='/') + if self.bitbucket.repo_tree: + with NamedTemporaryFile(delete=False) as archive: + with ZipFile(archive, 'w') as zip_archive: + for name, file in self.bitbucket.repo_tree.items(): + with NamedTemporaryFile(delete=False) as temp_file: + temp_file.write(file.encode('utf-8')) + zip_archive.write(temp_file.name, prefix + name) + return (True, archive.name) + return (False, 'Could not archive your project.') diff --git a/bitbucket/tests/private/issue.py b/bitbucket/tests/private/issue.py index 41edce2..906ef3c 100644 --- a/bitbucket/tests/private/issue.py +++ b/bitbucket/tests/private/issue.py @@ -17,15 +17,15 @@ def _create_issue(self): self.assertFalse(success) # Test create an issue success, result = self.bb.issue.create( - title=u'Test Issue Bitbucket API', - content=u'Test Issue Bitbucket API', + title='Test Issue Bitbucket API', + content='Test Issue Bitbucket API', responsible=self.bb.username, - status=u'new', - kind=u'bug',) + status='new', + kind='bug',) self.assertTrue(success) self.assertIsInstance(result, dict) # Save latest issue's id - self.issue_id = result[u'local_id'] + self.issue_id = result['local_id'] def _get_issue(self): # Test get an issue. @@ -43,7 +43,7 @@ def _update_issue(self): content=test_content) self.assertTrue(success) self.assertIsInstance(result, dict) - self.assertEqual(test_content, result[u'content']) + self.assertEqual(test_content, result['content']) def _delete_issue(self): # Test issue delete. diff --git a/bitbucket/tests/private/issue.py.bak b/bitbucket/tests/private/issue.py.bak new file mode 100644 index 0000000..41edce2 --- /dev/null +++ b/bitbucket/tests/private/issue.py.bak @@ -0,0 +1,62 @@ +# -*- coding: utf-8 -*- +from bitbucket.tests.private.private import AuthenticatedBitbucketTest + + +class IssueAuthenticatedMethodsTest(AuthenticatedBitbucketTest): + """ Testing bitbucket.issue methods.""" + + def test_all(self): + """ Test get all issues.""" + success, result = self.bb.issue.all() + self.assertTrue(success) + self.assertIsInstance(result, dict) + + def _create_issue(self): + # Test create an invalid issue + success, result = self.bb.issue.create() + self.assertFalse(success) + # Test create an issue + success, result = self.bb.issue.create( + title=u'Test Issue Bitbucket API', + content=u'Test Issue Bitbucket API', + responsible=self.bb.username, + status=u'new', + kind=u'bug',) + self.assertTrue(success) + self.assertIsInstance(result, dict) + # Save latest issue's id + self.issue_id = result[u'local_id'] + + def _get_issue(self): + # Test get an issue. + success, result = self.bb.issue.get(issue_id=self.issue_id) + self.assertTrue(success) + self.assertIsInstance(result, dict) + # Test get an invalid issue. + success, result = self.bb.issue.get(issue_id=99999999999) + self.assertFalse(success) + + def _update_issue(self): + # Test issue update. + test_content = 'Test content' + success, result = self.bb.issue.update(issue_id=self.issue_id, + content=test_content) + self.assertTrue(success) + self.assertIsInstance(result, dict) + self.assertEqual(test_content, result[u'content']) + + def _delete_issue(self): + # Test issue delete. + success, result = self.bb.issue.delete(issue_id=self.issue_id) + self.assertTrue(success) + self.assertEqual(result, '') + + success, result = self.bb.issue.get(issue_id=self.issue_id) + self.assertFalse(success) + + def test_CRUD(self): + """ Test issue create/read/update/delete.""" + self._create_issue() + self._get_issue() + self._update_issue() + self._delete_issue() diff --git a/bitbucket/tests/private/issue_comment.py b/bitbucket/tests/private/issue_comment.py index 822de94..f9522ae 100644 --- a/bitbucket/tests/private/issue_comment.py +++ b/bitbucket/tests/private/issue_comment.py @@ -10,14 +10,14 @@ def setUp(self): super(IssueCommentAuthenticatedMethodsTest, self).setUp() # Create an issue. success, result = self.bb.issue.create( - title=u'Test Issue Bitbucket API', - content=u'Test Issue Bitbucket API', + title='Test Issue Bitbucket API', + content='Test Issue Bitbucket API', responsible=self.bb.username, - status=u'new', - kind=u'bug',) + status='new', + kind='bug',) # Save latest issue's id assert success - self.bb.issue.comment.issue_id = result[u'local_id'] + self.bb.issue.comment.issue_id = result['local_id'] def tearDown(self): """ Delete the issue.""" @@ -31,15 +31,15 @@ def test_all(self): self.assertIsInstance(result, list) def _create_issue_comment(self): - content = u'Test Issue comment Bitbucket API' + content = 'Test Issue comment Bitbucket API' # Test create an issue comment success, result = self.bb.issue.comment.create( content=content) self.assertTrue(success) self.assertIsInstance(result, dict) - self.assertEqual(result[u'content'], content) + self.assertEqual(result['content'], content) # Save latest issue comment's id - self.comment_id = result[u'comment_id'] + self.comment_id = result['comment_id'] def _get_issue_comment(self): # Test get an issue comment. @@ -58,7 +58,7 @@ def _update_issue_comment(self): content=test_content) self.assertTrue(success) self.assertIsInstance(result, dict) - self.assertEqual(test_content, result[u'content']) + self.assertEqual(test_content, result['content']) def _delete_issue_comment(self): # Test issue comment delete. diff --git a/bitbucket/tests/private/issue_comment.py.bak b/bitbucket/tests/private/issue_comment.py.bak new file mode 100644 index 0000000..822de94 --- /dev/null +++ b/bitbucket/tests/private/issue_comment.py.bak @@ -0,0 +1,78 @@ +# -*- coding: utf-8 -*- +from bitbucket.tests.private.private import AuthenticatedBitbucketTest + + +class IssueCommentAuthenticatedMethodsTest(AuthenticatedBitbucketTest): + """ Testing bitbucket.issue.comments methods.""" + + def setUp(self): + """ Add an issue to the test repository and save it's id.""" + super(IssueCommentAuthenticatedMethodsTest, self).setUp() + # Create an issue. + success, result = self.bb.issue.create( + title=u'Test Issue Bitbucket API', + content=u'Test Issue Bitbucket API', + responsible=self.bb.username, + status=u'new', + kind=u'bug',) + # Save latest issue's id + assert success + self.bb.issue.comment.issue_id = result[u'local_id'] + + def tearDown(self): + """ Delete the issue.""" + self.bb.issue.delete(issue_id=self.bb.issue.comment.issue_id) + super(IssueCommentAuthenticatedMethodsTest, self).tearDown() + + def test_all(self): + """ Test get all issue comments.""" + success, result = self.bb.issue.comment.all() + self.assertTrue(success) + self.assertIsInstance(result, list) + + def _create_issue_comment(self): + content = u'Test Issue comment Bitbucket API' + # Test create an issue comment + success, result = self.bb.issue.comment.create( + content=content) + self.assertTrue(success) + self.assertIsInstance(result, dict) + self.assertEqual(result[u'content'], content) + # Save latest issue comment's id + self.comment_id = result[u'comment_id'] + + def _get_issue_comment(self): + # Test get an issue comment. + success, result = self.bb.issue.comment.get(comment_id=self.comment_id) + self.assertTrue(success) + self.assertIsInstance(result, dict) + # Test get an invalid issue comment. + success, result = self.bb.issue.comment.get(comment_id=99999999999) + self.assertFalse(success) + + def _update_issue_comment(self): + # Test issue comment update. + test_content = 'Test content' + success, result = self.bb.issue.comment.update( + comment_id=self.comment_id, + content=test_content) + self.assertTrue(success) + self.assertIsInstance(result, dict) + self.assertEqual(test_content, result[u'content']) + + def _delete_issue_comment(self): + # Test issue comment delete. + success, result = self.bb.issue.comment.delete( + comment_id=self.comment_id) + self.assertTrue(success) + self.assertEqual(result, '') + + success, result = self.bb.issue.comment.get(comment_id=self.comment_id) + self.assertFalse(success) + + def test_CRUD(self): + """ Test issue comment create/read/update/delete.""" + self._create_issue_comment() + self._get_issue_comment() + self._update_issue_comment() + self._delete_issue_comment() diff --git a/bitbucket/tests/private/private.py b/bitbucket/tests/private/private.py index 6af399b..311a7dd 100644 --- a/bitbucket/tests/private/private.py +++ b/bitbucket/tests/private/private.py @@ -45,7 +45,7 @@ def setUp(self): token_is_valid = False while not token_is_valid: # Ensure a valid oauth_verifier before starting tests - oauth_verifier = raw_input('Enter verifier from url [oauth_verifier]') + oauth_verifier = input('Enter verifier from url [oauth_verifier]') token_is_valid = bool(oauth_verifier and self.bb.verify(oauth_verifier)[0]) if not token_is_valid: print('Invalid oauth_verifier, please try again or quit with CONTROL-C.') @@ -58,7 +58,7 @@ def setUp(self): success, result = self.bb.repository.create(TEST_REPO_SLUG, has_issues=True) # Save repository's id assert success - self.bb.repo_slug = result[u'slug'] + self.bb.repo_slug = result['slug'] def tearDown(self): """Destroying the Bitbucket...""" diff --git a/bitbucket/tests/private/private.py.bak b/bitbucket/tests/private/private.py.bak new file mode 100644 index 0000000..6af399b --- /dev/null +++ b/bitbucket/tests/private/private.py.bak @@ -0,0 +1,89 @@ +# -*- coding: utf-8 -*- +import unittest +import webbrowser + +from bitbucket.bitbucket import Bitbucket + +TEST_REPO_SLUG = 'test_bitbucket_api' + +# Store oauth credentials between tests +OAUTH_ACCESS_TOKEN = '' +OAUTH_ACCESS_TOKEN_SECRET = '' + + +class AuthenticatedBitbucketTest(unittest.TestCase): + """ Bitbucket test base class for authenticated methods.""" + def setUp(self): + """Creating a new authenticated Bitbucket...""" + try: + # Try and get OAuth credentials first, if that fails try basic auth + from settings import USERNAME, CONSUMER_KEY, CONSUMER_SECRET + PASSWORD = None + except ImportError: + try: + # TODO : check validity of credentials ? + from settings import USERNAME, PASSWORD + CONSUMER_KEY = None + CONSUMER_SECRET = None + except ImportError: + # Private tests require username and password of an existing user. + raise ImportError('Please provide either USERNAME and PASSWORD or USERNAME, CONSUMER_KEY and CONSUMER_SECRET in bitbucket/tests/private/settings.py.') + + if USERNAME and PASSWORD: + self.bb = Bitbucket(USERNAME, PASSWORD) + elif USERNAME and CONSUMER_KEY and CONSUMER_SECRET: + # Try Oauth authentication + global OAUTH_ACCESS_TOKEN, OAUTH_ACCESS_TOKEN_SECRET + self.bb = Bitbucket(USERNAME) + + # First time we need to open up a browser to enter the verifier + if not OAUTH_ACCESS_TOKEN and not OAUTH_ACCESS_TOKEN_SECRET: + self.bb.authorize(CONSUMER_KEY, CONSUMER_SECRET, 'http://localhost/') + # open a webbrowser and get the token + webbrowser.open(self.bb.url('AUTHENTICATE', token=self.bb.access_token)) + # Copy the verifier field from the URL in the browser into the console + token_is_valid = False + while not token_is_valid: + # Ensure a valid oauth_verifier before starting tests + oauth_verifier = raw_input('Enter verifier from url [oauth_verifier]') + token_is_valid = bool(oauth_verifier and self.bb.verify(oauth_verifier)[0]) + if not token_is_valid: + print('Invalid oauth_verifier, please try again or quit with CONTROL-C.') + OAUTH_ACCESS_TOKEN = self.bb.access_token + OAUTH_ACCESS_TOKEN_SECRET = self.bb.access_token_secret + else: + self.bb.authorize(CONSUMER_KEY, CONSUMER_SECRET, 'http://localhost/', OAUTH_ACCESS_TOKEN, OAUTH_ACCESS_TOKEN_SECRET) + + # Create a repository. + success, result = self.bb.repository.create(TEST_REPO_SLUG, has_issues=True) + # Save repository's id + assert success + self.bb.repo_slug = result[u'slug'] + + def tearDown(self): + """Destroying the Bitbucket...""" + # Delete the repository. + self.bb.repository.delete() + self.bb = None + + +class BitbucketAuthenticatedMethodsTest(AuthenticatedBitbucketTest): + """ Testing Bitbucket annonymous methods.""" + + def test_get_tags(self): + """ Test get_tags.""" + success, result = self.bb.get_tags() + self.assertTrue(success) + self.assertIsInstance(result, dict) + # test with invalid repository name + success, result = self.bb.get_tags(repo_slug='azertyuiop') + self.assertFalse(success) + + def test_get_branches(self): + """ Test get_branches.""" + success, result = self.bb.get_branches() + self.assertTrue(success) + self.assertIsInstance(result, dict) + # test with invalid repository name + success, result = self.bb.get_branches(repo_slug='azertyuiop') + self.assertFalse(success) diff --git a/bitbucket/tests/private/repository.py b/bitbucket/tests/private/repository.py index c3465ec..5e4de58 100644 --- a/bitbucket/tests/private/repository.py +++ b/bitbucket/tests/private/repository.py @@ -56,7 +56,7 @@ def test_update(self): success, result = self.bb.repository.update(description=test_description) self.assertTrue(success) self.assertIsInstance(result, dict) - self.assertEqual(test_description, result[u'description']) + self.assertEqual(test_description, result['description']) def test_delete(self): """ Test repository deletion.""" diff --git a/bitbucket/tests/private/repository.py.bak b/bitbucket/tests/private/repository.py.bak new file mode 100644 index 0000000..c3465ec --- /dev/null +++ b/bitbucket/tests/private/repository.py.bak @@ -0,0 +1,116 @@ +# -*- coding: utf-8 -*- +from functools import wraps +from zipfile import is_zipfile +import os +import random +import sh +import string +import unittest + +from bitbucket.tests.private.private import AuthenticatedBitbucketTest + +TEST_REPO_SLUG = "test_repository_creation" + + +def skipUnlessHasGit(f): + """ This decorator pass the test if git is not found.""" + @wraps(f) + def _decorator(): + try: + sh.git(version=True, _out='/dev/null') + return f() + except sh.CommandNotFound: + return unittest.skip("Git is not installed") + return _decorator + + +class RepositoryAuthenticatedMethodsTest(AuthenticatedBitbucketTest): + """ Testing bitbucket.repository methods.""" + + def test_all(self): + """ Test get all repositories.""" + success, result = self.bb.repository.all() + self.assertTrue(success) + self.assertIsInstance(result, list) + + def test_get(self): + """ Test get a repository.""" + success, result = self.bb.repository.get() + self.assertTrue(success) + self.assertIsInstance(result, dict) + + def test_create(self): + """ Test repository creation.""" + # TODO : test private/public repository creation + success, result = self.bb.repository.create(TEST_REPO_SLUG) + self.assertTrue(success) + self.assertIsInstance(result, dict) + # Delete repo + success, result = self.bb.repository.delete(repo_slug=TEST_REPO_SLUG) + assert success + + def test_update(self): + """ Test repository update.""" + # Try to change description + test_description = 'Test Description' + success, result = self.bb.repository.update(description=test_description) + self.assertTrue(success) + self.assertIsInstance(result, dict) + self.assertEqual(test_description, result[u'description']) + + def test_delete(self): + """ Test repository deletion.""" + # Create repo + success, result = self.bb.repository.create(TEST_REPO_SLUG) + assert success + # Delete it + success, result = self.bb.repository.delete(repo_slug=TEST_REPO_SLUG) + self.assertTrue(success) + self.assertEqual(result, '') + + success, result = self.bb.repository.get(repo_slug=TEST_REPO_SLUG) + self.assertFalse(success) + + +class ArchiveRepositoryAuthenticatedMethodsTest(AuthenticatedBitbucketTest): + """ + Testing bitbucket.repository.archive method, which require + custom setUp and tearDown methods. + + test_archive require a commit to download the repository. + """ + + def setUp(self): + """ Clone the test repo locally, then add and push a commit.""" + super(ArchiveRepositoryAuthenticatedMethodsTest, self).setUp() + # Clone test repository localy. + repo_origin = 'git@bitbucket.org:%s/%s.git' % (self.bb.username, self.bb.repo_slug) + # TODO : Put the temp folder on the right place for windows. + repo_folder = os.path.join( + '/tmp', + 'bitbucket-' + ''.join(random.choice(string.digits + string.letters) for x in range(10))) + sh.mkdir(repo_folder) + sh.cd(repo_folder) + self.pwd = sh.pwd().strip() + sh.git.init() + sh.git.remote('add', 'origin', repo_origin) + # Add commit with empty file. + sh.touch('file') + sh.git.add('.') + sh.git.commit('-m', '"Add empty file."') + sh.git.push('origin', 'master') + + def tearDown(self): + """ Delete the git folder.""" + super(ArchiveRepositoryAuthenticatedMethodsTest, self).tearDown() + sh.rm('-rf', self.pwd) + + @skipUnlessHasGit + def test_archive(self): + """ Test repository download as archive.""" + success, archive_path = self.bb.repository.archive() + self.assertTrue(success) + self.assertTrue(os.path.exists(archive_path)) + self.assertTrue(is_zipfile(archive_path)) + # delete temporary file + os.unlink(archive_path) diff --git a/bitbucket/tests/private/service.py b/bitbucket/tests/private/service.py index 25b902b..00f59bf 100644 --- a/bitbucket/tests/private/service.py +++ b/bitbucket/tests/private/service.py @@ -18,12 +18,12 @@ def _create_service(self): self.bb.service.create() # Test create an service success, result = self.bb.service.create( - service=u'POST', + service='POST', URL=httpbin + 'post',) self.assertTrue(success) self.assertIsInstance(result, dict) # Save latest service's id - self.service_id = result[u'id'] + self.service_id = result['id'] def _get_service(self): # Test get an service. @@ -42,7 +42,7 @@ def _update_service(self): URL=test_url) self.assertTrue(success) self.assertIsInstance(result, dict) - self.assertEqual(test_url, result[u'service'][u'fields'][0][u'value']) + self.assertEqual(test_url, result['service']['fields'][0]['value']) def _delete_service(self): # Test service delete. diff --git a/bitbucket/tests/private/service.py.bak b/bitbucket/tests/private/service.py.bak new file mode 100644 index 0000000..25b902b --- /dev/null +++ b/bitbucket/tests/private/service.py.bak @@ -0,0 +1,62 @@ +# -*- coding: utf-8 -*- +from bitbucket.tests.private.private import AuthenticatedBitbucketTest +from bitbucket.tests.public import httpbin + + +class ServiceAuthenticatedMethodsTest(AuthenticatedBitbucketTest): + """ Testing bitbucket.service methods.""" + + def test_all(self): + """ Test get all services.""" + success, result = self.bb.service.all() + self.assertTrue(success) + self.assertIsInstance(result, list) + + def _create_service(self): + # Test create an invalid service + with self.assertRaises(TypeError): + self.bb.service.create() + # Test create an service + success, result = self.bb.service.create( + service=u'POST', + URL=httpbin + 'post',) + self.assertTrue(success) + self.assertIsInstance(result, dict) + # Save latest service's id + self.service_id = result[u'id'] + + def _get_service(self): + # Test get an service. + success, result = self.bb.service.get(service_id=self.service_id) + self.assertTrue(success) + self.assertIsInstance(result, list) + # Test get an invalid service. + success, result = self.bb.service.get(service_id=99999999999) + self.assertTrue(success) + self.assertEqual(result, []) + + def _update_service(self): + # Test service update. + test_url = httpbin + 'get' + success, result = self.bb.service.update(service_id=self.service_id, + URL=test_url) + self.assertTrue(success) + self.assertIsInstance(result, dict) + self.assertEqual(test_url, result[u'service'][u'fields'][0][u'value']) + + def _delete_service(self): + # Test service delete. + success, result = self.bb.service.delete(service_id=self.service_id) + self.assertTrue(success) + self.assertEqual(result, '') + + success, result = self.bb.service.get(service_id=self.service_id) + self.assertTrue(success) + self.assertEqual(result, []) + + def test_CRUD(self): + """ Test service create/read/update/delete.""" + self._create_service() + self._get_service() + self._update_service() + self._delete_service() diff --git a/bitbucket/tests/private/ssh.py b/bitbucket/tests/private/ssh.py index 76a8111..08d3dff 100644 --- a/bitbucket/tests/private/ssh.py +++ b/bitbucket/tests/private/ssh.py @@ -19,11 +19,11 @@ def _create_ssh(self): success, result = self.bb.ssh.create( key=r'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDftGyHMtFSVkIxESnJQQDGy+uXT3LuUqkaLKKjb+WeXxJEabVyur8z4urzRQyHSenrrAyd9GTLtx1zmxCn7LP626ztrIYqjdK2WBhx+wjBsF39+DNvokwLAzHpQVZnywZZXaf8aeKdwiLmUpBSpfk7dSYsjQvfkmsjBpDJz9z9NsOzVK3fIVjEdnu7nPgINiJ/DlqB9zfdXpu0o98tH/WfhDo+PvkIWYrkH/cms9LIsc4zNZIKJF6i0hDAAnC0V27GQKRXpXcnj32PZvk2eXF8TxiO0rGjkEBSd1J638GHvgLI9d8iQUAVIOm69x/trQhUKcGlcHcbU0VzaFaIYawr baptiste@smoothie-creative.com\ ', - label=u'test key',) + label='test key',) self.assertTrue(success) self.assertIsInstance(result, dict) # Save latest ssh's id - self.ssh_id = result[u'pk'] + self.ssh_id = result['pk'] def _get_ssh(self): # Test get an ssh. diff --git a/bitbucket/tests/private/ssh.py.bak b/bitbucket/tests/private/ssh.py.bak new file mode 100644 index 0000000..76a8111 --- /dev/null +++ b/bitbucket/tests/private/ssh.py.bak @@ -0,0 +1,50 @@ +# -*- coding: utf-8 -*- +from bitbucket.tests.private.private import AuthenticatedBitbucketTest + + +class SSHAuthenticatedMethodsTest(AuthenticatedBitbucketTest): + """ Testing bitbucket.ssh methods.""" + + def test_all(self): + """ Test get all sshs.""" + success, result = self.bb.ssh.all() + self.assertTrue(success) + self.assertIsInstance(result, list) + + def _create_ssh(self): + # Test create an invalid ssh + success, result = self.bb.ssh.create() + self.assertFalse(success) + # Test create an ssh + success, result = self.bb.ssh.create( + key=r'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDftGyHMtFSVkIxESnJQQDGy+uXT3LuUqkaLKKjb+WeXxJEabVyur8z4urzRQyHSenrrAyd9GTLtx1zmxCn7LP626ztrIYqjdK2WBhx+wjBsF39+DNvokwLAzHpQVZnywZZXaf8aeKdwiLmUpBSpfk7dSYsjQvfkmsjBpDJz9z9NsOzVK3fIVjEdnu7nPgINiJ/DlqB9zfdXpu0o98tH/WfhDo+PvkIWYrkH/cms9LIsc4zNZIKJF6i0hDAAnC0V27GQKRXpXcnj32PZvk2eXF8TxiO0rGjkEBSd1J638GHvgLI9d8iQUAVIOm69x/trQhUKcGlcHcbU0VzaFaIYawr baptiste@smoothie-creative.com\ +', + label=u'test key',) + self.assertTrue(success) + self.assertIsInstance(result, dict) + # Save latest ssh's id + self.ssh_id = result[u'pk'] + + def _get_ssh(self): + # Test get an ssh. + success, result = self.bb.ssh.get(key_id=self.ssh_id) + self.assertTrue(success) + self.assertIsInstance(result, dict) + # Test get an invalid ssh. + success, result = self.bb.ssh.get(key_id=99999999999) + self.assertFalse(success) + + def _delete_ssh(self): + # Test ssh delete. + success, result = self.bb.ssh.delete(key_id=self.ssh_id) + self.assertTrue(success) + self.assertEqual(result, '') + + success, result = self.bb.ssh.get(key_id=self.ssh_id) + self.assertFalse(success) + + def test_CRUD(self): + """ Test ssh create/read/delete.""" + self._create_ssh() + self._get_ssh() + self._delete_ssh() diff --git a/bitbucket/tests/public.py b/bitbucket/tests/public.py index 867f7cd..7b956d5 100755 --- a/bitbucket/tests/public.py +++ b/bitbucket/tests/public.py @@ -5,8 +5,8 @@ httpbin = 'http://httpbin.org/' -foo = u'foo' -bar = u'bar' +foo = 'foo' +bar = 'bar' username = 'baptistemillou' diff --git a/bitbucket/tests/public.py.bak b/bitbucket/tests/public.py.bak new file mode 100755 index 0000000..867f7cd --- /dev/null +++ b/bitbucket/tests/public.py.bak @@ -0,0 +1,140 @@ +# -*- coding: utf-8 -*- +# run with `site-packages$> python -m bitbucket.tests.public` +import unittest +from bitbucket.bitbucket import Bitbucket + + +httpbin = 'http://httpbin.org/' +foo = u'foo' +bar = u'bar' +username = 'baptistemillou' + + +class AnonymousBitbucketTest(unittest.TestCase): + """ Bitbucket test base class.""" + def setUp(self): + """Create a new annonymous Bitbucket...""" + self.bb = Bitbucket() + + def tearDown(self): + """Destroy the Bitbucket...""" + self.bb = None + + +class BitbucketUtilitiesTest(AnonymousBitbucketTest): + """ Test Bitbucket utilities functions.""" + + def test_default_credential(self): + self.assertEqual(self.bb.username, '') + self.assertEqual(self.bb.password, '') + self.assertEqual(self.bb.repo_slug, '') + + def test_dispatch_get(self): + success, result = self.bb.dispatch('GET', httpbin + 'get') + self.assertTrue(success) + self.assertIsInstance(result, dict) + + def test_dispatch_post(self): + success, result = self.bb.dispatch('POST', httpbin + 'post', foo='bar') + self.assertTrue(success) + self.assertIsInstance(result, dict) + self.assertEqual(result['form'], {foo: bar}) + + def test_dispatch_put(self): + success, result = self.bb.dispatch('PUT', httpbin + 'put', foo='bar') + self.assertTrue(success) + self.assertIsInstance(result, dict) + self.assertEqual(result['form'], {foo: bar}) + + def test_dispatch_delete(self): + success, result = self.bb.dispatch('DELETE', httpbin + 'delete') + self.assertTrue(success) + self.assertIsInstance(result, dict) + + def test_url_simple(self): + base = self.bb.URLS['BASE'] + create_repo = self.bb.URLS['CREATE_REPO'] + self.assertEqual(self.bb.url('CREATE_REPO'), base % create_repo) + + def test_url_complex(self): + base = self.bb.URLS['BASE'] + get_branches = self.bb.URLS['GET_BRANCHES'] + self.assertEqual( + self.bb.url('GET_BRANCHES', + username=self.bb.username, + repo_slug=self.bb.repo_slug), + base % get_branches % {'username': '', 'repo_slug': ''}) + + def test_auth(self): + self.assertEqual(self.bb.auth, (self.bb.username, self.bb.password)) + + def test_username(self): + self.bb.username = foo + self.assertEqual(self.bb.username, foo) + + del self.bb.username + with self.assertRaises(AttributeError): + self.bb.username + + def test_password(self): + self.bb.password = foo + self.assertEqual(self.bb.password, foo) + + del self.bb.password + with self.assertRaises(AttributeError): + self.bb.password + + def test_repo_slug(self): + self.bb.repo_slug = foo + self.assertEqual(self.bb.repo_slug, foo) + + del self.bb.repo_slug + with self.assertRaises(AttributeError): + self.bb.repo_slug + + +class BitbucketAnnonymousMethodsTest(AnonymousBitbucketTest): + """ Test Bitbucket annonymous methods.""" + + def test_get_user(self): + """ Test get_user on specific user.""" + success, result = self.bb.get_user(username=username) + self.assertTrue(success) + self.assertIsInstance(result, dict) + + def test_get_self_user(self): + """ Test get_user on self username.""" + self.bb.username = username + success, result = self.bb.get_user() + self.assertTrue(success) + self.assertIsInstance(result, dict) + + def test_get_none_user(self): + """ Test get_user with no username.""" + self.bb.username = None + success, result = self.bb.get_user() + self.assertFalse(success) + self.assertEqual(result, 'Service not found.') + + def test_get_public_repos(self): + """ Test public_repos on specific user.""" + success, result = self.bb.repository.public(username=username) + self.assertTrue(success) + self.assertIsInstance(result, (dict, list)) + + def test_get_self_public_repos(self): + """ Test public_repos on specific user.""" + self.bb.username = username + success, result = self.bb.repository.public() + self.assertTrue(success) + self.assertIsInstance(result, (dict, list)) + + def test_get_none_public_repos(self): + """ Test public_repos on specific user.""" + self.bb.username = None + success, result = self.bb.repository.public() + self.assertFalse(success) + self.assertEqual(result, 'Service not found.') + +if __name__ == "__main__": + unittest.main() diff --git a/docs/conf.py b/docs/conf.py index 10e2e7b..a639885 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -40,8 +40,8 @@ master_doc = 'index' # General information about the project. -project = u'Bitbucket-API' -copyright = u'2013, Baptiste Millou' +project = 'Bitbucket-API' +copyright = '2013, Baptiste Millou' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the @@ -186,8 +186,8 @@ # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, documentclass [howto/manual]). latex_documents = [ - ('index', 'Bitbucket-API.tex', u'Bitbucket-API Documentation', - u'Baptiste Millou', 'manual'), + ('index', 'Bitbucket-API.tex', 'Bitbucket-API Documentation', + 'Baptiste Millou', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of @@ -216,8 +216,8 @@ # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ - ('index', 'bitbucket-api', u'Bitbucket-API Documentation', - [u'Baptiste Millou'], 1) + ('index', 'bitbucket-api', 'Bitbucket-API Documentation', + ['Baptiste Millou'], 1) ] # If true, show URL addresses after external links. @@ -230,8 +230,8 @@ # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ - ('index', 'Bitbucket-API', u'Bitbucket-API Documentation', - u'Baptiste Millou', 'Bitbucket-API', 'One line description of project.', + ('index', 'Bitbucket-API', 'Bitbucket-API Documentation', + 'Baptiste Millou', 'Bitbucket-API', 'One line description of project.', 'Miscellaneous'), ] diff --git a/docs/conf.py.bak b/docs/conf.py.bak new file mode 100644 index 0000000..10e2e7b --- /dev/null +++ b/docs/conf.py.bak @@ -0,0 +1,248 @@ +# -*- coding: utf-8 -*- +# +# Bitbucket-API documentation build configuration file, created by +# sphinx-quickstart on Thu May 23 14:55:30 2013. +# +# This file is execfile()d with the current directory set to its containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +import sys, os + +# 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. +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.coverage', 'sphinx.ext.viewcode'] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix of source filenames. +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'Bitbucket-API' +copyright = u'2013, Baptiste Millou' + +# 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. +version = '0.4' +# The full version, including alpha/beta/rc tags. +release = '0.4.4dev' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +#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. +exclude_patterns = ['_build', ] + +# 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 + + +# -- 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 = 'default' + +# 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 = None + +# 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'] + +# 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 = {} + +# 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 + +# Output file base name for HTML help builder. +htmlhelp_basename = 'Bitbucket-APIdoc' + + +# -- 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': '', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, author, documentclass [howto/manual]). +latex_documents = [ + ('index', 'Bitbucket-API.tex', u'Bitbucket-API Documentation', + u'Baptiste Millou', '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 = [] + +# 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 = [ + ('index', 'bitbucket-api', u'Bitbucket-API Documentation', + [u'Baptiste Millou'], 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 = [ + ('index', 'Bitbucket-API', u'Bitbucket-API Documentation', + u'Baptiste Millou', 'Bitbucket-API', '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