2323from ibis import util
2424from ibis .common .deferred import Deferred , Resolver
2525from ibis .expr .types .core import Expr , _FixedTextJupyterMixin
26- from ibis .expr .types .generic import ValueExpr , literal
26+ from ibis .expr .types .generic import Value , literal
2727from ibis .expr .types .pretty import to_rich
2828from ibis .selectors import Selector
2929from ibis .util import deprecated
@@ -97,15 +97,23 @@ def f( # noqa: D417
9797
9898# TODO(kszucs): should use (table, *args, **kwargs) instead to avoid interpreting
9999# nested inputs
100- def bind (table : Table , value : Any ) -> Iterator [ir .Value ]:
100+ def bind (table : Table , value : Any , int_as_column = False ) -> Iterator [ir .Value ]:
101101 """Bind a value to a table expression."""
102- if type (value ) in (str , int ):
103- yield table ._get_column (value )
104- elif isinstance (value , ValueExpr ):
102+ if isinstance (value , str ):
103+ # TODO(kszucs): perhaps use getattr(table, value) instead for nicer error msg
104+ yield ops .Field (table , value ).to_expr ()
105+ elif isinstance (value , bool ):
106+ yield literal (value )
107+ elif int_as_column and isinstance (value , int ):
108+ name = table .columns [value ]
109+ yield ops .Field (table , name ).to_expr ()
110+ elif isinstance (value , ops .Value ):
111+ yield value .to_expr ()
112+ elif isinstance (value , Value ):
105113 yield value
106114 elif isinstance (value , Table ):
107115 for name in value .columns :
108- yield value . _get_column ( name )
116+ yield ops . Field ( table , name ). to_expr ( )
109117 elif isinstance (value , Deferred ):
110118 yield value .resolve (table )
111119 elif isinstance (value , Resolver ):
@@ -114,17 +122,11 @@ def bind(table: Table, value: Any) -> Iterator[ir.Value]:
114122 yield from value .expand (table )
115123 elif isinstance (value , Mapping ):
116124 for k , v in value .items ():
117- for val in bind (table , v ):
125+ for val in bind (table , v , int_as_column = int_as_column ):
118126 yield val .name (k )
119127 elif util .is_iterable (value ):
120128 for v in value :
121- yield from bind (table , v )
122- elif isinstance (value , ops .Value ):
123- # TODO(kszucs): from certain builders, like ir.GroupedTable we pass
124- # operation nodes instead of expressions to table methods, it would
125- # be better to convert them to expressions before passing them to
126- # this function
127- yield value .to_expr ()
129+ yield from bind (table , v , int_as_column = int_as_column )
128130 elif callable (value ):
129131 yield value (table )
130132 else :
@@ -567,13 +569,6 @@ def preview(
567569 console_width = console_width ,
568570 )
569571
570- # TODO(kszucs): expose this method in the public API
571- def _get_column (self , name : str | int ) -> ir .Column :
572- """Get a column from the table."""
573- if isinstance (name , int ):
574- name = self .schema ().name_at_position (name )
575- return ops .Field (self , name ).to_expr ()
576-
577572 def __getitem__ (self , what ):
578573 """Select items from a table expression.
579574
@@ -820,22 +815,18 @@ def __getitem__(self, what):
820815 """
821816 from ibis .expr .types .logical import BooleanValue
822817
823- if isinstance (what , (str , int )):
824- return self ._get_column (what )
825- elif isinstance (what , slice ):
818+ if isinstance (what , slice ):
826819 limit , offset = util .slice_to_limit_offset (what , self .count ())
827820 return self .limit (limit , offset = offset )
828- elif isinstance (what , (list , tuple , Table )):
829- # Projection case
830- return self .select (what )
831-
832- items = tuple (bind (self , what ))
833- if util .all_of (items , BooleanValue ):
834- # TODO(kszucs): this branch should be removed, .filter should be
835- # used instead
836- return self .filter (items )
821+
822+ values = tuple (bind (self , what , int_as_column = True ))
823+ if isinstance (what , (str , int )):
824+ assert len (values ) == 1
825+ return values [0 ]
826+ elif util .all_of (values , BooleanValue ):
827+ return self .filter (values )
837828 else :
838- return self .select (items )
829+ return self .select (values )
839830
840831 def __len__ (self ):
841832 raise com .ExpressionError ("Use .count() instead" )
@@ -878,7 +869,7 @@ def __getattr__(self, key: str) -> ir.Column:
878869 └───────────┘
879870 """
880871 try :
881- return self . _get_column ( key )
872+ return ops . Field ( self , key ). to_expr ( )
882873 except com .IbisTypeError :
883874 pass
884875
@@ -2073,7 +2064,7 @@ def select(
20732064
20742065 Projection by zero-indexed column position
20752066
2076- >>> t.select(0, 4 ).head()
2067+ >>> t.select(t[0], t[4] ).head()
20772068 ┏━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━┓
20782069 ┃ species ┃ flipper_length_mm ┃
20792070 ┡━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━┩
@@ -4409,10 +4400,10 @@ def relocate(
44094400 where = 0
44104401
44114402 # all columns that should come BEFORE the matched selectors
4412- front = [left for left in range (where ) if left not in sels ]
4403+ front = [self [ left ] for left in range (where ) if left not in sels ]
44134404
44144405 # all columns that should come AFTER the matched selectors
4415- back = [right for right in range (where , ncols ) if right not in sels ]
4406+ back = [self [ right ] for right in range (where , ncols ) if right not in sels ]
44164407
44174408 # selected columns
44184409 middle = [self [i ].name (name ) for i , name in sels .items ()]
0 commit comments