# Buggy code
def table(self, name, path):
    if name not in self.list_tables(path):
        raise AttributeError(name)

    if path is None:
        path = self.root

    # get the schema
    f = path / "{}.parquet".format(name)

    parquet_file = pq.ParquetFile(str(f))
    schema = sch.infer(parquet_file.schema)

    table = self.table_class(name, schema, self).to_expr()
    self.dictionary[name] = f

    return table


# Traceback (KeyError)
alltypes[alltypes.string_col.topk(3)].count().compile()

---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-39-95fa1f84c573> in <module>
----> 1 alltypes[alltypes.string_col.topk(3)].count().compile()

/mnt/sda1/dev/quansight/ibis-project/ibis/ibis/expr/types.py in compile(self, limit, params)
213         from ibis.client import compile
214
--> 215         return compile(self, limit=limit, params=params)
216
217     def verify(self):

/mnt/sda1/dev/quansight/ibis-project/ibis/ibis/client.py in compile(expr, limit, params, **kwargs)
288 def compile(expr, limit=None, params=None, **kwargs):
289     backend, = validate_backends(list(find_backends(expr)))
--> 290     return backend.compile(expr, limit=limit, params=params, **kwargs)
291
292

/mnt/sda1/dev/quansight/ibis-project/ibis/ibis/client.py in compile(self, expr, params, limit)
199         """
200         query_ast = self._build_ast_ensure_limit(expr, limit, params=params)
--> 201         return query_ast.compile()
202
203     def _build_ast_ensure_limit(self, expr, limit, params=None):

/mnt/sda1/dev/quansight/ibis-project/ibis/ibis/sql/compiler.py in compile(self)
52     def compile(self):
53         compiled_setup_queries = [q.compile() for q in self.setup_queries]
---> 54         compiled_queries = [q.compile() for q in self.queries]
55         compiled_teardown_queries = [
56             q.compile() for q in self.teardown_queries

/mnt/sda1/dev/quansight/ibis-project/ibis/ibis/sql/compiler.py in <listcomp>(.0)
52     def compile(self):
53         compiled_setup_queries = [q.compile() for q in self.setup_queries]
---> 54         compiled_queries = [q.compile() for q in self.queries]
55         compiled_teardown_queries = [
56             q.compile() for q in self.teardown_queries

/mnt/sda1/dev/quansight/ibis-project/ibis/ibis/sql/compiler.py in compile(self)
1565
1566         # FROM, JOIN, UNION
-> 1567         from_frag = self.format_table_set()
1568
1569         # WHERE

/mnt/sda1/dev/quansight/ibis-project/ibis/ibis/sql/compiler.py in format_table_set(self)
1682
1683         helper = self.table_set_formatter(self, self.table_set)
-> 1684         fragment += helper.get_result()
1685
1686         return fragment

/mnt/sda1/dev/quansight/ibis-project/ibis/ibis/mapd/compiler.py in get_result(self)
143
144         if isinstance(op, ops.Join):
--> 145             self._walk_join_tree(op)
146         else:
147             self.join_tables.append(self._format_table(self.expr))

/mnt/sda1/dev/quansight/ibis-project/ibis/ibis/sql/compiler.py in _walk_join_tree(self, op)
1793         self._validate_join_predicates(op.predicates)
1794
-> 1795         jname = self._get_join_type(op)
1796
1797         # Read off tables and join predicates left-to-right in

/mnt/sda1/dev/quansight/ibis-project/ibis/ibis/sql/compiler.py in _get_join_type(self, op)
1834
1835     def _get_join_type(self, op):
-> 1836         return self._join_names[type(op)]
1837
1838     def _quote_identifier(self, name):

KeyError: <class 'ibis.expr.operations.LeftSemiJoin'>

# Fixed code
def table(self, name: str, path: Optional[str] = None) -> ir.TableExpr:
    if name not in self.list_tables(path):
        raise AttributeError(name)

    if path is None:
        path = self.root

    # get the schema
    f = path / "{}.parquet".format(name)

    parquet_file = pq.ParquetFile(str(f))
    schema = sch.infer(parquet_file.schema)

    table = self.table_class(name, schema, self).to_expr()
    self.dictionary[name] = f

    return table