define_app#
- define_app(klass=None, *, app_type: AppType = AppType.GENERIC, skip_not_completed: bool = True) type#
decorator for building callable apps
- Parameters:
- klass
either a class or a function. If a function, it is converted to a class with the function bound as a static method.
- app_type
what type of app, typically you just want GENERIC.
- skip_not_completed
if True (default), NotCompleted instances are returned without being passed to the app.
Notes
Instances of
cogent3apps are callable. If an exception occurs, the app returns aNotCompletedinstance with logging information. Apps defined with app_typeLOADER,GENERICorWRITERcan be “composed” (summed together) to produce a single callable that sequentially invokes the composed apps. For example, the independent usage of app instancesapp1andapp2asapp2(app1(data))
is equivalent to
combined = app1 + app2 combined(data)
The
app_typeattribute is used to constrain how apps can be composed.LOADERandWRITERare special cases. If included, aLOADERmust always be first, e.g.app = a_loader + a_generic
If included, a
WRITERmust always be last, e.g.app = a_generic + a_writer
Changing the order for either of the above will result in a
TypeError.There are no constraints on ordering of
GENERICaside from compatability of their input and return types (see below).In order to be decorated with
@define_appa class mustimplement a method called
maintype hint the first argument of
maintype hint the return type for
main
While you can have more than one argument in
main, this is currently not supported in composable apps.Overlap between the return type hint and first argument hint is required for two apps to be composed together.
define_appadds a__call__method which checks an input value prior to passing it toapp.main()as a positional argument. The data checking results inNotCompletedbeing returned immediately, unlessskip_not_completed==False. If the input value type is consistent with the type hint on the first argument of main it is passed toapp.main(). If it does not match, a newNotCompletedinstance is returned.Examples
An example app definition.
>>> from typing import Union >>> from cogent3.app.composable import define_app >>> from cogent3.app.typing import AlignedSeqsType, SerialisableType >>> >>> @define_app ... class drop_bad: ... def __init__(self, quantile=None, gap_fraction=1, moltype="dna"): ... self.quantile = quantile ... self.gap_fraction = gap_fraction ... self.moltype = moltype ... ... T = Union[AlignedSeqsType, SerialisableType] ... ... def main(self, aln: AlignedSeqsType) -> T: ... return aln.omit_bad_seqs( ... quantile=self.quantile, ... gap_fraction=self.gap_fraction, ... moltype=self.moltype, ... )
drop_badis a composable app withapp_type=GENERIC. The input data must be a sequence alignment instance. It returns the same type, which is also serialisable. (If invalid input data is provided aNotCompletedinstance is returned.)You can also decorate functions. In that case, they will be converted into a class with the same name as the original function. The function itself is bound to this new class as a
staticmethod, e.g.>>> from typing import Union >>> from cogent3.app.composable import define_app >>> from cogent3.app.typing import AlignedSeqsType, SerialisableType >>> >>> T = Union[AlignedSeqsType, SerialisableType] >>> >>> @define_app ... def omit_seqs( ... aln: AlignedSeqsType, quantile=None, gap_fraction=1, moltype="dna" ... ) -> T: ... return aln.omit_bad_seqs( ... quantile=quantile, gap_fraction=gap_fraction, moltype=moltype ... )
omit_seqsis now an app, allowing creating different variants which can be composed as per ones defined via a class.>>> omit_bad = omit_seqs(quantile=0.95)
and
omit_badis an instance of that app.