Skip to content

Commit 05e483a

Browse files
committed
BB: refresh atlassian-api#604
1 parent 0dbf33a commit 05e483a

5 files changed

Lines changed: 78 additions & 23 deletions

File tree

atlassian/bitbucket/cloud/workspaces/__init__.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ def __init__(self, url, *args, **kwargs):
1616
def __get_object(self, data):
1717
return Workspace(data, **self._new_session_args)
1818

19-
def each(self, role=None, q=None, sort=None):
19+
def each(self, role=None, q=None, sort=None, administrator=None):
2020
"""
2121
Get all workspaces matching the criteria.
2222
@@ -33,6 +33,9 @@ def each(self, role=None, q=None, sort=None):
3333
:param sort: string (default is None):
3434
Name of a response property to sort results.
3535
See https://developer.atlassian.com/bitbucket/api/2/reference/meta/filtering for details.
36+
:param administrator: bool (default is None):
37+
Filter workspaces by whether the authenticated user
38+
is a workspace administrator.
3639
3740
:return: A generator for the Workspace objects
3841
@@ -48,6 +51,8 @@ def each(self, role=None, q=None, sort=None):
4851
# would produce an invalid request.
4952
if sort is not None:
5053
params["sort"] = sort
54+
if administrator is not None:
55+
params["administrator"] = administrator
5156
user_workspaces_url = f"{self.url.rsplit('/', 1)[0]}/user/workspaces"
5257
for workspace_access in self._get_paged(user_workspaces_url, params=params, absolute=True):
5358
workspace_data = workspace_access.get("workspace", workspace_access)

docs/bitbucket.rst

Lines changed: 52 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -496,34 +496,67 @@ Conditions-Reviewers management
496496
Bitbucket Cloud
497497
---------------
498498

499+
Bitbucket Cloud and Bitbucket Server/Data Center have different REST API
500+
models. Use :class:`atlassian.bitbucket.cloud.Cloud` for Cloud: it starts from
501+
``workspaces`` and then navigates to repositories. Use ``Bitbucket`` or
502+
:class:`atlassian.bitbucket.server.Server` for Server/Data Center project
503+
endpoints. Do not pass a Cloud URL to the legacy Server/Data Center methods.
504+
505+
Use an Atlassian account email and a scoped Bitbucket API token with the
506+
required repository and workspace permissions. The client uses HTTP Basic
507+
authentication automatically. App passwords were retired by Bitbucket Cloud in
508+
July 2026, so new integrations must use API tokens.
509+
510+
.. code-block:: python
511+
512+
import os
513+
514+
from atlassian.bitbucket import Cloud
515+
516+
cloud = Cloud(
517+
username=os.environ["ATLASSIAN_EMAIL"],
518+
password=os.environ["BITBUCKET_API_TOKEN"],
519+
)
520+
521+
# /2.0/user/workspaces is the supported listing route. ``each()`` resolves
522+
# each entry and yields full workspace objects.
523+
for workspace in cloud.workspaces.each():
524+
print(workspace.slug)
525+
526+
# Restrict the list to workspaces administered by the authenticated user.
527+
admin_workspaces = list(cloud.workspaces.each(administrator=True))
528+
529+
repository = cloud.workspaces.get("workspace-slug").repositories.get("repository-slug")
530+
print(repository.name)
531+
499532
.. code-block:: python
500533
501-
# Get a list of workplaces:
534+
# Get a list of workspaces.
502535
cloud.workspaces.each()
503536
504-
# Get a single workplace by workplace slug
505-
workplace = cloud.workspaces.get(workspace_slug)
537+
# Get a single workspace by workspace slug.
538+
workspace = cloud.workspaces.get(workspace_slug)
506539
507540
# Get a list of permissions in a workspace (this may not work depending on the size of your workspace)
508-
workplace.permissions.each():
541+
workspace.permissions.each()
509542
510543
# Get a list of repository permissions in a workspace (this may not work depending on the size of your workspace)
511-
workplace.permissions.repositories():
544+
workspace.permissions.repositories()
512545
513546
# Get a single repository permissions in a workspace
514-
workplace.permissions.repositories(repo_slug):
547+
workspace.permissions.repositories(repo_slug)
515548
516549
# Get a list of projects in a workspace
517-
workplace.projects.each():
550+
workspace.projects.each()
518551
519-
# Get a single project from a workplace by project key
520-
project = workplace.projects.get(project_key)
552+
# Get a single project from a workspace by project key
553+
project = workspace.projects.get(project_key)
521554
522555
# Get a list of repos from a project
523-
project.repositories.each():
556+
project.repositories.each()
524557
525558
# Get a repository
526-
repository = workplace.repositories.get(repository_slug)
559+
repository = workspace.repositories.get(repository_slug)
527560
528561
# Read raw bytes from a file at a branch, tag, or commit SHA
529562
readme = repository.get_source_file("main", "README.md")
@@ -532,13 +565,13 @@ Bitbucket Cloud
532565
source_entries = repository.get_source_directory("main", "src")["values"]
533566
534567
# Get a list of deployment environments from a repository
535-
repository.deployment_environments.each():
568+
repository.deployment_environments.each()
536569
537570
# Get a single deployment environment from a repository by deployment environment key
538571
deployment_environment = repository.deployment_environments.get(deployment_environment_key)
539572
540573
# Get a list of deployment environment variables from a deployment environment
541-
deployment_environment_variables = deployment_environment.deployment_environment_variables.each():
574+
deployment_environment_variables = deployment_environment.deployment_environment_variables.each()
542575
543576
# Create a new deployment environment variable with a name of 'KEY', value of 'VALUE' and is not secured.
544577
new_deployment_environment_variable = deployment_environment.deployment_environment_variables.create("KEY", "VALUE", False)
@@ -553,13 +586,13 @@ Bitbucket Cloud
553586
updated_deployment_environment_variable.delete()
554587
555588
# Get a list of group permissions from a repository
556-
repository.group_permissions.each():
589+
repository.group_permissions.each()
557590
558591
# Get a single group permission from a repository by group slug
559592
repository.group_permissions.get(group_slug)
560593
561594
# Get a list of repository variables from a repository
562-
repository.repository_variables.each():
595+
repository.repository_variables.each()
563596
564597
# Get a single repository variable from a repository by repository variable key
565598
repository_variable = repository.repository_variables.get(repository_variable_key)
@@ -577,7 +610,7 @@ Bitbucket Cloud
577610
repository_variable.delete()
578611
579612
# Get a list of hooks from a repository
580-
repository.hooks.each():
613+
repository.hooks.each()
581614
582615
# Create a hook for a repository
583616
hook = repo.hooks.create(url="endpoint-url", description="description", active=True, events=["a-repository-event"])
@@ -592,11 +625,11 @@ Bitbucket Cloud
592625
hook.delete()
593626
594627
# Get a list of workspace members
595-
workplace.members.each()
628+
workspace.members.each()
596629
597630
# Get a specific workspace member
598-
workplace.members.get("a-user-account-id")
599-
workplace.members.get("{a-user-uuid}")
631+
workspace.members.get("a-user-account-id")
632+
workspace.members.get("{a-user-uuid}")
600633
601634
Pipelines management
602635
--------------------

examples/bitbucket/bitbucket_cloud_oo.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
# coding=utf-8
22

3+
import os
34
from textwrap import indent
45

56
from atlassian.bitbucket import Cloud
67

7-
cloud = Cloud(url="https://api.bitbucket.org/", username="admin", password="admin")
8+
cloud = Cloud(
9+
username=os.environ["ATLASSIAN_EMAIL"],
10+
password=os.environ["BITBUCKET_API_TOKEN"],
11+
)
812

913
index = 0
1014
for w in cloud.workspaces.each():

examples/bitbucket/bitbucket_cloud_read_source.py

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

77

88
bitbucket = Cloud(
9-
username=os.environ["BITBUCKET_USERNAME"],
10-
password=os.environ["BITBUCKET_APP_PASSWORD"],
9+
username=os.environ["ATLASSIAN_EMAIL"],
10+
password=os.environ["BITBUCKET_API_TOKEN"],
1111
)
1212
repository = bitbucket.workspaces.get(os.environ["BITBUCKET_WORKSPACE"]).repositories.get(
1313
os.environ["BITBUCKET_REPOSITORY"]

tests/test_bitbucket_cloud_oo.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,19 @@ def get_paged(url, params=None, absolute=False):
9090
assert list(workspaces.each()) == [workspace]
9191
assert calls == [(f"{workspaces.url.rsplit('/', 1)[0]}/user/workspaces", {}, True)]
9292

93+
def test_each_workspace_supports_administrator_filter(self, monkeypatch):
94+
workspaces = CLOUD.workspaces
95+
calls = []
96+
97+
def get_paged(url, params=None, absolute=False):
98+
calls.append((url, params, absolute))
99+
return iter([])
100+
101+
monkeypatch.setattr(workspaces, "_get_paged", get_paged)
102+
103+
assert list(workspaces.each(administrator=True)) == []
104+
assert calls == [(f"{workspaces.url.rsplit('/', 1)[0]}/user/workspaces", {"administrator": True}, True)]
105+
93106
def test_exists_workspace(self):
94107
assert CLOUD.workspaces.exists("TestWorkspace1"), "Exists workspace"
95108

0 commit comments

Comments
 (0)