Completed
Push — master ( 79ee92...bc9c0f )
by Klaus
01:06
created

sacred.ForceOption   A

Complexity

Total Complexity 1

Size/Duplication

Total Lines 7
Duplicated Lines 0 %
Metric Value
dl 0
loc 7
rs 10
wmc 1

1 Method

Rating   Name   Duplication   Size   Complexity  
A apply() 0 4 1
1
#!/usr/bin/env python
2
# coding=utf-8
3
"""
4
This module provides the basis for all command-line options (flags) in sacred.
5
6
It defines the base class CommandLineOption and the standard supported flags.
7
Some further options that add observers to the run are defined alongside those.
8
"""
9
10
from __future__ import division, print_function, unicode_literals
11
from sacred.utils import convert_camel_case_to_snake_case, get_inheritors
12
13
14
class CommandLineOption(object):
15
    """
16
    Base class for all command-line options.
17
18
    To implement a new command-line option just inherit from this class.
19
    Then add the `flag` class-attribute to specify the name and a class
20
    docstring with the description.
21
    If your command-line option should take an argument you must also provide
22
    its name via the `arg` class attribute and its description as
23
    `arg_description`.
24
    Finally you need to implement the `execute` classmethod. It receives the
25
    value of the argument (if applicable) and the current run. You can modify
26
    the run object in any way.
27
    """
28
29
    short_flag = None
30
    """ The (one-letter) short form (defaults to first letter of flag) """
31
32
    arg = None
33
    """ Name of the argument (optional) """
34
35
    arg_description = None
36
    """ Description of the argument (optional) """
37
38
    @classmethod
39
    def get_flag(cls):
40
        """
41
        Return the short and the long version of this option.
42
43
        The long flag (e.g. 'foo_bar'; used on the command-line like this:
44
        --foo_bar[=ARGS]) is derived from the class-name by stripping away any
45
        -Option suffix and converting the rest to snake_case.
46
47
        The short flag (e.g. 'f'; used on the command-line like this:
48
        -f [ARGS]) the short_flag class-member if that is set, or the first
49
        letter of the long flag otherwise.
50
51
        :return: tuple of short-flag, and long-flag
52
        :rtype: (str, str)
53
        """
54
        # Get the flag name from the class name
55
        flag = cls.__name__
56
        if flag.endswith("Option"):
57
            flag = flag[:-6]
58
        flag = convert_camel_case_to_snake_case(flag)
59
60
        if cls.short_flag is None:
61
            return flag[:1], flag
62
        else:
63
            return cls.short_flag, flag
64
65
    @classmethod
66
    def apply(cls, args, run):
67
        """
68
        Modify the current Run base on this command-line option.
69
70
        This function is executed after contstructing the Run object, but
71
        before actually starting it.
72
        :param args: If this command-line option accepts an argument this will
73
                     be value of that argument if set or None.
74
                     Otherwise it is either True or False.
75
        :type args: bool | str
76
        :param run: The current run to be modified
77
        :type run: sacred.run.Run
78
        """
79
        pass
80
81
82
def gather_command_line_options():
83
    """Get a sorted list of all CommandLineOption subclasses."""
84
    return sorted(get_inheritors(CommandLineOption), key=lambda x: x.__name__)
85
86
87
class HelpOption(CommandLineOption):
88
    """Print this help message and exit."""
89
90
91
class DebugOption(CommandLineOption):
92
    """
93
    Suppress warnings about missing observers and don't filter the stacktrace.
94
95
    Also enables usage with ipython --pdb.
96
    """
97
98
    @classmethod
99
    def apply(cls, args, run):
100
        """Set this run to debug mode."""
101
        run.debug = True
102
103
104
class PDBOption(CommandLineOption):
105
    """Automatically enter post-mortem debugging with pdb on failure."""
106
107
    short_flag = 'D'
108
109
    @classmethod
110
    def apply(cls, args, run):
111
        run.pdb = True
112
113
114
class LoglevelOption(CommandLineOption):
115
    """Adjust the loglevel."""
116
117
    arg = 'LEVEL'
118
    arg_description = 'Loglevel either as 0 - 50 or as string: DEBUG(10), ' \
119
                      'INFO(20), WARNING(30), ERROR(40), CRITICAL(50)'
120
121
    @classmethod
122
    def apply(cls, args, run):
123
        """Adjust the loglevel of the root-logger of this run."""
124
        try:
125
            lvl = int(args)
126
        except ValueError:
127
            lvl = args
128
        run.root_logger.setLevel(lvl)
129
130
131
class CommentOption(CommandLineOption):
132
    """Adds a message to the run."""
133
134
    arg = 'COMMENT'
135
    arg_description = 'A comment that should be stored along with the run.'
136
137
    @classmethod
138
    def apply(cls, args, run):
139
        """Add a comment to this run."""
140
        run.comment = args
141
142
143
class BeatIntervalOption(CommandLineOption):
144
    """Control the rate of heartbeat events."""
145
146
    arg = 'BEAT_INTERVAL'
147
    arg_description = "Time between two heartbeat events measured in seconds."
148
149
    @classmethod
150
    def apply(cls, args, run):
151
        """Set the heart-beat interval for this run."""
152
        run.beat_interval = float(args)
153
154
155
class UnobservedOption(CommandLineOption):
156
    """Ignore all observers for this run."""
157
158
    @classmethod
159
    def apply(cls, args, run):
160
        """Set this run to unobserved mode."""
161
        run.unobserved = True
162
163
164
class ForceOption(CommandLineOption):
165
    """Disable warnings about suspicious changes for this run."""
166
167
    @classmethod
168
    def apply(cls, args, run):
169
        """Set this run to not warn about suspicous changes."""
170
        run.force = True
171