Photon

Photon logo, not a moustache

Welcome to the Photon Documentation.



Photon Intro

It could be best described as a shell backend as python module

Contributions are highly welcome [1], also feel free to use the issue tracker if you encounter any problems.

Repository:github.com/spookey/photon
Documentation:photon.readthedocs.org
Package:pypi.python.org/pypi/photon_core

Examples

The /examples directory contains some basic receipts on how to use Photon in your scripts.

Photon helps at Freifunk MWU to solve some tasks:

Installation

Photon is available as package on pypi, it is called photon_core [2].

You can install/update the package via pip3 [3]:

pip3 install photon_core
pip3 install -U photon_core

Bleeding-Edge

Development is still at an very early stage, expect anything to change completely in near future.

As long we still have a leading zero in the version (see info file) use pip3 with the --pre switch:

pip3 install -U photon_core --pre

Versions

Tags in the git repository will be released as a new pypi package version. Versions of a pypi package has always it’s git tag. And vice versa.

Not every version increase will be tagged/released. I will only do so if I feel the urge to do so.

[1]Teach me how to write good code, help me to improve.
[2]because photon itself was already taken :/
[3]Photon is written in python3 ~ be careful with easy_install

Structure

Photon aimes to be modular and can be divided into The core, it’s Utility and some Tools, provided through Photon itself.

If you just want to use Photon in your Scripts as a normal User you may especially be interested in the parts Photon and Tools.

The core

All three modules depend on the Utility:

Settings and Meta could be used independently or both together.

Bundling Settings and Meta together plus adding the Tools, Photon provides a interface to use in your scripts.

Settings

class settings.Settings(defaults, config='config.yaml', verbose=True)[source]

Settings is a class which provides access to compiled settings loaded from YAML-files.

The YAML-files will be read with specific loaders which enables certain logic within the configuration. It is possible to:

  • Insert references to existing fields via anchors and !str_join or !loc_join
  • Insert keywords like hostname or timestamp using !str_join
  • Combine path-segments using !loc_join
  • Insert keywords like home_dir or conf_dir using !loc_join

It is also possible to import or merge further content.

Parameters:
  • defaults

    The initial configuration to load. Will be located using util.locations.search_location()

    • The common way is to use a short-filename to locate it next to the script using Photon.
    • Can also be a full path.
    • Can also passed directly as a dict
    • Bring your own defaults! Tears down (using util.system.shell_notify() with state set to True) whole application if not found or none passed.
  • config

    Where to store the loaded output from the defaults. Will be located using util.locations.search_location()

    • File must already exist, will be created in ‘conf_dir’ from util.locations.get_locations() otherwise
      • Therefore use a short name (or full path) if one should be created

    Note

    The last loaded file wins

    • The config is intended to provide a editable file for the end-user
    • If a value differs from the original values in defaults, the value in config wins
      • Other values which not exist in config will be set from defaults
      • If a value in config contains a loader call which expresses the same as the value in defaults it will be skipped.
    • Be careful using timestamp s in a config. The timestamp of the first launch will always be used.
    • Simply delete all lines within the config to completely reset it to the defaults
    • Can be skipped by explicitly setting it to None
  • verbose – Sets the verbose flag for the underlying Utility functions
get
Returns:Current settings
load(skey, sdesc, sdict=None, loaders=None, merge=False, writeback=False)[source]

Loads a dictionary into current settings

Parameters:
  • skey – Type of data to load. Is be used to reference the data in the files sections within settings
  • sdesc – Either filename of yaml-file to load or further description of imported data when sdict is used
  • sdict (dict) – Directly pass data as dictionary instead of loading it from a yaml-file. Make sure to set skey and sdesc accordingly
  • loaders (list) – Append custom loaders to the YAML-loader.
  • merge – Merge received data into current settings or place it under skey within meta
  • writeback – Write back loaded (and merged/imported) result back to the original file. This is used to generate the summary files
Returns:

The loaded (or directly passed) content

Example Settings File

defaults.sample.yaml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# The syntax of the settings files is YAML:

01_syntax:
    dictionary: 'value is a string'
    dictionary_with_list: ['value', 'is', 'a', 'list']
    dictionary_with_list2:
    - this
    - is
    - another
    - list


# ----

# YAML supports backreferences by anchors.

# First yo have define a dictionary value as anchor:
02_anchor:
    prefix: &MY_PRFX 'Photon is a software that '

# Then use them together with !str_join:
    poll:
        yay: !str_join [*MY_PRFX, 'realy helps me']
        nay: !str_join [*MY_PRFX, 'sucks']


# This turns into:
#     yay: Photon is a software that really helps me
#     nay: Photon is a software that sucks
# (The anchor ('&'-sign) must appear before the Reference ('*'-sign) in the YAML-file.
# (Note the whitespace.)


# ----

# !str_join can listen to the keywords - 'hostname' & 'timestamp':

03_keywords:
    message:
    - !str_join ['my machine "', 'hostname', '" is the best']
    - !str_join ['yours, herbert. date: ', 'timestamp']


# This turns into:
#     message:
#     - my machine "blechschachtel" is the best
#     - 'yours, herbert. date: YYYY.MM.DD-HH.MM.SS'
# (with current date expanded)


# ----

# Use !loc_join to combine files and paths:

04_locations:
    simple_file: !loc_join ['/', 'usr', 'local', 'bin', 'myscript.sh']
    same_simple_file: !loc_join ['/usr/local/bin', 'myscript.sh']
# This turns into:
#    simple_file: /usr/local/bin/myscript.sh
#    same_simple_file: /usr/local/bin/myscript.sh

# But be careful with leading '/'-signs:
    not_the_simple_file: !loc_join ['/usr/local', '/bin', 'myscript.sh']
# This turns into not what we wanted:
#     not_the_simple_file: /bin/myscript.sh


# It can also listen to keywords:
    in_the_home_dir: !loc_join ['home_dir', 'my_directory']
#     in_the_home_dir: /home/herbert/my_directory


# ----

# Combine them alltogether:

05_combined:
    name: &MY_ASS my_awesome_server_software

    main: &OH_MY !loc_join ['home_dir', *MY_ASS, 'main']

    main_run: !loc_join [*OH_MY, 'run.py']

    backup_dir: !loc_join ['data_dir', *MY_ASS, !str_join ['backup-', 'timestamp']]

    git-remote: !str_join
    - 'https://github.com/user404/'
    - *MY_ASS
    - .git

# This turns into:
#     name: my_awesome_server_software
#     main: /home/herbert/my_awesome_server_software/main
#     main_run: /home/herbert/my_awesome_server_software/main/run.py
#     backup_dir: /home/herbert/.local/share/photon/my_awesome_server_software/backup-YYYY.MM.DD-HH.MM.SS
#     git-remote: https://github.com/user404/my_awesome_server_software.git

See also

The wikipedia page on YAML for some syntax reference.

See also

(get locations by keyword and join paths)

(get variables by keyword and join strings)

Meta

class meta.Meta(meta='meta.json', verbose=True)[source]

Meta is a class which bounds to an actual json-file on disk. It provides a logger storing the entries in that json-file.

It is also possible to import contents. By staging out to a different directory meta-files are left behind for further debugging or to see what was going on.

Parameters:
  • meta – Initial, clean meta file to use. See stage() for more
  • verbose – Sets the verbose flag for the underlying Utility functions
load(mkey, mdesc, mdict=None, merge=False)[source]

Loads a dictionary into current meta

Parameters:
  • mkey – Type of data to load. Is be used to reference the data from the ‘header’ within meta
  • mdesc – Either filename of json-file to load or further description of imported data when mdict is used
  • mdict (dict) – Directly pass data as dictionary instead of loading it from a json-file. Make sure to set mkey and mdesc accordingly
  • merge – Merge received data into current meta or place it under ‘import’ within meta
Returns:

The loaded (or directly passed) content

log
Parameters:elem

Add a new log entry to the meta.

Returns:Current meta
stage(name, clean=False)[source]

Switch stage

Parameters:
  • name

    Filename of new meta file. Will be located using util.locations.search_location()

    • File must not already exist, will be created in ‘data_dir’ from util.locations.get_locations()
    • Can also be a full path to place it anywhere desired
  • clean

    What to do with preexisting meta files?

    • False: Merge current meta with preexisting one
    • True: Replace preexisting meta with current one

Photon

class photon.Photon(defaults, config='config.yaml', meta='meta.json', verbose=True)[source]

Photon uses The core and some functions from Utility in its m()-method.

The m()-method itself is used in each tool to interact with photon to:

  • Launch shell commands, and receive the results
  • Add messages to the meta-file
  • Show the messages if necessary
  • Tear down application completely in case of any serious problems

Further, Photon provides direct handlers for settings.Settings and meta.Meta and a handler for each tool from Tools by it’s methods.

Parameters:
Variables:
  • settings – The settings handler initialized with defaults and config
  • meta – The meta handler initialized with meta

At startup the loaded settings are imported into meta

git_handler(*args, **kwargs)[source]
Returns:A new git handler

See also

Git Tool

m(msg, state=False, more=None, cmdd=None, critical=True, verbose=None)[source]

Mysterious mega method managing multiple meshed modules magically

Note

If this function is used, the code contains facepalms: m(

  • It is possible to just show a message, or to run a command with message.
  • But it is not possible to run a command without a message, use the verbose-flag to hide your debug message.
Parameters:
Returns:

A dictionary specified the following:

  • ‘more’:

    more if it is not a dictionary otherwise it gets merged in if more is specified

  • The output of util.system.shell_run() gets merged in if cmdd is specified

  • ‘failed’: True if command failed

util.system.shell_notify() is used with this dictionary to pipe it’s output into meta.Meta.log() before returning.

mail_handler(punchline=None, add_meta=False, add_settings=True, *args, **kwargs)[source]
Parameters:
  • punchline – Adds a punchline before further text
  • add_meta – Appends current meta to the mail
  • add_settings – Appends current settings to the mail
Returns:

A new mail handler

See also

Mail Tool

ping_handler(*args, **kwargs)[source]
Returns:A new ping handler

See also

Ping Tool

s2m

Imports settings to meta

signal_handler(*args, **kwargs)[source]
Returns:A new signal handler

See also

Signal Tool

template_handler(*args, **kwargs)[source]
Returns:A new template handler

See also

Template Tool

photon.check_m(pm)[source]

Shared helper function for all Tools to check if the passed m-function is indeed photon.Photon.m()

Params pm:Suspected m-function
Returns:Now to be proven correct m-function, tears down whole application otherwise.

Tools

This are the tools for the user using Photon. You should not directly use them, instead they will get provided to you by Photon.

See also

Settings, Meta, Photon

Some functionality here is bought from the Utility:

Git Tool

class tools.git.Git(m, local, remote_url=None, mbranch=None)[source]

The git tool helps to deal with git repositories.

Parameters:
  • local

    The local folder of the repository

    • If None given (default), it will be ignored if there is already a git repo at local
    • If no git repo is found at local, a new one gets cloned from remote_url
  • remote_url

    The remote URL of the repository

    • Tears down (using util.system.shell_notify() with state set to True) whole application if remote_url is set to None but a new clone is necessary
  • mbranch – The repository’s main branch. Is set to master when left to None
_checkout(treeish)[source]

Helper function to checkout something

Parameters:treeish – String for ‘tag‘, ‘branch‘, or remote tracking ‘-B banch
_get_branch(remotes=False)[source]

Helper function to determine current branch

Parameters:remotes – List the remote-tracking branches
_get_remote(cached=True)[source]

Helper function to determine remote

Parameters:cached – Use cached values or query remotes
_log(num=None, format=None)[source]

Helper function to receive git log

Parameters:
  • num – Number of entries
  • format – Use formatted output with specified format string
_pull()[source]

Helper function to pull from remote

branch
Parameters:branch – Checks out specified branch (tracking if it exists on remote). If set to None, ‘master’ will be checked out
Returns:The current branch (This could also be ‘master (Detatched-Head)’ - Be warned)
cleanup

Commits all local changes (if any) into a working branch, merges it with ‘master’.

Checks out your old branch afterwards.

Tears down (using util.system.shell_notify() with state set to True) whole application if conflicts are discovered

commit
Parameters:tag – Checks out specified commit. If set to None the latest commit will be checked out
Returns:A list of all commits, descending
local
Returns:The local folder of the repository
log
Returns:The last 10 commit entries as dictionary
  • ‘commit’: The commit-ID
  • ‘message’: First line of the commit message
publish

Runs cleanup() first, then pushes the changes to the remote.

remote
Returns:Current remote
remote_url
Returns:The remote URL of the repository
short_commit
Returns:A list of all commits, descending

See also

commit

status
Returns:Current repository status as dictionary:
  • ‘clean’: True if there are no changes False otherwise
  • ‘untracked’: A list of untracked files (if any and not ‘clean’)
  • ‘modified’: A list of modified files (if any and not ‘clean’)
  • ‘deleted’: A list of deleted files (if any and not ‘clean’)
  • ‘conflicting’: A list of conflicting files (if any and not ‘clean’)
tag
Parameters:tag – Checks out specified tag. If set to None the latest tag will be checked out
Returns:A list of all tags, sorted as version numbers, ascending

Mail Tool

class tools.mail.Mail(m, to, sender, subject=None, cc=None, bcc=None)[source]

The Mail tool helps to send out mails.

Parameters:
  • to – Where to send the mail ('user@example.com‘)
  • sender

    Yourself ('me@example.com‘)

    • set a reverse DNS entry for example.com so your mail does not get caught up in spamfilters.
  • subject – The subject line
  • cc – One or a list of CCs
  • bcc – One or a list of BCCs
send
Returns:A dictionary with the following:
  • ‘sender’: The sender
  • ‘recipients’: All recipients, compiled from to, cc and bcc
  • ‘result’: The smtplib.SMTP.sendmail()-result
  • ‘exception’: The exception message (if any)

Note

You need to have a postfix/sendmail running and listening on localhost.

text
Parameters:text – Add some more text
Returns:All text & headers as raw mail source
Mail Tool Example

mail.sample.yaml

1
2
3
4
5
mail:
    recipient: you@example.com
    sender: me@example.com
    subject: 'Fire!'
    punchline: 'Dear Sir or Madam, I am writing to inform you about a fire in the building ...'

mail.sample.py

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
from photon import Photon

photon = Photon('mail.sample.yaml')

settings = photon.settings.get['mail']

mail = photon.mail_handler(
    to=settings['recipient'],
    sender=settings['sender'],
    subject=settings['subject'],
    punchline=settings['punchline'],
    add_meta=True
)

###
# Shows the message source so far
print(mail.text)

###
# Add some more text (do this as often as you like):
mail.text = '''
Dear Sir or Madam,
bla bla

No, that's too formal..
'''

###
# Guess what happens here:
mail.send

Ping Tool

class tools.ping.Ping(m, six=False, net_if=None, num=5, max_pool_size=None)[source]

The Ping tool helps to send pings, returning detailed results each probe, and calculates a summary of all probes.

Parameters:
  • six – Either use ping or ping6
  • net_if – Specify network interface to send pings from
  • num – How many pings to send each probe
  • max_pool_size – Hosts passed to probe() in form of a list, will be processed in parallel. Specify the maximum size of the thread pool workers here. If skipped, the number of current CPUs is used
probe
Parameters:hosts

One or a list of hosts (URLs, IP-addresses) to send pings to

  • If you need to check multiple hosts, it is best to pass them together as a list.
  • This will probe all hosts in parallel, with max_pool_size workers.
Returns:A dictionary with all hosts probed as keys specified as following:
  • ‘up’: True or False depending if ping was successful
  • ‘loss’: The packet loss as list (if ‘up’)
  • ‘ms’: A list of times each packet sent (if ‘up’)
  • ‘rtt’: A dictionary with the fields avg, min, max & stddev (if ‘up’)
status
Returns:A dictionary with the following:
  • ‘num’: Total number of hosts already probed
  • ‘up’: Number of hosts up
  • ‘down’: Number of hosts down
  • ‘ratio’: Ratio between ‘up’/’down’ as float

Ratio:

  • 100% up == 1.0
  • 10% up == 0.1
  • 0% up == 0.0
Ping Tool Example

ping.sample.yaml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
hosts:
    addresses:
    - '127.0.0.1'
    - '127.0.0.2'
    - '127.0.0.3'
    urls:
    - exampla.com
    - example.com
    - exampli.com
    - examplo.com
    - examplu.com

ping.sample.py

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
from pprint import pprint
from photon import Photon

photon = Photon('ping.sample.yaml')

hosts = photon.settings.get['hosts']

ping = photon.ping_handler()

###
# Let's start off with localhost to demonstrate the handling of the probe-function:

pprint(hosts)

a = hosts['addresses'][0]
ping.probe = a

if ping.probe[a]['up']:
    print('%s is reachable - %s ms rtt in average' %(a, ping.probe[a]['rtt']['avg']))
else:
    print('%s could not be reached!' %(a))

pprint(ping.probe)

print('-' * 8)


###
# You can also pass a complete list to probe. This will be faster, because the list is processed in parallel.
# The status per host will be overwritten with new information if it encounters the same host again:

ping.probe = hosts['addresses']
pprint(ping.probe)

print('These are the statistics so far:')
pprint(ping.status)

print('-' * 8)


###
# Another round of pings to demonstrate the handling of the status-function:

ping.probe = hosts['urls']

if ping.status['ratio'] <= 0.75:
    print('more than three quarters of all addresses are not reachable!!1!')

print('The statistics have changed now:')
pprint(ping.status)

Signal Tool

class tools.signal.Signal(m, pid, sudo=True, cmdd_if_no_pid=None)[source]

The Signal tool can send signals to processes via kill, returning the results.

Parameters:
  • pid – Either the full path to the pidfile (e.g. /var/run/proc.pid) or the pid as number
  • sudo – Prepend sudo before command. (Make sure to be root yourself if set to False or expect errors. Further for unattended operation add the user to sudoers file.)
_Signal__signal(sig, verbose=None)

Helper class preventing code duplication..

Parameters:
  • sig – Signal to use (e.g. “HUP”, “ALRM”)
  • verbose – Overwrite photon.Photon.m()‘s verbose
Returns:

photon.Photon.m()‘s result of killing pid with specified pid

alrm
Returns:photon.Photon.m()‘s result of killing pid using SIGALRM
hup
Returns:photon.Photon.m()‘s result of killing pid using SIGHUP
int
Returns:photon.Photon.m()‘s result of killing pid using SIGINT with visible shell warning
kill
Returns:photon.Photon.m()‘s result of killing pid using SIGKILL with visible shell warning
quit
Returns:photon.Photon.m()‘s result of killing pid using SIGQUIT with visible shell warning
stop
Returns:photon.Photon.m()‘s result of killing pid using SIGSTOP with visible shell warning
usr1
Returns:photon.Photon.m()‘s result of killing pid using SIGUSR1
usr2
Returns:photon.Photon.m()‘s result of killing pid using SIGUSR2

Template Tool

class tools.template.Template(m, template, fields=None)[source]

The Template tool helps to process on strings.

Parameters:
  • template

    The initial template to start with.

    Note

    If the file is not found, you will be doing string processing on the filename instead of the contents!

  • fields – Initially set up fields. Can be done later, using sub()

The templating-language itself are normal Template strings, see there for syntax.

raw
Returns:The raw template
sub
Parameters:fields – Set fields to substitute
Returns:Substituted Template with given fields. If no fields were set up beforehand, raw() is used.
write(filename, append=True, backup=True)[source]
Parameters:
  • filename – File to write into
  • append – Either append to existing content (if not already included) or completely replace filename
  • backup – Create a backup of filename before writing. Only applies when append is set

Utility

This is the toolbox used by The core:

See also

Settings, Meta, Photon

As well as used by the Tools:

Note

If you have no explicit reason, do not use the functions here directly.

  • Always try to work trough photon.Photon and it’s handlers.
  • If you discover you are repeatedly calling backend functions

consider adding a tool for that job!

Files

util.files.read_file(filename)[source]

Reads files

Parameters:filename – The full path of the file to read
Returns:The content of the file as string (if filename exists)

Note

If filename‘s content is empty, None will also returned.

To check if a file really exists use util.locations.search_location()

util.files.read_json(filename)[source]

Reads json files

Parameters:filename – The full path to the json file
Returns:Loaded json content as represented data structure
util.files.read_yaml(filename, add_constructor=None)[source]

Reads YAML files

Parameters:
  • filename – The full path to the YAML file
  • add_constructor – A list of yaml constructors (loaders)
Returns:

Loaded YAML content as represented data structure

util.files.write_file(filename, content)[source]

Writes files

Parameters:
  • filename – The full path of the file to write (enclosing folder must already exist)
  • content – The content to write
Returns:

The size of the data written

util.files.write_json(filename, content)[source]

Writes json files

Parameters:
  • filename – The full path to the json file
  • content – The content to dump
Returns:

The size written

util.files.write_yaml(filename, content)[source]

Writes YAML files

Parameters:
  • filename – The full path to the YAML file
  • content – The content to dump
Returns:

The size written

Locations

util.locations.backup_location(src, loc=None)[source]

Writes Backups of locations

Parameters:
  • src – The source file/folder to backup
  • loc

    The target folder to backup into

    The backup will be called src + util.system.get_timestamp(). * If loc left to none, the backup gets written in the same folder like src resides in

    • Otherwise the specified path will be used.
util.locations.change_location(src, tgt, move=False, verbose=True)[source]

Copies/moves/deletes locations

Parameters:
  • src – Source location where to copy from
  • tgt

    Target location where to copy to

  • move

    Deletes original location after copy (a.k.a. move)

    • To delete src , set tgt explicitly to False and move to True (be careful!!1!)
  • verbose – Show warnings
util.locations.get_locations()[source]

Compiles default locations

Returns:A dictionary with folders as values:
  • ‘home_dir’: Your home-directory (~)
  • ‘call_dir’: Where you called the first Python script from. (argv[0])
  • ‘conf_dir’: The XDG_CONFIG_HOME-directory + photon (~/.config/photon)
  • ‘data_dir’: The XDG_DATA_HOME-directory + photon (~/.local/share/photon)

Note

util.locations.make_locations(locations=None, verbose=True)[source]

Creates folders

Parameters:
  • locations – A list of folders to create (can be a dictionary, see note below)
  • verbose – Warn if any folders were created

Note

  • If locations is not a list, but a dictionary, all values in the dictionary will be used (as specified in util.structures.to_list())
  • If locations is set to None (by default), it will be filled with the output of get_locations().
util.locations.search_location(loc, locations=None, critical=False, create_in=None, verbose=True)[source]

Locates files with a twist:

  • Check the existence of a file using the full path in loc
  • Search for the filename loc in locations
  • Create it’s enclosing folders if the file does not exist. use create_in
Parameters:
  • loc – Filename to search
  • locations – A list of possible locations to search within (can be a dictionary, see note below)
  • critical – Tears down (using util.system.shell_notify() with state set to True) whole application if file was not found
  • create_in – If loc was not found, the folder create_in is created. If locations is a dictionary, create_in can also specify a key of locations. The value will be used then.
  • verbose – Pass verbose flag to make_locations()
Returns:

The full path of loc in matched location

Note

  • If locations is not a list, but a dictionary, all values in the dictionary will be used (as specified in util.structures.to_list())
  • If locations is set to None (by default), it will be filled with the output of get_locations().

Structures

util.structures.dict_merge(o, v)[source]

Recursively climbs through dictionaries and merges them together.

Parameters:
  • o – The first dictionary
  • v – The second dictionary
Returns:

A dictionary (who would have guessed?)

Note

Make sure o & v are indeed dictionaries, bad things will happen otherwise!

util.structures.to_list(i, use_keys=False)[source]

Converts items to a list.

Parameters:
  • i

    Item to convert

    • If i is None, the result is an empty list
    • If i is ‘string’, the result won’t be ['s', 't', 'r',...] rather more like ['string']
    • If i is a nested dictionary, the result will be a flattened list.
  • use_keys – If i is a dictionary, use the keys instead of values
Returns:

All items in i as list

util.structures.yaml_loc_join(l, n)[source]

YAML loader to join paths

The keywords come directly from util.locations.get_locations(). See there!

Returns:A path seperator (/) joined string with keywords extended. Used in settings.Settings.load()

See also

The YAML files mentioned in Example Settings File, Mail Tool Example, Ping Tool Example

util.structures.yaml_str_join(l, n)[source]

YAML loader to join strings

The keywords are as following:

Returns:A non character joined string with keywords extended. Used in settings.Settings.load()

Note

Be careful with timestamps when using a config in Settings.

See also

The YAML files mentioned in Example Settings File, Mail Tool Example, Ping Tool Example

System

util.system.get_hostname()[source]

Determines the current hostname by probing uname -n. Falls back to hostname in case of problems.

Tears down (using util.system.shell_notify() with state set to True) whole application if both failed (usually they don’t but consider this if you are debugging weird problems..)

Returns:The hostname as string. Domain parts will be split off
util.system.get_timestamp(time=True, precice=False)[source]

What time is it?

Parameters:
  • time – Append -%H.%M.%S to the final string.
  • precice – Append -%f to the final string. Is only recognized when time is set to True
Returns:

A timestamp string of now in the format %Y.%m.%d-%H.%M.%S-%f

See also

strftime.org is awesome!

util.system.shell_notify(msg, state=False, more=None, exitcode=None, verbose=True)[source]

A pretty long wrapper for a print() function. But this print() is the only one in Photon.

Note

This method is just a helper method within photon. If you need this functionality use photon.Photon.m() instead

Parameters:
  • msg – The message to show
  • state

    The message will be prefixed with [state]

    • If False (default): Prefixed with ~
    • If None: Prefixed with [WARNING]
    • If True: Prefixed with [FATAL] and the exitcode will be set (see below)
  • more

    Something to add to the message (see below)

    • Anything you have. Just for further information.
    • Will be displayed after the message, pretty printed using pprint.pformat()
  • exitcode – Tears down (using util.system.shell_notify() with state set to True) whole application with given code
  • verbose

    Show message or not (see below)

    • If set to False, you can use shell_notify() for the dictionary it returns.
    • Will be overruled if exitcode is set.
Returns:

A dictionary containing untouched msg, more and verbose

util.system.shell_run(cmd, cin=None, cwd=None, timeout=10, critical=True, verbose=True)[source]

Runs a shell command within a controlled environment.

Note

This method is just a helper method within photon. If you need this functionality use photon.Photon.m() instead

Parameters:
  • cmd

    The command to run

    • A string one would type into a console like git push -u origin master.
    • Will be split using shlex.split().
    • It is possible to use a list here, but then no splitting is done.
  • cin – Add something to stdin of cmd
  • cwd – Run cmd insde specified current working directory
  • timeout – Catch infinite loops (e.g. ping). Exit after timeout seconds
  • critical – If set to True: Tears down (using util.system.shell_notify() with state set to True) whole application on failure of cmd
  • verbose – Show messages and warnings
Returns:

A dictionary containing the results from running cmd with the following:

  • ‘command’: cmd
  • ‘stdin’: cin (If data was set in cin)
  • ‘cwd’: cwd (If cwd was set)
  • ‘exception’: exception message (If an exception was thrown)
  • ‘timeout’: timeout (If a timeout exception was thrown)
  • ‘stdout’: List from stdout (If any)
  • ‘stderr’: List from stderr (If any)
  • ‘returncode’: The returncode (If not any exception)
  • ‘out’: The most urgent message as joined string. (‘exception’ > ‘stderr’ > ‘stdout’)

I am lost:

Info

The info file

The info file is not vital to Photon, it just helps to share common values between documentation and the package builder (setup file).

info.author()[source]
Returns:The main author (last entry of contributors())
info.contributors()[source]
Returns:A list of all contributors
info.contributors_str()[source]
Returns:The contributors() as comma joined string
info.email()[source]
Returns:Main author()‘s mail
info.pkg_name()[source]
Returns:The package name (on pypi)
info.release()[source]
Returns:Current release string
Current:0.4
info.url()[source]
Returns:The repo url (on github)
info.version()[source]
Returns:Current version string
Current:0.4 (Release: 0.4)