patme 0.4.4__py3-none-any.whl
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.
Potentially problematic release.
This version of patme might be problematic. Click here for more details.
- patme/__init__.py +52 -0
- patme/buildtools/__init__.py +7 -0
- patme/buildtools/rce_releasecreator.py +336 -0
- patme/buildtools/release.py +26 -0
- patme/femtools/__init__.py +5 -0
- patme/femtools/abqmsgfilechecker.py +137 -0
- patme/femtools/fecall.py +1092 -0
- patme/geometry/__init__.py +0 -0
- patme/geometry/area.py +124 -0
- patme/geometry/coordinatesystem.py +635 -0
- patme/geometry/intersect.py +284 -0
- patme/geometry/line.py +183 -0
- patme/geometry/misc.py +420 -0
- patme/geometry/plane.py +464 -0
- patme/geometry/rotate.py +244 -0
- patme/geometry/scale.py +152 -0
- patme/geometry/shape2d.py +50 -0
- patme/geometry/transformations.py +1831 -0
- patme/geometry/translate.py +139 -0
- patme/mechanics/__init__.py +4 -0
- patme/mechanics/loads.py +435 -0
- patme/mechanics/material.py +1260 -0
- patme/service/__init__.py +7 -0
- patme/service/decorators.py +85 -0
- patme/service/duration.py +96 -0
- patme/service/exceptionhook.py +104 -0
- patme/service/exceptions.py +36 -0
- patme/service/io/__init__.py +3 -0
- patme/service/io/basewriter.py +122 -0
- patme/service/logger.py +375 -0
- patme/service/mathutils.py +108 -0
- patme/service/misc.py +71 -0
- patme/service/moveimports.py +217 -0
- patme/service/stringutils.py +419 -0
- patme/service/systemutils.py +290 -0
- patme/sshtools/__init__.py +3 -0
- patme/sshtools/cara.py +435 -0
- patme/sshtools/clustercaller.py +420 -0
- patme/sshtools/facluster.py +350 -0
- patme/sshtools/sshcall.py +168 -0
- patme-0.4.4.dist-info/LICENSE +21 -0
- patme-0.4.4.dist-info/LICENSES/MIT.txt +9 -0
- patme-0.4.4.dist-info/METADATA +168 -0
- patme-0.4.4.dist-info/RECORD +46 -0
- patme-0.4.4.dist-info/WHEEL +4 -0
- patme-0.4.4.dist-info/entry_points.txt +3 -0
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
# Copyright (C) 2013 Deutsches Zentrum fuer Luft- und Raumfahrt(DLR, German Aerospace Center) <www.dlr.de>
|
|
2
|
+
# SPDX-FileCopyrightText: 2022 German Aerospace Center (DLR)
|
|
3
|
+
#
|
|
4
|
+
# SPDX-License-Identifier: MIT
|
|
5
|
+
|
|
6
|
+
"""
|
|
7
|
+
Utilities on system level.
|
|
8
|
+
"""
|
|
9
|
+
import os
|
|
10
|
+
import re
|
|
11
|
+
import shutil
|
|
12
|
+
import subprocess
|
|
13
|
+
import tarfile
|
|
14
|
+
import time
|
|
15
|
+
import zipfile
|
|
16
|
+
from contextlib import contextmanager
|
|
17
|
+
from datetime import datetime
|
|
18
|
+
|
|
19
|
+
from patme.service.logger import log, resetLoggerToNewRunDir
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def dos2unix(filename):
|
|
23
|
+
"""doc"""
|
|
24
|
+
with open(filename, "rb") as f:
|
|
25
|
+
stream = f.read()
|
|
26
|
+
|
|
27
|
+
stream = stream.decode().replace("\r\n", "\n")
|
|
28
|
+
with open(filename, "wb") as f:
|
|
29
|
+
f.write(stream.encode())
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def searchForWordsWithinFile(filename=None, words=None):
|
|
33
|
+
"""doc"""
|
|
34
|
+
if not filename:
|
|
35
|
+
filename = ""
|
|
36
|
+
|
|
37
|
+
if isinstance(words, list):
|
|
38
|
+
words = re.compile("(%s)" % "|".join(words), re.RegexFlag.MULTILINE)
|
|
39
|
+
|
|
40
|
+
if os.path.exists(filename):
|
|
41
|
+
with open(filename, "rb") as f:
|
|
42
|
+
wordMatches = words.finditer(f.read().decode(errors="replace"))
|
|
43
|
+
if wordMatches:
|
|
44
|
+
return [match.group() for match in wordMatches]
|
|
45
|
+
return None
|
|
46
|
+
else:
|
|
47
|
+
log.error('Filename "%s" not found.' % filename)
|
|
48
|
+
return None
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def checkForLibraryInPaths(library, pathsToCheck):
|
|
52
|
+
"""Checks if library is found in any of the path set in global PATH variable.
|
|
53
|
+
If the library is found the base directory is returned"""
|
|
54
|
+
for path in pathsToCheck:
|
|
55
|
+
if os.path.isdir(path) and os.path.exists(path) and library in os.listdir(path):
|
|
56
|
+
return path
|
|
57
|
+
|
|
58
|
+
return None
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
@contextmanager
|
|
62
|
+
def changeDirTemporary(newDir):
|
|
63
|
+
"""Method to change the directory temporarily to do some things and change back to the original directory
|
|
64
|
+
after some things are done.
|
|
65
|
+
Example:
|
|
66
|
+
|
|
67
|
+
>>> import os
|
|
68
|
+
>>> currentDir = os.getcwd()
|
|
69
|
+
>>> with changeDirTemporary(os.path.join(currentDir, '..')): changedDir = os.getcwd()
|
|
70
|
+
>>> currentDirNew = os.getcwd()
|
|
71
|
+
>>> currentDir == currentDirNew
|
|
72
|
+
True
|
|
73
|
+
>>> currentDir != changedDir
|
|
74
|
+
True
|
|
75
|
+
>>> #print(currentDir,changedDir,currentDirNew)
|
|
76
|
+
>>> with changeDirTemporary(None): changedDir = os.getcwd()
|
|
77
|
+
>>> currentDirNew = os.getcwd()
|
|
78
|
+
>>> currentDir == currentDirNew
|
|
79
|
+
True
|
|
80
|
+
>>> currentDir == changedDir
|
|
81
|
+
True
|
|
82
|
+
>>> #print(currentDir,changedDir,currentDirNew)
|
|
83
|
+
|
|
84
|
+
"""
|
|
85
|
+
if newDir is None:
|
|
86
|
+
yield
|
|
87
|
+
return
|
|
88
|
+
tmpDir = os.getcwd()
|
|
89
|
+
os.chdir(newDir)
|
|
90
|
+
yield
|
|
91
|
+
os.chdir(tmpDir)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def getTimeString(useMilliSeconds=False):
|
|
95
|
+
"""returns a time string of the format: yyyymmdd_hhmmss"""
|
|
96
|
+
dt = datetime.now()
|
|
97
|
+
return dt.strftime("%Y%m%d_%H%M%S") + (f"_{dt.microsecond}" if useMilliSeconds else "")
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def makeAllDirs(directory):
|
|
101
|
+
absPath = os.path.abspath(directory)
|
|
102
|
+
for i in range(0, absPath.count(os.sep))[::-1]:
|
|
103
|
+
# Split path into subpaths beginning from the top of the drive
|
|
104
|
+
subPath = absPath.rsplit(os.sep, i)[0]
|
|
105
|
+
if not os.path.exists(subPath):
|
|
106
|
+
os.makedirs(subPath)
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def getRunDir(baseName="tmp", runDirExtension="", moveLogFilesToRunDir=True, basePath=".", useMilliSeconds=False):
|
|
110
|
+
"""Creates a folder that will be used as directory for the actual run.
|
|
111
|
+
|
|
112
|
+
The created folder has this name::
|
|
113
|
+
|
|
114
|
+
basePath/<baseName>_<timestamp><runDirExtension>
|
|
115
|
+
|
|
116
|
+
:param runDirExtension: optional string appended to the folder name. Defaults to ''
|
|
117
|
+
:param moveLogFilesToRunDir: Flag if the log files should be put in this directory.
|
|
118
|
+
:param basePath: working directory where folder shall be created.
|
|
119
|
+
:param useMilliSeconds: include milliseconds to the run dir name or not
|
|
120
|
+
:returns: absolute path to the new folder
|
|
121
|
+
|
|
122
|
+
Example::
|
|
123
|
+
|
|
124
|
+
>> getRunDir('foo', '_bar', False, False, 'foobar')
|
|
125
|
+
foobar/foo_20170206_152323_bar
|
|
126
|
+
|
|
127
|
+
"""
|
|
128
|
+
while True:
|
|
129
|
+
runDir = os.path.join(basePath, baseName + "_" + getTimeString(useMilliSeconds)) + runDirExtension
|
|
130
|
+
if os.path.exists(runDir):
|
|
131
|
+
log.warning("runDir already exists. Wait 1s and retry with new timestring.")
|
|
132
|
+
time.sleep(1)
|
|
133
|
+
else:
|
|
134
|
+
makeAllDirs(runDir)
|
|
135
|
+
break
|
|
136
|
+
|
|
137
|
+
if moveLogFilesToRunDir:
|
|
138
|
+
resetLoggerToNewRunDir(runDir)
|
|
139
|
+
|
|
140
|
+
return runDir
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def getGitInformation(wcDirectory=None):
|
|
144
|
+
"""Return information of the state of this git repository if it is present.
|
|
145
|
+
|
|
146
|
+
:param wcDirectory: main directory of the git clone
|
|
147
|
+
:return: tuple (description of the actual version and commit, has local modifications)
|
|
148
|
+
describe is either something like "0.2.0" if the tag-commit is active or
|
|
149
|
+
"0.1.1-31-g23a6851" describing
|
|
150
|
+
0.1.1: last tag name
|
|
151
|
+
31: number of commits since this tag
|
|
152
|
+
23a6851: actual commit
|
|
153
|
+
"""
|
|
154
|
+
gitBin = shutil.which("git")
|
|
155
|
+
if gitBin is None:
|
|
156
|
+
return ("No git binary found", "No git binary found")
|
|
157
|
+
|
|
158
|
+
with changeDirTemporary(wcDirectory):
|
|
159
|
+
p = subprocess.run(
|
|
160
|
+
[gitBin, "describe", "--tags"], stdout=subprocess.PIPE, stderr=subprocess.PIPE
|
|
161
|
+
) # use text=True for python >= 3.7
|
|
162
|
+
|
|
163
|
+
describe = p.stderr if p.stdout == b"" else p.stdout
|
|
164
|
+
describe = describe.decode("utf-8").strip()
|
|
165
|
+
|
|
166
|
+
p = subprocess.run(
|
|
167
|
+
[gitBin, "status"], stdout=subprocess.PIPE, stderr=subprocess.PIPE
|
|
168
|
+
) # use text=True for python >= 3.7
|
|
169
|
+
|
|
170
|
+
status = p.stderr if p.stdout == b"" else p.stdout
|
|
171
|
+
status = status.decode("utf-8").strip()
|
|
172
|
+
|
|
173
|
+
if "not a git repository" in describe:
|
|
174
|
+
return ("not a git repository", "not a git repository")
|
|
175
|
+
hasLocalModifications = "Changes to be committed" in status or "Changes not staged for commit" in status
|
|
176
|
+
return describe, hasLocalModifications
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
def getFormattedTimeStampForFile(ffile):
|
|
180
|
+
return int(datetime.fromtimestamp(os.path.getmtime(ffile)).strftime("%Y%m%d%H%M"))
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
def compressFilesInDir(
|
|
184
|
+
direc, regEx, zipFilename=None, thresholdMB=0, olderThan=0, removeOrigFiles=False, autoCRCCheck=True
|
|
185
|
+
):
|
|
186
|
+
"""Compresses files in a given directory with a given minimal file size and a modification time.
|
|
187
|
+
|
|
188
|
+
The resulting file archive is a general zip file.
|
|
189
|
+
|
|
190
|
+
:param direc: Directory where several files should be compressed
|
|
191
|
+
:param regEx: Regular expression which the filenames should match to compress
|
|
192
|
+
:param zipFilename: Filename of the Zip-file to store files. If it is None, all matching files in a directory.
|
|
193
|
+
will be compressed as seperate files with the original filename and the new .zip ending
|
|
194
|
+
:param thresholdMB: Minimum file size in megabytes for compression to exclude very small files.
|
|
195
|
+
:param olderThan: Timestamp (Format '%Y%m%d%H%M') to exclude files from compression which are generated in the shorter past.
|
|
196
|
+
Timestamp can be helpful to avoid compressing files which may be needed again in a long term process.
|
|
197
|
+
:param removeOrigFiles: Flag if original files should be deleted if they were compressed successfully
|
|
198
|
+
:param autoCRCCheck: Flag if created zip files should be checked by CRC algorithm
|
|
199
|
+
|
|
200
|
+
"""
|
|
201
|
+
|
|
202
|
+
direc = os.path.abspath(direc)
|
|
203
|
+
p = re.compile(regEx)
|
|
204
|
+
thresholdBytes = int(thresholdMB * 1024**2)
|
|
205
|
+
|
|
206
|
+
for root, __, files in os.walk(direc, topdown=True):
|
|
207
|
+
compressDict = {}
|
|
208
|
+
for name in files:
|
|
209
|
+
filenameWithRoot = os.path.join(root, name)
|
|
210
|
+
getLastModifiedTime = getFormattedTimeStampForFile(filenameWithRoot)
|
|
211
|
+
|
|
212
|
+
if int(olderThan) > 0 and getLastModifiedTime > int(olderThan):
|
|
213
|
+
continue
|
|
214
|
+
|
|
215
|
+
if p.match(name) and os.stat(filenameWithRoot).st_size > thresholdBytes:
|
|
216
|
+
if not zipFilename:
|
|
217
|
+
newZiPFile = os.path.join(root, name + ".zip")
|
|
218
|
+
else:
|
|
219
|
+
newZiPFile = os.path.join(root, zipFilename)
|
|
220
|
+
|
|
221
|
+
with zipfile.ZipFile(newZiPFile, "a", zipfile.ZIP_DEFLATED, allowZip64=True) as myzip:
|
|
222
|
+
myzip.write(filenameWithRoot, name)
|
|
223
|
+
|
|
224
|
+
if compressDict.get(newZiPFile, None):
|
|
225
|
+
compressDict[newZiPFile].append(filenameWithRoot)
|
|
226
|
+
else:
|
|
227
|
+
compressDict[newZiPFile] = [filenameWithRoot]
|
|
228
|
+
|
|
229
|
+
if autoCRCCheck:
|
|
230
|
+
for zFile, cFiles in list(compressDict.items()):
|
|
231
|
+
with zipfile.ZipFile(zFile, "r", allowZip64=True) as myzip:
|
|
232
|
+
if myzip.testzip():
|
|
233
|
+
print("Something went wrong with zip file creation: ", zFile)
|
|
234
|
+
raise
|
|
235
|
+
elif removeOrigFiles:
|
|
236
|
+
for ffile in cFiles:
|
|
237
|
+
os.remove(ffile)
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
def tarGzDirectory(directory, tarFileName):
|
|
241
|
+
"""put a directory in a targz"""
|
|
242
|
+
if not os.path.isabs(tarFileName):
|
|
243
|
+
tarFileName = os.path.join(directory, tarFileName)
|
|
244
|
+
directory = os.path.abspath(directory)
|
|
245
|
+
if os.path.exists(tarFileName):
|
|
246
|
+
os.remove(tarFileName)
|
|
247
|
+
|
|
248
|
+
with tarfile.open(tarFileName, "x:gz") as tarFileDescriptor:
|
|
249
|
+
for fileOrDir in os.listdir(directory):
|
|
250
|
+
tarFileDescriptor.add(os.path.join(directory, fileOrDir), arcname=fileOrDir)
|
|
251
|
+
|
|
252
|
+
return tarFileName
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
def zipDirectory(directory, zipFileName):
|
|
256
|
+
"""Puts all files in the given directory to a zip file in the same dir
|
|
257
|
+
|
|
258
|
+
Attention: Extracting of empty (sub)directories does not work with python's zipfile module
|
|
259
|
+
|
|
260
|
+
:param directory: directory that will be zipped
|
|
261
|
+
:param zipFileName: name of the zip file that is created. If it as an abs path, then it is
|
|
262
|
+
used directly. If it has a relative path, it is used relative to directory.
|
|
263
|
+
"""
|
|
264
|
+
if not os.path.isabs(zipFileName):
|
|
265
|
+
zipFileName = os.path.join(directory, zipFileName)
|
|
266
|
+
directory = os.path.abspath(directory)
|
|
267
|
+
if os.path.exists(zipFileName):
|
|
268
|
+
os.remove(zipFileName)
|
|
269
|
+
with zipfile.ZipFile(zipFileName, "x") as zipFileDescriptor:
|
|
270
|
+
for root, dirs, files in os.walk(directory):
|
|
271
|
+
for file in files:
|
|
272
|
+
if file != os.path.basename(zipFileName):
|
|
273
|
+
fullFileName = os.path.join(root, file)
|
|
274
|
+
fileInZipName = os.path.join(os.path.relpath(root, directory), file)
|
|
275
|
+
zipFileDescriptor.write(fullFileName, fileInZipName)
|
|
276
|
+
for directory in dirs: # add folder in order to also have empty folders added
|
|
277
|
+
with changeDirTemporary(root):
|
|
278
|
+
zif = zipfile.ZipInfo(os.path.join(directory))
|
|
279
|
+
zif.external_attr = 16
|
|
280
|
+
zipFileDescriptor.writestr(zif, "")
|
|
281
|
+
|
|
282
|
+
|
|
283
|
+
if __name__ == "__main__":
|
|
284
|
+
pass
|
|
285
|
+
# print(getRunDir('foo', '_bar', False, False, 'foobar'))
|
|
286
|
+
# directory = 'D:\\freu_se\\DELiS\\tmp\\delis_20170206_143544_functionCreator\\abq_abq'
|
|
287
|
+
# tarFileName = 'a.tar.gz'
|
|
288
|
+
# if os.path.exists(os.path.join(directory, tarFileName)):
|
|
289
|
+
# os.remove(os.path.join(directory, tarFileName))
|
|
290
|
+
# tarGzDirectory(directory, tarFileName)
|