'create a join condition between two tables or selectables.
e.g.::
join_condition(tablea, tableb)
would produce an expression along the lines of::
tablea.c.id==tableb.c.tablea_id
The join is determined based on the foreign key relationships
between the two selectables.   If there are multiple ways
to join, or no way to join, an error is raised.
:param ignore_nonexistent_tables:  Deprecated - this
flag is no longer used.  Only resolution errors regarding
the two given tables are propagated.
:param a_subset: An optional expression that is a sub-component
of ``a``.  An attempt will be made to join to just this sub-component
first before looking at the full ``a`` construct, and if found
will be successful even if there are other ways to join to ``a``.
This allows the "right side" of a join to be passed thereby
providing a "natural join".'

@classmethod
def _join_condition(cls, a, b, ignore_nonexistent_tables=False, a_subset=None, consider_as_foreign_keys=None):

    constraints = collections.defaultdict(list)
    for left in (a_subset, a):
        if (left is None):
            continue
        for fk in sorted(b.foreign_keys, key=(lambda fk: fk.parent._creation_order)):
            if ((consider_as_foreign_keys is not None) and (fk.parent not in consider_as_foreign_keys)):
                continue
            try:
                col = fk.get_referent(left)
            except exc.NoReferenceError as nrte:
                if (nrte.table_name == left.name):
                    raise
                else:
                    continue
            if (col is not None):
                constraints[fk.constraint].append((col, fk.parent))
        if (left is not b):
            for fk in sorted(left.foreign_keys, key=(lambda fk: fk.parent._creation_order)):
                if ((consider_as_foreign_keys is not None) and (fk.parent not in consider_as_foreign_keys)):
                    continue
                try:
                    col = fk.get_referent(b)
                except exc.NoReferenceError as nrte:
                    if (nrte.table_name == b.name):
                        raise
                    else:
                        continue
                if (col is not None):
                    constraints[fk.constraint].append((col, fk.parent))
        if constraints:
            break
    if (len(constraints) > 1):
        if consider_as_foreign_keys:
            for const in list(constraints):
                if (set((f.parent for f in const.elements)) != set(consider_as_foreign_keys)):
                    del constraints[const]
        if (len(constraints) > 1):
            dedupe = set((tuple(crit) for crit in constraints.values()))
            if (len(dedupe) == 1):
                key = list(constraints)[0]
                constraints = {key: constraints[key]}
        if (len(constraints) != 1):
            raise exc.AmbiguousForeignKeysError(("Can't    determine    join    between    '%s'    and    '%s';    tables    have    more    than    one    foreign    key    constraint    relationship    between    them.    Please    specify    the    'onclause'    of    this    join    explicitly." % (a.description, b.description)))
    if (len(constraints) == 0):
        if isinstance(b, FromGrouping):
            hint = '    Perhaps    you    meant    to    convert    the    right    side    to    a    subquery    using    alias()?'
        else:
            hint = ''
        raise exc.NoForeignKeysError(("Can't    find    any    foreign    key    relationships    between    '%s'    and    '%s'.%s" % (a.description, b.description, hint)))
    crit = [(x == y) for (x, y) in list(constraints.values())[0]]
    if (len(crit) == 1):
        return crit[0]
    else:
        return and_(*crit)
