Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added basic API for Column-level attributes (issue #821) #893

Merged
merged 49 commits into from May 31, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
707f13d
Added basic API for Column-level attributes (issue #821)
jondoesntgit Mar 9, 2021
afe1951
Addressed most of the comments
jondoesntgit Mar 25, 2021
95b1af8
Move code to table.py to avoid circular dependency
jondoesntgit Mar 26, 2021
fa91c95
Enhancement for Index
zequihg50 Feb 18, 2021
a4e2585
Add linux aarch64 wheel support
odidev Mar 10, 2021
b00e361
convert np.typeDict to np.sctypeDict
sroet Jul 19, 2021
cace9e8
Do not use PyArray_DATA in nogitl sections
avalentino Aug 29, 2021
5bde35f
Add 'import ctypes.util'
mnishida Sep 1, 2021
0082489
pyx: adjust indentation to match surrounding calls
keszybz Sep 24, 2021
19b87e9
Fix two typos
keszybz Sep 24, 2021
c842a2f
Stop creating vl arrays with fletcher32 filter
keszybz Sep 24, 2021
ee050d1
Remove duplicate test
avalentino Sep 26, 2021
101df8c
Do not flush when read only
lrepiton Dec 6, 2021
b9d21a2
Do not build wheels for musllinux
avalentino Dec 8, 2021
b68f92d
Update links to CI in the project pointers page
avalentino Dec 8, 2021
1c7adb2
Fix broken links
avalentino Dec 8, 2021
3aaad24
Fix compatibility with numpy 1.20
avalentino Dec 8, 2021
f0e6af5
Run CI against python 3.10
xmatthias Dec 11, 2021
2d97ca6
Build linux/MacOS wheels for python 3.10
xmatthias Dec 11, 2021
b43e787
Don't build wheels for PR branch
xmatthias Dec 11, 2021
6845283
Remove configuration file for Travis-CI
avalentino Dec 12, 2021
e4b0977
Switch to conda-incubator/setup-miniconda
avalentino Dec 12, 2021
0227676
Do not install doc dependencies
avalentino Dec 12, 2021
d9b2304
Add conda-forge channel
avalentino Dec 12, 2021
2078ed1
Do not fail-fast
avalentino Dec 12, 2021
046dfd7
Enable verbose messages in pip install to display build logs
avalentino Dec 12, 2021
7e51ed5
Exclude Python 3.9 and 3.10 from CI on Windows
avalentino Dec 12, 2021
1b731a3
Cleanup
avalentino Dec 12, 2021
7eec00f
Create CONTRIBUTING.md
logankilpatrick Dec 13, 2021
09a1d41
Enable CI on windows 3.9 and 3.10
xmatthias Dec 13, 2021
90f95ec
Don't run CI on python3.10 in appveyor
xmatthias Dec 14, 2021
f879681
Readme should no longer show badge from travis
xmatthias Dec 14, 2021
eba95e7
Add wheel testing and windows CI
xmatthias Dec 14, 2021
4469e74
Windows run wheel repair
xmatthias Dec 14, 2021
89c29b1
also test x86 binaries
xmatthias Dec 14, 2021
90a9364
Try build MacOS wheels
xmatthias Dec 15, 2021
028dde4
Update build matrix
xmatthias Dec 15, 2021
e41228b
build macos ARM wheels
xmatthias Dec 15, 2021
344c7ef
Added support for attributes in the Col class.
mennthor Dec 17, 2021
f68d89f
Extends the Column and ColumnAttributeSet to be agnostic of Col._v_co…
mennthor Dec 17, 2021
ba92d9e
Place ColumnAttributeSet instantiation in the Column __init__
mennthor Dec 17, 2021
1abf377
Added unit tests for
mennthor Dec 17, 2021
71e7d00
Added basic documentation for the Column attributes
mennthor Dec 17, 2021
8804d24
Suggested change: Exception to TypeError
mennthor Dec 17, 2021
d07eef2
Merge pull request #1 from mennthor/master
jondoesntgit Jan 10, 2023
af152a5
Added a blurb in docs
jondoesntgit Apr 14, 2021
53688b3
Changed version in documentation
jondoesntgit Jan 12, 2023
acc27ca
Merge remote-tracking branch 'upstream/master'
jondoesntgit May 31, 2023
0e30264
Removed appveyor.yml per @avalentino's request
jondoesntgit May 31, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
133 changes: 133 additions & 0 deletions tables/attributeset.py
Expand Up @@ -680,6 +680,139 @@ def __repr__(self):
return str(self)


class ColumnAttributeSet:

def __init__(self, column):

self._v_tableattrs = column.table.attrs
avalentino marked this conversation as resolved.
Show resolved Hide resolved
self.__dict__['_v_fieldindex'] = column._v_pos
self.__dict__['_v_column'] = column # Does this need to be a weak reference?
avalentino marked this conversation as resolved.
Show resolved Hide resolved

def issystemcolumnname(self, key):
"""Checks whether a key is a reserved attribute name, or should be passed through."""
return key in ['_v_tableattrs', '_v_fieldindex', '_v_column']

def _prefix(self, string):
"""Prefixes a key with a special pattern for storing with table attributes"""
field_index = self.__dict__['_v_fieldindex']
return 'FIELD_%i_ATTR_%s' % (field_index, string)

def __getattr__(self, key):
"""Retrieves a PyTables attribute for this column"""
if not self.issystemcolumnname(key):
return getattr(self._v_tableattrs, self._prefix(key))
else:
return super().__getattr__(key)

def __setattr__(self, key, val):
"""Sets a PyTables attribute for this column"""
if not self.issystemcolumnname(key):
setattr(self._v_tableattrs, self._prefix(key), val)
else:
return super().__setattr__(key, val)

def __getitem__(self, key):
"""A dictionary-like interface for __getattr__"""
if not self.issystemcolumnname(key):
return self._v_tableattrs[self._prefix(key)]
else:
return self[key]

def __setitem__(self, key, value):
"""A dictionary-like interface for __setattr__"""
if not self.issystemcolumnname(key):
self._v_tableattrs[self._prefix(key)] = value
else:
self[key] = value

def __delattr__(self, key):
"""Deletes the attribute for this column"""
if self.issystemcolumnname(key):
# This is a bad idea, but if the user really wants it, do it
super().__delattr__(key)
avalentino marked this conversation as resolved.
Show resolved Hide resolved
else:
delattr(self._v_tableattrs, self._prefix(key))

def __delitem__(self, key):
"""A dictionary-like interface for __delattr__"""
if self.issystemcolumnname(key):
# This is a bad idea, but if the user really wants it, do it
super().__delitem__(key)
avalentino marked this conversation as resolved.
Show resolved Hide resolved
else:
del self._v_tableattrs[self._prefix(key)]

def _f_rename(self, oldattrname, newattrname):
"""Rename an attribute from oldattrname to newattrname."""

if oldattrname == newattrname:
# Do nothing
return

avalentino marked this conversation as resolved.
Show resolved Hide resolved
# First, fetch the value of the oldattrname
attrvalue = getattr(self, oldattrname)

# Now, create the new attribute
setattr(self, newattrname, attrvalue)

# Finally, remove the old attribute
delattr(self, oldattrname)

def _f_copy(self, where):
"""Copy attributes to another column"""

# Is there a better way to do this?
from .table import Column
if not isinstance(where, Column):
avalentino marked this conversation as resolved.
Show resolved Hide resolved
raise TypeError(f"destination object is not a column: {where!r}")

for key in self.keys():
where.attrs[key] = self[key]

def keys(self):
"""Returns the list of attributes for this column"""
col_prefix = self._prefix('')
length = len(col_prefix)
return [key[length:] for key in self._v_tableattrs._v_attrnames if key.startswith(col_prefix)]

def contains(self, key):
"""Returns whether a key is in the attribute set"""
return key in self.keys()

def __str__(self):
avalentino marked this conversation as resolved.
Show resolved Hide resolved
"""A string representation of this object"""

def __repr__(self):
avalentino marked this conversation as resolved.
Show resolved Hide resolved
"""A detailed string representation for this object"""
print('TODO')


def __str__(self):
"""The string representation for this object."""


avalentino marked this conversation as resolved.
Show resolved Hide resolved
# The pathname
pathname = self._v_tableattrs._v__nodepath
# Get this class name
classname = self._v_column.__class__.__name__ #self._v_tableattrs._v_node.__class__.__name__
avalentino marked this conversation as resolved.
Show resolved Hide resolved
# The attribute names
attrnumber = sum(1 for _ in self.keys())
# The column name
columnname = self._v_column.name

return f"{pathname}.cols.{columnname}._v_attrs ({classname}), {attrnumber} attributes"

def __repr__(self):
"""A detailed string representation for this object."""

# print additional info only if there are attributes to show
attrnames = self.keys()
if attrnames:
rep = [f'{attr} := {getattr(self, attr)!r}' for attr in attrnames]
return f"{self!s}:\n [" + ',\n '.join(rep) + "]"
else:
return str(self)


class NotLoggedAttributeSet(AttributeSet):
def _g_log_add(self, name):
pass
Expand Down
13 changes: 13 additions & 0 deletions tables/table.py
Expand Up @@ -29,6 +29,7 @@
from .index import (
OldIndex, default_index_filters, default_auto_index, Index, IndexesDescG,
IndexesTableG)
from .attributeset import ColumnAttributeSet


profile = False
Expand Down Expand Up @@ -3674,3 +3675,15 @@ def __repr__(self):
"""A detailed string representation for this object."""

return str(self)

@lazyattr
def _v_pos(self):
return self.descr._v_colobjects[self.name]._v_pos

@lazyattr
def _v_attrs(self):
return ColumnAttributeSet(self)

@lazyattr
def attrs(self):
avalentino marked this conversation as resolved.
Show resolved Hide resolved
return self._v_attrs