<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def graph_query(kind, source, target=None, neighbor_limit=1, database_filter=None):
 """Perform a graph query on PathwayCommons. For more information on these queries, see http://www.pathwaycommons.org/pc2/#graph Parameters kind : str The kind of graph query to perform. Currently 3 options are implemented, 'neighborhood', 'pathsbetween' and 'pathsfromto'. source : list[str] A list of gene names which are the source set for the graph query. target : Optional[list[str]] A list of gene names which are the target set for the graph query. Only needed for 'pathsfromto' queries. neighbor_limit : Optional[int] This limits the length of the longest path considered in the graph query. Default: 1 Returns ------- model : org.biopax.paxtools.model.Model A BioPAX model (java object). """


    default_databases = ['wp', 'smpdb', 'reconx', 'reactome', 'psp', 'pid',
                         'panther', 'netpath', 'msigdb', 'mirtarbase', 'kegg',
                         'intact', 'inoh', 'humancyc', 'hprd',
                         'drugbank', 'dip', 'corum']
    if not database_filter:
        query_databases = default_databases
    else:
        query_databases = database_filter
    # excluded: ctd

    params = {}
    params['format'] = 'BIOPAX'
    params['organism'] = '9606'
    params['datasource'] = query_databases
    # Get the "kind" string
    kind_str = kind.lower()
    if kind not in ['neighborhood', 'pathsbetween', 'pathsfromto']:
        logger.warn('Invalid query type %s' % kind_str)
        return None
    params['kind'] = kind_str
    # Get the source string
    if isinstance(source, basestring):
        source_str = source
    else:
        source_str = ','.join(source)
    params['source'] = source_str
    try:
        neighbor_limit = int(neighbor_limit)
        params['limit'] = neighbor_limit
    except (TypeError, ValueError):
        logger.warn('Invalid neighborhood limit %s' % neighbor_limit)
        return None
    if target is not None:
        if isinstance(target, basestring):
            target_str = target
        else:
            target_str = ','.join(target)
        params['target'] = target_str
    logger.info('Sending Pathway Commons query with parameters: ')
    for k, v in params.items():
        logger.info(' %s: %s' % (k, v))

    logger.info('Sending Pathway Commons query...')
    res = requests.get(pc2_url + 'graph', params=params)
    if not res.status_code == 200:
        logger.error('Response is HTTP code %d.' % res.status_code)
        if res.status_code == 500:
            logger.error('Note: HTTP code 500 can mean empty '
                         'results for a valid query.')
        return None
    # We don't decode to Unicode here because owl_str_to_model expects
    # a byte stream
    model = owl_str_to_model(res.content)
    if model is not None:
        logger.info('Pathway Commons query returned a model...')
    return model