-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathJSONMaker.py
More file actions
147 lines (116 loc) · 4.84 KB
/
JSONMaker.py
File metadata and controls
147 lines (116 loc) · 4.84 KB
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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
import json
import subprocess
import functions
import os
import sys
class JSONMaker:
"""
A class that deals with makefile functionality.
Methods:
replaceVar(string)
build(rule)
"""
def __init__(self, json_object):
self.__json_object = json_object
if 'Rules' not in json_object:
print >> sys.stderr, "Invalid make file! Please include 'Rules'"
raise IOError
def __replaceVar(self, string):
"""
Takes an input string that represents a variable, and replaces it with it's corresponding value
The variable will usually have a preceding $ char to denote that it is a variable, but this should be dealt with before calling this method.
Arguments:
string: The variable to be replaced
"""
try:
return self.__json_object['Variables'][string]
except KeyError:
print >> sys.stderr, "Invalid JSON Object! Check your variables"
raise KeyError
def __needsToBeBuilt(self, rule):
"""
Checks to see if a rule needs to be built.
This is based on when the rule was last modified compared to it's dependencies.
It is assumed that the rule exists, because that check should have been already made.
Arguments:
rule - String representing the name of the rule
"""
if rule not in self.__json_object['Rules']:
#If this is true, then this base case must be the result of a recursive call
#This is a dependency for some other rule that does exist.
if functions.isFileInDir(rule):
return
else:
print >> stderr, "File not found: " + rule
raise KeyError
thisRule = self.__json_object['Rules'][rule]
time_last_modified = os.path.getmtime(rule)
if 'depends' in thisRule:
for dependency in thisRule['depends']:
#In all of the following cases, it is decided that the rule must be built.
#If none of them are true for all dependencies of a rule, then False is returned.
if not functions.isFileInDir(dependency):
#This means that the dependency does not exist in the directory.
return True
if time_last_modified < os.path.getmtime(dependency):
#This means that a dependency has been modified.
return True
if self.__needsToBeBuilt(dependency):
#Now a recursive check is made for every dependency of this rule
return True
#None of the other cases returned True
return False
def build(self, rule):
"""
Attempts to recursively build from a rule
Arguments:
rule: String representing the name of the rule
"""
thisRule = ""
if functions.isFileInDir(rule):
if rule not in self.__json_object['Rules']:
#There is no rule for this. Nothing needs to be done.
return
else:
if not self.__needsToBeBuilt(rule):
return
try:
thisRule = self.__json_object['Rules'][rule]
except KeyError:
print >> sys.stderr, "Rule not found: " + rule
raise KeyError
if 'depends' in thisRule:
for dependency in thisRule['depends']:
try:
self.build(dependency)
except subprocess.CalledProcessError as e:
raise e
if 'commands' in thisRule:
commands = thisRule['commands']
#Go through every command and run each one separately
for command in commands:
command_to_execute = []
#Replace all variables in the commands string
for word in command.split():
if word[0] == '$':
#send in the word without the preceding '$'
for replacement in self.__replaceVar(word[1:]).split():
command_to_execute.append(replacement)
else:
command_to_execute.append(word)
#Actually execute the commands
try:
print "Executing: " + " ".join(command_to_execute)
self.__execute_command(command_to_execute)
except subprocess.CalledProcessError as e:
raise e
def __execute_command(self, command):
"""
Executes the command given. The command argument should be in list form.
Arguments:
command: The command to be executed.
"""
try:
return subprocess.check_call(command)
except subprocess.CalledProcessError as e:
raise e