<commit_before># -*- coding: utf-8 -*-
import calendar
import time
from datetime import datetime
import httplib2
from xml.dom import minidom
import sys
import youtrack
from xml.dom import Node
import urllib
import urllib.parse
import urllib.request
import urllib.error
from xml.sax.saxutils import escape, quoteattr
import json
import tempfile
import functools
import re
import io


def urlquote(s):
    return urllib.parse.quote(utf8encode(s), safe="")


def utf8encode(source):
    if isinstance(source, str):
        source = source.encode('utf-8')
    return source


def relogin_on_401(f):
    @functools.wraps(f)
    def wrapped(self, *args, **kwargs):
        attempts = 10
        while attempts:
            try:
                return f(self, *args, **kwargs)
            except youtrack.YouTrackException as e:
                if e.response.status not in (401, 403, 500, 504):
                    raise e
                if e.response.status == 504:
                    time.sleep(30)
                else:
                    self._login(*self._credentials)
                attempts -= 1
        return f(self, *args, **kwargs)

    return wrapped


class Connection(object):
    def __init__(self, url, login=None, password=None, proxy_info=None, api_key=None):
        self.http = httplib2.Http(disable_ssl_certificate_validation=True) if proxy_info is None else httplib2.Http(
            proxy_info=proxy_info, disable_ssl_certificate_validation=True)

        # Remove the last character of the url ends with "/"
        if url:
            url = url.rstrip('/')

        self.url = url
        self.base_url = url + "/rest"
        if api_key is None:
            self._credentials = (login, password)
            self._login(*self._credentials)
        else:
            self.headers = {'X-YouTrack-ApiKey': api_key}

    def _login(self, login, password):
        response, content = self.http.request(
            self.base_url + "/user/login?login=" + urllib.parse.quote_plus(login) + "&password=" +
            urllib.parse.quote_plus(password), 'POST',
            headers={'Content-Length': '0', 'Connection': 'keep-alive'})
        if response.status != 200:
            raise youtrack.YouTrackException('/user/login', response, content)
        self.headers = {'Cookie': response['set-cookie'],
                        'Cache-Control': 'no-cache'}

    @relogin_on_401
    def _req(self, method, url, body=None, ignore_status=None, content_type=None, accept_header=None):
        headers = self.headers
        headers = headers.copy()
        if method == 'PUT' or method == 'POST':
            if content_type is None:
                content_type = 'application/xml; charset=UTF-8'
            headers['Content-Type'] = content_type
            headers['Content-Length'] = str(len(body)) if body else '0'

        if accept_header is not None:
            headers['Accept'] = accept_header

        response, content = self.http.request(self.base_url + url, method, headers=headers, body=body)
        content = content.translate(None, '\0'.encode('utf-8'))
        _illegal_unichrs = [(0x00, 0x08), (0x0B, 0x0C), (0x0E, 0x1F),
                            (0x7F, 0x84), (0x86, 0x9F), (0xFDD0, 0xFDDF),
                            (0xFFFE, 0xFFFF)]
        _illegal_ranges = ["%s-%s" % (chr(low), chr(high))
                           for (low, high) in _illegal_unichrs]
        _illegal_xml_chars_re = re.compile('[%s]' % ''.join(_illegal_ranges))
        content = re.sub(_illegal_xml_chars_re, '', content.decode('utf-8')).encode('utf-8')
        if response.status != 200 and response.status != 201 and (ignore_status != response.status):
            raise youtrack.YouTrackException(url, response, content)

        return response, content

    def _req_xml(self, method, url, body=None, ignore_status=None):
        response, content = self._req(method, url, body, ignore_status)
        if 'content-type' in response:
            if (response["content-type"].find('application/xml') != -1 or response["content-type"].find(
                    'text/xml') != -1) and content is not None and content != '':
                try:
                    return minidom.parseString(content)
                except youtrack.YouTrackBroadException:
                    return ""
            elif response['content-type'].find('application/json') != -1 and content is not None and content != '':
                try:
                    return json.loads(content)
                except youtrack.YouTrackBroadException:
                    return ""

        if method == 'PUT' and ('location' in response.keys()):
            return 'Created: ' + response['location']
        else:
            return content

    def _get(self, url):
        return self._req_xml('GET', url)

    def _put(self, url):
        return self._req_xml('PUT', url, '<empty/>\n\n')

    def get_issue(self, _id):
        return youtrack.Issue(self._get("/issue/" + _id), self)

    def create_issue(self, project, assignee, summary, description, priority=None, issue_type=None, subsystem=None,
                     state=None,
                     affects_version=None,
                     fixed_version=None, fixed_in_build=None, permitted_group=None):
        params = {'project': project,
                  'summary': summary}
        if description is not None:
            params['description'] = description
        if assignee is not None:
            params['assignee'] = assignee
        if priority is not None:
            params['priority'] = priority
        if issue_type is not None:
            params['type'] = issue_type
        if subsystem is not None:
            params['subsystem'] = subsystem
        if state is not None:
            params['state'] = state
        if affects_version is not None:
            params['affectsVersion'] = affects_version
        if fixed_version is not None:
            params['fixVersion'] = fixed_version
        if fixed_in_build is not None:
            params['fixedInBuild'] = fixed_in_build
        if permitted_group is not None:
            params['permittedGroup'] = permitted_group

        return self._req('PUT', '/issue', urllib.parse.urlencode(params),
                         content_type='application/x-www-form-urlencoded')

    def delete_issue(self, issue_id):
        return self._req('DELETE', '/issue/%s' % issue_id)

    def get_changes_for_issue(self, issue):
        return [youtrack.IssueChange(change, self) for change in
                self._get("/issue/%s/changes" % issue).getElementsByTagName('change')]
<commit_msg>Add update_issue function for updating summary & description<commit_after># -*- coding: utf-8 -*-
import calendar
import time
from datetime import datetime
import httplib2
from xml.dom import minidom
import sys
import youtrack
from xml.dom import Node
import urllib
import urllib.parse
import urllib.request
import urllib.error
from xml.sax.saxutils import escape, quoteattr
import json
import tempfile
import functools
import re
import io


def urlquote(s):
    return urllib.parse.quote(utf8encode(s), safe="")


def utf8encode(source):
    if isinstance(source, str):
        source = source.encode('utf-8')
    return source


def relogin_on_401(f):
    @functools.wraps(f)
    def wrapped(self, *args, **kwargs):
        attempts = 10
        while attempts:
            try:
                return f(self, *args, **kwargs)
            except youtrack.YouTrackException as e:
                if e.response.status not in (401, 403, 500, 504):
                    raise e
                if e.response.status == 504:
                    time.sleep(30)
                else:
                    self._login(*self._credentials)
                attempts -= 1
        return f(self, *args, **kwargs)

    return wrapped


class Connection(object):
    def __init__(self, url, login=None, password=<PASSWORD>, proxy_info=None, api_key=None):
        self.http = httplib2.Http(disable_ssl_certificate_validation=True) if proxy_info is None else httplib2.Http(
            proxy_info=proxy_info, disable_ssl_certificate_validation=True)

        # Remove the last character of the url ends with "/"
        if url:
            url = url.rstrip('/')

        self.url = url
        self.base_url = url + "/rest"
        if api_key is None:
            self._credentials = (login, password)
            self._login(*self._credentials)
        else:
            self.headers = {'X-YouTrack-ApiKey': api_key}

    def _login(self, login, password):
        response, content = self.http.request(
            self.base_url + "/user/login?login=" + urllib.parse.quote_plus(login) + "&password=" +
            urllib.parse.quote_plus(password), 'POST',
            headers={'Content-Length': '0', 'Connection': 'keep-alive'})
        if response.status != 200:
            raise youtrack.YouTrackException('/user/login', response, content)
        self.headers = {'Cookie': response['set-cookie'],
                        'Cache-Control': 'no-cache'}

    @relogin_on_401
    def _req(self, method, url, body=None, ignore_status=None, content_type=None, accept_header=None):
        headers = self.headers
        headers = headers.copy()
        if method == 'PUT' or method == 'POST':
            if content_type is None:
                content_type = 'application/xml; charset=UTF-8'
            headers['Content-Type'] = content_type
            headers['Content-Length'] = str(len(body)) if body else '0'

        if accept_header is not None:
            headers['Accept'] = accept_header

        response, content = self.http.request(self.base_url + url, method, headers=headers, body=body)
        content = content.translate(None, '\0'.encode('utf-8'))
        _illegal_unichrs = [(0x00, 0x08), (0x0B, 0x0C), (0x0E, 0x1F),
                            (0x7F, 0x84), (0x86, 0x9F), (0xFDD0, 0xFDDF),
                            (0xFFFE, 0xFFFF)]
        _illegal_ranges = ["%s-%s" % (chr(low), chr(high))
                           for (low, high) in _illegal_unichrs]
        _illegal_xml_chars_re = re.compile('[%s]' % ''.join(_illegal_ranges))
        content = re.sub(_illegal_xml_chars_re, '', content.decode('utf-8')).encode('utf-8')
        if response.status != 200 and response.status != 201 and (ignore_status != response.status):
            raise youtrack.YouTrackException(url, response, content)

        return response, content

    def _req_xml(self, method, url, body=None, ignore_status=None):
        response, content = self._req(method, url, body, ignore_status)
        if 'content-type' in response:
            if (response["content-type"].find('application/xml') != -1 or response["content-type"].find(
                    'text/xml') != -1) and content is not None and content != '':
                try:
                    return minidom.parseString(content)
                except youtrack.YouTrackBroadException:
                    return ""
            elif response['content-type'].find('application/json') != -1 and content is not None and content != '':
                try:
                    return json.loads(content)
                except youtrack.YouTrackBroadException:
                    return ""

        if method == 'PUT' and ('location' in response.keys()):
            return 'Created: ' + response['location']
        else:
            return content

    def _get(self, url):
        return self._req_xml('GET', url)

    def _put(self, url):
        return self._req_xml('PUT', url, '<empty/>\n\n')

    def get_issue(self, _id):
        return youtrack.Issue(self._get("/issue/" + _id), self)

    def create_issue(self, project, assignee, summary, description, priority=None, issue_type=None, subsystem=None,
                     state=None,
                     affects_version=None,
                     fixed_version=None, fixed_in_build=None, permitted_group=None):
        params = {'project': project,
                  'summary': summary}
        if description is not None:
            params['description'] = description
        if assignee is not None:
            params['assignee'] = assignee
        if priority is not None:
            params['priority'] = priority
        if issue_type is not None:
            params['type'] = issue_type
        if subsystem is not None:
            params['subsystem'] = subsystem
        if state is not None:
            params['state'] = state
        if affects_version is not None:
            params['affectsVersion'] = affects_version
        if fixed_version is not None:
            params['fixVersion'] = fixed_version
        if fixed_in_build is not None:
            params['fixedInBuild'] = fixed_in_build
        if permitted_group is not None:
            params['permittedGroup'] = permitted_group

        return self._req('PUT', '/issue', urllib.parse.urlencode(params),
                         content_type='application/x-www-form-urlencoded')

    def update_issue(self, issue_id, summary, description=''):
        url_summary = urlquote(utf8encode(summary))
        url_description = urlquote(utf8encode(description))

        response, _ = self._req('POST',
                                '/issue/%s?summary=%s&description=%s' % (issue_id, url_summary, url_description))
        return response

    def delete_issue(self, issue_id):
        return self._req('DELETE', '/issue/%s' % issue_id)

    def get_changes_for_issue(self, issue):
        return [youtrack.IssueChange(change, self) for change in
                self._get("/issue/%s/changes" % issue).getElementsByTagName('change')]

{'fraction_non_alphanumeric': 0.1151532932374945, 'fraction_numerical': 0.01202875165028605, 'mean_word_length': 2.2348754448398576, 'pattern_counts': {'":': 0, '<': 6, '<?xml version=': 0, '>': 6, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 22}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '624652', 'n_tokens_mistral': 4003, 'n_tokens_neox': 3821, 'n_words': 979}