middleman-wizard-template 1.0.0.pre.1 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -4
- data/lib/middleman-wizard-template/template.rb +1 -0
- data/lib/middleman-wizard-template/template/README.tt +25 -0
- data/lib/middleman-wizard-template/template/closure/library/closure/bin/build/closurebuilder.py +256 -0
- data/lib/middleman-wizard-template/template/closure/library/closure/bin/build/depstree.py +189 -0
- data/lib/middleman-wizard-template/template/closure/library/closure/bin/build/depstree.pyc +0 -0
- data/lib/middleman-wizard-template/template/closure/library/closure/bin/build/depstree_test.py +127 -0
- data/lib/middleman-wizard-template/template/closure/library/closure/bin/build/depswriter.py +202 -0
- data/lib/middleman-wizard-template/template/closure/library/closure/bin/build/jscompiler.py +71 -0
- data/lib/middleman-wizard-template/template/closure/library/closure/bin/build/jscompiler.pyc +0 -0
- data/lib/middleman-wizard-template/template/closure/library/closure/bin/build/source.py +114 -0
- data/lib/middleman-wizard-template/template/closure/library/closure/bin/build/source.pyc +0 -0
- data/lib/middleman-wizard-template/template/closure/library/closure/bin/build/source_test.py +121 -0
- data/lib/middleman-wizard-template/template/closure/library/closure/bin/build/treescan.py +78 -0
- data/lib/middleman-wizard-template/template/closure/library/closure/bin/build/treescan.pyc +0 -0
- data/lib/middleman-wizard-template/template/config.tt +66 -0
- data/lib/middleman-wizard-template/template/shared/Gemfile.tt +2 -1
- data/lib/middleman-wizard-template/template/source/javascripts/app.js +3 -5
- data/lib/middleman-wizard-template/version.rb +1 -1
- metadata +21 -6
- data/lib/middleman-wizard-template/template/source/javascripts/_lib/asset_loader.js +0 -492
Binary file
|
data/lib/middleman-wizard-template/template/closure/library/closure/bin/build/depstree_test.py
ADDED
@@ -0,0 +1,127 @@
|
|
1
|
+
#!/usr/bin/env python
|
2
|
+
#
|
3
|
+
# Copyright 2009 The Closure Library Authors. All Rights Reserved.
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS-IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
|
17
|
+
|
18
|
+
"""Unit test for depstree."""
|
19
|
+
|
20
|
+
__author__ = 'nnaze@google.com (Nathan Naze)'
|
21
|
+
|
22
|
+
|
23
|
+
import unittest
|
24
|
+
|
25
|
+
import depstree
|
26
|
+
|
27
|
+
|
28
|
+
def _GetProvides(sources):
|
29
|
+
"""Get all namespaces provided by a collection of sources."""
|
30
|
+
|
31
|
+
provides = set()
|
32
|
+
for source in sources:
|
33
|
+
provides.update(source.provides)
|
34
|
+
return provides
|
35
|
+
|
36
|
+
|
37
|
+
class MockSource(object):
|
38
|
+
"""Mock Source file."""
|
39
|
+
|
40
|
+
def __init__(self, provides, requires):
|
41
|
+
self.provides = set(provides)
|
42
|
+
self.requires = set(requires)
|
43
|
+
|
44
|
+
def __repr__(self):
|
45
|
+
return 'MockSource %s' % self.provides
|
46
|
+
|
47
|
+
|
48
|
+
class DepsTreeTestCase(unittest.TestCase):
|
49
|
+
"""Unit test for DepsTree. Tests several common situations and errors."""
|
50
|
+
|
51
|
+
def AssertValidDependencies(self, deps_list):
|
52
|
+
"""Validates a dependency list.
|
53
|
+
|
54
|
+
Asserts that a dependency list is valid: For every source in the list,
|
55
|
+
ensure that every require is provided by a source earlier in the list.
|
56
|
+
|
57
|
+
Args:
|
58
|
+
deps_list: A list of sources that should be in dependency order.
|
59
|
+
"""
|
60
|
+
|
61
|
+
for i in range(len(deps_list)):
|
62
|
+
source = deps_list[i]
|
63
|
+
previous_provides = _GetProvides(deps_list[:i])
|
64
|
+
for require in source.requires:
|
65
|
+
self.assertTrue(
|
66
|
+
require in previous_provides,
|
67
|
+
'Namespace "%s" not provided before required by %s' % (
|
68
|
+
require, source))
|
69
|
+
|
70
|
+
def testSimpleDepsTree(self):
|
71
|
+
a = MockSource(['A'], ['B', 'C'])
|
72
|
+
b = MockSource(['B'], [])
|
73
|
+
c = MockSource(['C'], ['D'])
|
74
|
+
d = MockSource(['D'], ['E'])
|
75
|
+
e = MockSource(['E'], [])
|
76
|
+
|
77
|
+
tree = depstree.DepsTree([a, b, c, d, e])
|
78
|
+
|
79
|
+
self.AssertValidDependencies(tree.GetDependencies('A'))
|
80
|
+
self.AssertValidDependencies(tree.GetDependencies('B'))
|
81
|
+
self.AssertValidDependencies(tree.GetDependencies('C'))
|
82
|
+
self.AssertValidDependencies(tree.GetDependencies('D'))
|
83
|
+
self.AssertValidDependencies(tree.GetDependencies('E'))
|
84
|
+
|
85
|
+
def testCircularDependency(self):
|
86
|
+
# Circular deps
|
87
|
+
a = MockSource(['A'], ['B'])
|
88
|
+
b = MockSource(['B'], ['C'])
|
89
|
+
c = MockSource(['C'], ['A'])
|
90
|
+
|
91
|
+
tree = depstree.DepsTree([a, b, c])
|
92
|
+
|
93
|
+
self.assertRaises(depstree.CircularDependencyError,
|
94
|
+
tree.GetDependencies, 'A')
|
95
|
+
|
96
|
+
def testRequiresUndefinedNamespace(self):
|
97
|
+
a = MockSource(['A'], ['B'])
|
98
|
+
b = MockSource(['B'], ['C'])
|
99
|
+
c = MockSource(['C'], ['D']) # But there is no D.
|
100
|
+
|
101
|
+
def MakeDepsTree():
|
102
|
+
return depstree.DepsTree([a, b, c])
|
103
|
+
|
104
|
+
self.assertRaises(depstree.NamespaceNotFoundError, MakeDepsTree)
|
105
|
+
|
106
|
+
def testDepsForMissingNamespace(self):
|
107
|
+
a = MockSource(['A'], ['B'])
|
108
|
+
b = MockSource(['B'], [])
|
109
|
+
|
110
|
+
tree = depstree.DepsTree([a, b])
|
111
|
+
|
112
|
+
# There is no C.
|
113
|
+
self.assertRaises(depstree.NamespaceNotFoundError,
|
114
|
+
tree.GetDependencies, 'C')
|
115
|
+
|
116
|
+
def testMultipleRequires(self):
|
117
|
+
a = MockSource(['A'], ['B'])
|
118
|
+
b = MockSource(['B'], ['C'])
|
119
|
+
c = MockSource(['C'], [])
|
120
|
+
d = MockSource(['D'], ['B'])
|
121
|
+
|
122
|
+
tree = depstree.DepsTree([a, b, c, d])
|
123
|
+
self.AssertValidDependencies(tree.GetDependencies(['D', 'A']))
|
124
|
+
|
125
|
+
|
126
|
+
if __name__ == '__main__':
|
127
|
+
unittest.main()
|
@@ -0,0 +1,202 @@
|
|
1
|
+
#!/usr/bin/env python
|
2
|
+
#
|
3
|
+
# Copyright 2009 The Closure Library Authors. All Rights Reserved.
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS-IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
|
17
|
+
|
18
|
+
"""Generates out a Closure deps.js file given a list of JavaScript sources.
|
19
|
+
|
20
|
+
Paths can be specified as arguments or (more commonly) specifying trees
|
21
|
+
with the flags (call with --help for descriptions).
|
22
|
+
|
23
|
+
Usage: depswriter.py [path/to/js1.js [path/to/js2.js] ...]
|
24
|
+
"""
|
25
|
+
|
26
|
+
import logging
|
27
|
+
import optparse
|
28
|
+
import os
|
29
|
+
import posixpath
|
30
|
+
import shlex
|
31
|
+
import sys
|
32
|
+
|
33
|
+
import source
|
34
|
+
import treescan
|
35
|
+
|
36
|
+
|
37
|
+
__author__ = 'nnaze@google.com (Nathan Naze)'
|
38
|
+
|
39
|
+
|
40
|
+
def MakeDepsFile(source_map):
|
41
|
+
"""Make a generated deps file.
|
42
|
+
|
43
|
+
Args:
|
44
|
+
source_map: A dict map of the source path to source.Source object.
|
45
|
+
|
46
|
+
Returns:
|
47
|
+
str, A generated deps file source.
|
48
|
+
"""
|
49
|
+
|
50
|
+
# Write in path alphabetical order
|
51
|
+
paths = sorted(source_map.keys())
|
52
|
+
|
53
|
+
lines = []
|
54
|
+
|
55
|
+
for path in paths:
|
56
|
+
js_source = source_map[path]
|
57
|
+
|
58
|
+
# We don't need to add entries that don't provide anything.
|
59
|
+
if js_source.provides:
|
60
|
+
lines.append(_GetDepsLine(path, js_source))
|
61
|
+
|
62
|
+
return ''.join(lines)
|
63
|
+
|
64
|
+
|
65
|
+
def _GetDepsLine(path, js_source):
|
66
|
+
"""Get a deps.js file string for a source."""
|
67
|
+
|
68
|
+
provides = sorted(js_source.provides)
|
69
|
+
requires = sorted(js_source.requires)
|
70
|
+
|
71
|
+
return 'goog.addDependency(\'%s\', %s, %s);\n' % (path, provides, requires)
|
72
|
+
|
73
|
+
|
74
|
+
def _GetOptionsParser():
|
75
|
+
"""Get the options parser."""
|
76
|
+
|
77
|
+
parser = optparse.OptionParser(__doc__)
|
78
|
+
|
79
|
+
parser.add_option('--output_file',
|
80
|
+
dest='output_file',
|
81
|
+
action='store',
|
82
|
+
help=('If specified, write output to this path instead of '
|
83
|
+
'writing to standard output.'))
|
84
|
+
parser.add_option('--root',
|
85
|
+
dest='roots',
|
86
|
+
default=[],
|
87
|
+
action='append',
|
88
|
+
help='A root directory to scan for JS source files. '
|
89
|
+
'Paths of JS files in generated deps file will be '
|
90
|
+
'relative to this path. This flag may be specified '
|
91
|
+
'multiple times.')
|
92
|
+
parser.add_option('--root_with_prefix',
|
93
|
+
dest='roots_with_prefix',
|
94
|
+
default=[],
|
95
|
+
action='append',
|
96
|
+
help='A root directory to scan for JS source files, plus '
|
97
|
+
'a prefix (if either contains a space, surround with '
|
98
|
+
'quotes). Paths in generated deps file will be relative '
|
99
|
+
'to the root, but preceded by the prefix. This flag '
|
100
|
+
'may be specified multiple times.')
|
101
|
+
parser.add_option('--path_with_depspath',
|
102
|
+
dest='paths_with_depspath',
|
103
|
+
default=[],
|
104
|
+
action='append',
|
105
|
+
help='A path to a source file and an alternate path to '
|
106
|
+
'the file in the generated deps file (if either contains '
|
107
|
+
'a space, surround with whitespace). This flag may be '
|
108
|
+
'specified multiple times.')
|
109
|
+
return parser
|
110
|
+
|
111
|
+
|
112
|
+
def _NormalizePathSeparators(path):
|
113
|
+
"""Replaces OS-specific path separators with POSIX-style slashes.
|
114
|
+
|
115
|
+
Args:
|
116
|
+
path: str, A file path.
|
117
|
+
|
118
|
+
Returns:
|
119
|
+
str, The path with any OS-specific path separators (such as backslash on
|
120
|
+
Windows) replaced with URL-compatible forward slashes. A no-op on systems
|
121
|
+
that use POSIX paths.
|
122
|
+
"""
|
123
|
+
return path.replace(os.sep, posixpath.sep)
|
124
|
+
|
125
|
+
|
126
|
+
def _GetRelativePathToSourceDict(root, prefix=''):
|
127
|
+
"""Scans a top root directory for .js sources.
|
128
|
+
|
129
|
+
Args:
|
130
|
+
root: str, Root directory.
|
131
|
+
prefix: str, Prefix for returned paths.
|
132
|
+
|
133
|
+
Returns:
|
134
|
+
dict, A map of relative paths (with prefix, if given), to source.Source
|
135
|
+
objects.
|
136
|
+
"""
|
137
|
+
# Remember and restore the cwd when we're done. We work from the root so
|
138
|
+
# that paths are relative from the root.
|
139
|
+
start_wd = os.getcwd()
|
140
|
+
os.chdir(root)
|
141
|
+
|
142
|
+
path_to_source = {}
|
143
|
+
for path in treescan.ScanTreeForJsFiles('.'):
|
144
|
+
prefixed_path = _NormalizePathSeparators(os.path.join(prefix, path))
|
145
|
+
path_to_source[prefixed_path] = source.Source(source.GetFileContents(path))
|
146
|
+
|
147
|
+
os.chdir(start_wd)
|
148
|
+
|
149
|
+
return path_to_source
|
150
|
+
|
151
|
+
|
152
|
+
def _GetPair(s):
|
153
|
+
"""Return a string as a shell-parsed tuple. Two values expected."""
|
154
|
+
try:
|
155
|
+
# shlex uses '\' as an escape character, so they must be escaped.
|
156
|
+
s = s.replace('\\', '\\\\')
|
157
|
+
first, second = shlex.split(s)
|
158
|
+
return (first, second)
|
159
|
+
except:
|
160
|
+
raise Exception('Unable to parse input line as a pair: %s' % s)
|
161
|
+
|
162
|
+
|
163
|
+
def main():
|
164
|
+
"""CLI frontend to MakeDepsFile."""
|
165
|
+
logging.basicConfig(format=(sys.argv[0] + ': %(message)s'),
|
166
|
+
level=logging.INFO)
|
167
|
+
options, args = _GetOptionsParser().parse_args()
|
168
|
+
|
169
|
+
path_to_source = {}
|
170
|
+
|
171
|
+
# Roots without prefixes
|
172
|
+
for root in options.roots:
|
173
|
+
path_to_source.update(_GetRelativePathToSourceDict(root))
|
174
|
+
|
175
|
+
# Roots with prefixes
|
176
|
+
for root_and_prefix in options.roots_with_prefix:
|
177
|
+
root, prefix = _GetPair(root_and_prefix)
|
178
|
+
path_to_source.update(_GetRelativePathToSourceDict(root, prefix=prefix))
|
179
|
+
|
180
|
+
# Source paths
|
181
|
+
for path in args:
|
182
|
+
path_to_source[path] = source.Source(source.GetFileContents(path))
|
183
|
+
|
184
|
+
# Source paths with alternate deps paths
|
185
|
+
for path_with_depspath in options.paths_with_depspath:
|
186
|
+
srcpath, depspath = _GetPair(path_with_depspath)
|
187
|
+
path_to_source[depspath] = source.Source(source.GetFileContents(srcpath))
|
188
|
+
|
189
|
+
# Make our output pipe.
|
190
|
+
if options.output_file:
|
191
|
+
out = open(options.output_file, 'w')
|
192
|
+
else:
|
193
|
+
out = sys.stdout
|
194
|
+
|
195
|
+
out.write('// This file was autogenerated by %s.\n' % sys.argv[0])
|
196
|
+
out.write('// Please do not edit.\n')
|
197
|
+
|
198
|
+
out.write(MakeDepsFile(path_to_source))
|
199
|
+
|
200
|
+
|
201
|
+
if __name__ == '__main__':
|
202
|
+
main()
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# Copyright 2010 The Closure Library Authors. All Rights Reserved.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS-IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
"""Utility to use the Closure Compiler CLI from Python."""
|
16
|
+
|
17
|
+
import distutils.version
|
18
|
+
import logging
|
19
|
+
import re
|
20
|
+
import subprocess
|
21
|
+
|
22
|
+
|
23
|
+
# Pulls a version number from the first line of 'java -version'
|
24
|
+
# See http://java.sun.com/j2se/versioning_naming.html to learn more about the
|
25
|
+
# command's output format.
|
26
|
+
_VERSION_REGEX = re.compile('"([0-9][.0-9]*)')
|
27
|
+
|
28
|
+
|
29
|
+
def _GetJavaVersion():
|
30
|
+
"""Returns the string for the current version of Java installed."""
|
31
|
+
proc = subprocess.Popen(['java', '-version'], stderr=subprocess.PIPE)
|
32
|
+
unused_stdoutdata, stderrdata = proc.communicate()
|
33
|
+
version_line = stderrdata.splitlines()[0]
|
34
|
+
return _VERSION_REGEX.search(version_line).group(1)
|
35
|
+
|
36
|
+
|
37
|
+
def Compile(compiler_jar_path, source_paths, flags=None):
|
38
|
+
"""Prepares command-line call to Closure Compiler.
|
39
|
+
|
40
|
+
Args:
|
41
|
+
compiler_jar_path: Path to the Closure compiler .jar file.
|
42
|
+
source_paths: Source paths to build, in order.
|
43
|
+
flags: A list of additional flags to pass on to Closure Compiler.
|
44
|
+
|
45
|
+
Returns:
|
46
|
+
The compiled source, as a string, or None if compilation failed.
|
47
|
+
"""
|
48
|
+
|
49
|
+
# User friendly version check.
|
50
|
+
if not (distutils.version.LooseVersion(_GetJavaVersion()) >=
|
51
|
+
distutils.version.LooseVersion('1.6')):
|
52
|
+
logging.error('Closure Compiler requires Java 1.6 or higher. '
|
53
|
+
'Please visit http://www.java.com/getjava')
|
54
|
+
return
|
55
|
+
|
56
|
+
args = ['java', '-jar', compiler_jar_path]
|
57
|
+
for path in source_paths:
|
58
|
+
args += ['--js', path]
|
59
|
+
|
60
|
+
if flags:
|
61
|
+
args += flags
|
62
|
+
|
63
|
+
logging.info('Compiling with the following command: %s', ' '.join(args))
|
64
|
+
|
65
|
+
proc = subprocess.Popen(args, stdout=subprocess.PIPE)
|
66
|
+
stdoutdata, unused_stderrdata = proc.communicate()
|
67
|
+
|
68
|
+
if proc.returncode != 0:
|
69
|
+
return
|
70
|
+
|
71
|
+
return stdoutdata
|
Binary file
|
@@ -0,0 +1,114 @@
|
|
1
|
+
# Copyright 2009 The Closure Library Authors. All Rights Reserved.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS-IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
|
16
|
+
"""Scans a source JS file for its provided and required namespaces.
|
17
|
+
|
18
|
+
Simple class to scan a JavaScript file and express its dependencies.
|
19
|
+
"""
|
20
|
+
|
21
|
+
__author__ = 'nnaze@google.com'
|
22
|
+
|
23
|
+
|
24
|
+
import re
|
25
|
+
|
26
|
+
_BASE_REGEX_STRING = '^\s*goog\.%s\(\s*[\'"](.+)[\'"]\s*\)'
|
27
|
+
_PROVIDE_REGEX = re.compile(_BASE_REGEX_STRING % 'provide')
|
28
|
+
_REQUIRES_REGEX = re.compile(_BASE_REGEX_STRING % 'require')
|
29
|
+
|
30
|
+
# This line identifies base.js and should match the line in that file.
|
31
|
+
_GOOG_BASE_LINE = (
|
32
|
+
'var goog = goog || {}; // Identifies this file as the Closure base.')
|
33
|
+
|
34
|
+
|
35
|
+
class Source(object):
|
36
|
+
"""Scans a JavaScript source for its provided and required namespaces."""
|
37
|
+
|
38
|
+
# Matches a "/* ... */" comment.
|
39
|
+
# Note: We can't definitively distinguish a "/*" in a string literal without a
|
40
|
+
# state machine tokenizer. We'll assume that a line starting with whitespace
|
41
|
+
# and "/*" is a comment.
|
42
|
+
_COMMENT_REGEX = re.compile(
|
43
|
+
r"""
|
44
|
+
^\s* # Start of a new line and whitespace
|
45
|
+
/\* # Opening "/*"
|
46
|
+
.*? # Non greedy match of any characters (including newlines)
|
47
|
+
\*/ # Closing "*/""",
|
48
|
+
re.MULTILINE | re.DOTALL | re.VERBOSE)
|
49
|
+
|
50
|
+
def __init__(self, source):
|
51
|
+
"""Initialize a source.
|
52
|
+
|
53
|
+
Args:
|
54
|
+
source: str, The JavaScript source.
|
55
|
+
"""
|
56
|
+
|
57
|
+
self.provides = set()
|
58
|
+
self.requires = set()
|
59
|
+
|
60
|
+
self._source = source
|
61
|
+
self._ScanSource()
|
62
|
+
|
63
|
+
def __str__(self):
|
64
|
+
return 'Source %s' % self._path
|
65
|
+
|
66
|
+
def GetSource(self):
|
67
|
+
"""Get the source as a string."""
|
68
|
+
return self._source
|
69
|
+
|
70
|
+
@classmethod
|
71
|
+
def _StripComments(cls, source):
|
72
|
+
return cls._COMMENT_REGEX.sub('', source)
|
73
|
+
|
74
|
+
def _ScanSource(self):
|
75
|
+
"""Fill in provides and requires by scanning the source."""
|
76
|
+
|
77
|
+
source = self._StripComments(self.GetSource())
|
78
|
+
|
79
|
+
source_lines = source.splitlines()
|
80
|
+
for line in source_lines:
|
81
|
+
match = _PROVIDE_REGEX.match(line)
|
82
|
+
if match:
|
83
|
+
self.provides.add(match.group(1))
|
84
|
+
match = _REQUIRES_REGEX.match(line)
|
85
|
+
if match:
|
86
|
+
self.requires.add(match.group(1))
|
87
|
+
|
88
|
+
# Closure's base file implicitly provides 'goog'.
|
89
|
+
for line in source_lines:
|
90
|
+
if line == _GOOG_BASE_LINE:
|
91
|
+
if len(self.provides) or len(self.requires):
|
92
|
+
raise Exception(
|
93
|
+
'Base files should not provide or require namespaces.')
|
94
|
+
self.provides.add('goog')
|
95
|
+
|
96
|
+
|
97
|
+
def GetFileContents(path):
|
98
|
+
"""Get a file's contents as a string.
|
99
|
+
|
100
|
+
Args:
|
101
|
+
path: str, Path to file.
|
102
|
+
|
103
|
+
Returns:
|
104
|
+
str, Contents of file.
|
105
|
+
|
106
|
+
Raises:
|
107
|
+
IOError: An error occurred opening or reading the file.
|
108
|
+
|
109
|
+
"""
|
110
|
+
fileobj = open(path)
|
111
|
+
try:
|
112
|
+
return fileobj.read()
|
113
|
+
finally:
|
114
|
+
fileobj.close()
|