Using rudiments¶
Web Access Helpers¶
The rudiments.www
module helps with handling web resources.
The context manager rudiments.www.url_as_file()
can be used to make the content
of an URL available as a local file, so it can be fed to things that only work with
local filesystem paths. House-keeping is automatic, so the file is removed on leaving
the context unless you removed or moved it yourself before that.
Security Helpers¶
Credentials Lookup¶
When using HTTP APIs or other secured web resources, you are confronted with the
question how to enable your users to store their credentials in a
secure but still convenient fashion.
The rudiments.security.Credentials
class tries to give an answer,
by providing some common methods for credential lookup that occupy different
spots in the secure vs. convenient spectrum.
See Configuration of Authentication Credentials for details regarding usage from the viewpoint
of an end-user and some information about the availabe credential providers.
To use the class, create a rudiments.security.Credentials
object,
passing in the target. Then to retrieve matching credentials, call the
rudiments.security.Credentials.auth_pair()
method.
access = Credentials('http://jane@doe.example.com')
username, password = access.auth_pair()
Note that this allows to only prompt the user for a password when it’s actually needed, but still create the credentials object early on, during some setup phase.
Humanized Input and Output¶
For accepting input from prompts and configuration files, and presenting values
in a form easily parsed by humans, the rudiments.humanize
module offers
conversion functions for common data types.
For handling byte sizes in IEC binary units, use
rudiments.humanize.bytes2iec()
and rudiments.humanize.iec2bytes()
.
Examples:
>>> bytes2iec(1536), bytes2iec(10**9)
(u' 1.5 KiB', u' 953.7 MiB')
>>> bytes2iec(1536, compact=True)
u'1.5KiB'
>>> iec2bytes(1), iec2bytes('64k'), iec2bytes('1.234TiB')
(1, 65536, 1356797348675)
By default, the formatted values are suited for tabulated output (they’re all the same length);
when passing compact=True
, you’ll get a result that better fits into log messages.
To present lists of numbers in a compact form, collapsing consecutive ranges,
rudiments.humanize.merge_adjacent()
can be used.
>>> ', '. join(humanize.merge_adjacent(('9', 5, 10, 7) + tuple(range(5))))
u'0..5, 7, 9..10'
Python Runtime Support¶
Use the rudiments.pysupport
module to access some helpers which
hide internals of the Python interpreter runtime and provide an easier to use interface.
The functions rudiments.pysupport.import_name()
and rudiments.pysupport.load_module()
can be used for dynamic imports and adding a simple plug-in system to your application.
To help with keeping code portable between Python 2.7 and 3.x,
the rudiments._compat
module offers unified names and semantics
for common features that differ between current and legacy Python versions.
It is based on the module with the same name found in Jinja2.
Extensions to 3rd Party Libraries¶
The sub-package rudiments.reamed
contains modules that
extend the API of some outside library.
Note that you need to add the underlying package to your dependencies
in addition to rudiments, in case you use one of the modules in that sub-package.
rudiments
itself does not publish any dependencies on them.
Where the extended package has a condensed public API (i.e. names are usually only imported from the package name), these modules can serve as a drop-in replacement, so you just have to change the import statement a little.
Extensions to Click¶
You can use the rudiments.reamed.click
module as a drop-in replacement
for Click, like this:
from rudiments.reamed import click
There are additional helper functions: rudiments.reamed.click.pretty_path()
wraps rudiments.reamed.click.format_filename()
to make a file system path
presentable to humans, especially for logging purposes.
The rudiments.reamed.click.serror()
function prints an already styled, very
visible error message, while using any arguments to format the message.
The rudiments.reamed.click.LoggedFailure
exception can be used when
you want to abort a command with a clearly visible error – the message is styled
identically to what serror()
produces, white bold text on a red background.
rudiments.reamed.click.AliasedGroup
allows you to define alias names
for commands you defined via the usual annotatons. Here is an example that maps
the ls
alias to the official list
command name:
from rudiments.reamed import click
class SmurfAliases(click.AliasedGroup):
"""Alias mapping for 'smurf' commands."""
MAP = dict(
ls='list',
)
@cli.group(cls=SmurfAliases)
def smurf():
"""Management of smurfs."""
@smurf.command(name='list')
def smurf_list():
"""A command that lists smurfs."""
# …
Finally, the biggest addition is a default configuration parsing machinery in
the rudiments.reamed.click.Configuration
class. It should be instantiated
in your root command, passing in the (optional) name of a specific configuration file,
or a path of such files.
@click.group()
@click.option('-c', '--config', "config_paths", metavar='FILE',
multiple=True, type=click.Path(), help='Load given configuration file(s).')
@click.pass_context
def cli(ctx, config_paths=None):
"""Some command line tool."""
config.Configuration.from_context(ctx, config_paths)
The prepared configuration object is then available to any sub-command via the context,
as ctx.obj.cfg
. For more details, see the rudiments.reamed.click.Configuration
documentation.