<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def run_job(self, job_spec, wait_until_done=True):
 """ Runs a job defined by jobspec, optionally non-blocking. Takes a GPJobSpec object that defines a request to run a job, and makes the request to the server. By default blocks until the job is finished by polling the server, but can also run asynchronously. Args: :param job_spec: A GPJobSpec object that contains the data defining the job to be run. :param wait_until_done: Whether to wait until the job is finished before returning. :return: Returns: a GPJob object that refers to the running job on the server. If called synchronously, this object will contain the info associated with the completed job. Otherwise, it will just wrap the URI of the running job. """


        # names should be a list of names,
        # values should be a list of **lists** of values
        json_string = json.dumps({'lsid': job_spec.lsid, 'params': job_spec.params, 'tags': ['GenePattern Python Client']}, cls=GPJSONEncoder)
        if sys.version_info.major == 3:  # Handle conversion to bytes for Python 3
            json_string = bytes(json_string, 'utf-8')
        request = urllib.request.Request(self.url + '/rest/v1/jobs')
        if self.authorization_header() is not None:
            request.add_header('Authorization', self.authorization_header())
        request.add_header('Content-Type', 'application/json')
        request.add_header('User-Agent', 'GenePatternRest')
        response = urllib.request.urlopen(request, json_string)
        if response.getcode() != 201:
            print(" job POST failed, status code = %i" % response.getcode())
            return None
        data = json.loads(response.read().decode('utf-8'))
        job = GPJob(self, data['jobId'])
        job.get_info()
        self.last_job = job  # Set the last job
        if wait_until_done:
            job.wait_until_done()
        return job