Skip to content

Commit 6253ee4

Browse files
authored
Merge branch 'master' into repo
2 parents 1438e21 + 725c7b8 commit 6253ee4

File tree

4 files changed

+109
-29
lines changed

4 files changed

+109
-29
lines changed

atlassian/VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
1.12.13
1+
1.12.15

atlassian/confluence.py

Lines changed: 51 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -279,25 +279,29 @@ def remove_page(self, page_id, status=None, recursive=False):
279279
params['status'] = status
280280
return self.delete(url, params=params)
281281

282-
def create_page(self, space, title, body, parent_id=None, type='page'):
282+
def create_page(self, space, title, body, parent_id=None, type='page',
283+
representation='storage'):
283284
"""
284285
Create page from scratch
285286
:param space:
286287
:param title:
287288
:param body:
288289
:param parent_id:
289290
:param type:
291+
:param representation: OPTIONAL: either Confluence 'storage' or 'wiki' markup format
290292
:return:
291293
"""
292294
log.info('Creating {type} "{space}" -> "{title}"'.format(space=space, title=title, type=type))
295+
if representation not in ['wiki', 'storage']:
296+
raise ValueError("Wrong value for representation, it should be either wiki or storage")
293297
url = 'rest/api/content/'
294298
data = {
295299
'type': type,
296300
'title': title,
297301
'space': {'key': space},
298-
'body': {'storage': {
302+
'body': {representation: {
299303
'value': body,
300-
'representation': 'storage'}}}
304+
'representation': representation}}}
301305
if parent_id:
302306
data['ancestors'] = [{'type': type, 'id': parent_id}]
303307
return self.post(url, data=data)
@@ -326,8 +330,8 @@ def add_comment(self, page_id, text):
326330
data = {'type': 'comment',
327331
'container': {'id': page_id, 'type': 'page', 'status': 'current'},
328332
'body': {'storage': {'value': text, 'representation': 'storage'}}}
329-
return self.post('rest/api/content/', data=data)
330-
333+
return self.post('rest/api/content/', data=data)
334+
331335
def attach_file(self, filename, page_id=None, title=None, space=None, comment=None):
332336
"""
333337
Attach (upload) a file to a page, if it exists it will update the
@@ -631,6 +635,28 @@ def get_space(self, space_key, expand='description.plain,homepage'):
631635
expand=expand)
632636
return self.get(url)
633637

638+
def create_space(self, space_key, space_name):
639+
"""
640+
Create space
641+
:param space_key:
642+
:param space_name:
643+
:return:
644+
"""
645+
data = {
646+
'key': space_key,
647+
'name': space_name
648+
}
649+
self.post('rest/api/space', data=data)
650+
651+
def delete_space(self, space_key):
652+
"""
653+
Delete space
654+
:param space_key:
655+
:return:
656+
"""
657+
url = 'rest/api/space/{}'.format(space_key)
658+
return self.delete(url)
659+
634660
def get_user_details_by_username(self, username, expand=None):
635661
"""
636662
Get information about a user through username
@@ -706,7 +732,7 @@ def get_page_as_pdf(self, page_id):
706732
url = self.get_pdf_download_url_for_confluence_cloud(url)
707733

708734
return self.get(url, headers=headers, not_json_response=True)
709-
735+
710736
def export_page(self, page_id):
711737
"""
712738
Alias method for export page as pdf
@@ -775,6 +801,7 @@ def get_pdf_download_url_for_confluence_cloud(self, url):
775801
:param url: URL to initiate PDF export
776802
:return: Download url for PDF file
777803
"""
804+
download_url = None
778805
try:
779806
long_running_task = True
780807
headers = self.form_token_headers
@@ -784,28 +811,30 @@ def get_pdf_download_url_for_confluence_cloud(self, url):
784811
task_id = response_string.split('name="ajs-taskId" content="')[1].split('">')[0]
785812
poll_url = 'runningtaskxml.action?taskId={0}'.format(task_id)
786813
while long_running_task:
787-
longrunning_task_response = self.get(poll_url, headers=headers, not_json_response=True)
788-
longrunning_task_response_parts = longrunning_task_response.decode(encoding='utf-8', errors='strict').split('\n')
789-
percentage_complete = longrunning_task_response_parts[6].strip()
790-
is_successful = longrunning_task_response_parts[7].strip()
791-
is_complete = longrunning_task_response_parts[8].strip()
814+
long_running_task_response = self.get(poll_url, headers=headers, not_json_response=True)
815+
long_running_task_response_parts = long_running_task_response.decode(encoding='utf-8',
816+
errors='strict').split('\n')
817+
percentage_complete = long_running_task_response_parts[6].strip()
818+
is_successful = long_running_task_response_parts[7].strip()
819+
is_complete = long_running_task_response_parts[8].strip()
792820
log.info('Sleep for 5s.')
793821
time.sleep(5)
794822
log.info('Check if export task has completed.')
795-
if is_successful == '<isSuccessful>true</isSuccessful>' and is_complete == '<isComplete>true</isComplete>':
796-
log.info(percentage_complete)
797-
log.info('Downloading content...')
798-
log.debug('Extract taskId and download PDF.')
799-
current_status = longrunning_task_response_parts[3]
800-
download_url = current_status.split('href=&quot;/wiki/')[1].split('&quot')[0]
801-
long_running_task = False
802-
elif is_successful == '<isSuccessful>false</isSuccessful>' and is_complete == '<isComplete>true</isComplete>':
803-
log.error('PDF conversion not successful.')
804-
return None
823+
if is_complete == '<isComplete>true</isComplete>':
824+
if is_successful == '<isSuccessful>true</isSuccessful>':
825+
log.info(percentage_complete)
826+
log.info('Downloading content...')
827+
log.debug('Extract taskId and download PDF.')
828+
current_status = long_running_task_response_parts[3]
829+
download_url = current_status.split('href=&quot;/wiki/')[1].split('&quot')[0]
830+
long_running_task = False
831+
elif is_successful == '<isSuccessful>false</isSuccessful>':
832+
log.error('PDF conversion not successful.')
833+
return None
805834
else:
806835
log.info(percentage_complete)
807836
except IndexError as e:
808837
log.error(e)
809838
return None
810-
839+
811840
return download_url

atlassian/jira.py

Lines changed: 56 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -384,15 +384,49 @@ def get_custom_fields(self, search=None, start=1, limit=50):
384384
params['maxResults'] = limit
385385
return self.get(url, params=params)
386386

387-
def get_all_screen_fields(self, screen_id):
387+
def get_all_available_screen_fields(self, screen_id):
388388
"""
389-
Screen id
389+
Get all available fields by screen id
390390
:param screen_id:
391391
:return:
392392
"""
393393
url = 'rest/api/2/screens/{}/availableFields'.format(screen_id)
394394
return self.get(url)
395395

396+
def get_screen_tabs(self, screen_id):
397+
"""
398+
Get tabs for the screen id
399+
:param screen_id:
400+
:return:
401+
"""
402+
url = 'rest/api/2/screens/{}/tabs'.format(screen_id)
403+
return self.get(url)
404+
405+
def get_screen_tab_fields(self, screen_id, tab_id):
406+
"""
407+
Get fields by the tab id and the screen id
408+
:param tab_id:
409+
:param screen_id:
410+
:return:
411+
"""
412+
url = 'rest/api/2/screens/{}/tabs/{}/fields'.format(screen_id, tab_id)
413+
return self.get(url)
414+
415+
def get_all_screen_fields(self, screen_id):
416+
"""
417+
Get all fields by screen id
418+
:param screen_id:
419+
:return:
420+
"""
421+
screen_tabs = self.get_screen_tabs(screen_id)
422+
fields = []
423+
for screen_tab in screen_tabs:
424+
tab_id = screen_tab['id']
425+
if tab_id:
426+
tab_fields = self.get_screen_tab_fields(screen_id=screen_id, tab_id=tab_id)
427+
fields = fields + tab_fields
428+
return fields
429+
396430
def get_issue_labels(self, issue_key):
397431
"""
398432
Get issue labels.
@@ -847,13 +881,22 @@ def delete_component(self, component_id):
847881
log.warning('Deleting component "{component_id}"'.format(component_id=component_id))
848882
return self.delete('rest/api/2/component/{component_id}'.format(component_id=component_id))
849883

850-
def get_resolution_by_id(self, id):
884+
def get_resolution_by_id(self, resolution_id):
851885
"""
852886
Get Resolution info by id
853-
:param id:
887+
:param resolution_id:
888+
:return:
889+
"""
890+
url = 'rest/api/2/resolution/{}'.format(resolution_id)
891+
return self.get(url)
892+
893+
def get_priority_by_id(self, priority_id):
894+
"""
895+
Get Priority info by id
896+
:param priority_id:
854897
:return:
855898
"""
856-
url = 'rest/api/2/resolution/{}'.format(id)
899+
url = 'rest/api/2/resolution/{}'.format(priority_id)
857900
return self.get(url)
858901

859902
def get_all_workflows(self):
@@ -880,6 +923,14 @@ def get_all_resolutions(self):
880923
url = 'rest/api/2/resolution'
881924
return self.get(url)
882925

926+
def get_all_priorities(self):
927+
"""
928+
Returns a list of all priorities.
929+
:return:
930+
"""
931+
url = 'rest/api/2/priority'
932+
return self.get(url)
933+
883934
def get_all_global_project_roles(self):
884935
"""
885936
Get all the ProjectRoles available in Jira. Currently this list is global.

atlassian/rest_client.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,4 +166,4 @@ def delete(self, path, data=None, headers=None, params=None):
166166
:return: Empty dictionary to have consistent interface.
167167
Some of Atlassian REST resources don't return any content.
168168
"""
169-
self.request('DELETE', path=path, data=data, headers=headers, params=params)
169+
self.request('DELETE', path=path, data=data, headers=headers, params=params)

0 commit comments

Comments
 (0)