Cython has moved to github.

cython-devel

view Cython/Utils.py @ 1859:750843d31989

Templating utility code
author Robert Bradshaw <robertwb@math.washington.edu>
date Sat Mar 14 21:42:28 2009 -0700 (3 years ago)
parents 519f0fb67849
children 2289ab00261d
line source
1 #
2 # Cython -- Things that don't belong
3 # anywhere else in particular
4 #
6 import os, sys, re, codecs
8 def replace_suffix(path, newsuf):
9 base, _ = os.path.splitext(path)
10 return base + newsuf
12 def open_new_file(path):
13 if os.path.exists(path):
14 # Make sure to create a new file here so we can
15 # safely hard link the output files.
16 os.unlink(path)
17 return open(path, "w")
19 def castrate_file(path, st):
20 # Remove junk contents from an output file after a
21 # failed compilation.
22 # Also sets access and modification times back to
23 # those specified by st (a stat struct).
24 try:
25 f = open_new_file(path)
26 except EnvironmentError:
27 pass
28 else:
29 f.write(
30 "#error Do not use this file, it is the result of a failed Cython compilation.\n")
31 f.close()
32 if st:
33 os.utime(path, (st.st_atime, st.st_mtime-1))
35 def modification_time(path):
36 st = os.stat(path)
37 return st.st_mtime
39 def file_newer_than(path, time):
40 ftime = modification_time(path)
41 return ftime > time
43 # support for source file encoding detection
45 def encode_filename(filename):
46 if isinstance(filename, unicode):
47 return filename
48 try:
49 filename_encoding = sys.getfilesystemencoding()
50 if filename_encoding is None:
51 filename_encoding = sys.getdefaultencoding()
52 filename = filename.decode(filename_encoding)
53 except UnicodeDecodeError:
54 pass
55 return filename
57 _match_file_encoding = re.compile(u"coding[:=]\s*([-\w.]+)").search
59 def detect_file_encoding(source_filename):
60 # PEPs 263 and 3120
61 f = codecs.open(source_filename, "rU", encoding="UTF-8")
62 try:
63 chars = []
64 for i in range(2):
65 c = f.read(1)
66 while c and c != u'\n':
67 chars.append(c)
68 c = f.read(1)
69 encoding = _match_file_encoding(u''.join(chars))
70 if encoding:
71 return encoding.group(1)
72 finally:
73 f.close()
74 return "UTF-8"
76 def open_source_file(source_filename, mode="rU"):
77 encoding = detect_file_encoding(source_filename)
78 return codecs.open(source_filename, mode=mode, encoding=encoding)
80 def long_literal(value):
81 if isinstance(value, basestring):
82 if len(value) < 2:
83 value = int(value)
84 elif value[0] == 0:
85 value = int(value, 8)
86 elif value[1] in 'xX':
87 value = int(value[2:], 16)
88 else:
89 value = int(value)
90 return not -2**31 <= value < 2**31
92 def none_or_sub(s, data):
93 if s is None:
94 return s
95 else:
96 return s % data
98 # a simple class that simplifies the usage of utility code
100 class UtilityCode(object):
101 def __init__(self, proto=None, impl=None, init=None, cleanup=None, requires=None):
102 self.proto = proto
103 self.impl = impl
104 self.init = init
105 self.cleanup = cleanup
106 self.requires = requires
107 self._cache = {}
109 def write_init_code(self, writer, pos):
110 if not self.init:
111 return
112 if callable(self.init):
113 self.init(writer, pos)
114 else:
115 writer.put(self.init)
117 def write_cleanup_code(self, writer, pos):
118 if not self.cleanup:
119 return
120 if callable(self.cleanup):
121 self.cleanup(writer, pos)
122 else:
123 writer.put(self.cleanup)
125 def specialize(self, **data):
126 # Dicts aren't hashable...
127 key = data.items(); key.sort(); key = tuple(key)
128 try:
129 return self._cache[key]
130 except KeyError:
131 if self.requires is None:
132 requires = None
133 else:
134 requires = [r.specialize(data) for r in self.requires]
135 s = self._cache[key] = UtilityCode(
136 none_or_sub(self.proto, data),
137 none_or_sub(self.impl, data),
138 none_or_sub(self.init, data),
139 none_or_sub(self.cleanup, data),
140 requires)
141 return s