1
# Copyright 2015, Kay Hayen, mailto:kay.hayen@gmail.com
3
# Part of "Nuitka", an optimizing Python compiler that is compatible and
4
# integrates with CPython, but also works on its own.
6
# Licensed under the Apache License, Version 2.0 (the "License");
7
# you may not use this file except in compliance with the License.
8
# You may obtain a copy of the License at
10
# http://www.apache.org/licenses/LICENSE-2.0
12
# Unless required by applicable law or agreed to in writing, software
13
# distributed under the License is distributed on an "AS IS" BASIS,
14
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
# See the License for the specific language governing permissions and
16
# limitations under the License.
20
Here the small things for file/dir names, Python version, CPU counting,
21
memory usage, etc. that fit nowhere else and don't deserve their own names.
29
from nuitka.PythonVersions import python_version
35
elif os.name == "posix":
41
def getArchitecture():
42
if getOS() == "Windows":
43
if "AMD64" in sys.version:
53
return os.path.relpath(path)
55
# On Windows, paths on different devices prevent it to work. Use that
57
if getOS() == "Windows":
58
return os.path.abspath(path)
63
return os.path.abspath(path)
67
return os.path.join(*parts)
80
return os.path.basename(path)
84
return os.path.dirname(path)
88
return os.path.normpath(path)
92
return os.path.normcase(path)
95
def getExtension(path):
96
return os.path.splitext(path)[1]
100
return os.path.isfile(path)
104
return os.path.isdir(path)
108
return os.path.islink(path)
111
def areSamePaths(path1, path2):
112
path1 = normcase(abspath(normpath(path1)))
113
path2 = normcase(abspath(normpath(path2)))
115
return path1 == path2
119
return os.readlink(path)
123
""" Give a sorted path, base filename pairs of a directory."""
128
joinpath(path, filename),
137
def getFileList(path):
138
for root, _dirnames, filenames in os.walk(path):
139
for filename in filenames:
140
yield joinpath(root, filename)
143
def deleteFile(path, must_exist):
144
if must_exist or isFile(path):
155
# Try to sum up the CPU cores, if the kernel shows them.
157
# Try to get the number of logical processors
158
with open("/proc/cpuinfo") as cpuinfo_file:
159
cpu_count = cpuinfo_file.read().count("processor\t:")
164
import multiprocessing
165
cpu_count = multiprocessing.cpu_count()
171
""" Do exec in a portable way preserving exit code.
173
On Windows, unfortunately there is no real exec, so we have to spawn
174
a new process instead.
177
# On Windows os.execl does not work properly
178
if getOS() != "Windows":
179
# The star arguments is the API of execl, pylint: disable=W0142
187
subprocess.call(args)
189
except KeyboardInterrupt:
190
# There was a more relevant stack trace already, so abort this
191
# right here, pylint: disable=W0212
195
def encodeNonAscii(var_name):
196
""" Encode variable name that is potentially not ASCII to ASCII only.
198
For Python3, unicode identifiers can be used, but these are not
199
possible in C++03, so we need to replace them.
201
if python_version < 300:
204
# Using a escaping here, because that makes it safe in terms of not
205
# to occur in the encoding escape sequence for unicode use.
206
var_name = var_name.replace("$$", "$_$")
208
var_name = var_name.encode("ascii", "xmlcharrefreplace")
209
var_name = var_name.decode("ascii")
211
return var_name.replace("&#", "$$").replace(';', "")
214
def isExecutableCommand(command):
215
path = os.environ["PATH"]
217
suffixes = (".exe",) if getOS() == "Windows" else ("",)
218
path_sep = ';' if getOS() == "Windows" else ':'
220
for part in path.split(path_sep):
224
for suffix in suffixes:
225
if isFile(joinpath(part, command + suffix)):
231
def getOwnProcessMemoryUsage():
232
""" Memory usage of own process in bytes.
236
if getOS() == "Windows":
237
# adapted from http://code.activestate.com/recipes/578513
239
from ctypes import wintypes
241
# Lets allow this to match Windows API it reflects,
242
# pylint: disable=C0103
243
class PROCESS_MEMORY_COUNTERS_EX(ctypes.Structure):
245
("cb", wintypes.DWORD),
246
("PageFaultCount", wintypes.DWORD),
247
("PeakWorkingSetSize", ctypes.c_size_t),
248
("WorkingSetSize", ctypes.c_size_t),
249
("QuotaPeakPagedPoolUsage", ctypes.c_size_t),
250
("QuotaPagedPoolUsage", ctypes.c_size_t),
251
("QuotaPeakNonPagedPoolUsage", ctypes.c_size_t),
252
("QuotaNonPagedPoolUsage", ctypes.c_size_t),
253
("PagefileUsage", ctypes.c_size_t),
254
("PeakPagefileUsage", ctypes.c_size_t),
255
("PrivateUsage", ctypes.c_size_t),
258
GetProcessMemoryInfo = ctypes.windll.psapi.GetProcessMemoryInfo
259
GetProcessMemoryInfo.argtypes = [
261
ctypes.POINTER(PROCESS_MEMORY_COUNTERS_EX),
264
GetProcessMemoryInfo.restype = wintypes.BOOL
266
counters = PROCESS_MEMORY_COUNTERS_EX()
267
rv = GetProcessMemoryInfo(
268
ctypes.windll.kernel32.GetCurrentProcess(),
269
ctypes.byref(counters),
270
ctypes.sizeof(counters)
274
raise ctypes.WinError()
276
return counters.PrivateUsage
278
# Posix only code, pylint: disable=F0401,I0021
281
# The value is from "getrusage", which has OS dependent scaling, at least
282
# MacOS and Linux different
283
if getOS() == "Darwin":
288
return resource.getrusage(resource.RUSAGE_SELF).ru_maxrss * factor
291
def getHumanReadableProcessMemoryUsage(value = None):
293
value = getOwnProcessMemoryUsage()
295
if abs(value) < 1024*1014:
296
return "%.2f KB (%d bytes)" % (
300
elif abs(value) < 1024*1014*1024:
301
return "%.2f MB (%d bytes)" % (
302
value / (1024*1024.0),
305
elif abs(value) < 1024*1014*1024*1024:
306
return "%.2f GB (%d bytes)" % (
307
value / (1024*1024*1024.0),
311
return "%d bytes" % value
316
self.start = getOwnProcessMemoryUsage()
320
self.stop = getOwnProcessMemoryUsage()
323
return getHumanReadableProcessMemoryUsage(self.stop - self.start)