From 8cf2cdcd8af152a3a503cadb24d180f5f5bd391f Mon Sep 17 00:00:00 2001 From: dimitri-yatsenko Date: Fri, 18 Mar 2016 12:53:29 -0600 Subject: [PATCH 1/3] fixed handling the case when columns in rows submitted to insert are ordered differently from one another. --- datajoint/base_relation.py | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/datajoint/base_relation.py b/datajoint/base_relation.py index 72d05afbe..ad37d5150 100644 --- a/datajoint/base_relation.py +++ b/datajoint/base_relation.py @@ -195,7 +195,7 @@ def insert(self, rows, replace=False, ignore_errors=False, skip_duplicates=False """ heading = self.heading - field_list = None + field_list = None # ensures that all rows have the same attributes in the same order as the first row. def make_row_to_insert(row): """ @@ -205,8 +205,8 @@ def make_row_to_insert(row): def make_placeholder(name, value): """ - For a given attribute `name` with `value, return its processed value or value placeholder - as a string to be included in the query and the value, if any to be submitted for + For a given attribute `name` with `value`, return its processed value or value placeholder + as a string to be included in the query and the value, if any, to be submitted for processing by mysql API. :param name: :param value: @@ -237,12 +237,8 @@ def check_fields(fields): for field in fields: if field not in heading: raise KeyError(u'{0:s} is not in the attribute list'.format(field)) - else: - if len(fields) < len(field_list): - raise KeyError('Inserted row is missing some attributes.') - for field in fields: - if field not in field_list: - raise KeyError(u'{0:s} is not found among the attributes of the first inserted row'.format(field)) + elif set(field_list) != set(fields): + raise DataJointError('Attempt to insert rows with different fields') if isinstance(row, np.void): # np.array check_fields(row.dtype.fields) @@ -268,9 +264,15 @@ def check_fields(fields): row_to_insert = dict(zip(('names', 'placeholders', 'values'), zip(*attributes))) nonlocal field_list if field_list is None: + # first row sets the composition of the field list field_list = row_to_insert['names'] - elif set(field_list) != set(row_to_insert['names']): - raise DataJointError('Attempt to insert rows with different fields') + else: + # reorder attributes in row_to_insert to match field_list + order = list(row_to_insert['names'].index(field) for field in field_list) + row_to_insert['names'] = list(row_to_insert['names'][i] for i in order) + row_to_insert['placeholders'] = list(row_to_insert['placeholders'][i] for i in order) + row_to_insert['values'] = list(row_to_insert['values'][i] for i in order) + return row_to_insert def row_exists(row): From d1e0ec5c52fad73cae11b65acaff04445fd1aa9e Mon Sep 17 00:00:00 2001 From: dimitri-yatsenko Date: Fri, 18 Mar 2016 13:18:32 -0600 Subject: [PATCH 2/3] minor --- datajoint/base_relation.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/datajoint/base_relation.py b/datajoint/base_relation.py index c2928cae7..4920307dd 100644 --- a/datajoint/base_relation.py +++ b/datajoint/base_relation.py @@ -232,7 +232,7 @@ def check_fields(fields): """ Validates that all items in `fields` are valid attributes in the heading :param fields: field names of a tuple - """ + """ if field_list is None: for field in fields: if field not in heading: @@ -240,7 +240,7 @@ def check_fields(fields): elif set(field_list) != set(fields): raise DataJointError('Attempt to insert rows with different fields') - if isinstance(row, np.void): # np.array + if isinstance(row, np.void): # np.array check_fields(row.dtype.fields) attributes = [make_placeholder(name, row[name]) for name in heading if name in row.dtype.fields] From 4db7a5d56657d903ad3a12587ed3fe730cd68923 Mon Sep 17 00:00:00 2001 From: dimitri-yatsenko Date: Tue, 22 Mar 2016 11:39:33 -0600 Subject: [PATCH 3/3] Bugfix in autopopulate for populate(order="reverse") --- datajoint/autopopulate.py | 5 ++++- datajoint/user_relations.py | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/datajoint/autopopulate.py b/datajoint/autopopulate.py index 8efdcb37b..c910925e6 100644 --- a/datajoint/autopopulate.py +++ b/datajoint/autopopulate.py @@ -85,10 +85,13 @@ def populate(self, restriction=None, suppress_errors=False, table_name = self.target.table_name keys = (todo - self.target.project()).fetch.keys() if order == "reverse": - keys = list(keys).reverse() + keys = list(keys) + keys.reverse() elif order == "random": keys = list(keys) random.shuffle(keys) + elif order != "original": + raise DataJointError('Invalid order specification') for key in keys: if not reserve_jobs or jobs.reserve(table_name, key): diff --git a/datajoint/user_relations.py b/datajoint/user_relations.py index 34c676c36..139bd2fda 100644 --- a/datajoint/user_relations.py +++ b/datajoint/user_relations.py @@ -70,7 +70,7 @@ class Lookup(UserRelation): """ _prefix = '#' - _regexp = r'(?P' + _prefix + _base_regexp.replace('TIER', 'lookup') + ')' + _regexp = r'(?P' + _prefix + _base_regexp.replace('TIER', 'lookup') + ')' @classproperty def table_name(cls): @@ -144,7 +144,7 @@ class Part(BaseRelation): """ _regexp = r'(?P' + '|'.join([c._regexp for c in [Manual, Imported, Computed, Lookup]]) + r'){1,1}' \ - + '__' + r'(?P' + _base_regexp + ')' + + '__' + r'(?P' + _base_regexp + ')' _master = None