diff --git a/pandas/io/pytables.py b/pandas/io/pytables.py index 1e382740240ab..56422e6c01a58 100644 --- a/pandas/io/pytables.py +++ b/pandas/io/pytables.py @@ -1895,6 +1895,9 @@ def __init__( freq=None, tz=None, index_name=None, + table=None, + meta=None, + metadata=None, ): if not isinstance(name, str): @@ -1910,9 +1913,9 @@ def __init__( self.freq = freq self.tz = tz self.index_name = index_name - self.table = None - self.meta = None - self.metadata = None + self.table = table + self.meta = meta + self.metadata = metadata if pos is not None: self.set_pos(pos) @@ -1968,19 +1971,6 @@ def is_indexed(self) -> bool: # 'error: "None" has no attribute "cols"' return getattr(self.table.cols, self.cname).is_indexed # type: ignore - def copy(self): - new_self = copy.copy(self) - return new_self - - def infer(self, handler: "Table"): - """infer this column from the table: create and return a new object""" - table = handler.table - new_self = self.copy() - new_self.table = table - new_self.get_attr() - new_self.read_metadata(handler) - return new_self - def convert(self, values: np.ndarray, nan_rep, encoding: str, errors: str): """ set the values from this selection: take = take ownership """ assert isinstance(values, np.ndarray), type(values) @@ -2136,10 +2126,6 @@ def set_attr(self): """ set the kind for this column """ setattr(self.attrs, self.kind_attr, self.kind) - def read_metadata(self, handler): - """ retrieve the metadata for this columns """ - self.metadata = handler.read_metadata(self.cname) - def validate_metadata(self, handler: "AppendableTable"): """ validate that kind=category does not change the categories """ if self.meta == "category": @@ -2207,10 +2193,27 @@ class DataCol(IndexCol): _info_fields = ["tz", "ordered"] def __init__( - self, name: str, values=None, kind=None, typ=None, cname=None, pos=None, + self, + name: str, + values=None, + kind=None, + typ=None, + cname=None, + pos=None, + table=None, + meta=None, + metadata=None, ): super().__init__( - name=name, values=values, kind=kind, typ=typ, pos=pos, cname=cname + name=name, + values=values, + kind=kind, + typ=typ, + pos=pos, + cname=cname, + table=table, + meta=meta, + metadata=metadata, ) self.dtype = None self.data = None @@ -3420,10 +3423,8 @@ def get_attrs(self): self.encoding = _ensure_encoding(getattr(self.attrs, "encoding", None)) self.errors = _ensure_decoded(getattr(self.attrs, "errors", "strict")) self.levels = getattr(self.attrs, "levels", None) or [] - self.index_axes = [a.infer(self) for a in self.indexables if a.is_an_indexable] - self.values_axes = [ - a.infer(self) for a in self.indexables if not a.is_an_indexable - ] + self.index_axes = [a for a in self.indexables if a.is_an_indexable] + self.values_axes = [a for a in self.indexables if not a.is_an_indexable] self.metadata = getattr(self.attrs, "metadata", None) or [] def validate_version(self, where=None): @@ -3466,7 +3467,18 @@ def indexables(self): # index columns for i, (axis, name) in enumerate(self.attrs.index_cols): atom = getattr(desc, name) - index_col = IndexCol(name=name, axis=axis, pos=i, typ=atom) + md = self.read_metadata(name) + meta = "category" if md is not None else None + index_col = IndexCol( + name=name, + axis=axis, + pos=i, + typ=atom, + table=self.table, + meta=meta, + metadata=md, + ) + index_col.get_attr() _indexables.append(index_col) # values columns @@ -3481,7 +3493,19 @@ def f(i, c): atom = getattr(desc, c) adj_name = _maybe_adjust_name(c, self.version) - return klass(name=adj_name, cname=c, pos=base_pos + i, typ=atom) + md = self.read_metadata(c) + meta = "category" if md is not None else None + obj = klass( + name=adj_name, + cname=c, + pos=base_pos + i, + typ=atom, + table=self.table, + meta=meta, + metadata=md, + ) + obj.get_attr() + return obj # Note: the definition of `values_cols` ensures that each # `c` below is a str. @@ -4474,10 +4498,8 @@ def get_attrs(self): self.nan_rep = None self.levels = [] - self.index_axes = [a.infer(self) for a in self.indexables if a.is_an_indexable] - self.values_axes = [ - a.infer(self) for a in self.indexables if not a.is_an_indexable - ] + self.index_axes = [a for a in self.indexables if a.is_an_indexable] + self.values_axes = [a for a in self.indexables if not a.is_an_indexable] self.data_columns = [a.name for a in self.values_axes] @cache_readonly @@ -4488,13 +4510,31 @@ def indexables(self): # TODO: can we get a typ for this? AFAICT it is the only place # where we aren't passing one # the index columns is just a simple index - _indexables = [GenericIndexCol(name="index", axis=0)] + md = self.read_metadata("index") + meta = "category" if md is not None else None + index_col = GenericIndexCol( + name="index", axis=0, table=self.table, meta=meta, metadata=md + ) + index_col.get_attr() + + _indexables = [index_col] for i, n in enumerate(d._v_names): assert isinstance(n, str) atom = getattr(d, n) - dc = GenericDataIndexableCol(name=n, pos=i, values=[n], typ=atom) + md = self.read_metadata(n) + meta = "category" if md is not None else None + dc = GenericDataIndexableCol( + name=n, + pos=i, + values=[n], + typ=atom, + table=self.table, + meta=meta, + metadata=md, + ) + dc.get_attr() _indexables.append(dc) return _indexables