middleman-wizard-template 1.0.0.pre.1 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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()
|