Convert param docs into parseable format.

This commit is contained in:
Anders Ingemann 2014-05-04 19:31:53 +02:00
parent ee6df57f3f
commit ee3fe0bf42
24 changed files with 168 additions and 240 deletions

View file

@ -7,10 +7,9 @@ from main import main
def validate_manifest(data, validator, error): def validate_manifest(data, validator, error):
"""Validates the manifest using the base manifest """Validates the manifest using the base manifest
Args: :param dict data: The data of the manifest
data (dict): The data of the manifest :param function validator: The function that validates the manifest given the data and a path
validator (function): The function that validates the manifest given the data and a path :param function error: The function tha raises an error when the validation fails
error (function): The function tha raises an error when the validation fails
""" """
import os.path import os.path
schema_path = os.path.normpath(os.path.join(os.path.dirname(__file__), 'manifest-schema.json')) schema_path = os.path.normpath(os.path.join(os.path.dirname(__file__), 'manifest-schema.json'))

View file

@ -9,9 +9,8 @@ class BootstrapInformation(object):
def __init__(self, manifest=None, debug=False): def __init__(self, manifest=None, debug=False):
"""Instantiates a new bootstrap info object. """Instantiates a new bootstrap info object.
Args: :param Manifest manifest: The manifest
manifest (Manifest): The manifest :param bool debug: Whether debugging is turned on
debug (bool): Whether debugging is turned on
""" """
# Set the manifest attribute. # Set the manifest attribute.
self.manifest = manifest self.manifest = manifest
@ -74,6 +73,14 @@ class BootstrapInformation(object):
setattr(self, '_' + pluginname, {}) setattr(self, '_' + pluginname, {})
def __create_manifest_vars(self, manifest, additional_vars={}): def __create_manifest_vars(self, manifest, additional_vars={}):
"""Creates the manifest variables dictionary, based on the manifest contents
and additional data.
:param Manifest manifest: The Manifest
:param dict additional_vars: Additional values (they will take precedence and overwrite anything else)
:return: The manifest_vars dictionary
:rtype: dict
"""
class DictClass(dict): class DictClass(dict):
"""Tiny extension of dict to allow setting and getting keys via attributes """Tiny extension of dict to allow setting and getting keys via attributes
""" """
@ -89,9 +96,8 @@ class BootstrapInformation(object):
def set_manifest_vars(obj, data): def set_manifest_vars(obj, data):
"""Runs through the manifest and creates DictClasses for every key """Runs through the manifest and creates DictClasses for every key
Args: :param dict obj: dictionary to set the values on
obj (dict): dictionary to set the values on :param dict data: dictionary of values to set on the obj
data (dict): dictionary of values to set on the obj
""" """
for key, value in data.iteritems(): for key, value in data.iteritems():
if isinstance(value, dict): if isinstance(value, dict):

View file

@ -2,12 +2,12 @@
def load_volume(data, bootloader): def load_volume(data, bootloader):
"""Instantiates a volume that corresponds to the data in the manifest """Instantiates a volume that corresponds to the data in the manifest
Args:
data (dict): The 'volume' section from the manifest
bootloader (str): Name of the bootloader the system will boot with
Returns: :param dict data: The 'volume' section from the manifest
Volume. The volume that represents all information pertaining to the volume we bootstrap on :param str bootloader: Name of the bootloader the system will boot with
:return: The volume that represents all information pertaining to the volume we bootstrap on.
:rtype: Volume
""" """
# Create a mapping between valid partition maps in the manifest and their corresponding classes # Create a mapping between valid partition maps in the manifest and their corresponding classes
from partitionmaps.gpt import GPTPartitionMap from partitionmaps.gpt import GPTPartitionMap

View file

@ -20,8 +20,7 @@ class AbstractPartitionMap(FSMProxy):
def __init__(self, bootloader): def __init__(self, bootloader):
""" """
Args: :param str bootloader: Name of the bootloader we will use for bootstrapping
bootloader (str): Name of the bootloader we will use for bootstrapping
""" """
# Create the configuration for the state machine # Create the configuration for the state machine
cfg = {'initial': 'nonexistent', 'events': self.events, 'callbacks': {}} cfg = {'initial': 'nonexistent', 'events': self.events, 'callbacks': {}}
@ -30,16 +29,15 @@ class AbstractPartitionMap(FSMProxy):
def is_blocking(self): def is_blocking(self):
"""Returns whether the partition map is blocking volume detach operations """Returns whether the partition map is blocking volume detach operations
Returns: :rtype: bool
bool.
""" """
return self.fsm.current == 'mapped' return self.fsm.current == 'mapped'
def get_total_size(self): def get_total_size(self):
"""Returns the total size the partitions occupy """Returns the total size the partitions occupy
Returns: :return: The size of all partitions
Bytes. The size of all the partitions :rtype: Bytes
""" """
# We just need the endpoint of the last partition # We just need the endpoint of the last partition
return self.partitions[-1].get_end() return self.partitions[-1].get_end()
@ -47,8 +45,7 @@ class AbstractPartitionMap(FSMProxy):
def create(self, volume): def create(self, volume):
"""Creates the partition map """Creates the partition map
Args: :param Volume volume: The volume to create the partition map on
volume (Volume): The volume to create the partition map on
""" """
self.fsm.create(volume=volume) self.fsm.create(volume=volume)
@ -59,15 +56,13 @@ class AbstractPartitionMap(FSMProxy):
def map(self, volume): def map(self, volume):
"""Maps the partition map to device nodes """Maps the partition map to device nodes
Args: :param Volume volume: The volume the partition map resides on
volume (Volume): The volume the partition map resides on
""" """
self.fsm.map(volume=volume) self.fsm.map(volume=volume)
def _before_map(self, event): def _before_map(self, event):
""" """
Raises: :raises PartitionError: In case a partition could not be mapped.
PartitionError
""" """
volume = event.volume volume = event.volume
try: try:
@ -105,15 +100,13 @@ class AbstractPartitionMap(FSMProxy):
def unmap(self, volume): def unmap(self, volume):
"""Unmaps the partition """Unmaps the partition
Args: :param Volume volume: The volume to unmap the partition map from
volume (Volume): The volume to unmap the partition map from
""" """
self.fsm.unmap(volume=volume) self.fsm.unmap(volume=volume)
def _before_unmap(self, event): def _before_unmap(self, event):
""" """
Raises: :raises PartitionError: If the a partition cannot be unmapped
PartitionError
""" """
volume = event.volume volume = event.volume
# Run through all partitions before unmapping and make sure they can all be unmapped # Run through all partitions before unmapping and make sure they can all be unmapped

View file

@ -10,9 +10,8 @@ class GPTPartitionMap(AbstractPartitionMap):
def __init__(self, data, bootloader): def __init__(self, data, bootloader):
""" """
Args: :param dict data: volume.partitions part of the manifest
data (dict): volume.partitions part of the manifest :param str bootloader: Name of the bootloader we will use for bootstrapping
bootloader (str): Name of the bootloader we will use for bootstrapping
""" """
from bootstrapvz.common.bytes import Bytes from bootstrapvz.common.bytes import Bytes
# List of partitions # List of partitions

View file

@ -11,9 +11,8 @@ class MSDOSPartitionMap(AbstractPartitionMap):
def __init__(self, data, bootloader): def __init__(self, data, bootloader):
""" """
Args: :param dict data: volume.partitions part of the manifest
data (dict): volume.partitions part of the manifest :param str bootloader: Name of the bootloader we will use for bootstrapping
bootloader (str): Name of the bootloader we will use for bootstrapping
""" """
from bootstrapvz.common.bytes import Bytes from bootstrapvz.common.bytes import Bytes
# List of partitions # List of partitions

View file

@ -9,9 +9,8 @@ class NoPartitions(object):
def __init__(self, data, bootloader): def __init__(self, data, bootloader):
""" """
Args: :param dict data: volume.partitions part of the manifest
data (dict): volume.partitions part of the manifest :param str bootloader: Name of the bootloader we will use for bootstrapping
bootloader (str): Name of the bootloader we will use for bootstrapping
""" """
from bootstrapvz.common.bytes import Bytes from bootstrapvz.common.bytes import Bytes
# In the NoPartitions partitions map we only have a single 'partition' # In the NoPartitions partitions map we only have a single 'partition'
@ -22,15 +21,14 @@ class NoPartitions(object):
def is_blocking(self): def is_blocking(self):
"""Returns whether the partition map is blocking volume detach operations """Returns whether the partition map is blocking volume detach operations
Returns: :rtype: bool
bool.
""" """
return self.root.fsm.current == 'mounted' return self.root.fsm.current == 'mounted'
def get_total_size(self): def get_total_size(self):
"""Returns the total size the partitions occupy """Returns the total size the partitions occupy
Returns: :return: The size of all the partitions
Bytes. The size of all the partitions :rtype: Bytes
""" """
return self.root.get_end() return self.root.get_end()

View file

@ -24,10 +24,9 @@ class AbstractPartition(FSMProxy):
""" """
def __init__(self, source, destination, opts): def __init__(self, source, destination, opts):
""" """
Args: :param str,AbstractPartition source: The path from where we mount or a partition
source (str,AbstractPartition): The path from where we mount or a partition :param str destination: The path of the mountpoint
destination (str): The path of the mountpoint :param list opts: List of options to pass to the mount command
opts (list): List of options to pass to the mount command
""" """
self.source = source self.source = source
self.destination = destination self.destination = destination
@ -36,8 +35,7 @@ class AbstractPartition(FSMProxy):
def mount(self, prefix): def mount(self, prefix):
"""Performs the mount operation or forwards it to another partition """Performs the mount operation or forwards it to another partition
Args: :param str prefix: Path prefix of the mountpoint
prefix (str): Path prefix of the mountpoint
""" """
mount_dir = os.path.join(prefix, self.destination) mount_dir = os.path.join(prefix, self.destination)
# If the source is another partition, we tell that partition to mount itself # If the source is another partition, we tell that partition to mount itself
@ -59,10 +57,9 @@ class AbstractPartition(FSMProxy):
def __init__(self, size, filesystem, format_command): def __init__(self, size, filesystem, format_command):
""" """
Args: :param Bytes size: Size of the partition
size (Bytes): Size of the partition :param str filesystem: Filesystem the partition should be formatted with
filesystem (str): Filesystem the partition should be formatted with :param list format_command: Optional format command, valid variables are fs, device_path and size
format_command (list): Optional format command, valid variables are fs, device_path and size
""" """
self.size = size self.size = size
self.filesystem = filesystem self.filesystem = filesystem
@ -79,8 +76,8 @@ class AbstractPartition(FSMProxy):
def get_uuid(self): def get_uuid(self):
"""Gets the UUID of the partition """Gets the UUID of the partition
Returns: :return: The UUID of the partition
str. The UUID of the partition :rtype: str
""" """
[uuid] = log_check_call(['blkid', '-s', 'UUID', '-o', 'value', self.device_path]) [uuid] = log_check_call(['blkid', '-s', 'UUID', '-o', 'value', self.device_path])
return uuid return uuid
@ -92,8 +89,8 @@ class AbstractPartition(FSMProxy):
def get_end(self): def get_end(self):
"""Gets the end of the partition """Gets the end of the partition
Returns: :return: The end of the partition
Bytes. The end of the partition :rtype: Bytes
""" """
return self.get_start() + self.size return self.get_start() + self.size
@ -141,10 +138,9 @@ class AbstractPartition(FSMProxy):
"""Associate a mount with this partition """Associate a mount with this partition
Automatically mounts it Automatically mounts it
Args: :param str,AbstractPartition source: The source of the mount
source (str,AbstractPartition): The source of the mount :param str destination: The path to the mountpoint
destination (str): The path to the mountpoint :param list opts: Any options that should be passed to the mount command
opts (list): Any options that should be passed to the mount command
""" """
# Create a new mount object, mount it if the partition is mounted and put it in the mounts dict # Create a new mount object, mount it if the partition is mounted and put it in the mounts dict
mount = self.Mount(source, destination, opts) mount = self.Mount(source, destination, opts)
@ -156,8 +152,7 @@ class AbstractPartition(FSMProxy):
"""Remove a mount from this partition """Remove a mount from this partition
Automatically unmounts it Automatically unmounts it
Args: :param str destination: The mountpoint path of the mount that should be removed
destination (str): The mountpoint path of the mount that should be removed
""" """
# Unmount the mount if the partition is mounted and delete it from the mounts dict # Unmount the mount if the partition is mounted and delete it from the mounts dict
# If the mount is already unmounted and the source is a partition, this will raise an exception # If the mount is already unmounted and the source is a partition, this will raise an exception

View file

@ -20,11 +20,10 @@ class BasePartition(AbstractPartition):
def __init__(self, size, filesystem, format_command, previous): def __init__(self, size, filesystem, format_command, previous):
""" """
Args: :param Bytes size: Size of the partition
size (Bytes): Size of the partition :param str filesystem: Filesystem the partition should be formatted with
filesystem (str): Filesystem the partition should be formatted with :param list format_command: Optional format command, valid variables are fs, device_path and size
format_command (list): Optional format command, valid variables are fs, device_path and size :param BasePartition previous: The partition that preceeds this one
previous (BasePartition): The partition that preceeds this one
""" """
# By saving the previous partition we have # By saving the previous partition we have
# a linked list that partitions can go backwards in to find the first partition. # a linked list that partitions can go backwards in to find the first partition.
@ -39,16 +38,15 @@ class BasePartition(AbstractPartition):
def create(self, volume): def create(self, volume):
"""Creates the partition """Creates the partition
Args: :param Volume volume: The volume to create the partition on
volume (Volume): The volume to create the partition on
""" """
self.fsm.create(volume=volume) self.fsm.create(volume=volume)
def get_index(self): def get_index(self):
"""Gets the index of this partition in the partition map """Gets the index of this partition in the partition map
Returns: :return: The index of the partition in the partition map
int. The index of the partition in the partition map :rtype: int
""" """
if self.previous is None: if self.previous is None:
# Partitions are 1 indexed # Partitions are 1 indexed
@ -60,8 +58,8 @@ class BasePartition(AbstractPartition):
def get_start(self): def get_start(self):
"""Gets the starting byte of this partition """Gets the starting byte of this partition
Returns: :return: The starting byte of this partition
Bytes. The starting byte of this partition :rtype: Bytes
""" """
if self.previous is None: if self.previous is None:
# If there is no previous partition, this partition begins at the offset # If there is no previous partition, this partition begins at the offset
@ -73,8 +71,7 @@ class BasePartition(AbstractPartition):
def map(self, device_path): def map(self, device_path):
"""Maps the partition to a device_path """Maps the partition to a device_path
Args: :param str device_path: The device patht his partition should be mapped to
device_path (str): The device patht his partition should be mapped to
""" """
self.fsm.map(device_path=device_path) self.fsm.map(device_path=device_path)

View file

@ -8,12 +8,11 @@ class GPTPartition(BasePartition):
def __init__(self, size, filesystem, format_command, name, previous): def __init__(self, size, filesystem, format_command, name, previous):
""" """
Args: :param Bytes size: Size of the partition
size (Bytes): Size of the partition :param str filesystem: Filesystem the partition should be formatted with
filesystem (str): Filesystem the partition should be formatted with :param list format_command: Optional format command, valid variables are fs, device_path and size
format_command (list): Optional format command, valid variables are fs, device_path and size :param str name: The name of the partition
name (str): The name of the partition :param BasePartition previous: The partition that preceeds this one
previous (BasePartition): The partition that preceeds this one
""" """
self.name = name self.name = name
super(GPTPartition, self).__init__(size, filesystem, format_command, previous) super(GPTPartition, self).__init__(size, filesystem, format_command, previous)

View file

@ -8,9 +8,8 @@ class GPTSwapPartition(GPTPartition):
def __init__(self, size, previous): def __init__(self, size, previous):
""" """
Args: :param Bytes size: Size of the partition
size (Bytes): Size of the partition :param BasePartition previous: The partition that preceeds this one
previous (BasePartition): The partition that preceeds this one
""" """
super(GPTSwapPartition, self).__init__(size, 'swap', None, 'swap', previous) super(GPTSwapPartition, self).__init__(size, 'swap', None, 'swap', previous)

View file

@ -8,9 +8,8 @@ class MSDOSSwapPartition(MSDOSPartition):
def __init__(self, size, previous): def __init__(self, size, previous):
""" """
Args: :param Bytes size: Size of the partition
size (Bytes): Size of the partition :param BasePartition previous: The partition that preceeds this one
previous (BasePartition): The partition that preceeds this one
""" """
super(MSDOSSwapPartition, self).__init__(size, 'swap', None, previous) super(MSDOSSwapPartition, self).__init__(size, 'swap', None, previous)

View file

@ -8,8 +8,8 @@ class SinglePartition(AbstractPartition):
def get_start(self): def get_start(self):
"""Gets the starting byte of this partition """Gets the starting byte of this partition
Returns: :return: The starting byte of this partition
Bytes. The starting byte of this partition :rtype: Bytes
""" """
from bootstrapvz.common.bytes import Bytes from bootstrapvz.common.bytes import Bytes
# On an unpartitioned volume there is no offset and no previous partition # On an unpartitioned volume there is no offset and no previous partition

View file

@ -14,8 +14,7 @@ class UnformattedPartition(BasePartition):
def __init__(self, size, previous): def __init__(self, size, previous):
""" """
Args: :param Bytes size: Size of the partition
size (Bytes): Size of the partition :param BasePartition previous: The partition that preceeds this one
previous (BasePartition): The partition that preceeds this one
""" """
super(UnformattedPartition, self).__init__(size, None, None, previous) super(UnformattedPartition, self).__init__(size, None, None, previous)

View file

@ -23,8 +23,7 @@ class Volume(FSMProxy):
def __init__(self, partition_map): def __init__(self, partition_map):
""" """
Args: :param PartitionMap partition_map: The partition map for the volume
partition_map (PartitionMap): The partition map for the volume
""" """
# Path to the volume # Path to the volume
self.device_path = None self.device_path = None
@ -50,10 +49,6 @@ class Volume(FSMProxy):
super(Volume, self).__init__(cfg) super(Volume, self).__init__(cfg)
def _after_create(self, e): def _after_create(self, e):
"""
Args:
e (_e_obj): Event object containing arguments to create()
"""
if isinstance(self.partition_map, NoPartitions): if isinstance(self.partition_map, NoPartitions):
# When the volume has no partitions, the virtual root partition # When the volume has no partitions, the virtual root partition
# is essentially created when the volume is created, forward that creation event. # is essentially created when the volume is created, forward that creation event.
@ -62,11 +57,7 @@ class Volume(FSMProxy):
def _check_blocking(self, e): def _check_blocking(self, e):
"""Checks whether the volume is blocked """Checks whether the volume is blocked
Args: :raises VolumeError: When the volume is blocked from being detached
e (_e_obj): Event object containing arguments to create()
Raises:
VolumeError
""" """
# Only the partition map can block the volume # Only the partition map can block the volume
if self.partition_map.is_blocking(): if self.partition_map.is_blocking():
@ -78,16 +69,16 @@ class Volume(FSMProxy):
Mainly it is used to fool grub into thinking that it is working with a real volume, Mainly it is used to fool grub into thinking that it is working with a real volume,
rather than a loopback device or a network block device. rather than a loopback device or a network block device.
Args: :param _e_obj e: Event object containing arguments to create()
e (_e_obj): Event object containing arguments to create() Keyword arguments to link_dm_node() are:
Arguments are:
logical_start_sector (int): The sector the volume should start at in the new volume :param int logical_start_sector: The sector the volume should start at in the new volume
start_sector (int): The offset at which the volume should begin to be mapped in the new volume :param int start_sector: The offset at which the volume should begin to be mapped in the new volume
sectors (int): The number of sectors that should be mapped :param int sectors: The number of sectors that should be mapped
Read more at: http://manpages.debian.org/cgi-bin/man.cgi?query=dmsetup&apropos=0&sektion=0&manpath=Debian+7.0+wheezy&format=html&locale=en Read more at: http://manpages.debian.org/cgi-bin/man.cgi?query=dmsetup&apropos=0&sektion=0&manpath=Debian+7.0+wheezy&format=html&locale=en
Raises: :raises VolumeError: When a free block device cannot be found.
VolumeError
""" """
import os.path import os.path
from bootstrapvz.common.fs import get_partitions from bootstrapvz.common.fs import get_partitions
@ -134,9 +125,6 @@ class Volume(FSMProxy):
def _before_unlink_dm_node(self, e): def _before_unlink_dm_node(self, e):
"""Unlinks the device mapping """Unlinks the device mapping
Args:
e (_e_obj): Event object containing arguments to create()
""" """
log_check_call(['dmsetup', 'remove', self.dm_node_name]) log_check_call(['dmsetup', 'remove', self.dm_node_name])
# Reset the device_path # Reset the device_path

View file

@ -1,6 +1,5 @@
"""This module holds functions and classes responsible for formatting the log output """This module holds functions and classes responsible for formatting the log output
both to a file and to the console. both to a file and to the console.
.. module:: log
""" """
import logging import logging
@ -9,11 +8,9 @@ def get_log_filename(manifest_path):
"""Returns the path to a logfile given a manifest """Returns the path to a logfile given a manifest
The logfile name is constructed from the current timestamp and the basename of the manifest The logfile name is constructed from the current timestamp and the basename of the manifest
Args: :param str manifest_path: The path to the manifest
manifest_path (str): The path to the manifest :return: The path to the logfile
:rtype: str
Returns:
str. The path to the logfile
""" """
import os.path import os.path
from datetime import datetime from datetime import datetime
@ -28,9 +25,8 @@ def get_log_filename(manifest_path):
def setup_logger(logfile=None, debug=False): def setup_logger(logfile=None, debug=False):
"""Sets up the python logger to log to both a file and the console """Sets up the python logger to log to both a file and the console
Args: :param str logfile: Path to a logfile
logfile (str): Path to a logfile :param bool debug: Whether to log debug output to the console
debug (bool): Whether to log debug output to the console
""" """
root = logging.getLogger() root = logging.getLogger()
# Make sure all logging statements are processed by our handlers, they decide the log level # Make sure all logging statements are processed by our handlers, they decide the log level

View file

@ -1,5 +1,4 @@
"""Main module containing all the setup necessary for running the bootstrapping process """Main module containing all the setup necessary for running the bootstrapping process
.. module:: main
""" """
import logging import logging
@ -9,8 +8,7 @@ log = logging.getLogger(__name__)
def main(): def main():
"""Main function for invoking the bootstrap process """Main function for invoking the bootstrap process
Raises: :raises Exception: When the invoking user is not root and --dry-run isn't specified
Exception
""" """
# Get the commandline arguments # Get the commandline arguments
opts = get_opts() opts = get_opts()
@ -58,8 +56,7 @@ Options:
def run(opts): def run(opts):
"""Runs the bootstrapping process """Runs the bootstrapping process
Args: :params dict opts: Dictionary of options from the commandline
opts (dict): Dictionary of options from the commandline
""" """
# Load the manifest # Load the manifest
from manifest import Manifest from manifest import Manifest
@ -97,9 +94,8 @@ def run(opts):
"""counter_task() adds the second argument to the rollback tasklist """counter_task() adds the second argument to the rollback tasklist
if the first argument is present in the list of completed tasks if the first argument is present in the list of completed tasks
Args: :param Task task: The task to look for in the completed tasks list
task (Task): The task to look for in the completed tasks list :param Task counter: The task to add to the rollback tasklist
counter (Task): The task to add to the rollback tasklist
""" """
if task in tasklist.tasks_completed and counter not in tasklist.tasks_completed: if task in tasklist.tasks_completed and counter not in tasklist.tasks_completed:
rollback_tasklist.tasks.add(counter) rollback_tasklist.tasks.add(counter)

View file

@ -1,7 +1,6 @@
"""The Manifest module contains the manifest that providers and plugins use """The Manifest module contains the manifest that providers and plugins use
to determine which tasks should be added to the tasklist, what arguments various to determine which tasks should be added to the tasklist, what arguments various
invocations should have etc.. invocations should have etc..
.. module:: manifest
""" """
from bootstrapvz.common.tools import load_json from bootstrapvz.common.tools import load_json
from bootstrapvz.common.tools import load_yaml from bootstrapvz.common.tools import load_yaml
@ -19,8 +18,7 @@ class Manifest(object):
def __init__(self, path): def __init__(self, path):
"""Initializer: Given a path we load, validate and parse the manifest. """Initializer: Given a path we load, validate and parse the manifest.
Args: :param str path: The path to the manifest
path (str): The path to the manifest
""" """
self.path = path self.path = path
self.load() self.load()
@ -100,9 +98,8 @@ class Manifest(object):
"""This convenience function is passed around to all the validation functions """This convenience function is passed around to all the validation functions
so that they may run a json-schema validation by giving it the data and a path to the schema. so that they may run a json-schema validation by giving it the data and a path to the schema.
Args: :param dict data: Data to validate (normally the manifest data)
data (dict): Data to validate (normally the manifest data) :param str schema_path: Path to the json-schema to use for validation
schema_path (str): Path to the json-schema to use for validation
""" """
import jsonschema import jsonschema
schema = load_json(schema_path) schema = load_json(schema_path)
@ -115,9 +112,9 @@ class Manifest(object):
"""This function is passed to all validation functions so that they may """This function is passed to all validation functions so that they may
raise a validation error because a custom validation of the manifest failed. raise a validation error because a custom validation of the manifest failed.
Args: :param str message: Message to user about the error
message (str): Message to user about the error :param list json_path: A path to the location in the manifest where the error occurred
json_path (list): A path to the location in the manifest where the error occurred :raises ManifestError: With absolute certainty
""" """
from bootstrapvz.common.exceptions import ManifestError from bootstrapvz.common.exceptions import ManifestError
raise ManifestError(message, self.path, json_path) raise ManifestError(message, self.path, json_path)

View file

@ -15,21 +15,21 @@ class Phase(object):
def pos(self): def pos(self):
"""Gets the position of the phase """Gets the position of the phase
Returns: :return: The positional index of the phase in relation to the other phases
int. The positional index of the phase in relation to the other phases :rtype: int
""" """
from bootstrapvz.common.phases import order from bootstrapvz.common.phases import order
return next(i for i, phase in enumerate(order) if phase is self) return next(i for i, phase in enumerate(order) if phase is self)
def __cmp__(self, other): def __cmp__(self, other):
"""Compares the phase order in relation to the other phases """Compares the phase order in relation to the other phases
:return int:
""" """
return self.pos() - other.pos() return self.pos() - other.pos()
def __str__(self): def __str__(self):
"""String representation of the phase, the name suffices """
:return: String representation of the phase
Returns: :rtype: str
string.
""" """
return self.name return self.name

View file

@ -9,17 +9,16 @@ class PackageList(object):
""" """
def __init__(self, name, target): def __init__(self, name, target):
""" """
Args: :param str name: The name of the package
name (str): The name of the package :param str target: The name of the target release
target (str): The name of the target release
""" """
self.name = name self.name = name
self.target = target self.target = target
def __str__(self): def __str__(self):
"""Converts the package into somehting that apt-get install can parse """Converts the package into somehting that apt-get install can parse
Returns:
string. :rtype: str
""" """
if self.target is None: if self.target is None:
return self.name return self.name
@ -31,23 +30,21 @@ class PackageList(object):
""" """
def __init__(self, path): def __init__(self, path):
""" """
Args: :param str path: The path to the local package
path (str): The path to the local package
""" """
self.path = path self.path = path
def __str__(self): def __str__(self):
""" """
Returns: :return: The path to the local package
string. The path to the local package :rtype: string
""" """
return self.path return self.path
def __init__(self, manifest_vars, source_lists): def __init__(self, manifest_vars, source_lists):
""" """
Args: :param dict manifest_vars: The manifest variables
manifest_vars (dict): The manifest variables :param SourceLists source_lists: The sourcelists for apt
source_lists (SourceLists): The sourcelists for apt
""" """
self.manifest_vars = manifest_vars self.manifest_vars = manifest_vars
self.source_lists = source_lists self.source_lists = source_lists
@ -63,12 +60,11 @@ class PackageList(object):
def add(self, name, target=None): def add(self, name, target=None):
"""Adds a package to the install list """Adds a package to the install list
Args: :param str name: The name of the package to install, may contain manifest vars references
name (str): The name of the package to install, may contain manifest vars references :param str target: The name of the target release for the package, may contain manifest vars references
target (str): The name of the target release for the package, may contain manifest vars references
Raises: :raises PackageError: When a package of the same name but with a different target has already been added.
PackageError :raises PackageError: When the specified target release could not be found.
""" """
from exceptions import PackageError from exceptions import PackageError
name = name.format(**self.manifest_vars) name = name.format(**self.manifest_vars)
@ -108,8 +104,7 @@ class PackageList(object):
def add_local(self, package_path): def add_local(self, package_path):
"""Adds a local package to the installation list """Adds a local package to the installation list
Args: :param str package_path: Path to the local package, may contain manifest vars references
package_path (str): Path to the local package, may contain manifest vars references
""" """
package_path = package_path.format(**self.manifest_vars) package_path = package_path.format(**self.manifest_vars)
self.install.append(self.Local(package_path)) self.install.append(self.Local(package_path))

View file

@ -6,8 +6,7 @@ class PreferenceLists(object):
def __init__(self, manifest_vars): def __init__(self, manifest_vars):
""" """
Args: :param dict manifest_vars: The manifest variables
manifest_vars (dict): The manifest variables
""" """
# A dictionary with the name of the file in preferences.d as the key # A dictionary with the name of the file in preferences.d as the key
# That values are lists of Preference objects # That values are lists of Preference objects
@ -18,9 +17,8 @@ class PreferenceLists(object):
def add(self, name, preferences): def add(self, name, preferences):
"""Adds a preference to the apt preferences list """Adds a preference to the apt preferences list
Args: :param str name: Name of the file in preferences.list.d, may contain manifest vars references
name (str): Name of the file in preferences.list.d, may contain manifest vars references :param object preferences: The preferences
preferences (object): The preferences
""" """
name = name.format(**self.manifest_vars) name = name.format(**self.manifest_vars)
self.preferences[name] = [Preference(p) for p in preferences] self.preferences[name] = [Preference(p) for p in preferences]
@ -32,18 +30,13 @@ class Preference(object):
def __init__(self, preference): def __init__(self, preference):
""" """
Args: :param dict preference: A apt preference dictionary
preference (dict): A apt preference dictionary
Raises:
PreferenceError
""" """
self.preference = preference self.preference = preference
def __str__(self): def __str__(self):
"""Convert the object into a preference block """Convert the object into a preference block
Returns: :rtype: str
string.
""" """
return "Package: {package}\nPin: {pin}\nPin-Priority: {pin-priority}\n".format(**self.preference) return "Package: {package}\nPin: {pin}\nPin-Priority: {pin-priority}\n".format(**self.preference)

View file

@ -6,8 +6,7 @@ class SourceLists(object):
def __init__(self, manifest_vars): def __init__(self, manifest_vars):
""" """
Args: :param dict manifest_vars: The manifest variables
manifest_vars (dict): The manifest variables
""" """
# A dictionary with the name of the file in sources.list.d as the key # A dictionary with the name of the file in sources.list.d as the key
# That values are lists of Source objects # That values are lists of Source objects
@ -18,9 +17,8 @@ class SourceLists(object):
def add(self, name, line): def add(self, name, line):
"""Adds a source to the apt sources list """Adds a source to the apt sources list
Args: :param str name: Name of the file in sources.list.d, may contain manifest vars references
name (str): Name of the file in sources.list.d, may contain manifest vars references :param str line: The line for the source file, may contain manifest vars references
line (str): The line for the source file, may contain manifest vars references
""" """
name = name.format(**self.manifest_vars) name = name.format(**self.manifest_vars)
line = line.format(**self.manifest_vars) line = line.format(**self.manifest_vars)
@ -31,11 +29,10 @@ class SourceLists(object):
def target_exists(self, target): def target_exists(self, target):
"""Checks whether the target exists in the sources list """Checks whether the target exists in the sources list
Args: :param str target: Name of the target to check for, may contain manifest vars references
target (str): Name of the target to check for, may contain manifest vars references
Returns: :return: Whether the target exists
bool. Whether the target exists :rtype: bool
""" """
target = target.format(**self.manifest_vars) target = target.format(**self.manifest_vars)
# Run through all the sources and return True if the target exists # Run through all the sources and return True if the target exists
@ -51,11 +48,9 @@ class Source(object):
def __init__(self, line): def __init__(self, line):
""" """
Args: :param str line: A apt source line
line (str): A apt source line
Raises: :raises SourceError: When the source line cannot be parsed
SourceError
""" """
# Parse the source line and populate the class attributes with it # Parse the source line and populate the class attributes with it
# The format is taken from `man sources.list` # The format is taken from `man sources.list`
@ -84,8 +79,7 @@ class Source(object):
"""Convert the object into a source line """Convert the object into a source line
This is pretty much the reverse of what we're doing in the initialization function. This is pretty much the reverse of what we're doing in the initialization function.
Returns: :rtype: str
string.
""" """
options = '' options = ''
if len(self.options) > 0: if len(self.options) > 0:

View file

@ -16,15 +16,14 @@ class Task(object):
""" """
def __repr__(cls): def __repr__(cls):
""" """
Returns: :return str: The full module path to the Task
string.
""" """
return cls.__module__ + '.' + cls.__name__ return cls.__module__ + '.' + cls.__name__
def __str__(cls): def __str__(cls):
""" """
Returns: :return: The full module path to the Task
string. :rtype: str
""" """
return repr(cls) return repr(cls)
@ -32,7 +31,6 @@ class Task(object):
def run(cls, info): def run(cls, info):
"""The run function, all work is done inside this function """The run function, all work is done inside this function
:param info: The bootstrap info object. :param BootstrapInformation info: The bootstrap info object.
:type info: BootstrapInformation
""" """
pass pass

View file

@ -1,5 +1,4 @@
"""The tasklist module contains the TaskList class. """The tasklist module contains the TaskList class.
.. module:: tasklist
""" """
from bootstrapvz.common.exceptions import TaskListError from bootstrapvz.common.exceptions import TaskListError
@ -22,10 +21,9 @@ class TaskList(object):
The function that is called shall accept the taskset as its first argument and the manifest The function that is called shall accept the taskset as its first argument and the manifest
as its second argument. as its second argument.
Args: :param str function: Name of the function to call
function (str): Name of the function to call :param Manifest manifest: The manifest
manifest (Manifest): The manifest :param list *args: Additional arguments that should be passed to the function that is called
\*args: Additional arguments that should be passed to the function that is called
""" """
# Call 'function' on the provider # Call 'function' on the provider
getattr(manifest.modules['provider'], function)(self.tasks, manifest, *args) getattr(manifest.modules['provider'], function)(self.tasks, manifest, *args)
@ -38,9 +36,8 @@ class TaskList(object):
def run(self, info, dry_run=False): def run(self, info, dry_run=False):
"""Converts the taskgraph into a list and runs all tasks in that list """Converts the taskgraph into a list and runs all tasks in that list
Args: :param dict info: The bootstrap information object
info (dict): The bootstrap information object :param bool dry_run: Whether to actually run the tasks or simply step through them
dry_run (bool): Whether to actually run the tasks or simply step through them
""" """
# Create a list for us to run # Create a list for us to run
task_list = self.create_list() task_list = self.create_list()
@ -109,8 +106,8 @@ class TaskList(object):
def get_all_tasks(self): def get_all_tasks(self):
"""Gets a list of all task classes in the package """Gets a list of all task classes in the package
Returns: :return: A list of all tasks in the package
list. A list of all tasks in the package :rtype: list
""" """
# Get a generator that returns all classes in the package # Get a generator that returns all classes in the package
import os.path import os.path
@ -126,15 +123,11 @@ class TaskList(object):
def get_all_classes(self, path=None, prefix=''): def get_all_classes(self, path=None, prefix=''):
""" Given a path to a package, this function retrieves all the classes in it """ Given a path to a package, this function retrieves all the classes in it
Args: :param str path: Path to the package
path (str): Path to the package :param str prefix: Name of the package followed by a dot
prefix (str): Name of the package followed by a dot :return: A generator that yields classes
:rtype: generator
Returns: :raises Exception: If a module cannot be inspected.
generator. A generator that yields classes
Raises:
Exception
""" """
import pkgutil import pkgutil
import importlib import importlib
@ -152,16 +145,14 @@ class TaskList(object):
yield obj yield obj
def check_ordering(self, task): def check_ordering(self, task):
"""Checks the ordering of a task in relation to other tasks and their phases """Checks the ordering of a task in relation to other tasks and their phases.
This function checks for a subset of what the strongly connected components algorithm does, This function checks for a subset of what the strongly connected components algorithm does,
but can deliver a more precise error message, namely that there is a conflict between but can deliver a more precise error message, namely that there is a conflict between
what a task has specified as its predecessors or successors and in which phase it is placed. what a task has specified as its predecessors or successors and in which phase it is placed.
Args: :param Task task: The task to check the ordering for
task (Task): The task to check the ordering for :raises TaskListError: If there is a conflict between task precedence and phase precedence
Raises:
TaskListError
""" """
for successor in task.successors: for successor in task.successors:
# Run through all successors and check whether the phase of the task # Run through all successors and check whether the phase of the task
@ -182,13 +173,12 @@ class TaskList(object):
def strongly_connected_components(self, graph): def strongly_connected_components(self, graph):
"""Find the strongly connected components in a graph using Tarjan's algorithm. """Find the strongly connected components in a graph using Tarjan's algorithm.
Source: http://www.logarithmic.net/pfh-files/blog/01208083168/sort.py Source: http://www.logarithmic.net/pfh-files/blog/01208083168/sort.py
Args: :param dict graph: mapping of tasks to lists of successor tasks
graph (dict): mapping of tasks to lists of successor tasks :return: List of tuples that are strongly connected comoponents
:rtype: list
Returns:
list. List of tuples that are strongly connected comoponents
""" """
result = [] result = []
@ -221,14 +211,13 @@ class TaskList(object):
return result return result
def topological_sort(self, graph): def topological_sort(self, graph):
"""Runs a topological sort on a graph """Runs a topological sort on a graph.
Source: http://www.logarithmic.net/pfh-files/blog/01208083168/sort.py Source: http://www.logarithmic.net/pfh-files/blog/01208083168/sort.py
Args: :param dict graph: mapping of tasks to lists of successor tasks
graph (dict): mapping of tasks to lists of successor tasks :return: A list of all tasks in the graph sorted according to ther dependencies
:rtype: list
Returns:
list. A list of all tasks in the graph sorted according to ther dependencies
""" """
count = {} count = {}
for node in graph: for node in graph: