rattail.app
¶
App Handler
- class rattail.app.AppHandler(config)[source]¶
Base class and default implementation for top-level Rattail app handler.
aka. “the handler to handle all handlers”
aka. “one handler to bind them all”
This now inherits from
wuttjamaican.app.AppHandler
although it still overrides most of the upstream methods. Over time more of this class logic will hopefully be moved upstream.There is normally no need to create one of these yourself; rather you should call
get_app()
on the config object if you need the app handler.- cache_model(session, model, **kwargs)[source]¶
Convenience method which invokes
rattail.db.cache.cache_model()
with the given model and keyword arguments.
- format_phone_number(number)[source]¶
Returns a “properly formatted” string based on the given phone number.
Default logic invokes
rattail.db.util.format_phone_number()
.- Parameters:
number¶ – Raw phone number string e.g. as found in some data source.
- Returns:
Formatted phone number string.
- get_active_stores(session, **kwargs)[source]¶
Returns the list of “active” stores. A store is considered active if it is not marked as archived.
- get_all_import_handlers(ignore_errors=True, sort=False, **kwargs)[source]¶
Returns all Import/Export Handler classes which are known to exist, i.e. all which are registered via
setup.py
for the various packages installed.This means it will include both “designated” handlers as well as non-designated. See
get_designated_import_handlers()
if you only want the designated ones.Note that this will return the Handler classes and not handler instances.
- Parameters:
- Returns:
List of all registered Import/Export Handler classes.
- get_auth_handler(**kwargs)[source]¶
Get the configured “auth” handler.
- Returns:
The
AuthHandler
instance for the app.
- get_autocompleter(key, **kwargs)[source]¶
Returns a new
Autocompleter
instance corresponding to the given key, e.g.'products'
.The app handler has some hard-coded defaults for the built-in autocompleters (see
default_autocompleters
in the source code). You can override any of these, and/or add your own with custom keys, via config, e.g.:[rattail] autocomplete.products = poser.autocomplete.products:ProductAutocompleter autocomplete.otherthings = poser.autocomplete.things:OtherThingAutocompleter
With the above you can then fetch your custom autocompleter with:
autocompleter = app.get_autocompleter('otherthings')
In any case if it can locate the class, it will create an instance of it and return that.
- Params key:
Unique key for the type of autocompleter you need. Often is a simple string, e.g.
'customers'
but sometimes there may be a “modifier” with it to get an autocompleter with more specific behavior.For instance
'customers.phone'
would effectively give you a customer autocompleter but which searched by phone number instead of customer name.Note that each key is still a simple string though, and that must be “unique” in the sense that only one autocompleter can be configured for each key.
- Returns:
An
Autocompleter
instance if found, otherwiseNone
.
- get_batch_handler(key, default=None, error=True, **kwargs)[source]¶
Get the configured batch handler of the given type.
- Parameters:
key¶ – Unique key designating which type of batch handler is being requested.
default¶ – Spec string to be used as the default, if no handler is configured for the given batch type. This spec string must itself refer to a
BatchHandler
class.error¶ – Flag indicating whether an error should be raised if no handler can be found.
- Returns:
A
BatchHandler
instance of the requested type. If no such handler can be found, and theerror
param is false, thenNone
is returned; otherwise an error will raise.
- get_board_handler(**kwargs)[source]¶
Get the configured “board” handler.
- Returns:
The
BoardHandler
instance for the app.
- get_bounce_handler(key, **kwargs)[source]¶
Get the configured email bounce handler of the given type.
- Parameters:
key¶ – Unique key designating which type of bounce handler is being requested.
- Returns:
A
BounceHandler
instance of the requested type. If no such handler can be found, an error will raise.
- get_class_prefix(default=None)[source]¶
Returns the “class prefix” for the app, used when naming model classes etc.
- get_cleanup_handler(**kwargs)[source]¶
Get the configured “cleanup” handler.
- Returns:
The
CleanupHandler
instance for the app.
- get_clientele_handler(**kwargs)[source]¶
Get the configured “clientele” handler.
- Returns:
The
ClienteleHandler
instance for the app.
- get_contact_email(obj, traverse=True, **kwargs)[source]¶
Return the first email record found for the given object.
Note that this returns the email record and not just the address as string. See also
get_contact_email_address()
.- Returns:
A
EmailAddress
(likely a subclass) instance, orNone
.
- get_contact_email_address(obj, **kwargs)[source]¶
Return the first email address found for the given object.
Note that this returns the email address as string and not the full email record. See also
get_contact_email_address()
.- Returns:
Email address as string, or
None
.
- get_contact_phone(obj, traverse=True, **kwargs)[source]¶
Return the first phone record found for the given object.
Note that this returns the phone record and not just the number as string. See also
get_contact_phone_number()
.- Returns:
A
PhoneNumber
(likely a subclass) instance, orNone
.
- get_contact_phone_number(obj, **kwargs)[source]¶
Return the first phone number found for the given object.
Note that this returns the phone number as string and not the full phone record. See also
get_contact_phone()
.- Returns:
Phone number as string, or
None
.
- get_customer(obj, **kwargs)[source]¶
Convenience method to locate a Customer record for the given object. This delegates to the
ClienteleHandler
for actual lookup logic.
- get_customer_key_label(field=None)[source]¶
Returns the configured field label for customer key, e.g.
'ID'
.
- get_custorder_handler(**kwargs)[source]¶
Get the configured “customer order” handler.
- Returns:
The
CustomerOrderHandler
instance for the app.
- get_datasync_handler(**kwargs)[source]¶
Get the configured “datasync” handler.
- Returns:
The
DatasyncHandler
instance for the app.
- get_db_handler(**kwargs)[source]¶
Get the configured “database” handler.
- Returns:
The
DatabaseHandler
instance for the app.
- get_designated_import_handler_spec(key, require=False, **kwargs)[source]¶
Return the designated import handler “spec” string for the given type key.
- Parameters:
key¶ – Unique key indicating the type of import handler.
- Require:
Flag indicating whether an error should be raised if no handler is found.
- Returns:
Spec string for the designated handler. If none is found, then
None
is returned unless therequire
param is true, in which case an error is raised.
- get_designated_import_handlers(with_alternates=False, **kwargs)[source]¶
Returns all “designated” import/export handler instances.
Each “handler type key” can have at most one Handler class which is “designated” in the config. This method collects all registered handlers and then sorts out which one is designated, for each type key, ultimately returning only the designated ones.
Note that this will return the handler instances and not Handler classes.
If you have a type key and just need its designated handler, see
get_import_handler()
.See also
get_all_import_handlers()
if you need all registered Handler classes.- Parameters:
with_alternates¶ –
If you specify
True
here then each designated handler returned will have an extra attribute namedalternate_handlers
, which will be a list of the other “available” (registered) handlers which match the designated handler’s type key.This is probably most / only useful for the Configuration UI, to allow admin to change which is designated.
- Returns:
List of all designated import/export handler instances.
- get_email_handler(**kwargs)[source]¶
Get the configured “email” handler.
- Returns:
The
EmailHandler
instance for the app.
- get_employee(obj, **kwargs)[source]¶
Convenience method to locate an Employee record for the given object. This delegates to the
EmploymentHandler
for actual lookup logic.
- get_employment_handler(**kwargs)[source]¶
Get the configured “employment” handler.
- Returns:
The
EmploymentHandler
instance for the app.
- get_feature_handler(**kwargs)[source]¶
Get the configured “feature” handler.
- Returns:
The
FeatureHandler
instance for the app.
- get_import_handler(key, require=False, **kwargs)[source]¶
Return the designated import/export handler instance, per the given handler type key.
See also
get_designated_import_handlers()
if you want the full set of designated handlers.- Parameters:
- Returns:
The import/export handler instance corresponding to the given key. If no handler can be found, then
None
is returned, unlessrequire
param is true, in which case error is raised.
- get_label_handler(**kwargs)[source]¶
Get the configured “label” handler.
See also Label Handler.
- Returns:
The
LabelHandler
instance for the app.
- get_luigi_handler(**kwargs)[source]¶
Get the configured “luigi” handler.
- Returns:
The
LuigiHandler
instance for the app.
- get_member(obj, **kwargs)[source]¶
Convenience method to locate a Member record for the given object. This delegates to the
MembershipHandler
for actual lookup logic.
- get_member_key_label(field=None)[source]¶
Returns the configured field label for member key, e.g.
'ID'
.
- get_membership_handler(**kwargs)[source]¶
Get the configured “membership” handler.
See also Membership Handler.
- Returns:
The
MembershipHandler
instance for the app.
- get_org_handler(**kwargs)[source]¶
Get the configured “org” handler.
- Returns:
The
OrgHandler
instance for the app.
- get_people_handler(**kwargs)[source]¶
Get the configured “people” handler.
See also People Handler.
- Returns:
The
PeopleHandler
instance for the app.
- get_person(obj, **kwargs)[source]¶
Convenience method to locate a Person record for the given object. This delegates to the
PeopleHandler
for actual lookup logic.
- get_poser_handler(**kwargs)[source]¶
Get the configured “poser” handler.
- Returns:
The
PoserHandler
instance for the app.
- get_problem_report_handler(**kwargs)[source]¶
Get the configured “problem reports” handler.
- Returns:
The
ProblemReportHandler
instance for the app.
- get_product_key_label(field=None)[source]¶
Returns the configured field label for product key, e.g.
'UPC'
.
- get_products_handler(**kwargs)[source]¶
Get the configured “products” handler.
- Returns:
The
ProductsHandler
instance for the app.
- get_project_handler(**kwargs)[source]¶
Get the configured “project” handler.
- Returns:
The
ProjectHandler
instance for the app.
- get_report_handler(**kwargs)[source]¶
Get the configured “reports” handler.
- Returns:
The
ReportHandler
instance for the app.
- get_session(obj)[source]¶
Returns the SQLAlchemy session with which the given object is associated. Simple convenience wrapper around
sqlalchemy.orm.object_session()
.
- get_setting(session, name, typ=None, **kwargs)[source]¶
Get a setting value from the DB.
This is mostly the same as upstream
get_setting()
but is customized for Rattail in the following way:- Parameters:
typ¶ – Most values are treated as simple strings, but if you specify
'utctime'
here, then the return value will be converted to a UTC-baseddatetime
object- Returns:
Usually a string, but can be some other type, depending on the
typ
param.
- get_table_prefix(default=None)[source]¶
Returns the “table prefix” for the app, used when naming tables etc.
- get_tailbone_handler(**kwargs)[source]¶
Get the configured “tailbone” handler.
- Returns:
The
TailboneHandler
instance for the app.
- get_telemetry_handler(**kwargs)[source]¶
Get the configured “telemetry” handler.
- Returns:
The
TelemetryHandler
instance for the app.
- get_timezone(key='default')[source]¶
Returns a configured time zone.
Default logic invokes
rattail.time.timezone()
to obtain the time zone object.- Parameters:
key¶ – Unique key designating which time zone should be returned. Note that most apps have only one (“default”), but may have others defined.
- get_title(default='Rattail')[source]¶
Returns the configured title (name) of the app.
- Parameters:
default¶ – Value to be returned if there is no app title configured.
- Returns:
Title for the app.
- get_trainwreck_handler(**kwargs)[source]¶
Get the configured “trainwreck” handler.
- Returns:
The
TrainwreckHandler
instance for the app.
- get_upgrade_handler(**kwargs)[source]¶
Get the configured “upgrade” handler.
- Returns:
The
UpgradeHandler
instance for the app.
- get_user(obj, **kwargs)[source]¶
Convenience method to locate a User record for the given object. This delegates to the
AuthHandler
for actual lookup logic.
- get_vendor_handler(**kwargs)[source]¶
Get the configured “vendor” handler.
- Returns:
The
VendorHandler
instance for the app.
- get_workorder_handler(**kwargs)[source]¶
Get the configured “work order” handler.
- Returns:
The
WorkOrderHandler
instance for the app.
- json_friendly(value)[source]¶
Coerce a Python value to one which is JSON-serializable.
So, this does not return a JSON string, but rather a Python object which can then be safely converted via
json.dumps()
.If the value is a container, it will be crawled recursively and all values it contains will be coerced.
- load_object(spec)[source]¶
Import and/or load and return the object designated by the given spec string.
Default logic invokes
rattail.util.load_object()
to obtain the object.The syntax of the spec string is not unique to Rattail, but is not a universal standard, so deserves a note here. The spec is basically just
modulepath:objname
wheremodulepath
is the dotted name of the full module where the object resides, andobjname
is the name of the object within that module. For instance,rattail.app:AppHandler
would be the spec for this class.Note also that the use of the word “object” may be confusing, as it does not signify an “instance” but rather an object in the generic sense. Most often a spec will either refer to a class or function within the module, although any valid named object is possible.
- Parameters:
spec¶ – String like
modulepath:objname
as described above.- Returns:
The object referred to by
spec
. If the module could not be imported, or did not contain an object of the given name, then an error will raise.
- localtime(*args, **kwargs)[source]¶
Produce or convert a timestamp in the default time zone.
Default logic invokes
rattail.time.localtime()
to obtain the timestamp. All args and kwargs are passed directly to that function.- Returns:
A
datetime.datetime
object. Usually this will be timezone-aware but this will depend on the args and kwargs you specify.
- make_appdir(path, subfolders=None, **kwargs)[source]¶
Establish an appdir at the given path.
This is mostly the same as upstream
make_appdir()
but (for now) for compatibility Rattail extends this by adding more subfolders to the default list.
- make_config_file(file_type, output_path, template=None, template_path=None, **kwargs)[source]¶
Write a new config file of given type to specified location.
- Parameters:
file_type¶ – The “type” of config file to create. This is used to locate the file template, if
template_path
is not specified. It also is used as default output filename, ifoutput_path
is a folder.output_path¶ – Path to which new config file should be written. If this is a folder, then the filename is deduced from the
file_type
.template¶ – Optional reference to a Mako template instance.
template_path¶ – Optional path to config file template to use. If not specified, it will be looked up dynamically based on the
file_type
. Note that the first template found to match will be used. Mako (*.mako
) templates are preferred, otherwise the template is assumed to be “plain” and will be copied as-is to the output path.**kwargs¶ – Context to be passed to the Mako template, if applicable.
- Returns:
Final path to which new config file was written.
- make_counter(session, key, **kwargs)[source]¶
Create a new counter sequence in the DB, if needed.
This should only be needed with PostgreSQL back-end. For others, the sequence should be auto-created as needed when calling
next_counter_value()
.
- make_engine_from_config(config_dict, prefix='sqlalchemy.', **kwargs)[source]¶
This is the same as
wuttjamaican.app.AppHandler.make_engine_from_config()
except Rattail may customize the engine a bit further:The engine can be told to “record changes” for sake of datasync; for instance:
[rattail.db] default.url = sqlite:/// default.record_changes = true
And/or the engine can be told to log its SQLAlchemy connection pool status:
[rattail.db] default.url = sqlite:/// default.log_pool_status = true
- make_gpc(value, **kwargs)[source]¶
Make and return a
GPC
instance from the given value.Default logic will invoke
make_gpc()
of the products handler; see alsoget_products_handler()
.
- make_object(**kwargs)[source]¶
Create and return a generic object. All kwargs will be assigned as attributes to the object.
- make_session(user=None, **kwargs)[source]¶
Creates and returns a new SQLAlchemy session for the Rattail DB.
- Parameters:
user¶ – A “user-ish” object which should be considered responsible for changes made during the session. Can be either a
User
object, or just a (string) username. If none is specified then the config will be consulted for a default.- Returns:
A
rattail.db.Session
instance.
- make_supervisorctl_proxy(url=None, **kwargs)[source]¶
Create and return a XML-RPC server proxy for the Supervisor process manager.
- make_temp_dir(**kwargs)[source]¶
Create a temporary directory. This is mostly a convenience wrapper around the built-in
tempfile.mkdtemp()
. However by default it will attempt to place the temp folder underneath the configured “workdir”, e.g.:[rattail] workdir = /srv/envs/poser/app/work
- make_temp_file(**kwargs)[source]¶
Reserve a temporary filename. This is mostly a convenience wrapper around the built-in
tempfile.mkstemp()
. However by default it will attempt to place the temp file underneath the configured “workdir”, e.g.:[rattail] workdir = /srv/envs/poser/app/work
- make_utc(*args, **kwargs)[source]¶
Produce or convert a timestamp to UTC time zone.
Default logic invokes
rattail.time.make_utc()
to obtain the timestamp. All args and kwargs are passed directly to that function.- Returns:
A
datetime.datetime
object. Usually this will be timezone-naive but this will depend on the args and kwargs you specify.
- maxlen(attr)[source]¶
Return the max size (length) for the given model attribute.
Note that you must pass the attribute proper, not just the name of one etc. For example:
size = app.maxlen(model.Product.description)
- Parameters:
attr¶ – Any column-based property of a model class.
- Returns:
Max length as integer.
- property model¶
Property which returns a reference to the DB model module.
Ultimately this is the same as calling
rattail.config.RattailConfig.get_model()
.
- next_counter_value(session, key, create=False, **kwargs)[source]¶
Return the next counter value for the given key.
- Parameters:
- Returns:
Next value as integer.
- normalize_phone_number(number, **kwargs)[source]¶
Normalize the given phone number, to a “common” format that can be more easily worked with for sync logic etc. In practice this usually just means stripping all non-digit characters from the string. The idea is that phone number data from any system can be “normalized” and thereby compared directly to see if they differ etc.
Default logic will invoke
rattail.db.util.normalize_phone_number()
.- Parameters:
number¶ – Raw phone number string e.g. as found in some data source.
- Returns:
Normalized string.
- parse_date(value, **kwargs)[source]¶
Parse a date value from the given string, which is assumed to be in ISO format.
- parse_utctime(value, local=False, tzinfo=None, **kwargs)[source]¶
Parse a datetime value from the given string, which is assumed to be in UTC timezone and formatted “typically” for Rattail.
- phone_number_is_invalid(number)[source]¶
This method should validate the given phone number string, and if the number is not considered valid, this method should return the reason.
- Parameters:
number¶ – Raw phone number string e.g. as found in some data source.
- Returns:
String describing reason the number is invalid, or
None
if the number is deemed valid.
- progress_loop(*args, **kwargs)[source]¶
Run a given function for a given sequence, and optionally show a progress indicator.
Default logic invokes the
rattail.util.progress_loop()
function; see that for more details.
- render_cases_units(cases, units)[source]¶
Render a human-friendly string showing the given number of cases and/or units. For instance:
>>> app.render_cases_units(1, None) '1 case' >>> app.render_cases_units(None, 1) '1 unit' >>> app.render_cases_units(3, 2) '3 cases + 2 units'
- render_currency(value, scale=2, **kwargs)[source]¶
Must return a human-friendly display string for the given currency value, e.g.
Decimal('4.20')
becomes"$4.20"
.- Parameters:
value¶ – Either a
decimal.Decimal
orfloat
value.scale¶ – Number of decimal digits to be displayed.
- Returns:
Display string for the value.
- render_date(value, **kwargs)[source]¶
Return a human-friendly display string for the given date.
- Parameters:
value¶ – A
datetime.date
instance.- Returns:
Display string for the date.
- render_datetime(value, **kwargs)[source]¶
Return a human-friendly display string for the given datetime.
- render_duration(delta=None, hours=None, seconds=None, **kwargs)[source]¶
Render a time duration for human eyes, e.g. “1:30” for 1.5 hours.
Note that you must specify either
delta
,hours
orseconds
.- Parameters:
- Returns:
Duration rendered as human-friendly string. Note that if all params are empty, this will return an empty string.
- render_gpc(value, **kwargs)[source]¶
Returns a human-friendly display string for the given GPC value.
- render_mako_template(template_path, context, template=None, output_path=None, **kwargs)[source]¶
Convenience method to render any (specified) Mako template.
- render_percent(value, places=2, from_decimal=False, **kwargs)[source]¶
Render a human-friendly display string for the given percentage value.
- Parameters:
value¶ – Should be a decimal representation of the percentage, e.g.
0.80
would indicate 80%.places¶ – Number of decimal places to display in the rendered string.
from_decimal¶ – If false (the default), then
value
should (normally) be between 0 - 100. But if true, thenvalue
is assumed to be between 0.0 and 1.0 instead.
- render_quantity(value, **kwargs)[source]¶
Return a human-friendly display string for the given quantity value, e.g.
1.000
becomes"1"
.- Parameters:
value¶ – The quantity to be rendered.
- Returns:
Display string for the quantity.
- render_time_ago(delta=None, seconds=None, fallback=<object object>, **kwargs)[source]¶
Return a human-friendly display string showing “how long ago” something happened.
You may specify either
delta
orseconds
but in either case these are assumed to represent time elapsed compared to “now” - e.g. the number of seconds ago which something occurred.This method is not suitable for displaying an arbitrary time duration contained in the past. It always assumes “now” is the endpoint for the time duration.
NB. this invokes
humanize.naturaltime()
under the hood.- Parameters:
delta¶ – A
datetime.timedelta
instance representing a time duration.seconds¶ – Optional number of seconds to use for the time duration, instead of specifying the
delta
.fallback¶ – Optional string value to return, if the time duration was not valid.
- Returns:
Human-friendly display string.
- save_setting(session, name, value, typ=None, force_create=False, **kwargs)[source]¶
Save a setting value to the DB.
- Parameters:
session¶ – Current DB session.
name¶ – Name of the setting to save.
value¶ – Value to be saved for the setting.
typ¶ – Most values are treated as simple strings, but if you specify
'utctime'
here, then thevalue
is assumed to be a UTC-baseddatetime
object, and the final setting value will be formatted appropriately.force_create¶ – If
False
(the default) then logic will first try to locate an existing setting of the given name, and update it if found, or create if not. But if this param isTrue
then logic will only try to create a new record, and not bother checking to see if it exists.
- send_email(key, data={}, **kwargs)[source]¶
Send an email message of the given type.
See
rattail.mail.send_email()
for more info.
- short_session(**kwargs)[source]¶
This is the same as upstream
short_session()
except Rattail customizes the defaultfactory
kwarg:Normally the default factory is just
make_session()
but (in Rattail) that may imply a lookup of the configured “runas” user for sake of Continuum versioning. So this method modifies the default factory to avoid that lookup.Note
The auto-lookup for runas user is a bit awkward, so this may change at some point.
- touch_object(session, obj)[source]¶
Mark the given object as having been changed, such that the datasync will pick it up and propagate the object to other nodes.
Note that this is minimal logic; only the given object will be “touched” in this way, i.e. no related records will be touched. So if those also need it, you must call this method for each related object separately.
- update_email(contact, email_address, email_fields={}, slot=1)[source]¶
Update an email address record for the contact.
- Parameters:
contact¶ – Contact object, e.g. a Customer, Person, etc.
email_address¶ – New/correct email address as string.
email_fields¶ – Additional field values if applicable. The email will be updated to match as needed.
slot¶ – Which email in the contact’s list should be updated. By default this will update (or add) the 1st email, but specify
slot=2
for the 2nd etc.
- update_phone(contact, phone_number, phone_fields={}, slot=1)[source]¶
Update a phone number record for the contact.
- Parameters:
contact¶ – Contact object, e.g. a Customer, Person, etc.
phone_number¶ – New/correct phone number as string.
phone_fields¶ – Additional field values if applicable. The phone will be updated to match as needed.
slot¶ – Which phone in the contact’s list should be updated. By default this will update (or add) the 1st phone, but specify
slot=2
for the 2nd etc.
- class rattail.app.GenericHandler(config, **kwargs)[source]¶
Base class for misc. “generic” feature handlers.
Most handlers which exist for sake of business logic, should inherit from this.
- class rattail.app.MergeMixin[source]¶
Mixin class for feature handlers supporting a record merge.
- get_merge_preview_data(obj, **kwargs)[source]¶
Must return a data dictionary for the given object, which can be presented to the user during a merge preview.
- get_merge_preview_fields(**kwargs)[source]¶
Returns a sequence of fields which will be used during a merge preview.
- get_merge_resulting_data(removing, keeping, **kwargs)[source]¶
Must return a dictionary to represent what the final data would look like, should the proposed merge occur. Note that we’re still in preview mode here, this doesn’t actually cause any particular data to become final.
- Parameters:
removing¶ – Data dictionary for the object to be removed, as obtained via
get_merge_preview_data()
.keeping¶ – Data dictionary for the object to be preserved, as obtained via
get_merge_preview_data()
.
- merge_update_keeping_object(removing, keeping)[source]¶
Update the object to be kept, with any relevant data from the object to be removed, in the context of a merge.
- class rattail.app.RattailProvider(config)[source]¶
Base class for Rattail app providers.
This inherits from upstream
AppProvider
and adds the following to it:- enum¶
Reference to the
enum
module for the app.
- model¶
Reference to the
model
module for the app.
- handlers¶
Dictionary of “secondary” handlers used by the provider, if applicable.
- load_object(*args, **kwargs)[source]¶
Convenience method which calls
AppHandler.load_object()
.