@@ -547,40 +547,66 @@ def _build_schema_resource(fields):
547547 """
548548 return [field .to_api_repr () for field in fields ]
549549
550-
551550def _to_schema_fields (schema ):
552- """Coerce `schema` to a list of schema field instances.
553-
554- Args:
555- schema(Sequence[Union[ \
556- :class:`~google.cloud.bigquery.schema.SchemaField`, \
557- Mapping[str, Any] \
558- ]]):
559- Table schema to convert. If some items are passed as mappings,
560- their content must be compatible with
561- :meth:`~google.cloud.bigquery.schema.SchemaField.from_api_repr`.
562-
563- Returns:
564- Sequence[:class:`~google.cloud.bigquery.schema.SchemaField`]
551+ """TODO docstring
552+ QUESTION: do we want a flag to force the generation of a Schema object?
565553
566- Raises:
567- Exception: If ``schema`` is not a sequence, or if any item in the
568- sequence is not a :class:`~google.cloud.bigquery.schema.SchemaField`
569- instance or a compatible mapping representation of the field.
554+ CAST a list of elements to either:
555+ * a Schema object with SchemaFields and an attribute
556+ * a list of SchemaFields but no attribute
570557 """
571-
572558 for field in schema :
573559 if not isinstance (field , (SchemaField , collections .abc .Mapping )):
574560 raise ValueError (
575561 "Schema items must either be fields or compatible "
576562 "mapping representations."
577563 )
578-
564+
565+ if isinstance (schema , Schema ):
566+ schema = Schema ([
567+ field if isinstance (field , SchemaField ) else SchemaField .from_api_repr (field )
568+ for field in schema
569+ ], foreign_type_info = schema .foreign_type_info )
570+ return schema
579571 return [
580572 field if isinstance (field , SchemaField ) else SchemaField .from_api_repr (field )
581573 for field in schema
582574 ]
583575
576+ # OLD TO DELETE
577+ # def _to_schema_fields(schema):
578+ # """Coerce `schema` to a list of schema field instances.
579+
580+ # Args:
581+ # schema(Sequence[Union[ \
582+ # :class:`~google.cloud.bigquery.schema.SchemaField`, \
583+ # Mapping[str, Any] \
584+ # ]]):
585+ # Table schema to convert. If some items are passed as mappings,
586+ # their content must be compatible with
587+ # :meth:`~google.cloud.bigquery.schema.SchemaField.from_api_repr`.
588+
589+ # Returns:
590+ # Sequence[:class:`~google.cloud.bigquery.schema.SchemaField`]
591+
592+ # Raises:
593+ # Exception: If ``schema`` is not a sequence, or if any item in the
594+ # sequence is not a :class:`~google.cloud.bigquery.schema.SchemaField`
595+ # instance or a compatible mapping representation of the field.
596+ # """
597+
598+ # for field in schema:
599+ # if not isinstance(field, (SchemaField, collections.abc.Mapping)):
600+ # raise ValueError(
601+ # "Schema items must either be fields or compatible "
602+ # "mapping representations."
603+ # )
604+
605+ # return [
606+ # field if isinstance(field, SchemaField) else SchemaField.from_api_repr(field)
607+ # for field in schema
608+ # ]
609+
584610
585611class PolicyTagList (object ):
586612 """Define Policy Tags for a column.
@@ -921,3 +947,58 @@ def from_api_repr(cls, resource: dict) -> SerDeInfo:
921947 config = cls ("" )
922948 config ._properties = copy .deepcopy (resource )
923949 return config
950+
951+
952+ class Schema :
953+ def __init__ (self , fields = None , foreign_type_info = None ):
954+ self ._properties = {}
955+ self ._fields = [] if fields is None else list (fields ) #Internal List
956+ self .foreign_type_info = foreign_type_info
957+
958+ @property
959+ def foreign_type_info (self ) -> Any :
960+ """TODO: docstring"""
961+ return self ._properties .get ("foreignTypeInfo" )
962+
963+ @foreign_type_info .setter
964+ def foreign_type_info (self , value : str ) -> None :
965+ value = _isinstance_or_raise (value , str , none_allowed = True )
966+ self ._properties ["foreignTypeInfo" ] = value
967+
968+ @property
969+ def _fields (self ) -> Any :
970+ """TODO: docstring"""
971+ return self ._properties .get ("_fields" )
972+
973+ @_fields .setter
974+ def _fields (self , value : list ) -> None :
975+ value = _isinstance_or_raise (value , list , none_allowed = True )
976+ self ._properties ["_fields" ] = value
977+
978+
979+ def __len__ (self ):
980+ return len (self ._properties ["_fields" ])
981+
982+ def __getitem__ (self , index ):
983+ return self ._properties ["_fields" ][index ]
984+
985+ def __setitem__ (self , index , value ):
986+ self ._properties ["_fields" ][index ] = value
987+
988+ def __delitem__ (self , index ):
989+ del self ._properties ["_fields" ][index ]
990+
991+ def __iter__ (self ):
992+ return iter (self ._properties ["_fields" ])
993+
994+ def __str__ (self ):
995+ return str (self ._properties ["_fields" ])
996+
997+ def __repr__ (self ):
998+ return f"Schema({ self .foreign_type_info !r} , { self ._properties ['_fields' ]!r} )"
999+
1000+ def append (self , item ):
1001+ self ._properties ["_fields" ].append (item )
1002+
1003+ def extend (self , iterable ):
1004+ self ._properties ["_fields" ].extend (iterable )
0 commit comments