@@ -551,6 +551,7 @@ def _before_synapse_store(self, syn):
551551 self .properties .columnIds .extend (column .id for column in syn .createColumns (self .columns_to_store ))
552552 self .columns_to_store = []
553553
554+
554555class Schema (SchemaBase ):
555556 """
556557 A Schema is an :py:class:`synapseclient.entity.Entity` that defines a set of columns in a table.
@@ -645,61 +646,62 @@ def add_scope(self, entities):
645646 self .scopeIds .append (id_of (entities ))
646647
647648 def _before_synapse_store (self , syn ):
648- if self .addAnnotationColumns :
649- self ._add_annotations_as_columns (syn )
650- self .addAnnotationColumns = False
651-
652649 #get the default EntityView columns from Synapse and add them to the columns list
650+ additional_columns = []
653651 if self .addDefaultViewColumns :
654- self .addColumns (syn ._get_default_entity_view_columns (self .type ))
655- self .addDefaultViewColumns = False
652+ additional_columns .extend (syn ._get_default_entity_view_columns (self .type ))
653+
654+ #get default annotations
655+ if self .addAnnotationColumns :
656+ anno_columns = [x for x in syn ._get_annotation_entity_view_columns (self .scopeIds , self .type ) if
657+ x ['name' ] not in self .ignoredAnnotationColumnNames ]
658+ additional_columns .extend (anno_columns )
659+
660+ self .addColumns (self ._filter_duplicate_columns (syn , additional_columns ))
661+
662+ #set these boolean flags to false so they are not repeated.
663+ self .addDefaultViewColumns = False
664+ self .addAnnotationColumns = False
656665
657666 super (EntityViewSchema , self )._before_synapse_store (syn )
658667
659668
660- def _add_annotations_as_columns (self , syn ):
661- column_type_to_annotation_names = {
662- 'STRING' : set (),
663- 'INTEGER' : set (),
664- 'DOUBLE' : set (),
665- 'DATE' : set ()
666- }
667- all_existing_column_names = set () # set of all existing columns names regardless of type
669+ def _filter_duplicate_columns (self , syn , columns_to_add ):
670+ """
671+ If a column to be added has the same name and same type as an existing column, it will be considered a duplicate and not added.
672+ :param syn: a :py:class:`synapseclient.client.Synapse` object that is logged in
673+ :param columns_to_add: iterable collection of type :py:class:`synapseclient.table.Column` objects
674+ :return: a filtered list of columns to add
675+ """
676+
677+ # no point in making HTTP calls to retrieve existing Columns if we not adding any new columns
678+ if not columns_to_add :
679+ return columns_to_add
680+
681+ # set up Column name/type tracking
682+ column_type_to_annotation_names = {} # map of str -> set(str), where str is the column type as a string and set is a set of column name strings
668683
669684 # add to existing columns the columns that user has added but not yet created in synapse
670- column_generator = itertools .chain (syn .getColumns (self .columnIds ), self .columns_to_store ) if self .columns_to_store else syn .getColumns (self .columnIds )
685+ column_generator = itertools .chain (syn .getColumns (self .columnIds ),
686+ self .columns_to_store ) if self .columns_to_store else syn .getColumns (self .columnIds )
671687
672688 for column in column_generator :
673689 column_name = column ['name' ]
674690 column_type = column ['columnType' ]
675691
676- all_existing_column_names .add (column_name )
677- #add to type specific set
678- if column_type in column_type_to_annotation_names :
679- column_type_to_annotation_names [column_type ].add (column_name )
680-
681-
682- #get annotations from each of the scopes and create columns
683- columns_to_add = [] #temporarily store all columns so that none are added if any errors occur
684- anno_columns = syn ._get_annotation_entity_view_columns (self .scopeIds , self .type )
685- for column in anno_columns :
686- anno_col_name = column ['name' ]
687- anno_col_type = column ['columnType' ]
688- typed_col_name_set = column_type_to_annotation_names [anno_col_type ]
689- if (anno_col_name not in self .ignoredAnnotationColumnNames
690- and anno_col_name not in typed_col_name_set ):
691-
692- if anno_col_name in all_existing_column_names :
693- raise ValueError ("The annotation column name [%s] has multiple types in your scopes or in your defined columns.\n "
694- "Please do one of the following:\n "
695- " Turn off the automatic conversion of annotations to column names: entityView.addAnnotationColumns = False\n "
696- " Modify your annotations/columns named [%s] to all be of the same type.\n "
697- " Add the annotation name to the set of ignored annotation names via entityView.ignoredAnnotations.add(%s).\n " % (anno_col_name , anno_col_name , anno_col_name ))
698- all_existing_column_names .add (anno_col_name )
699- typed_col_name_set .add (anno_col_name )
700- columns_to_add .append (column )
701- self .addColumns (columns_to_add )
692+ column_type_to_annotation_names .setdefault (column_type ,set ()).add (column_name )
693+
694+
695+ valid_columns = []
696+ for column in columns_to_add :
697+ new_col_name = column ['name' ]
698+ new_col_type = column ['columnType' ]
702699
700+ typed_col_name_set = column_type_to_annotation_names .setdefault (new_col_type , set ())
701+ if new_col_name not in typed_col_name_set :
702+ typed_col_name_set .add (new_col_name )
703+ valid_columns .append (column )
704+ return valid_columns
703705
704706
705707## add Schema to the map of synapse entity types to their Python representations
0 commit comments