Skip to content

Commit 6f4f70c

Browse files
authored
[Bitbucket] Add OO interface for projects and repositories in bitbucket server. (#640)
1 parent 1669543 commit 6f4f70c

File tree

80 files changed

+2320
-190
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

80 files changed

+2320
-190
lines changed

atlassian-python-api.code-workspace

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,12 @@
1111
"**/__pycache__": true,
1212
"**/*.pyc": true,
1313
"atlassian_python_api.egg-info": true
14+
},
15+
"files.associations": {
16+
"DELETE": "python",
17+
"GET": "python",
18+
"POST": "python",
19+
"PUT": "python",
1420
}
1521
}
1622
}

atlassian/bitbucket/__init__.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@
1010

1111

1212
class Bitbucket(BitbucketBase):
13-
bulk_headers = {"Content-Type": "application/vnd.atl.bitbucket.bulk+json"}
14-
1513
def __init__(self, url, *args, **kwargs):
1614
if "cloud" not in kwargs and ("bitbucket.org" in url):
1715
kwargs["cloud"] = True

atlassian/bitbucket/base.py

Lines changed: 15 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
# coding=utf-8
2-
import copy
3-
4-
from pprint import PrettyPrinter
52

63
from ..rest_client import AtlassianRestAPI
74

85

96
class BitbucketBase(AtlassianRestAPI):
7+
bulk_headers = {"Content-Type": "application/vnd.atl.bitbucket.bulk+json"}
8+
109
def __init__(self, url, *args, **kwargs):
1110
"""
1211
Init the rest api wrapper
@@ -16,28 +15,19 @@ def __init__(self, url, *args, **kwargs):
1615
1716
:return: nothing
1817
"""
19-
if "data" in kwargs:
20-
self.__data = kwargs.pop("data")
21-
expected_type = kwargs.pop("expected_type")
22-
if not self.get_data("type") == expected_type:
23-
raise ValueError(
24-
"Expected type of data is [{}], got [{}].".format(expected_type, self.get_data("type"))
25-
)
26-
if url is None:
27-
url = self.get_link("self")
2818
super(BitbucketBase, self).__init__(url, *args, **kwargs)
2919

30-
def __str__(self):
31-
return PrettyPrinter(indent=4).pformat(self.__data)
32-
3320
def _get_paged(self, url, params=None, data=None, flags=None, trailing=None, absolute=False):
3421
"""
3522
Used to get the paged data
3623
:param url: The url to retrieve.
3724
:param params: The parameters (optional).
3825
:param data: The data (optional).
26+
:param flags: The flags (optional).
27+
:param trailing: If True, a trailing slash is added to the url (optional).
28+
:param absolute: If True, the url is used absolute and not relative to the root (optional).
3929
40-
:return: nothing
30+
:return: A generator for the project objects
4131
"""
4232

4333
if params is None:
@@ -48,7 +38,15 @@ def _get_paged(self, url, params=None, data=None, flags=None, trailing=None, abs
4838
if "values" not in response:
4939
return
5040

51-
for value in response.get("values", []):
41+
values = response.get("values", [])
42+
if not response.get("size", -1) == len(values):
43+
raise AssertionError(
44+
"Wrong response for url [{}], the size attribute doesn't match the number of recieved values:\n{}".format(
45+
self.url, response
46+
)
47+
)
48+
49+
for value in values:
5250
yield value
5351

5452
if self.cloud:
@@ -72,20 +70,3 @@ def _new_session_args(self):
7270
api_root=self.api_root,
7371
api_version=self.api_version,
7472
)
75-
76-
def update(self, **kwargs):
77-
"""
78-
Fields not present in the request body are ignored.
79-
"""
80-
self.__data = super(BitbucketBase, self).put(None, data=kwargs)
81-
return self
82-
83-
@property
84-
def data(self):
85-
return copy.copy(self.__data)
86-
87-
def get_data(self, id):
88-
return copy.copy(self.__data[id])
89-
90-
def get_link(self, link):
91-
return self.__data["links"][link]["href"]

atlassian/bitbucket/cloud/__init__.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@
66

77

88
class Cloud(BitbucketCloudBase):
9-
bulk_headers = {"Content-Type": "application/vnd.atl.bitbucket.bulk+json"}
10-
119
def __init__(self, url, *args, **kwargs):
1210
kwargs["cloud"] = True
1311
kwargs["api_root"] = None

atlassian/bitbucket/cloud/base.py

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
# coding=utf-8
2+
import copy
3+
4+
from pprint import PrettyPrinter
25

36
from ..base import BitbucketBase
47

@@ -9,20 +12,35 @@ def __init__(self, url, *args, **kwargs):
912
Init the rest api wrapper
1013
:param url: The base url used for the rest api.
1114
:param *args: The fixed arguments for the AtlassianRestApi.
12-
:param **kwargs: The fixed arguments for the AtlassianRestApi.
15+
:param **kwargs: The keyword arguments for the AtlassianRestApi.
1316
1417
:return: nothing
1518
"""
19+
if "data" in kwargs:
20+
self.__data = kwargs.pop("data")
21+
expected_type = kwargs.pop("expected_type")
22+
if not self.get_data("type") == expected_type:
23+
raise ValueError(
24+
"Expected type of data is [{}], got [{}].".format(expected_type, self.get_data("type"))
25+
)
26+
if url is None:
27+
url = self.get_link("self")
1628
super(BitbucketCloudBase, self).__init__(url, *args, **kwargs)
1729

30+
def __str__(self):
31+
return PrettyPrinter(indent=4).pformat(self.__data)
32+
1833
def _get_paged(self, url, params=None, data=None, flags=None, trailing=None, absolute=False):
1934
"""
2035
Used to get the paged data
2136
:param url: The url to retrieve.
2237
:param params: The parameters (optional).
2338
:param data: The data (optional).
39+
:param flags: The flags (optional).
40+
:param trailing: If True, a trailing slash is added to the url (optional).
41+
:param absolute: If True, the url is used absolute and not relative to the root (optional).
2442
25-
:return: nothing
43+
:return: A generator for the project objects
2644
"""
2745

2846
if params is None:
@@ -40,7 +58,15 @@ def _get_paged(self, url, params=None, data=None, flags=None, trailing=None, abs
4058
if "values" not in response:
4159
return
4260

43-
for value in response.get("values", []):
61+
values = response.get("values", [])
62+
if not response.get("size", -1) == len(values):
63+
raise AssertionError(
64+
"Wrong response for url [{}], the size attribute doesn't match the number of recieved values:\n{}".format(
65+
self.url, response
66+
)
67+
)
68+
69+
for value in values:
4470
yield value
4571

4672
url = response.get("next")
@@ -50,3 +76,20 @@ def _get_paged(self, url, params=None, data=None, flags=None, trailing=None, abs
5076
absolute = True
5177

5278
return
79+
80+
def update(self, **kwargs):
81+
"""
82+
Fields not present in the request body are ignored.
83+
"""
84+
self.__data = super(BitbucketBase, self).put(None, data=kwargs)
85+
return self
86+
87+
@property
88+
def data(self):
89+
return copy.copy(self.__data)
90+
91+
def get_data(self, id):
92+
return copy.copy(self.__data[id])
93+
94+
def get_link(self, link):
95+
return self.__data["links"][link]["href"]

atlassian/bitbucket/cloud/repositories/__init__.py

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ def __init__(self, url, *args, **kwargs):
2323

2424
def each(self, after=None, role=None, q=None, sort=None):
2525
"""
26-
Returns a list of repositories accessible by the authenticated user.
26+
Get all repositories matching the criteria.
2727
2828
The result can be narrowed down based on the authenticated user"s role.
2929
E.g. with ?role=contributor, only those repositories that the authenticated user has write access to
@@ -44,7 +44,6 @@ def each(self, after=None, role=None, q=None, sort=None):
4444
4545
:return: A generator for the Rorkspace objects
4646
"""
47-
url = None
4847
if q is not None and role is None:
4948
raise ValueError("Argument [q] requires argument [role].")
5049

@@ -57,7 +56,7 @@ def each(self, after=None, role=None, q=None, sort=None):
5756
params["q"] = q
5857
if sort is not None:
5958
params["sort"] = sort
60-
for repository in self._get_paged(url, params):
59+
for repository in self._get_paged(None, params):
6160
yield self._get_repository_object(repository)
6261

6362

@@ -67,7 +66,7 @@ def __init__(self, url, *args, **kwargs):
6766

6867
def each(self, role=None, q=None, sort=None):
6968
"""
70-
Returns a list of repositories which belong to the workspace.
69+
Get all repositories in the workspace matching the criteria.
7170
7271
:param role: string: Filters the workspaces based on the authenticated user"s role on each workspace.
7372
* member: returns a list of all the workspaces which the caller is a member of
@@ -82,15 +81,14 @@ def each(self, role=None, q=None, sort=None):
8281
8382
:return: A generator for the Rorkspace objects
8483
"""
85-
url = None
8684
params = {}
8785
if role is not None:
8886
params["role"] = role
8987
if q is not None:
9088
params["q"] = q
9189
if sort is not None:
9290
params["sort"] = sort
93-
for repository in self._get_paged(url, params):
91+
for repository in self._get_paged(None, params):
9492
yield self._get_object(repository)
9593

9694
def get(self, repository, by="slug"):
@@ -120,18 +118,17 @@ def __init__(self, url, *args, **kwargs):
120118

121119
def each(self, sort=None):
122120
"""
123-
Returns a list of repositories which belong to the project.
121+
Get all repositories in the project matching the criteria.
124122
125123
:param sort: string: Name of a response property to sort results.
126124
See https://developer.atlassian.com/bitbucket/api/2/reference/meta/filtering for details.
127125
128126
:return: A generator for the Rorkspace objects
129127
"""
130-
url = None
131128
params = {}
132129
if sort is not None:
133130
params["sort"] = sort
134-
for repository in self._get_paged(url, params):
131+
for repository in self._get_paged(None, params):
135132
yield self._get_object(repository)
136133

137134
def get(self, repository, by="slug"):

atlassian/bitbucket/cloud/repositories/branchRestrictions.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ class BranchRestrictions(BitbucketCloudBase):
77
def __init__(self, url, *args, **kwargs):
88
super(BranchRestrictions, self).__init__(url, *args, **kwargs)
99

10-
def _get_object(self, data):
10+
def __get_object(self, data):
1111
if "errors" in data:
1212
return
1313
return BranchRestriction(data, **self._new_session_args)
@@ -63,7 +63,7 @@ def create(
6363
if value is not None:
6464
data["value"] = value
6565

66-
return self._get_object(self.post(None, data=data))
66+
return self.__get_object(self.post(None, data=data))
6767

6868
def each(self, kind=None, pattern=None, q=None, sort=None):
6969
"""
@@ -88,7 +88,7 @@ def each(self, kind=None, pattern=None, q=None, sort=None):
8888
if q is not None:
8989
params["q"] = q
9090
for branch_restriction in self._get_paged(None, params=params):
91-
yield self._get_object(branch_restriction)
91+
yield self.__get_object(branch_restriction)
9292

9393
return
9494

@@ -100,7 +100,7 @@ def get(self, id):
100100
101101
:return: The requested BranchRestriction objects
102102
"""
103-
return self._get_object(super(BranchRestrictions, self).get(id))
103+
return self.__get_object(super(BranchRestrictions, self).get(id))
104104

105105

106106
class BranchRestriction(BitbucketCloudBase):

atlassian/bitbucket/cloud/repositories/defaultReviewers.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ class DefaultReviewers(BitbucketCloudBase):
99
def __init__(self, url, *args, **kwargs):
1010
super(DefaultReviewers, self).__init__(url, *args, **kwargs)
1111

12-
def _get_object(self, data):
12+
def __get_object(self, data):
1313
if "errors" in data:
1414
return
1515
return DefaultReviewer(self.url_joiner(self.url, data["display_name"]), data, **self._new_session_args)
@@ -25,7 +25,7 @@ def add(self, user):
2525
:return: The added DefaultReviewer object
2626
"""
2727
# the mention_id parameter is undocumented but if missed, leads to 400 statuses
28-
return self._get_object(self.put(user, data={"mention_id": user}))
28+
return self.__get_object(self.put(user, data={"mention_id": user}))
2929

3030
def each(self, q=None, sort=None):
3131
"""
@@ -46,7 +46,7 @@ def each(self, q=None, sort=None):
4646
if q is not None:
4747
params["q"] = q
4848
for default_reviewer in self._get_paged(None, params=params):
49-
yield self._get_object(default_reviewer)
49+
yield self.__get_object(default_reviewer)
5050

5151
return
5252

@@ -60,7 +60,7 @@ def get(self, user):
6060
"""
6161
default_reviewer = None
6262
try:
63-
default_reviewer = self._get_object(super(DefaultReviewers, self).get(user))
63+
default_reviewer = self.__get_object(super(DefaultReviewers, self).get(user))
6464
except HTTPError as e:
6565
# A 404 indicates that the specified user is not a default reviewer.
6666
if not e.response.status_code == 404:

atlassian/bitbucket/cloud/repositories/issues.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ class Issues(BitbucketCloudBase):
77
def __init__(self, url, *args, **kwargs):
88
super(Issues, self).__init__(url, *args, **kwargs)
99

10-
def _get_object(self, data):
10+
def __get_object(self, data):
1111
if "errors" in data:
1212
return
1313
return Issue(data, **self._new_session_args)
@@ -29,7 +29,7 @@ def create(self, title, description, kind, priority):
2929
"priority": priority,
3030
"content": {"raw": description},
3131
}
32-
return self._get_object(self.post(None, data=data))
32+
return self.__get_object(self.post(None, data=data))
3333

3434
def each(self, q=None, sort=None):
3535
"""
@@ -48,7 +48,7 @@ def each(self, q=None, sort=None):
4848
if q is not None:
4949
params["q"] = q
5050
for issue in self._get_paged(None, params=params):
51-
yield self._get_object(issue)
51+
yield self.__get_object(issue)
5252

5353
return
5454

@@ -60,7 +60,7 @@ def get(self, id):
6060
6161
:return: The requested Issue objects
6262
"""
63-
return self._get_object(super(Issues, self).get(id))
63+
return self.__get_object(super(Issues, self).get(id))
6464

6565

6666
class Issue(BitbucketCloudBase):

0 commit comments

Comments
 (0)