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/base_relation.py b/datajoint/base_relation.py index 5b3ffffd0..4920307dd 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,13 +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) @@ -269,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): 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