lino.core.utils

A collection of utilities which require Django settings to be importable.

(This module's source code is available here.)

Functions

babel_values(*args, **kw)

babelattr(*args, **kw)

babelkw(*args, **kw)

class_dict_items(cl[, exclude])

comma()

db2param(spec)

Return a copy of the specified database field for usage as an actor parameter field.

dbfield2params_field(db_field)

originally just for setting up actor parameters from get_simple_params() but also used in calview.

djangoname(o)

error2str(self, e)

Convert the given Exception object into a string, but handling ValidationError specially.

format_request(request)

Format a Django HttpRequest for logging it.

full_model_name(model[, sep])

Returns the "full name" of the given model, e.g.

get_field(model, name)

Returns the field descriptor of the named field in the specified model.

getrqdata(request)

Return the request data.

inrange_filter(fld, rng, **kw)

Assuming a database model with a field named fld, return a Q object to select those rows whose fld value is not null and within the given range rng.

is_devserver()

Returns True if this process is running as a development server.

is_valid_email(s)

Returns True if the given string is a valid email.

is_valid_url(s)

Returns True if the given string is a valid URL.

lazy_format(tpl, *args, **kwargs)

See Internationalization.

model_class_path(model)

models_by_base(base[, toplevel_only])

Yields a list of installed models that are subclass of the given base class.

navinfo(qs, elem)

Return a dict with navigation information for the given model instance elem within the given queryset.

obj2str(i[, force_detailed])

Returns a human-readable ascii string representation of a model instance, even in some edge cases.

obj2unicode(i)

Returns a user-friendly unicode representation of a model instance.

qs2summary(ar, objects[, separator, max_items])

Render a collection of objects as a single paragraph.

range_filter(value, f1, f2)

Assuming a database model with two fields of same data type named f1 and f2, return a Q object to select those rows whose f1 and f2 encompass the given value value.

require_app_models(app_label)

resolve_app(app_label[, strict])

Return the modules module of the given app_label if it is installed.

resolve_field(name[, app_label])

Returns the field descriptor specified by the string name which should be either model.field or app_label.model.field.

resolve_fields_list(model, k[, ...])

resolve_model(model_spec[, app_label, strict])

Return the class object of the specified model.

simplify_name(name)

Simplify the given full Python name.

sorted_models_list()

traverse_ddh_fklist(model[, ignore_mti_parents])

When an application uses MTI (e.g.

Classes

ParameterPanel(**kw)

A utility class for defining reusable definitions for parameters.

Parametrizable()

Base class for both Actors and Actions.

PseudoRequest(username)

A Django HTTP request which isn't really one.

UnresolvedField(name)

Returned by resolve_field() if the specified field doesn't exist.

UnresolvedModel(model_spec, app_label)

The object returned by resolve_model() if the specified model is not installed.

lino.core.utils.qs2summary(ar, objects, separator=<function comma>, max_items=5, **kw)

Render a collection of objects as a single paragraph.

Parameters

max_items -- don't include more than the specified number of items.

lino.core.utils.getrqdata(request)

Return the request data.

Unlike the now defunct REQUEST attribute, this inspects the request's method in order to decide what to return.

lino.core.utils.is_valid_url(s)

Returns True if the given string is a valid URL. This calls Django's URLValidator(), but does not raise an exception.

lino.core.utils.is_valid_email(s)

Returns True if the given string is a valid email. This calls Django's validate_email(), but does not raise an exception.

lino.core.utils.is_devserver()

Returns True if this process is running as a development server.

Thanks to Aryeh Leib Taurog in How can I tell whether my Django application is running on development server or not?

My additions:

  • Added the len(sys.argv) > 1 test because in a wsgi application the process is called without arguments.

  • Not only for runserver but also for testserver and test.

lino.core.utils.format_request(request)

Format a Django HttpRequest for logging it.

This was written for the warning to be logged in lino.utils.ajax when an error occurs while processing an AJAX request.

lino.core.utils.full_model_name(model, sep='.')

Returns the "full name" of the given model, e.g. "contacts.Person" etc.

lino.core.utils.obj2unicode(i)

Returns a user-friendly unicode representation of a model instance.

lino.core.utils.obj2str(i, force_detailed=False)

Returns a human-readable ascii string representation of a model instance, even in some edge cases.

lino.core.utils.models_by_base(base, toplevel_only=False)

Yields a list of installed models that are subclass of the given base class.

If toplevel_only is True, then do not include MTI children.

Changed 2015-11-03: The list is sorted alphabetically using full_model_name() because anyway the sort order was unpredictable and changed between Django versions.

lino.core.utils.range_filter(value, f1, f2)

Assuming a database model with two fields of same data type named f1 and f2, return a Q object to select those rows whose f1 and f2 encompass the given value value.

lino.core.utils.inrange_filter(fld, rng, **kw)

Assuming a database model with a field named fld, return a Q object to select those rows whose fld value is not null and within the given range rng. rng must be a tuple or list with two items.

class lino.core.utils.UnresolvedModel(model_spec, app_label)

Bases: object

The object returned by resolve_model() if the specified model is not installed.

We don't want resolve_model() to raise an Exception because there are cases of Database Migration where it would disturb. Asking for a non-installed model is not a sin, but trying to use it is.

I didn't yet bother very much about finding a way to make the model_spec appear in error messages such as AttributeError: UnresolvedModel instance has no attribute '_meta'. Current workaround is to uncomment the print statement below in such situations...

lino.core.utils.resolve_model(model_spec, app_label=None, strict=False)

Return the class object of the specified model. model_spec is usually the global model name (i.e. a string like 'contacts.Person').

If model_spec does not refer to a known model, the function returns UnresolvedModel (unless strict=True is specified).

Using this method is better than simply importing the class object, because Lino applications can override the model implementation.

This function does not trigger a loading of Django's model cache, so you should not use it at module-level of a models.py module.

In general we recommend to use from lino.api import rt and rt.models.contacts.Person over resolve_model('contacts.Person'). Note however that this works only in a local scope, not at global module level.

lino.core.utils.resolve_app(app_label, strict=False)

Return the modules module of the given app_label if it is installed. Otherwise return either the dummy module for app_label if it exists, or None.

If the optional second argument strict is True, raise ImportError if the app is not installed.

This function is designed for use in models modules and available through the shortcut dd.resolve_app.

For example, instead of writing:

from lino.modlib.sales import models as sales

it is recommended to write:

sales = dd.resolve_app('sales')

because it makes your code usable (1) in applications that don't have the 'sales' module installed and (2) in applications who have another implementation of the sales module (e.g. lino.modlib.auto.sales)

lino.core.utils.get_field(model, name)

Returns the field descriptor of the named field in the specified model.

class lino.core.utils.UnresolvedField(name)

Bases: object

Returned by resolve_field() if the specified field doesn't exist. This case happens when sphinx autodoc tries to import a module. See ticket docs/tickets/4.

lino.core.utils.resolve_field(name, app_label=None)

Returns the field descriptor specified by the string name which should be either model.field or app_label.model.field.

lino.core.utils.navinfo(qs, elem)

Return a dict with navigation information for the given model instance elem within the given queryset. The dictionary contains the following keys:

Recno

row number (index +1) of elem in qs

First

pk of the first element in qs (None if qs is empty)

Prev

pk of the previous element in qs (None if qs is empty)

Next

pk of the next element in qs (None if qs is empty)

Last

pk of the last element in qs (None if qs is empty)

Message

text "Row x of y" or "No navigation"

class lino.core.utils.Parametrizable

Bases: object

Base class for both Actors and Actions.

This is a pseudo-mixins with common functionality for both actors and actions,

FOO_choices()

For every parameter field named "FOO", if the action has a method called "FOO_choices" (which must be decorated by dd.chooser()), then this method will be installed as a chooser for this parameter field.

parameters = None

User-definable parameter fields for this actor or action. Set this to a dict of name = models.XyzField() pairs.

On an actor you can alternatively or additionally implement a class method lino.core.actors.Actor.setup_parameters().

TODO: write documentation.

params_layout = None

The layout to be used for the parameter panel. If this table or action has parameters, specify here how they should be laid out in the parameters panel.

params_panel_hidden = True

If this table has parameters, set this to True if the parameters panel should be initially hidden when this table is being displayed.

use_detail_param_panel = False

Set to true if you want the params panel to be displayed in the detail view. Used only in lino_xl.lib.cal.CalView.

check_params(pv)

Called when a request comes in.

class lino.core.utils.ParameterPanel(**kw)

Bases: object

A utility class for defining reusable definitions for parameters.

Subclassed e.g. by lino.mixins.periods.ObservedDateRange. lino_xl.lib.ledger.AccountingPeriodRange.

get_title_tags(ar)

A hook for specifying title tags for the actor which uses this parameter panel.

See lino.core.actor.Actor.get_title_tags().

check_values(pv)

Return an error message if the specified parameter values are invalid.

class lino.core.utils.PseudoRequest(username)

Bases: object

A Django HTTP request which isn't really one.

Typical usage example:

from lino.core.diff import PseudoRequest, ChangeWatcher

REQUEST = PseudoRequest("robin")

for obj in qs:
    cw = ChangeWatcher(obj)
    # update `obj`
    obj.full_clean()
    obj.save()
    cw.send_update(REQUEST)
lino.core.utils.error2str(self, e)

Convert the given Exception object into a string, but handling ValidationError specially.

lino.core.utils.lazy_format(tpl, *args, **kwargs)

See Internationalization.

lino.core.utils.simplify_name(name)

Simplify the given full Python name.

Removes any part 'models', 'desktop', 'ui', 'choicelists', 'mixins' or 'actions' from the name.

This is used when we want to ignore where exactly a model or table or action is being defined within its plugin.

lino.core.utils.dbfield2params_field(db_field)

originally just for setting up actor parameters from get_simple_params() but also used in calview.

lino.core.utils.db2param(spec)

Return a copy of the specified database field for usage as an actor parameter field.

A usage example is lino_xl.lib.tickets.SpawnTicket action. This action has two parameter fields, one for the type of link to create, the other for the summary of the ticket to create. We might copy the definitions of these to fields from their respective models and say:

parameters = dict(
    link_type=LinkTypes.field(default='requires'),
    ticket_summary=models.CharField(
        pgettext("Ticket", "Summary"), max_length=200,
        blank=False,
        help_text=_("Short summary of the problem."))
    )

But it is easier and more maintainable to say:

parameters = dict(
    link_type=db2param('tickets.Link.type'),
    ticket_summary=db2param('tickets.Ticket.summary'))

Unfortunately that doesn't yet work because actions get instantiated when models aren't yet fully loaded :-/

TODO: One idea to get it working is to say that parameter fields can be specified as names of fields, and Lino would resolve them at startup:

parameters = dict(
    link_type='tickets.Link.type',
    ticket_summary='tickets.Ticket.summary')
lino.core.utils.traverse_ddh_fklist(model, ignore_mti_parents=True)

When an application uses MTI (e.g. with a Participant model being a specialization of Person, which itself a specialization of Partner) and we merge two Participants, then we must of course also merge their invoices and bank statement items (linked via a FK to Partner) and their contact roles (linked via a FK to Person).