I recently gave running SCons under PyPy a shot. It actually worked,
except for running out of file descriptors due to the GC not closing
things immediately.
I went through and added some explicit close calls (actually, mostly
'with's) and then it worked fine. It looks like you actually picked up
most of them (probably all the important ones) in 8716da8, but in case
you wanted, I thought I'd send a patch with a few more. (We're using
2.5.0, and I'm not sure if the commit cited above landed in time for .1
or after that.)
I don't know if the remainder matter though, or in the case of the MD5
change, if it's in code that's even called. (Though if it is called, it
may well matter.) I just did a search for 'open' and made replacements
for ones where it looked easy to do and I didn't have to think too hard. :-)
Evan
P.S. On scons.org, Development -> Development, the "Developer's
Guidelines" link is broken.
P.P.S. The FAQ still has the question "why is SCons written for Python 2.4"
Index: Debug.py
===================================================================
--- Debug.py (revision 137834)
+++ Debug.py (working copy)
@@ -72,57 +72,58 @@
file.write("%s: %d\n" % (classname, len(tracked_classes[classname])))
def listLoggedInstances(classes, file=sys.stdout):
for classname in string_to_classes(classes):
file.write('\n%s:\n' % classname)
for ref in tracked_classes[classname]:
if inspect.isclass(ref):
obj = ref()
else:
obj = ref
if obj is not None:
file.write(' %s\n' % repr(obj))
def dumpLoggedInstances(classes, file=sys.stdout):
for classname in string_to_classes(classes):
file.write('\n%s:\n' % classname)
for ref in tracked_classes[classname]:
obj = ref()
if obj is not None:
file.write(' %s:\n' % obj)
for key, value in obj.__dict__.items():
file.write(' %20s : %s\n' % (key, value))
if sys.platform[:5] == "linux":
# Linux doesn't actually support memory usage stats from getrusage().
def memory():
- mstr = open('/proc/self/stat').read()
+ with open('/proc/self/stat') as f:
+ mstr = f.read()
mstr = mstr.split()[22]
return int(mstr)
elif sys.platform[:6] == 'darwin':
#TODO really get memory stats for OS X
def memory():
return 0
else:
try:
import resource
except ImportError:
try:
import win32process
import win32api
except ImportError:
def memory():
return 0
else:
def memory():
process_handle = win32api.GetCurrentProcess()
memory_info = win32process.GetProcessMemoryInfo( process_handle )
return memory_info['PeakWorkingSetSize']
else:
def memory():
res = resource.getrusage(resource.RUSAGE_SELF)
return res[4]
# returns caller's stack
def caller_stack():
@@ -208,34 +209,35 @@
def Trace(msg, file=None, mode='w', tstamp=None):
"""Write a trace message to a file. Whenever a file is specified,
it becomes the default for the next call to Trace()."""
global TraceDefault
global TimeStampDefault
global PreviousTime
if file is None:
file = TraceDefault
else:
TraceDefault = file
if tstamp is None:
tstamp = TimeStampDefault
else:
TimeStampDefault = tstamp
try:
fp = TraceFP[file]
except KeyError:
try:
fp = TraceFP[file] = open(file, mode)
except TypeError:
# Assume we were passed an open file pointer.
fp = file
if tstamp:
now = time.time()
fp.write('%8.4f %8.4f: ' % (now - StartTime, now - PreviousTime))
PreviousTime = now
fp.write(msg)
fp.flush()
+ fp.close()
# Local Variables:
# tab-width:4
# indent-tabs-mode:nil
# End:
# vim: set expandtab tabstop=4 shiftwidth=4:
Index: Tool/linkloc.py
===================================================================
--- Tool/linkloc.py (revision 137834)
+++ Tool/linkloc.py (working copy)
@@ -27,58 +27,58 @@
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
__revision__ = "src/engine/SCons/Tool/linkloc.py rel_2.5.0:3543:937e55cd78f7 2016/04/09 11:29:54 bdbaddog"
import os.path
import re
import SCons.Action
import SCons.Defaults
import SCons.Errors
import SCons.Tool
import SCons.Util
from SCons.Tool.MSCommon import msvs_exists, merge_default_version
from SCons.Tool.PharLapCommon import addPharLapPaths
_re_linker_command = re.compile(r'(\s)@\s*([^\s]+)')
def repl_linker_command(m):
# Replaces any linker command file directives (e.g. "@foo.lnk") with
# the actual contents of the file.
try:
- f=open(m.group(2), "r")
- return m.group(1) + f.read()
+ with open(m.group(2), "r") as f:
+ return m.group(1) + f.read()
except IOError:
# the linker should return an error if it can't
# find the linker command file so we will remain quiet.
# However, we will replace the @ with a # so we will not continue
# to find it with recursive substitution
return m.group(1) + '#' + m.group(2)
class LinklocGenerator(object):
def __init__(self, cmdline):
self.cmdline = cmdline
def __call__(self, env, target, source, for_signature):
if for_signature:
# Expand the contents of any linker command files recursively
subs = 1
strsub = env.subst(self.cmdline, target=target, source=source)
while subs:
strsub, subs = _re_linker_command.subn(repl_linker_command, strsub)
return strsub
else:
return "${TEMPFILE('" + self.cmdline + "')}"
def generate(env):
"""Add Builders and construction variables for ar to an Environment."""
SCons.Tool.createSharedLibBuilder(env)
SCons.Tool.createProgBuilder(env)
env['SUBST_CMD_FILE'] = LinklocGenerator
Index: Util.py
===================================================================
--- Util.py (revision 137834)
+++ Util.py (working copy)
@@ -1404,60 +1404,58 @@
if name is None:
name = function.func_name
else:
function = RenameFunction(function, name)
if hasattr(obj, '__class__') and obj.__class__ is not type:
# "obj" is an instance, so it gets a bound method.
setattr(obj, name, MethodType(function, obj, obj.__class__))
else:
# "obj" is a class, so it gets an unbound method.
setattr(obj, name, MethodType(function, None, obj))
def RenameFunction(function, name):
"""
Returns a function identical to the specified function, but with
the specified name.
"""
return FunctionType(function.func_code,
function.func_globals,
name,
function.func_defaults)
md5 = False
def MD5signature(s):
return str(s)
def MD5filesignature(fname, chunksize=65536):
- f = open(fname, "rb")
- result = f.read()
- f.close()
- return result
+ with open(fname, "rb") as f:
+ return f.read()
try:
import hashlib
except ImportError:
pass
else:
if hasattr(hashlib, 'md5'):
md5 = True
def MD5signature(s):
m = hashlib.md5()
m.update(str(s))
return m.hexdigest()
def MD5filesignature(fname, chunksize=65536):
m = hashlib.md5()
f = open(fname, "rb")
while True:
blck = f.read(chunksize)
if not blck:
break
m.update(str(blck))
f.close()
return m.hexdigest()
def MD5collect(signatures):
"""
Collects a list of signatures into an aggregate signature.
Index: Variables/__init__.py
===================================================================
--- Variables/__init__.py (revision 137834)
+++ Variables/__init__.py (working copy)
@@ -150,57 +150,59 @@
)
"""
for o in optlist:
self._do_add(*o)
def Update(self, env, args=None):
"""
Update an environment with the option variables.
env - the environment to update.
"""
values = {}
# first set the defaults:
for option in self.options:
if not option.default is None:
values[option.key] = option.default
# next set the value specified in the options file
for filename in self.files:
if os.path.exists(filename):
dir = os.path.split(os.path.abspath(filename))[0]
if dir:
sys.path.insert(0, dir)
try:
values['__name__'] = filename
- exec open(filename, 'rU').read() in {}, values
+ with open(filename, 'rU') as f:
+ contents = f.read()
+ exec contents in {}, values
finally:
if dir:
del sys.path[0]
del values['__name__']
# set the values specified on the command line
if args is None:
args = self.args
for arg, value in args.items():
added = False
for option in self.options:
if arg in list(option.aliases) + [ option.key ]:
values[option.key] = value
added = True
if not added:
self.unknown[arg] = value
# put the variables in the environment:
# (don't copy over variables that are not declared as options)
for option in self.options:
try:
env[option.key] = values[option.key]
except KeyError:
pass
# Call the convert functions:
for option in self.options:
Index: cpp.py
===================================================================
--- cpp.py (revision 137834)
+++ cpp.py (working copy)
@@ -354,57 +354,58 @@
eval()ing it in the C preprocessor namespace we use to
track #define values.
"""
t = CPP_to_Python(' '.join(t[1:]))
try: return eval(t, self.cpp_namespace)
except (NameError, TypeError): return 0
def initialize_result(self, fname):
self.result = [fname]
def finalize_result(self, fname):
return self.result[1:]
def find_include_file(self, t):
"""
Finds the #include file for a given preprocessor tuple.
"""
fname = t[2]
for d in self.searchpath[t[1]]:
if d == os.curdir:
f = fname
else:
f = os.path.join(d, fname)
if os.path.isfile(f):
return f
return None
def read_file(self, file):
- return open(file).read()
+ with open(file) as f:
+ return f.read()
# Start and stop processing include lines.
def start_handling_includes(self, t=None):
"""
Causes the PreProcessor object to start processing #import,
#include and #include_next lines.
This method will be called when a #if, #ifdef, #ifndef or #elif
evaluates True, or when we reach the #else in a #if, #ifdef,
#ifndef or #elif block where a condition already evaluated
False.
"""
d = self.dispatch_table
p = self.stack[-1] if self.stack else self.default_table
for k in ('import', 'include', 'include_next'):
d[k] = p[k]
def stop_handling_includes(self, t=None):
"""
Causes the PreProcessor object to stop processing #import,
#include and #include_next lines.
This method will be called when a #if, #ifdef, #ifndef or #elif
evaluates False, or when we reach the #else in a #if, #ifdef,
#ifndef or #elif block where a condition already evaluated True.
_______________________________________________
Scons-dev mailing list
[email protected]
https://pairlist2.pair.net/mailman/listinfo/scons-dev