1 | from __future__ import ( |
||
0 ignored issues
–
show
|
|||
2 | absolute_import, |
||
3 | division, |
||
4 | print_function |
||
5 | ) |
||
6 | |||
7 | import abc |
||
8 | import json |
||
9 | import logging |
||
10 | |||
11 | import jinja2 |
||
0 ignored issues
–
show
The import
jinja2 could not be resolved.
This can be caused by one of the following: 1. Missing DependenciesThis error could indicate a configuration issue of Pylint. Make sure that your libraries are available by adding the necessary commands. # .scrutinizer.yml
before_commands:
- sudo pip install abc # Python2
- sudo pip3 install abc # Python3
Tip: We are currently not using virtualenv to run pylint, when installing your modules make sure to use
the command for the correct version.
2. Missing __init__.py filesThis error could also result from missing ![]() |
|||
12 | import jinja2.meta |
||
0 ignored issues
–
show
The import
jinja2.meta could not be resolved.
This can be caused by one of the following: 1. Missing DependenciesThis error could indicate a configuration issue of Pylint. Make sure that your libraries are available by adding the necessary commands. # .scrutinizer.yml
before_commands:
- sudo pip install abc # Python2
- sudo pip3 install abc # Python3
Tip: We are currently not using virtualenv to run pylint, when installing your modules make sure to use
the command for the correct version.
2. Missing __init__.py filesThis error could also result from missing ![]() |
|||
13 | |||
14 | from .state_status import StepStateStatus |
||
15 | from .step_results import ( |
||
16 | ActivityStepResult, |
||
17 | TemplatedStepResult, |
||
18 | ) |
||
19 | |||
20 | _LOGGER = logging.getLogger(__name__) |
||
21 | |||
22 | |||
23 | class StepError(StandardError): |
||
0 ignored issues
–
show
This class should have a docstring.
The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods: class SomeClass:
def some_method(self):
"""Do x and return foo."""
If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions. ![]() Comprehensibility
Best Practice
introduced
by
|
|||
24 | pass |
||
25 | |||
26 | |||
27 | class StepDefinitionError(StepError): |
||
0 ignored issues
–
show
This class should have a docstring.
The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods: class SomeClass:
def some_method(self):
"""Do x and return foo."""
If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions. ![]() |
|||
28 | pass |
||
29 | |||
30 | |||
31 | class Step(object): |
||
32 | """Base `Step` in a workflow. |
||
33 | |||
34 | A `Step` is composed of a name and a collection of its requirements. |
||
35 | """ |
||
36 | |||
37 | __slots__ = ('name', 'requires') |
||
38 | __metaclass__ = abc.ABCMeta |
||
39 | |||
40 | def __init__(self, name, requires=()): |
||
41 | self.name = name |
||
42 | self.requires = dict([self._resolve_parent(parent_def) |
||
43 | for parent_def in requires]) |
||
44 | |||
45 | @staticmethod |
||
46 | def _resolve_parent(parent_def): |
||
0 ignored issues
–
show
This method should have a docstring.
The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods: class SomeClass:
def some_method(self):
"""Do x and return foo."""
If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions. ![]() |
|||
47 | |||
48 | if isinstance(parent_def, basestring): |
||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||
49 | return (parent_def, StepStateStatus.completed) |
||
50 | else: |
||
51 | try: |
||
52 | parent_name, status_name = parent_def |
||
53 | return (parent_name, getattr(StepStateStatus, status_name)) |
||
54 | |||
55 | except AttributeError as err: |
||
56 | raise StepDefinitionError('Invalid Step status name: %r' % |
||
0 ignored issues
–
show
|
|||
57 | err.args[0]) |
||
58 | except StandardError: |
||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||
59 | raise StepDefinitionError('Invalid Step definition: %r' % |
||
0 ignored issues
–
show
|
|||
60 | parent_def) |
||
61 | |||
62 | @classmethod |
||
63 | def from_data(cls, step_data, activities): |
||
64 | """Create a new Step object from a step definition""" |
||
65 | # FIXME: pass data through JSONSchema |
||
0 ignored issues
–
show
|
|||
66 | if 'activity' in step_data: |
||
67 | activity_name = step_data['activity'] |
||
68 | activity = activities[activity_name] |
||
69 | |||
70 | step = ActivityStep( |
||
71 | name=step_data['name'], |
||
72 | requires=step_data.get('requires', ()), |
||
73 | activity=activity, |
||
74 | input_template=step_data.get('input', None), |
||
75 | ) |
||
76 | |||
77 | elif 'eval' in step_data: |
||
78 | step = TemplatedStep( |
||
79 | name=step_data['name'], |
||
80 | requires=step_data.get('requires', ()), |
||
81 | eval_block=step_data['eval'], |
||
82 | ) |
||
83 | |||
84 | else: |
||
85 | raise ValueError('Invalid Step data: %r' % step_data) |
||
86 | |||
87 | return step |
||
88 | |||
89 | @abc.abstractmethod |
||
90 | def prepare(self, _context): |
||
91 | """Prepare step's input from context. |
||
92 | |||
93 | :returns: |
||
94 | Step's input |
||
95 | """ |
||
96 | pass |
||
97 | |||
98 | @abc.abstractmethod |
||
99 | def run(self, _step_input): |
||
100 | """Run the step from its input. |
||
101 | |||
102 | :returns: |
||
103 | A StepResult object |
||
104 | """ |
||
105 | pass |
||
106 | |||
107 | @abc.abstractmethod |
||
108 | def render(self, _output): |
||
109 | """Renders the Step's output for usage by other steps. |
||
110 | |||
111 | :returns: |
||
112 | A dictionary of 'key: value' pairs. |
||
113 | """ |
||
114 | pass |
||
115 | |||
116 | def __repr__(self): |
||
117 | return '{ctype}(name={name})'.format(ctype=self.__class__.__name__, |
||
118 | name=self.name) |
||
119 | |||
120 | |||
121 | class ActivityStep(Step): |
||
0 ignored issues
–
show
This class should have a docstring.
The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods: class SomeClass:
def some_method(self):
"""Do x and return foo."""
If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions. ![]() |
|||
122 | |||
123 | __slots__ = ('activity', 'input_template', '__env') |
||
124 | |||
125 | def __init__(self, name, activity, input_template, requires=()): |
||
126 | super(ActivityStep, self).__init__(name, requires) |
||
127 | self.activity = activity |
||
128 | self.input_template = None |
||
129 | |||
130 | # Define the Jinga2 environment |
||
131 | self.__env = jinja2.Environment(finalize=self.__jsonify) |
||
132 | |||
133 | if input_template is not None: |
||
134 | tp_required = self._check_template_dependencies(input_template) |
||
135 | for tp_var in tp_required: |
||
136 | # `__input__` is a "magic" step referencing the workflow input |
||
137 | if tp_var == '__input__': |
||
138 | continue |
||
139 | if tp_var not in self.requires: |
||
140 | raise StepDefinitionError( |
||
0 ignored issues
–
show
|
|||
141 | 'Invalid step %r: Template used %r is not required' % |
||
142 | (self.name, tp_var,) |
||
143 | ) |
||
144 | |||
145 | self.input_template = self.__env.from_string(input_template) |
||
146 | |||
147 | def __jsonify(self, obj): |
||
0 ignored issues
–
show
This method should have a docstring.
The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods: class SomeClass:
def some_method(self):
"""Do x and return foo."""
If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions. ![]() |
|||
148 | # Note: This method is called by Jinja2 to "finalize" its variables. |
||
149 | # Jinja2 also calls it to "finalize" the non-variable chunks |
||
150 | # of a template's string when compiling the template, so we have |
||
151 | # to be careful of extra quoting. |
||
152 | if self.input_template is not None: |
||
153 | # Now that the templates are defined, we can define the "finalize" |
||
154 | # function to JSON dump all template variables. |
||
155 | return json.dumps(obj, indent=4, sort_keys=True) |
||
156 | else: |
||
157 | return obj |
||
158 | |||
159 | def prepare(self, context): |
||
160 | if self.input_template is not None: |
||
161 | activity_input_json = self.input_template.render(context) |
||
162 | # FIXME: We are assuming JSON activity input here |
||
0 ignored issues
–
show
|
|||
163 | try: |
||
164 | activity_input = json.loads(activity_input_json) |
||
165 | except ValueError: |
||
166 | _LOGGER.exception('Invalid template result: %r', |
||
167 | activity_input_json) |
||
168 | raise |
||
169 | else: |
||
170 | activity_input = None |
||
171 | |||
172 | self.activity.check_input(activity_input) |
||
173 | return activity_input |
||
174 | |||
175 | def run(self, step_input): |
||
176 | return ActivityStepResult( |
||
177 | name=self.name, |
||
178 | activity=self.activity, |
||
179 | activity_input=step_input, |
||
180 | ) |
||
181 | |||
182 | def render(self, output): |
||
183 | return self.activity.render_outputs(output) |
||
184 | |||
185 | def _check_template_dependencies(self, input_template): |
||
186 | """Return the list of used external variable in the template. |
||
187 | """ |
||
188 | parsed_template = self.__env.parse(input_template) |
||
189 | return jinja2.meta.find_undeclared_variables(parsed_template) |
||
190 | |||
191 | |||
192 | class TemplatedStep(Step): |
||
0 ignored issues
–
show
This class should have a docstring.
The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods: class SomeClass:
def some_method(self):
"""Do x and return foo."""
If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions. ![]() |
|||
193 | |||
194 | __slots__ = ('eval_block') |
||
195 | |||
196 | def __init__(self, name, eval_block, requires=()): |
||
197 | super(TemplatedStep, self).__init__(name, requires) |
||
198 | self.eval_block = jinja2.Template(eval_block) |
||
199 | |||
0 ignored issues
–
show
|
|||
200 | def prepare(self, context): |
||
201 | return self.eval_block.render(context) |
||
202 | |||
203 | def run(self, _step_input): |
||
204 | return TemplatedStepResult() |
||
205 | |||
206 | def render(self, _output): |
||
207 | # NOTE: Templated steps do not have any usable attributes |
||
208 | return {} |
||
209 |
The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods:
If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions.