'Either requests the creation of a new circuit or extends an existing one.
When called with a circuit value of zero (the default) a new circuit is
created, and when non-zero the circuit with that id is extended. If the
path isn\'t provided, one is automatically selected.
A python interpreter session used to create circuits could look like this...
>>> controller.extend_circuit(\'0\', [\'718BCEA286B531757ACAFF93AE04910EA73DE617\', \'30BAB8EE7606CBD12F3CC269AE976E0153E7A58D\', \'2765D8A8C4BBA3F89585A9FFE0E8575615880BEB\'])
19
>>> controller.extend_circuit(\'0\')
20
>>> print(controller.get_info(\'circuit-status\'))
20 EXTENDED $718BCEA286B531757ACAFF93AE04910EA73DE617=KsmoinOK,$649F2D0ACF418F7CFC6539AB2257EB2D5297BAFA=Eskimo BUILD_FLAGS=NEED_CAPACITY PURPOSE=GENERAL TIME_CREATED=2012-12-06T13:51:11.433755
19 BUILT $718BCEA286B531757ACAFF93AE04910EA73DE617=KsmoinOK,$30BAB8EE7606CBD12F3CC269AE976E0153E7A58D=Pascal1,$2765D8A8C4BBA3F89585A9FFE0E8575615880BEB=Anthracite PURPOSE=GENERAL TIME_CREATED=2012-12-06T13:50:56.969938
:param str circuit_id: id of a circuit to be extended
:param list,str path: one or more relays to make a circuit through, this is
required if the circuit id is non-zero
:param str purpose: \'general\' or \'controller\'
:param bool await_build: blocks until the circuit is built if **True**
:returns: str of the circuit id of the created or extended circuit
:raises:
* :class:`stem.InvalidRequest` if one of the parameters were invalid
* :class:`stem.CircuitExtensionFailed` if we were waiting for the circuit
to build but it failed
* :class:`stem.ControllerError` if the call fails'

def extend_circuit(self, circuit_id='0', path=None, purpose='general', await_build=False):

    (circ_queue, circ_listener) = (queue.Queue(), None)
    if await_build:
        def circ_listener(event):
            circ_queue.put(event)
        self.add_event_listener(circ_listener, EventType.CIRC)
    try:
        circuit_id = str(circuit_id)
        if ((path is None) and (circuit_id == '0')):
            path_opt_version = stem.version.Requirement.EXTENDCIRCUIT_PATH_OPTIONAL
            if (not (self.get_version() >= path_opt_version)):
                raise stem.InvalidRequest(512, ('EXTENDCIRCUIT    requires    the    path    prior    to    version    %s' % path_opt_version))
        args = [circuit_id]
        if isinstance(path, (bytes, str_type)):
            path = [path]
        if path:
            args.append(','.join(path))
        if purpose:
            args.append(('purpose=%s' % purpose))
        response = self.msg(('EXTENDCIRCUIT    %s' % '    '.join(args)))
        stem.response.convert('SINGLELINE', response)
        if (response.code in ('512', '552')):
            raise stem.InvalidRequest(response.code, response.message)
        elif (not response.is_ok()):
            raise stem.ProtocolError(('EXTENDCIRCUIT    returned    unexpected    response    code:    %s' % response.code))
        if (not response.message.startswith('EXTENDED    ')):
            raise stem.ProtocolError('EXTENDCIRCUIT    response    invalid:\n%s', response)
        new_circuit = response.message.split('    ', 1)[1]
        if await_build:
            while True:
                circ = circ_queue.get()
                if (circ.id == new_circuit):
                    if (circ.status == CircStatus.BUILT):
                        break
                    elif (circ.status == CircStatus.FAILED):
                        raise stem.CircuitExtensionFailed(('Circuit    failed    to    be    created:    %s' % circ.reason), circ)
                    elif (circ.status == CircStatus.CLOSED):
                        raise stem.CircuitExtensionFailed('Circuit    was    closed    prior    to    build', circ)
        return new_circuit
    finally:
        if circ_listener:
            self.remove_event_listener(circ_listener)
