1
- '''
2
- Documentation Builder Environments
3
- '''
1
+ """Documentation Builder Environments"""
4
2
5
3
import os
6
4
import re
38
36
39
37
class BuildCommand (BuildCommandResultMixin ):
40
38
41
- ''' Wrap command execution for execution in build environments
39
+ """ Wrap command execution for execution in build environments
42
40
43
41
This wraps subprocess commands with some logic to handle exceptions,
44
42
logging, and setting up the env for the build command.
@@ -57,7 +55,7 @@ class BuildCommand(BuildCommandResultMixin):
57
55
:param build_env: build environment to use to execute commands
58
56
:param bin_path: binary path to add to PATH resolution
59
57
:param description: a more grokable description of the command being run
60
- '''
58
+ """
61
59
62
60
def __init__ (self , command , cwd = None , shell = False , environment = None ,
63
61
combine_output = True , input_data = None , build_env = None ,
@@ -94,12 +92,12 @@ def __str__(self):
94
92
return '\n ' .join ([self .get_command (), output ])
95
93
96
94
def run (self ):
97
- ''' Set up subprocess and execute command
95
+ """ Set up subprocess and execute command
98
96
99
97
:param cmd_input: input to pass to command in STDIN
100
98
:type cmd_input: str
101
99
:param combine_output: combine STDERR into STDOUT
102
- '''
100
+ """
103
101
log .info ("Running: '%s' [%s]" , self .get_command (), self .cwd )
104
102
105
103
self .start_time = datetime .utcnow ()
@@ -159,14 +157,14 @@ def run(self):
159
157
self .end_time = datetime .utcnow ()
160
158
161
159
def get_command (self ):
162
- ''' Flatten command'''
160
+ """ Flatten command"""
163
161
if hasattr (self .command , '__iter__' ) and not isinstance (self .command , str ):
164
162
return ' ' .join (self .command )
165
163
else :
166
164
return self .command
167
165
168
166
def save (self ):
169
- ''' Save this command and result via the API'''
167
+ """ Save this command and result via the API"""
170
168
data = {
171
169
'build' : self .build_env .build .get ('id' ),
172
170
'command' : self .get_command (),
@@ -181,18 +179,18 @@ def save(self):
181
179
182
180
class DockerBuildCommand (BuildCommand ):
183
181
184
- ''' Create a docker container and run a command inside the container
182
+ """ Create a docker container and run a command inside the container
185
183
186
184
Build command to execute in docker container
187
- '''
185
+ """
188
186
189
187
def run (self ):
190
- ''' Execute command in existing Docker container
188
+ """ Execute command in existing Docker container
191
189
192
190
:param cmd_input: input to pass to command in STDIN
193
191
:type cmd_input: str
194
192
:param combine_output: combine STDERR into STDOUT
195
- '''
193
+ """
196
194
log .info ("Running in container %s: '%s' [%s]" ,
197
195
self .build_env .container_id , self .get_command (), self .cwd )
198
196
@@ -310,16 +308,16 @@ def handle_exception(self, exc_type, exc_value, _):
310
308
return True
311
309
312
310
def run (self , * cmd , ** kwargs ):
313
- ''' Shortcut to run command from environment'''
311
+ """ Shortcut to run command from environment"""
314
312
return self .run_command_class (cls = self .command_class , cmd = cmd , ** kwargs )
315
313
316
314
def run_command_class (self , cls , cmd , ** kwargs ):
317
- ''' Run command from this environment
315
+ """ Run command from this environment
318
316
319
317
Use ``cls`` to instantiate a command
320
318
321
319
:param warn_only: Don't raise an exception on command failure
322
- '''
320
+ """
323
321
warn_only = kwargs .pop ('warn_only' , False )
324
322
# Remove PATH from env, and set it to bin_path if it isn't passed in
325
323
env_path = self .environment .pop ('BIN_PATH' , None )
@@ -353,21 +351,21 @@ def run_command_class(self, cls, cmd, **kwargs):
353
351
354
352
@property
355
353
def successful (self ):
356
- ''' Is build completed, without top level failures or failing commands'''
354
+ """ Is build completed, without top level failures or failing commands"""
357
355
return (self .done and self .failure is None and
358
356
all (cmd .successful for cmd in self .commands ))
359
357
360
358
@property
361
359
def failed (self ):
362
- ''' Is build completed, but has top level failure or failing commands'''
360
+ """ Is build completed, but has top level failure or failing commands"""
363
361
return (self .done and (
364
362
self .failure is not None or
365
363
any (cmd .failed for cmd in self .commands )
366
364
))
367
365
368
366
@property
369
367
def done (self ):
370
- ''' Is build in finished state'''
368
+ """ Is build in finished state"""
371
369
return (self .build is not None and
372
370
self .build ['state' ] == BUILD_STATE_FINISHED )
373
371
@@ -429,13 +427,14 @@ def update_build(self, state=None):
429
427
430
428
class LocalEnvironment (BuildEnvironment ):
431
429
432
- '''Local execution environment'''
430
+ """Local execution environment"""
431
+
433
432
command_class = BuildCommand
434
433
435
434
436
435
class DockerEnvironment (BuildEnvironment ):
437
436
438
- '''
437
+ """
439
438
Docker build environment, uses docker to contain builds
440
439
441
440
If :py:data:`settings.DOCKER_ENABLE` is true, build documentation inside a
@@ -447,7 +446,8 @@ class DockerEnvironment(BuildEnvironment):
447
446
data.
448
447
449
448
:param docker_socket: Override to Docker socket URI
450
- '''
449
+ """
450
+
451
451
command_class = DockerBuildCommand
452
452
container_image = DOCKER_IMAGE
453
453
container_mem_limit = DOCKER_LIMITS .get ('memory' )
@@ -471,7 +471,7 @@ def __init__(self, *args, **kwargs):
471
471
self .container_time_limit = self .project .container_time_limit
472
472
473
473
def __enter__ (self ):
474
- ''' Start of environment context'''
474
+ """ Start of environment context"""
475
475
log .info ('Creating container' )
476
476
try :
477
477
# Test for existing container. We remove any stale containers that
@@ -511,7 +511,7 @@ def __enter__(self):
511
511
return self
512
512
513
513
def __exit__ (self , exc_type , exc_value , tb ):
514
- ''' End of environment context'''
514
+ """ End of environment context"""
515
515
ret = self .handle_exception (exc_type , exc_value , tb )
516
516
517
517
# Update buildenv state given any container error states first
@@ -541,7 +541,7 @@ def __exit__(self, exc_type, exc_value, tb):
541
541
return ret
542
542
543
543
def get_client (self ):
544
- ''' Create Docker client connection'''
544
+ """ Create Docker client connection"""
545
545
try :
546
546
if self .client is None :
547
547
self .client = Client (
@@ -561,14 +561,14 @@ def get_client(self):
561
561
562
562
@property
563
563
def container_id (self ):
564
- ''' Return id of container if it is valid'''
564
+ """ Return id of container if it is valid"""
565
565
if self .container_name :
566
566
return self .container_name
567
567
elif self .container :
568
568
return self .container .get ('Id' )
569
569
570
570
def container_state (self ):
571
- ''' Get container state'''
571
+ """ Get container state"""
572
572
client = self .get_client ()
573
573
try :
574
574
info = client .inspect_container (self .container_id )
@@ -577,13 +577,13 @@ def container_state(self):
577
577
return None
578
578
579
579
def update_build_from_container_state (self ):
580
- ''' Update buildenv state from container state
580
+ """ Update buildenv state from container state
581
581
582
582
In the case of the parent command exiting before the exec commands
583
583
finish and the container is destroyed, or in the case of OOM on the
584
584
container, set a failure state and error message explaining the failure
585
585
on the buildenv.
586
- '''
586
+ """
587
587
state = self .container_state ()
588
588
if state is not None and state .get ('Running' ) is False :
589
589
if state .get ('ExitCode' ) == DOCKER_TIMEOUT_EXIT_CODE :
@@ -598,7 +598,7 @@ def update_build_from_container_state(self):
598
598
.format (state .get ('Error' ))))
599
599
600
600
def create_container (self ):
601
- ''' Create docker container'''
601
+ """ Create docker container"""
602
602
client = self .get_client ()
603
603
image = self .container_image
604
604
if self .project .container_image :
0 commit comments