@@ -124,6 +124,19 @@ def _normalize_typehint_type(typehint_type):
124124 def register_coder (
125125 self , typehint_type : Any ,
126126 typehint_coder_class : Type [coders .Coder ]) -> None :
127+ """
128+ Register a user type with a coder.
129+
130+ Typical usage::
131+
132+ class MyCustomType:
133+ pass
134+
135+ coders.registry.register_coder(MyCustomType, MyCustomCoder)
136+
137+ To register a supported user type (data class or named tuple) with Beam Row,
138+ use :meth:`register_row` instead, as it registers both coder and schema.
139+ """
127140 if not isinstance (typehint_coder_class , type ):
128141 raise TypeError (
129142 'Coder registration requires a coder class object. '
@@ -133,6 +146,34 @@ def register_coder(
133146 self ._register_coder_internal (
134147 self ._normalize_typehint_type (typehint_type ), typehint_coder_class )
135148
149+ def register_row (self , typehint_type : type [Any ]) -> type [Any ]:
150+ """
151+ Register a user type with a Beam Row.
152+
153+ This registers the type with a RowCoder and register its schema.
154+
155+ Register a dataclass::
156+
157+ @coders.registry.register_row
158+ @dataclass
159+ class MyDataClass:
160+ id: int
161+ name: str
162+
163+ Register a named tuple::
164+
165+ coders.registry.register_row(MyNamedTuple)
166+ """
167+ from apache_beam .coders import RowCoder
168+ from apache_beam .typehints .schemas import typing_to_runner_api
169+
170+ # Register with row coder
171+ self .register_coder (typehint_type , RowCoder )
172+ # This call generated a schema id for the type and register it with
173+ # schema registry
174+ typing_to_runner_api (typehint_type )
175+ return typehint_type
176+
136177 def get_coder (self , typehint : Any ) -> coders .Coder :
137178 if typehint and typehint .__module__ == '__main__' :
138179 # See https://github.com/apache/beam/issues/21541
0 commit comments