|
24 | 24 | from pandas.core.common import _asarray_tuplesafe, _try_sort
|
25 | 25 | from pandas.core.internals import BlockManager, make_block, form_blocks
|
26 | 26 | from pandas.core.reshape import block2d_to_block3d, block2d_to_blocknd, factor_indexer
|
| 27 | +from pandas.core.index import Int64Index |
27 | 28 | import pandas.core.common as com
|
28 | 29 | from pandas.tools.merge import concat
|
29 | 30 |
|
@@ -71,6 +72,7 @@ class IncompatibilityWarning(Warning): pass
|
71 | 72 |
|
72 | 73 | # table class map
|
73 | 74 | _TABLE_MAP = {
|
| 75 | + 'generic_table' : 'GenericTable', |
74 | 76 | 'appendable_frame' : 'AppendableFrameTable',
|
75 | 77 | 'appendable_multiframe' : 'AppendableMultiFrameTable',
|
76 | 78 | 'appendable_panel' : 'AppendablePanelTable',
|
@@ -609,7 +611,7 @@ def create_table_index(self, key, **kwargs):
|
609 | 611 |
|
610 | 612 | def groups(self):
|
611 | 613 | """ return a list of all the top-level nodes (that are not themselves a pandas storage object) """
|
612 |
| - return [ g for g in self.handle.walkGroups() if getattr(g._v_attrs,'pandas_type',None) ] |
| 614 | + return [ g for g in self.handle.walkGroups() if getattr(g._v_attrs,'pandas_type',None) or getattr(g,'table',None) ] |
613 | 615 |
|
614 | 616 | def get_node(self, key):
|
615 | 617 | """ return the node with the key or None if it does not exist """
|
@@ -684,16 +686,22 @@ def error(t):
|
684 | 686 | # infer the pt from the passed value
|
685 | 687 | if pt is None:
|
686 | 688 | if value is None:
|
687 |
| - raise Exception("cannot create a storer if the object is not existing nor a value are passed") |
688 | 689 |
|
689 |
| - try: |
690 |
| - pt = _TYPE_MAP[type(value)] |
691 |
| - except: |
692 |
| - error('_TYPE_MAP') |
| 690 | + if getattr(group,'table',None): |
| 691 | + pt = 'frame_table' |
| 692 | + tt = 'generic_table' |
| 693 | + else: |
| 694 | + raise Exception("cannot create a storer if the object is not existing nor a value are passed") |
| 695 | + else: |
| 696 | + |
| 697 | + try: |
| 698 | + pt = _TYPE_MAP[type(value)] |
| 699 | + except: |
| 700 | + error('_TYPE_MAP') |
693 | 701 |
|
694 |
| - # we are actually a table |
695 |
| - if table or append: |
696 |
| - pt += '_table' |
| 702 | + # we are actually a table |
| 703 | + if table or append: |
| 704 | + pt += '_table' |
697 | 705 |
|
698 | 706 | # a storer node
|
699 | 707 | if 'table' not in pt:
|
@@ -959,6 +967,24 @@ def set_attr(self):
|
959 | 967 | """ set the kind for this colummn """
|
960 | 968 | setattr(self.attrs, self.kind_attr, self.kind)
|
961 | 969 |
|
| 970 | +class GenericIndexCol(IndexCol): |
| 971 | + """ an index which is not represented in the data of the table """ |
| 972 | + |
| 973 | + @property |
| 974 | + def is_indexed(self): |
| 975 | + return False |
| 976 | + |
| 977 | + def convert(self, values, nan_rep): |
| 978 | + """ set the values from this selection: take = take ownership """ |
| 979 | + |
| 980 | + self.values = Int64Index(np.arange(self.table.nrows)) |
| 981 | + return self |
| 982 | + |
| 983 | + def get_attr(self): |
| 984 | + pass |
| 985 | + |
| 986 | + def set_attr(self): |
| 987 | + pass |
962 | 988 |
|
963 | 989 | class DataCol(IndexCol):
|
964 | 990 | """ a data holding column, by definition this is not indexable
|
@@ -1194,6 +1220,12 @@ def get_atom_data(self, block):
|
1194 | 1220 | def get_atom_datetime64(self, block):
|
1195 | 1221 | return _tables().Int64Col()
|
1196 | 1222 |
|
| 1223 | +class GenericDataIndexableCol(DataIndexableCol): |
| 1224 | + """ represent a generic pytables data column """ |
| 1225 | + |
| 1226 | + def get_attr(self): |
| 1227 | + pass |
| 1228 | + |
1197 | 1229 | class Storer(object):
|
1198 | 1230 | """ represent an object in my store
|
1199 | 1231 | facilitate read/write of various types of objects
|
@@ -2632,6 +2664,47 @@ def read(self, where=None, columns=None, **kwargs):
|
2632 | 2664 | return df
|
2633 | 2665 |
|
2634 | 2666 |
|
| 2667 | +class GenericTable(AppendableFrameTable): |
| 2668 | + """ a table that read/writes the generic pytables table format """ |
| 2669 | + pandas_kind = 'frame_table' |
| 2670 | + table_type = 'generic_table' |
| 2671 | + ndim = 2 |
| 2672 | + obj_type = DataFrame |
| 2673 | + |
| 2674 | + @property |
| 2675 | + def pandas_type(self): |
| 2676 | + return self.pandas_kind |
| 2677 | + |
| 2678 | + def get_attrs(self): |
| 2679 | + """ retrieve our attributes """ |
| 2680 | + self.non_index_axes = [] |
| 2681 | + self.nan_rep = None |
| 2682 | + self.levels = [] |
| 2683 | + t = self.table |
| 2684 | + self.index_axes = [ a.infer(t) for a in self.indexables if a.is_an_indexable ] |
| 2685 | + self.values_axes = [ a.infer(t) for a in self.indexables if not a.is_an_indexable ] |
| 2686 | + self.data_columns = [ a.name for a in self.values_axes ] |
| 2687 | + |
| 2688 | + @property |
| 2689 | + def indexables(self): |
| 2690 | + """ create the indexables from the table description """ |
| 2691 | + if self._indexables is None: |
| 2692 | + |
| 2693 | + d = self.description |
| 2694 | + |
| 2695 | + # the index columns is just a simple index |
| 2696 | + self._indexables = [ GenericIndexCol(name='index',axis=0) ] |
| 2697 | + |
| 2698 | + for i, n in enumerate(d._v_names): |
| 2699 | + |
| 2700 | + dc = GenericDataIndexableCol(name = n, pos=i, values = [ n ], version = self.version) |
| 2701 | + self._indexables.append(dc) |
| 2702 | + |
| 2703 | + return self._indexables |
| 2704 | + |
| 2705 | + def write(self, **kwargs): |
| 2706 | + raise NotImplementedError("cannot write on an generic table") |
| 2707 | + |
2635 | 2708 | class AppendableMultiFrameTable(AppendableFrameTable):
|
2636 | 2709 | """ a frame with a multi-index """
|
2637 | 2710 | table_type = 'appendable_multiframe'
|
|
0 commit comments