Cython API: various improvements and checks

This commit is contained in:
Celine Mercier
2017-07-28 13:15:13 +02:00
parent b9c65a871f
commit 35b0c55a8c
10 changed files with 178 additions and 94 deletions

View File

@ -18,16 +18,16 @@ import string
import random import random
VIEW_TYPES = ["", "NUC_SEQS_VIEW"] VIEW_TYPES = [b"", b"NUC_SEQS_VIEW"]
COL_TYPES = [OBI_INT, OBI_FLOAT, OBI_BOOL, OBI_CHAR, OBI_STR, OBI_SEQ] COL_TYPES = [OBI_INT, OBI_FLOAT, OBI_BOOL, OBI_CHAR, OBI_STR, OBI_SEQ]
NUC_SEQUENCE_COLUMN = "NUC_SEQ" NUC_SEQUENCE_COLUMN = b"NUC_SEQ"
ID_COLUMN = "ID" ID_COLUMN = b"ID"
DEFINITION_COLUMN = "DEFINITION" DEFINITION_COLUMN = b"DEFINITION"
QUALITY_COLUMN = "QUALITY" QUALITY_COLUMN = b"QUALITY"
SPECIAL_COLUMNS = [NUC_SEQUENCE_COLUMN, ID_COLUMN, DEFINITION_COLUMN, QUALITY_COLUMN] SPECIAL_COLUMNS = [NUC_SEQUENCE_COLUMN, ID_COLUMN, DEFINITION_COLUMN, QUALITY_COLUMN]
#TAXDUMP = "" TODO path=? #TAXDUMP = "" TODO path=?
TAXTEST = "taxtest" TAXTEST = b"taxtest"
NAME_MAX_LEN = 200 NAME_MAX_LEN = 200
COL_COMMENTS_MAX_LEN = 2048 COL_COMMENTS_MAX_LEN = 2048
@ -94,7 +94,7 @@ def random_str_with_max_len(max_len):
def random_bytes_with_max_len(max_len): def random_bytes_with_max_len(max_len):
return str2bytes(''.join(random.choice(string.ascii_lowercase) for i in range(random_length(max_len)))) return str2bytes(random_str_with_max_len(max_len))
def random_column(infos): def random_column(infos):
@ -102,17 +102,17 @@ def random_column(infos):
def random_unique_name(infos): def random_unique_name(infos):
name = "" name = b""
while name == "" or name in infos['unique_names'] : while name == b"" or name in infos['unique_names'] :
name = random_str_with_max_len(NAME_MAX_LEN) name = random_bytes_with_max_len(NAME_MAX_LEN)
infos['unique_names'].append(name) infos['unique_names'].append(name)
return name return name
def random_unique_element_name(config, infos): def random_unique_element_name(config, infos):
name = "" name = b""
while name == "" or name in infos['unique_names'] : while name == b"" or name in infos['unique_names'] :
name = random_str_with_max_len(config['test']['elt_name_max_len']) name = random_bytes_with_max_len(config['test']['elt_name_max_len'])
infos['unique_names'].append(name) infos['unique_names'].append(name)
return name return name
@ -128,7 +128,7 @@ def test_set_and_get(config, infos):
col = infos['view'][col_name] col = infos['view'][col_name]
element_names = col.elements_names element_names = col.elements_names
data_type = col.data_type data_type = col.data_type
if data_type == "OBI_QUAL" : if data_type == b"OBI_QUAL" :
print_test(config, "-") print_test(config, "-")
return return
idx = random_int(config) idx = random_int(config)
@ -217,7 +217,7 @@ def fill_column(config, infos, col) :
def create_random_column(config, infos) : def create_random_column(config, infos) :
alias = random.choice(['', random_unique_name(infos)]) alias = random.choice([b'', random_unique_name(infos)])
nb_elements_per_line=random.randint(1, config['test']['maxelts']) nb_elements_per_line=random.randint(1, config['test']['maxelts'])
elements_names = [] elements_names = []
for i in range(nb_elements_per_line) : for i in range(nb_elements_per_line) :
@ -235,7 +235,7 @@ def create_random_column(config, infos) :
alias=alias alias=alias
) )
if alias != '' : if alias != b'' :
assert infos['view'][alias] == column assert infos['view'][alias] == column
else : else :
assert infos['view'][name] == column assert infos['view'][name] == column
@ -257,7 +257,7 @@ def random_new_view(config, infos, first=False):
infos['view_names'].append(infos['view'].name) infos['view_names'].append(infos['view'].name)
infos['view'].close() infos['view'].close()
v_to_clone = View.open(infos['dms'], random.choice(infos["view_names"])) v_to_clone = View.open(infos['dms'], random.choice(infos["view_names"]))
v_type = "" v_type = b""
print_test(config, "View to clone: ") print_test(config, "View to clone: ")
print_test(config, repr(v_to_clone)) print_test(config, repr(v_to_clone))
create_line_selection = random_bool(config) create_line_selection = random_bool(config)
@ -271,14 +271,14 @@ def random_new_view(config, infos, first=False):
v_type = random_view_type() v_type = random_view_type()
if line_selection is not None : if line_selection is not None :
infos['view'] = line_selection.materialize(random_unique_name(infos), comments=random_str_with_max_len(config['test']['commentsmaxlen'])) infos['view'] = line_selection.materialize(random_unique_name(infos), comments=random_bytes_with_max_len(config['test']['commentsmaxlen']))
elif v_to_clone is not None : elif v_to_clone is not None :
infos['view'] = v_to_clone.clone(random_unique_name(infos), comments=random_str_with_max_len(config['test']['commentsmaxlen'])) infos['view'] = v_to_clone.clone(random_unique_name(infos), comments=random_bytes_with_max_len(config['test']['commentsmaxlen']))
else : else :
if v_type == "NUC_SEQS_VIEW" : if v_type == "NUC_SEQS_VIEW" :
infos['view'] = View_NUC_SEQS.new(infos['dms'], random_unique_name(infos), comments=random_str_with_max_len(config['test']['commentsmaxlen'])) # TODO quality column infos['view'] = View_NUC_SEQS.new(infos['dms'], random_unique_name(infos), comments=random_bytes_with_max_len(config['test']['commentsmaxlen'])) # TODO quality column
else : else :
infos['view'] = View.new(infos['dms'], random_unique_name(infos), comments=random_str_with_max_len(config['test']['commentsmaxlen'])) # TODO quality column infos['view'] = View.new(infos['dms'], random_unique_name(infos), comments=random_bytes_with_max_len(config['test']['commentsmaxlen'])) # TODO quality column
print_test(config, repr(infos['view'])) print_test(config, repr(infos['view']))
if v_to_clone is not None : if v_to_clone is not None :

View File

@ -20,7 +20,6 @@ cdef class Column(OBIWrapper) :
cdef bytes _alias cdef bytes _alias
cdef inline OBIDMS_column_p pointer(self) cdef inline OBIDMS_column_p pointer(self)
cpdef close(self)
@staticmethod @staticmethod
cdef type get_column_class(obitype_t obitype, bint multi_elts) cdef type get_column_class(obitype_t obitype, bint multi_elts)

View File

@ -20,7 +20,7 @@ from ..capi.obiview cimport obi_view_add_column, \
obi_view_get_pointer_on_column_in_view, \ obi_view_get_pointer_on_column_in_view, \
Obiview_p Obiview_p
from ..object cimport OBIObjectClosedInstance from ..object cimport OBIDeactivatedInstanceError
from obitools3.utils cimport tobytes, \ from obitools3.utils cimport tobytes, \
bytes2str, \ bytes2str, \
@ -76,7 +76,7 @@ cdef class Column(OBIWrapper) :
cdef char* elements_names_p cdef char* elements_names_p
if not view.active() : if not view.active() :
raise OBIObjectClosedInstance() raise OBIDeactivatedInstanceError()
if alias_b == b"" : if alias_b == b"" :
alias_b = column_name_b alias_b = column_name_b
@ -117,7 +117,7 @@ cdef class Column(OBIWrapper) :
cdef type column_class cdef type column_class
if not view.active() : if not view.active() :
raise OBIObjectClosedInstance() raise OBIDeactivatedInstanceError()
column_pp = obi_view_get_pointer_on_column_in_view(view.pointer(), column_pp = obi_view_get_pointer_on_column_in_view(view.pointer(),
column_name_b) column_name_b)
@ -140,6 +140,7 @@ cdef class Column(OBIWrapper) :
return column return column
@OBIWrapper.checkIsActive
def add_to_view(self, def add_to_view(self,
View view, View view,
object column_name=None) : object column_name=None) :
@ -148,7 +149,7 @@ cdef class Column(OBIWrapper) :
cdef OBIDMS_column_p column_p = self.pointer() cdef OBIDMS_column_p column_p = self.pointer()
if not view.active() : if not view.active() :
raise OBIObjectClosedInstance() raise OBIDeactivatedInstanceError()
if (column_name is None): if (column_name is None):
alias = self._alias alias = self._alias
@ -178,6 +179,7 @@ cdef class Column(OBIWrapper) :
view.register(self) view.register(self)
@OBIWrapper.checkIsActive
def __len__(self): def __len__(self):
''' '''
implements the len() function for the Column class implements the len() function for the Column class
@ -187,6 +189,7 @@ cdef class Column(OBIWrapper) :
return self.lines_used return self.lines_used
@OBIWrapper.checkIsActive
def __sizeof__(self): def __sizeof__(self):
''' '''
returns the size of the C object wrapped by the Column instance returns the size of the C object wrapped by the Column instance
@ -195,20 +198,25 @@ cdef class Column(OBIWrapper) :
return header.header_size + header.data_size return header.header_size + header.data_size
@OBIWrapper.checkIsActive
def __iter__(self): def __iter__(self):
cdef index_t line_nb cdef index_t line_nb
for line_nb in range(self.lines_used): for line_nb in range(self.lines_used):
yield self.get_line(line_nb) yield self.get_line(line_nb)
# TODO check time efficiency with and without
@OBIWrapper.checkIsActive
def __setitem__(self, index_t line_nb, object value): def __setitem__(self, index_t line_nb, object value):
self.set_line(line_nb, value) self.set_line(line_nb, value)
@OBIWrapper.checkIsActive
def __getitem__(self, index_t line_nb): def __getitem__(self, index_t line_nb):
return self.get_line(line_nb) return self.get_line(line_nb)
@OBIWrapper.checkIsActive
def __str__(self) : def __str__(self) :
cdef str to_print cdef str to_print
cdef object line cdef object line
@ -218,13 +226,14 @@ cdef class Column(OBIWrapper) :
return to_print return to_print
@OBIWrapper.checkIsActive
def __repr__(self) : def __repr__(self) :
cdef bytes s cdef bytes s
s = self._alias + b", original name: " + self.original_name + b", version " + str2bytes(str(self.version)) + b", data type: " + self.data_type s = self._alias + b", original name: " + self.original_name + b", version " + str2bytes(str(self.version)) + b", data type: " + self.data_type
return bytes2str(s) return bytes2str(s)
cpdef close(self): # TODO discuss, can't be called bc then bug when closing view that tries to close it in C def close(self): # TODO discuss, can't be called bc then bug when closing view that tries to close it in C
cdef OBIDMS_column_p pointer cdef OBIDMS_column_p pointer
@ -239,54 +248,76 @@ cdef class Column(OBIWrapper) :
# Column alias property getter and setter # Column alias property getter and setter
@property @property
def name(self): def name(self):
if not self.active() :
raise OBIDeactivatedInstanceError()
return self._alias return self._alias
@name.setter @name.setter
def name(self, object new_alias): # @DuplicatedSignature def name(self, object new_alias): # @DuplicatedSignature
if not self.active() :
raise OBIDeactivatedInstanceError()
self._view.rename_column(self._alias, new_alias) self._view.rename_column(self._alias, new_alias)
# elements_names property getter # elements_names property getter
@property @property
def elements_names(self): def elements_names(self):
if not self.active() :
raise OBIDeactivatedInstanceError()
return obi_get_elements_names(self.pointer()).split(b';') return obi_get_elements_names(self.pointer()).split(b';')
# nb_elements_per_line property getter # nb_elements_per_line property getter
@property @property
def nb_elements_per_line(self): def nb_elements_per_line(self):
if not self.active() :
raise OBIDeactivatedInstanceError()
return self.pointer().header.nb_elements_per_line return self.pointer().header.nb_elements_per_line
# data_type property getter # data_type property getter
@property @property
def data_type(self): def data_type(self):
if not self.active() :
raise OBIDeactivatedInstanceError()
return name_data_type(self.data_type_int) return name_data_type(self.data_type_int)
# data_type integer code property getter # data_type integer code property getter
@property @property
def data_type_int(self): def data_type_int(self):
if not self.active() :
raise OBIDeactivatedInstanceError()
return self.pointer().header.returned_data_type return self.pointer().header.returned_data_type
# original_name property getter # original_name property getter
@property @property
def original_name(self): def original_name(self):
if not self.active() :
raise OBIDeactivatedInstanceError()
return self.pointer().header.name return self.pointer().header.name
# version property getter # version property getter
@property @property
def version(self): def version(self):
if not self.active() :
raise OBIDeactivatedInstanceError()
return self.pointer().header.version return self.pointer().header.version
# lines_used property getter # lines_used property getter
@property @property
def lines_used(self): def lines_used(self):
if not self.active() :
raise OBIDeactivatedInstanceError()
return self.pointer().header.lines_used return self.pointer().header.lines_used
# comments property getter # comments property getter
@property @property
def comments(self): def comments(self):
if not self.active() :
raise OBIDeactivatedInstanceError()
return self.pointer().header.comments return self.pointer().header.comments
# creation_date property getter # creation_date property getter
@property @property
def creation_date(self): def creation_date(self):
if not self.active() :
raise OBIDeactivatedInstanceError()
return obi_format_date(self.pointer().header.creation_date) return obi_format_date(self.pointer().header.creation_date)
@ -295,10 +326,14 @@ cdef class Column(OBIWrapper) :
cdef class Column_multi_elts(Column) : cdef class Column_multi_elts(Column) :
@OBIWrapper.checkIsActive
def __getitem__(self, index_t line_nb): def __getitem__(self, index_t line_nb):
return Column_line(self, line_nb) return Column_line(self, line_nb)
cpdef set_line(self, index_t line_nb, object values): cpdef set_line(self, index_t line_nb, object values):
cdef object element_name
if not self.active() :
raise OBIDeactivatedInstanceError()
if values is None : if values is None :
for element_name in self.elements_names : for element_name in self.elements_names :
self.set_item(line_nb, element_name, None) self.set_item(line_nb, element_name, None)

View File

@ -17,11 +17,12 @@ from obitools3.utils cimport bytes2str, \
tobytes, \ tobytes, \
tostr tostr
from .object cimport OBIObjectClosedInstance from .object cimport OBIDeactivatedInstanceError
from pathlib import Path from pathlib import Path
from .view import view from .view import view
from .object import OBIWrapper
cdef class DMS(OBIWrapper): cdef class DMS(OBIWrapper):
@ -102,6 +103,7 @@ cdef class DMS(OBIWrapper):
return <bytes> self.pointer().dms_name return <bytes> self.pointer().dms_name
@OBIWrapper.checkIsActive
def keys(self) : def keys(self) :
cdef const_char_p path = obi_dms_get_full_path(self.pointer(), b"VIEWS") cdef const_char_p path = obi_dms_get_full_path(self.pointer(), b"VIEWS")
@ -117,18 +119,21 @@ cdef class DMS(OBIWrapper):
yield str2bytes(v.stem) yield str2bytes(v.stem)
@OBIWrapper.checkIsActive
def values(self) : def values(self) :
cdef bytes view_name cdef bytes view_name
for view_name in self.keys(): for view_name in self.keys():
yield self.get_view(view_name) yield self.get_view(view_name)
@OBIWrapper.checkIsActive
def items(self) : def items(self) :
cdef bytes view_name cdef bytes view_name
for view_name in self.keys(): for view_name in self.keys():
yield (view_name, self.get_view(view_name)) yield (view_name, self.get_view(view_name))
@OBIWrapper.checkIsActive
def __contains__(self, key) : def __contains__(self, key) :
cdef str key_s = tostr(key) cdef str key_s = tostr(key)
@ -145,18 +150,22 @@ cdef class DMS(OBIWrapper):
return PyList_Size(list(self.keys())) return PyList_Size(list(self.keys()))
@OBIWrapper.checkIsActive
def __len__(self) : def __len__(self) :
return self.view_count() return self.view_count()
@OBIWrapper.checkIsActive
def __getitem__(self, object view_name): def __getitem__(self, object view_name):
return self.get_view(view_name) return self.get_view(view_name)
@OBIWrapper.checkIsActive
def __iter__(self) : def __iter__(self) :
return self.keys() return self.keys()
@OBIWrapper.checkIsActive
def get_view(self, object view_name) : def get_view(self, object view_name) :
return view.View.open(self, view_name) return view.View.open(self, view_name)

View File

@ -10,7 +10,6 @@ cdef class OBIObject:
cdef register(self, OBIObject object) cdef register(self, OBIObject object)
cdef unregister(self, OBIObject object) cdef unregister(self, OBIObject object)
cpdef close(self)
cdef class OBIWrapper(OBIObject): cdef class OBIWrapper(OBIObject):
@ -24,5 +23,5 @@ cdef class OBIWrapper(OBIObject):
cdef object new_wrapper(type constructor, void* pointer) cdef object new_wrapper(type constructor, void* pointer)
cdef class OBIObjectClosedInstance(Exception): cdef class OBIDeactivatedInstanceError(Exception):
pass pass

View File

@ -1,5 +1,7 @@
#cython: language_level=3 #cython: language_level=3
import functools
__c_cython_mapping__ = {} __c_cython_mapping__ = {}
@ -26,7 +28,7 @@ cdef class OBIObject:
del self._dependent_objects[id(object)] del self._dependent_objects[id(object)]
cpdef close(self): def close(self):
cdef OBIObject object cdef OBIObject object
cdef list to_close = list((self._dependent_objects).values()) cdef list to_close = list((self._dependent_objects).values())
@ -42,6 +44,18 @@ cdef class OBIWrapper(OBIObject) :
The OBIWrapper class enables to wrap a C object representing a DMS or an element from a DMS. The OBIWrapper class enables to wrap a C object representing a DMS or an element from a DMS.
''' '''
@staticmethod
def checkIsActive(instance):
'''
Decorator function to check that an instance is still active (associated pointer not NULL)
'''
@functools.wraps(instance)
def check(self,*args,**kargs):
if self.dead:
raise OBIDeactivatedInstanceError()
return instance(self,*args,**kargs)
return check
cdef inline size_t cid(self) : cdef inline size_t cid(self) :
return <size_t>(self._pointer) return <size_t>(self._pointer)
@ -50,7 +64,7 @@ cdef class OBIWrapper(OBIObject) :
return self._pointer != NULL return self._pointer != NULL
cpdef close(self): def close(self):
if (self._pointer != NULL): if (self._pointer != NULL):
OBIObject.close(self) OBIObject.close(self)
del __c_cython_mapping__[<size_t>self._pointer] del __c_cython_mapping__[<size_t>self._pointer]
@ -68,6 +82,9 @@ cdef class OBIWrapper(OBIObject) :
''' '''
self.close() self.close()
@property
def dead(self):
return self._pointer==NULL
@staticmethod @staticmethod
cdef object new_wrapper(type constructor, void* pointer) : cdef object new_wrapper(type constructor, void* pointer) :

View File

@ -16,7 +16,6 @@ cdef class Taxonomy(OBIWrapper) :
cpdef get_taxon_by_idx(self, int idx) cpdef get_taxon_by_idx(self, int idx)
cpdef write(self, str prefix) cpdef write(self, str prefix)
cpdef int add_taxon(self, str name, str rank_name, int parent_taxid, int min_taxid=*) cpdef int add_taxon(self, str name, str rank_name, int parent_taxid, int min_taxid=*)
cpdef close(self)
cdef class Taxon : cdef class Taxon :
cdef ecotx_t* _pointer cdef ecotx_t* _pointer

View File

@ -108,7 +108,7 @@ cdef class Taxonomy(OBIWrapper) :
return taxid return taxid
cpdef close(self) : def close(self) :
cdef OBIDMS_taxonomy_p pointer = self.pointer() cdef OBIDMS_taxonomy_p pointer = self.pointer()

View File

@ -23,7 +23,7 @@ from obitools3.utils cimport tobytes, \
bytes2str, \ bytes2str, \
tostr tostr
from ..object cimport OBIObjectClosedInstance from ..object cimport OBIDeactivatedInstanceError
from obitools3.dms.view import typed_view from obitools3.dms.view import typed_view
@ -92,14 +92,13 @@ cdef class View(OBIWrapper) :
object view_name, object view_name,
object comments=None): object comments=None):
cdef bytes view_name_b = tobytes(view_name) cdef bytes view_name_b = tobytes(view_name)
cdef bytes comments_b cdef bytes comments_b
cdef void* pointer cdef void* pointer
cdef View view cdef View view
if not self.active() : if not self.active() :
raise OBIObjectClosedInstance() raise OBIDeactivatedInstanceError()
if comments is not None: if comments is not None:
comments_b = tobytes(comments) comments_b = tobytes(comments)
@ -149,7 +148,7 @@ cdef class View(OBIWrapper) :
return view return view
cpdef close(self): def close(self):
cdef Obiview_p pointer = self.pointer() cdef Obiview_p pointer = self.pointer()
if self.active() : if self.active() :
@ -160,34 +159,29 @@ cdef class View(OBIWrapper) :
bytes2str(self.name)) bytes2str(self.name))
@OBIWrapper.checkIsActive
def __repr__(self) : def __repr__(self) :
# TODO check everywhere
if not self.active() :
raise OBIObjectClosedInstance()
cdef str s = "{name:s}\n{comments:s}\n{line_count:d} lines\n".format(name = str(self.name), cdef str s = "{name:s}\n{comments:s}\n{line_count:d} lines\n".format(name = str(self.name),
comments = str(self.comments), comments = str(self.comments),
line_count = self.line_count) line_count = self.line_count)
for column_name in self.keys() : for column_name in self.keys() :
s = s + repr(self[column_name]) + '\n' s = s + repr(self[column_name]) + '\n'
return s return s
def keys(self): def keys(self):
cdef str col_alias cdef bytes col_alias
cdef int i cdef int i
cdef Obiview_p pointer = self.pointer() cdef Obiview_p pointer = self.pointer()
cdef int nb_column = pointer.infos.column_count cdef int nb_column = pointer.infos.column_count
cdef Alias_column_pair_p column_p = pointer.infos.column_references cdef Alias_column_pair_p column_p = pointer.infos.column_references
if not self.active() : if not self.active() :
raise OBIObjectClosedInstance() raise OBIDeactivatedInstanceError()
for i in range(nb_column) : for i in range(nb_column) :
col_alias = bytes2str(column_p[i].alias) col_alias = column_p[i].alias
yield col_alias yield col_alias
@ -195,9 +189,9 @@ cdef class View(OBIWrapper) :
object column_name): object column_name):
if not self.active() : if not self.active() :
raise OBIObjectClosedInstance() raise OBIDeactivatedInstanceError()
return Column.open(self, column_name) return Column.open(self, tobytes(column_name))
def get_column_with_idx(self, def get_column_with_idx(self,
@ -207,7 +201,7 @@ cdef class View(OBIWrapper) :
cdef int nb_column = pointer.infos.column_count cdef int nb_column = pointer.infos.column_count
if not self.active() : if not self.active() :
raise OBIObjectClosedInstance() raise OBIDeactivatedInstanceError()
if column_idx > nb_column : if column_idx > nb_column :
raise IndexError(column_idx, "No column with this index") raise IndexError(column_idx, "No column with this index")
@ -221,10 +215,10 @@ cdef class View(OBIWrapper) :
cdef bytes column_name_b = tobytes(column_name) cdef bytes column_name_b = tobytes(column_name)
if not self.active() : if not self.active() :
raise OBIObjectClosedInstance() raise OBIDeactivatedInstanceError()
# Close the cython instance first # Close the cython instance first
col = self[column_name] col = self[column_name_b]
col.close() col.close()
# Remove the column from the view which closes the C structure # Remove the column from the view which closes the C structure
@ -242,7 +236,7 @@ cdef class View(OBIWrapper) :
cdef bytes new_name_b = tobytes(new_name) cdef bytes new_name_b = tobytes(new_name)
if not self.active() : if not self.active() :
raise OBIObjectClosedInstance() raise OBIDeactivatedInstanceError()
if (obi_view_create_column_alias(self.pointer(), if (obi_view_create_column_alias(self.pointer(),
tobytes(current_name_b), tobytes(current_name_b),
@ -262,8 +256,12 @@ cdef class View(OBIWrapper) :
cdef Column old_column cdef Column old_column
cdef Column new_column cdef Column new_column
cdef index_t length = len(self) cdef index_t length = len(self)
cdef column_name_b = tobytes(column_name)
old_column = self.get_column(column_name) if not self.active() :
raise OBIDeactivatedInstanceError()
old_column = self.get_column(column_name_b)
if new_data_type == 0 : if new_data_type == 0 :
new_data_type = old_column.data_type new_data_type = old_column.data_type
@ -276,24 +274,27 @@ cdef class View(OBIWrapper) :
new_column = Column.new_column(self, old_column.pointer().header.name, new_data_type, new_column = Column.new_column(self, old_column.pointer().header.name, new_data_type,
nb_elements_per_line=new_nb_elements_per_line, elements_names=new_elements_names, nb_elements_per_line=new_nb_elements_per_line, elements_names=new_elements_names,
comments=old_column.comments, alias=tobytes(column_name)+tobytes('___new___')) comments=old_column.comments, alias=column_name_b+tobytes('___new___'))
for i in range(length) : for i in range(length) :
new_column[i] = old_column[i] new_column[i] = old_column[i]
# Remove old column from view # Remove old column from view
self.delete_column(column_name) self.delete_column(column_name_b)
# Rename new # Rename new
new_column.name = column_name new_column.name = column_name_b
return new_column return new_column
cpdef Line_selection new_selection(self,list lines=None): cpdef Line_selection new_selection(self, list lines=None):
if not self.active() :
raise OBIDeactivatedInstanceError()
return Line_selection(self, lines) return Line_selection(self, lines)
@OBIWrapper.checkIsActive
def __iter__(self): def __iter__(self):
# Iteration on each line of all columns # Iteration on each line of all columns
@ -305,6 +306,8 @@ cdef class View(OBIWrapper) :
yield Line(self, line_nb) yield Line(self, line_nb)
# TODO test time gain without
@OBIWrapper.checkIsActive
def __getitem__(self, object ref) : def __getitem__(self, object ref) :
if type(ref) == int : if type(ref) == int :
return Line(self, ref) return Line(self, ref)
@ -312,6 +315,7 @@ cdef class View(OBIWrapper) :
return self.get_column(ref) # TODO hyper lent dans la pratique return self.get_column(ref) # TODO hyper lent dans la pratique
@OBIWrapper.checkIsActive
def __setitem__(self, index_t idx, object item) : def __setitem__(self, index_t idx, object item) :
cdef Column col cdef Column col
line = self[idx] line = self[idx]
@ -330,14 +334,17 @@ cdef class View(OBIWrapper) :
line[k] = item[k] line[k] = item[k]
def __contains__(self, str column_name): @OBIWrapper.checkIsActive
return (column_name in self.keys()) def __contains__(self, object column_name):
return (tobytes(column_name) in self.keys())
@OBIWrapper.checkIsActive
def __len__(self): def __len__(self):
return(self.line_count) return(self.line_count)
@OBIWrapper.checkIsActive
def __str__(self) : def __str__(self) :
cdef Line line cdef Line line
cdef str to_print cdef str to_print
@ -350,36 +357,48 @@ cdef class View(OBIWrapper) :
# Width (column count) property getter # Width (column count) property getter
@property @property
def width(self): def width(self):
if not self.active() :
raise OBIDeactivatedInstanceError()
return self.pointer().infos.column_count return self.pointer().infos.column_count
# DMS property getter # DMS property getter
@property @property
def dms(self): def dms(self):
if not self.active() :
raise OBIDeactivatedInstanceError()
return self._dms return self._dms
# line_count property getter # line_count property getter
@property @property
def line_count(self): def line_count(self):
if not self.active() :
raise OBIDeactivatedInstanceError()
return self.pointer().infos.line_count return self.pointer().infos.line_count
# name property getter # name property getter
@property @property
def name(self): def name(self):
if not self.active() :
raise OBIDeactivatedInstanceError()
return <bytes> self.pointer().infos.name return <bytes> self.pointer().infos.name
# view type property getter # view type property getter
@property @property
def type(self): # @ReservedAssignment def type(self): # @ReservedAssignment
if not self.active() :
raise OBIDeactivatedInstanceError()
return <bytes> self.pointer().infos.view_type return <bytes> self.pointer().infos.view_type
# comments property getter # comments property getter
@property @property
def comments(self): def comments(self):
if not self.active() :
raise OBIDeactivatedInstanceError()
return <bytes> self.pointer().infos.comments return <bytes> self.pointer().infos.comments
# TODO setter that concatenates new comments? # TODO setter that concatenates new comments?
@ -391,20 +410,21 @@ cdef class Line :
self._view = view self._view = view
def __getitem__(self, str column_name) : def __getitem__(self, object column_name) :
return (self._view).get_column(column_name)[self._index] return (self._view).get_column(tobytes(column_name))[self._index]
def __setitem__(self, object column_name_, object value): # TODO discuss def __setitem__(self, object column_name, object value): # TODO discuss
# TODO detect multiple elements (dict type)? put somewhere else? but more risky (in get) # TODO detect multiple elements (dict type)? put somewhere else? but more risky (in get)
# TODO OBI_QUAL ? # TODO OBI_QUAL ?
cdef type value_type cdef type value_type
cdef obitype_t value_obitype cdef obitype_t value_obitype
cdef bytes value_b cdef bytes value_b
cdef bytes column_name_b
column_name = tostr(column_name_) # TODO column_name_b = tobytes(column_name)
if column_name not in self._view : if column_name_b not in self._view :
if value == None : if value == None :
raise Exception("Trying to create a column from a None value (can't guess type)") raise Exception("Trying to create a column from a None value (can't guess type)")
value_type = type(value) value_type = type(value)
@ -428,27 +448,33 @@ cdef class Line :
else : else :
raise Exception("Could not guess the type of a value to create a new column") raise Exception("Could not guess the type of a value to create a new column")
Column.new_column(self._view, column_name, value_obitype) Column.new_column(self._view, column_name_b, value_obitype)
(self._view).get_column(column_name).set_line(self._index, value) (self._view).get_column(column_name_b).set_line(self._index, value)
def __iter__(self): def __iter__(self):
cdef bytes column_name
for column_name in (self._view).keys() : for column_name in (self._view).keys() :
yield column_name yield column_name
def keys(self): def keys(self):
return self._view.keys() return self._view.keys()
def __contains__(self, str column_name):
return (column_name in self.keys()) def __contains__(self, object column_name):
return (tobytes(column_name) in self.keys())
def __repr__(self): def __repr__(self):
cdef dict line cdef dict line
cdef str column_name cdef bytes column_name_b
cdef str column_name_str
line = {} line = {}
for column_name in self._view.keys() : for column_name_b in self._view.keys() :
line[column_name] = self[column_name] column_name_str = bytes2str(column_name_b)
line[column_name_str] = self[column_name_str]
return str(line) return str(line)
# View property getter # View property getter
@ -559,7 +585,7 @@ cdef class Line_selection(list):
cdef View view cdef View view
if not self._view.active() : if not self._view.active() :
raise OBIObjectClosedInstance() raise OBIDeactivatedInstanceError()
if comments is not None: if comments is not None:
comments_b = tobytes(comments) comments_b = tobytes(comments)