wahwahwah
wahwahwah

Reputation: 851

Compatibility issue (python 2 vs python 3)

I have a program that will auto create a Github issue via the API. It works in Python 2.7, but when I run it with Python 3 I get the following error:

Traceback (most recent call last):
  File "/home/baal/bin/python/zeus-scanner/var/auto_issue/github.py", line 92, in request_issue_creation
    urllib2.urlopen(req, timeout=10).read()
  File "/usr/lib/python3.5/urllib/request.py", line 163, in urlopen
    return opener.open(url, data, timeout)
  File "/usr/lib/python3.5/urllib/request.py", line 464, in open
    req = meth(req)
  File "/usr/lib/python3.5/urllib/request.py", line 1183, in do_request_
    raise TypeError(msg)
TypeError: POST data should be bytes or an iterable of bytes. It cannot be of type str.

I have the following method that creates a github issue (successful in python 2 unsuccessful in python 3):

def request_issue_creation():
    logger.info(set_color(
        "Zeus got an unexpected error and will automatically create an issue for this error, please wait..."
    ))

    def __extract_stacktrace(file_data):
        logger.info(set_color(
            "extracting traceback from log file..."
        ))
        retval, buff_mode, _buffer = [], False, ""
        with open(file_data, "r+") as log:
            for line in log:
                if "Traceback" in line:
                    buff_mode = True
                if line and len(line) < 5:
                    buff_mode = False
                    retval.append(_buffer)
                    _buffer = ""
                if buff_mode:
                    if len(line) > 400:
                        line = line[:400] + "...\n"
                    _buffer += line
        return "".join(retval)

    logger.info(set_color(
        "getting authorization..."
    ))

    encoded = __get_encoded_string()
    n = get_decode_num(encoded)
    token = decode(n, encoded)

    current_log_file = get_latest_log_file(CURRENT_LOG_FILE_PATH)
    stacktrace = __extract_stacktrace(current_log_file)
    issue_title = stacktrace.split("\n")[-2]

    issue_data = {
        "title": issue_title,
        "body": "Error info:\n```{}````\n\n"
                "Running details:\n`{}`\n\n"
                "Commands used:\n`{}`\n\n"
                "Log file info:\n```{}```".format(
                     str(stacktrace),
                     str(platform.platform()),
                     " ".join(sys.argv),
                     open(current_log_file).read()
                ),
    }

    try:
        req = urllib2.Request(
            url="https://api.github.com/repos/<API-REPO>/issues", data=json.dumps(issue_data),
            headers={"Authorization": "token {}".format(token)}
        )
        urllib2.urlopen(req, timeout=10).read()
        logger.info(set_color(
            "issue has been created successfully with the following name '{}'...".format(issue_title)
        ))
    except Exception as e:
        logger.exception(set_color(
            "failed to auto create the issue, got exception '{}', "
            "you may manually create an issue...".format(e), level=50
        ))

I read online that encoding the string to utf-8 will fix the issue, however I'm not sure if that is possible here? Any help would be greatly appreciated, thank you.

Upvotes: 2

Views: 104

Answers (1)

Martijn Pieters
Martijn Pieters

Reputation: 1125148

You need to encode your JSON payload:

data = json.dumps(issue_data)
if sys.version_info > (3,):  # Python 3
    data = data.encode('utf8')

req = urllib2.Request(
    url="https://api.github.com/repos/<API-REPO>/issues", data=data,
    headers={"Authorization": "token {}".format(token),
             "Content-Type": "application/json; charset=utf-8"}
)

I added a Content-Type header with a charset parameter to communicate the codec used to the server. This is not always needed, JSON's default codec is UTF-8. If you don't specify the header, a (wrong) default would be supplied; it depends on the server whether or not that matters.

Upvotes: 4

Related Questions