def get(self): """ Returns the file content as a string. """ r = self._session.get(self.content) raise_on_error(r) return r.content
def delete(self, params=None): """ Delete this resource from the server, passing the specified query parameters. If this resource doesn't support ``DELETE``, a :py:exc:`.JIRAError` will be raised; subclasses that specialize this method will only raise errors in case of user error. """ r = self._session.delete(self.self, params=params) raise_on_error(r)
def add_comment(self, build, body): data = { 'author': self.jira_user, 'content': body } url = self.jira._get_url('result/' + build + '/comment') r = self.jira._session.post(url, headers={'content-type':'application/json'}, data=json.dumps(data)) raise_on_error(r)
def run_plan(self, plan, **extra_variables): params = None if extra_variables: params = {} for k, v in extra_variables.items(): params['bamboo.variable.%s' % k] = v url = self.jira._get_url('queue/%s' % plan) print "POST %s" % url r = self.jira._session.post(url, headers={'content-type':'application/json'}, params=params, data=json.dumps({})) raise_on_error(r)
def update(self, **kwargs): """ Update this resource on the server. Keyword arguments are marshalled into a dict before being sent. If this resource doesn't support ``PUT``, a :py:exc:`.JIRAError` will be raised; subclasses that specialize this method will only raise errors in case of user error. """ data = {} for arg in kwargs: data[arg] = kwargs[arg] r = self._session.put(self.self, data=json.dumps(data)) raise_on_error(r) self._load(self.self)
def delete(self, params=None): """ Delete this resource from the server, passing the specified query parameters. If this resource doesn't support ``DELETE``, a :py:exc:`.JIRAError` will be raised; subclasses that specialize this method will only raise errors in case of user error. """ if self._options['async']: if not hasattr(self._session, '_async_jobs'): self._session._async_jobs = set() self._session._async_jobs.add(threaded_requests.delete(self.self, params=params)) else: r = self._session.delete(self.self, params=params) raise_on_error(r)
def delete(self, params=None): """ Delete this resource from the server, passing the specified query parameters. If this resource doesn't support ``DELETE``, a :py:exc:`.JIRAError` will be raised; subclasses that specialize this method will only raise errors in case of user error. """ if self._options['async']: if not hasattr(self._session, '_async_jobs'): self._session._async_jobs = set() self._session._async_jobs.add(grequests.delete(self.self, params=params)) else: r = self._session.delete(self.self, params=params) raise_on_error(r)
def _load(self, url, headers=None, params=None): r = self._session.get(url, headers=headers, params=params) raise_on_error(r) self._parse_raw(json.loads(r.text))
class Resource(object): """ Models a URL-addressable resource in the JIRA REST API. All Resource objects provide the following: ``find()`` -- get a resource from the server and load it into the current object (though clients should use the methods in the JIRA class instead of this method directly) ``update()`` -- changes the value of this resource on the server and returns a new resource object for it ``delete()`` -- deletes this resource from the server ``self`` -- the URL of this resource on the server ``raw`` -- dict of properties parsed out of the JSON response from the server Subclasses will implement ``update()`` and ``delete()`` as appropriate for the specific resource. All Resources have a resource path of the form: * ``issue`` * ``project/{0}`` * ``issue/{0}/votes`` * ``issue/{0}/comment/{1}`` where the bracketed numerals are placeholders for ID values that are filled in from the ``ids`` parameter to ``find()``. """ # A prioritized list of the keys in self.raw most likely to contain a human # readable name or identifier, or that offer other key information. _READABLE_IDS = ('displayName', 'key', 'name', 'filename', 'value', 'scope', 'votes', 'id', 'mimeType', 'closed') def __init__(self, resource, options, session): self._resource = resource self._options = options self._session = session # explicitly define as None so we know when a resource has actually been loaded self.raw = None self.self = None def __str__(self): # Return the first value we find that is likely to be human readable. if self.raw: for name in self._READABLE_IDS: if name in self.raw: pretty_name = unicode(self.raw[name]) # Include any child to support nested select fields. if hasattr(self, 'child'): pretty_name += ' - ' + unicode(self.child) return pretty_name # If all else fails, use repr to make sure we get something. return repr(self) def __repr__(self): # Identify the class and include any and all relevant values. names = [] if self.raw: for name in self._READABLE_IDS: if name in self.raw: names.append(name + '=' + repr(self.raw[name])) if not names: return '<JIRA %s at %s>' % (self.__class__.__name__, unicode(hex(id(self)))) return '<JIRA %s: %s>' % (self.__class__.__name__, ', '.join(names)) def find(self, ids=None, headers=None, params=None): if ids is None: ids = () if isinstance(ids, basestring): ids = (ids, ) if headers is None: headers = {} if params is None: params = {} url = self._url(ids) headers = self._default_headers(headers) self._load(url, headers, params) def update(self, async=False, jira=None, **kwargs): """ Update this resource on the server. Keyword arguments are marshalled into a dict before being sent. If this resource doesn't support ``PUT``, a :py:exc:`.JIRAError` will be raised; subclasses that specialize this method will only raise errors in case of user error. :param async: if true the request will be added to the queue so it can be executed later using async_run() """ data = {} for arg in kwargs: data[arg] = kwargs[arg] r = self._session.put(self.self, headers={'content-type': 'application/json'}, data=json.dumps(data)) if 'autofix' in self._options and \ r.status_code == 400: user = None error_list = get_error_list(r) logging.error(error_list) if "The reporter specified is not a user." in error_list: if 'reporter' not in data['fields']: logging.warning( "autofix: setting reporter to '%s' and retrying the update." % self._options['autofix']) data['fields']['reporter'] = { 'name': self._options['autofix'] } print data if "Issues must be assigned." in error_list: if 'assignee' not in data['fields']: logging.warning( "autofix: setting assignee to '%s' for %s and retrying the update." % (self._options['autofix'], self.key)) data['fields']['assignee'] = { 'name': self._options['autofix'] } # for some reason the above approach fails on Jira 5.2.11 so we need to change the assignee before if "Issue type is a sub-task but parent issue key or id not specified." in error_list: logging.warning( "autofix: trying to fix sub-task without parent by converting to it to bug" ) data['fields']['issuetype'] = {"name": "Bug"} if "The summary is invalid because it contains newline characters." in error_list: logging.warning("autofix: trying to fix newline in summary") data['fields']['summary'] = self.fields.summary.replace( "/n", "") for error in error_list: if re.search(u"^User '(.*)' was not found in the system\.", error, re.U): m = re.search( u"^User '(.*)' was not found in the system\.", error, re.U) if m: user = m.groups()[0] else: raise NotImplemented() if re.search("^User '(.*)' does not exist\.", error): m = re.search("^User '(.*)' does not exist\.", error) if m: user = m.groups()[0] else: raise NotImplemented() if user: logging.warning( "Trying to add missing orphan user '%s' in order to complete the previous failed operation." % user) # print pprint.pprint(self.__dict__) jira.add_user(user, '*****@*****.**', 10100, active=False) # if 'assignee' not in data['fields']: # logging.warning("autofix: setting assignee to '%s' and retrying the update." % self._options['autofix']) # data['fields']['assignee'] = {'name': self._options['autofix']} # if async and 'grequests' in sys.modules: # if not hasattr(self._session, '_async_jobs'): # self._session._async_jobs = set() # self._session._async_jobs.add(grequests.put(self.self, headers={'content-type': 'application/json'}, data=json.dumps(data))) # else: # print "x", data r = self._session.put(self.self, headers={'content-type': 'application/json'}, data=json.dumps(data)) raise_on_error(r) self._load(self.self)
# data['fields']['assignee'] = {'name': self._options['autofix']} # EXPERIMENTAL ---> # import grequests if async and 'grequests' in sys.modules: if not hasattr(self._session, '_async_jobs'): self._session._async_jobs = set() self._session._async_jobs.add( grequests.put(self.self, headers={'content-type': 'application/json'}, data=json.dumps(data))) else: r = self._session.put( self.self, headers={'content-type': 'application/json'}, data=json.dumps(data)) raise_on_error(r) self._load(self.self) def delete(self, params=None): """ Delete this resource from the server, passing the specified query parameters. If this resource doesn't support ``DELETE``, a :py:exc:`.JIRAError` will be raised; subclasses that specialize this method will only raise errors in case of user error. """ if self._options['async']: if not hasattr(self._session, '_async_jobs'): self._session._async_jobs = set() self._session._async_jobs.add( grequests.delete(self.self, params=params)) else:
data['fields']['issuetype'] = {"name": "Bug"} if "The summary is invalid because it contains newline characters." in error_list: logging.warning("autofix: trying to fix newline in summary") data['fields']['summary'] = self.fields.summary.replace("/n", "") for error in error_list: if re.search("^User.* does not exist\.", error) or re.search("^User '.*' was not found in the system\.", error): if 'assignee' not in data['fields']: logging.warning("autofix: setting assignee to '%s' and retrying the update." % self._options['autofix']) data['fields']['assignee'] = {'name': self._options['autofix']} if async and 'grequests' in sys.modules: if not hasattr(self._session, '_async_jobs'): self._session._async_jobs = set() self._session._async_jobs.add(grequests.put(self.self, headers={'content-type': 'application/json'}, data=json.dumps(data))) else: r = self._session.put(self.self, headers={'content-type': 'application/json'}, data=json.dumps(data)) raise_on_error(r) self._load(self.self) def delete(self, params=None): """ Delete this resource from the server, passing the specified query parameters. If this resource doesn't support ``DELETE``, a :py:exc:`.JIRAError` will be raised; subclasses that specialize this method will only raise errors in case of user error. """ r = self._session.delete(self.self, params=params) raise_on_error(r) def _load(self, url, headers=None, params=None): r = self._session.get(url, headers=headers, params=params)