6Create a make object to define the building environment and to execute the
7build commands. The make event is subdivided in a pre-, main- and a post-build
14----------------------------------------------------------------------------------------------
21@author: garb_ma [DLR-FA,STM Braunschweig]
22----------------------------------------------------------------------------------------------
34 from builtins
import object
41 FileNotFoundError = IOError
43import sys, os, platform
73from packaging
import version
74from shutil
import copyfile
75from types
import MethodType
76from collections
import OrderedDict
77from PIL
import Image, ImageColor
81 if os.path.exists(os.path.join(sys.prefix,
"conda-meta"))
and not os.path.join(sys.prefix,
"conda-meta")
in os.getenv(
"PATH",
""):
82 os.environ[
"PATH"] = os.pathsep.join([os.path.join(sys.prefix,
"Library",
"bin"),os.getenv(
"PATH",
"")])
88from ..Tools
import Utility
91PyXMakePath = Utility.GetPyXMakePath()
93Path2Config = os.path.join(PyXMakePath,
"Build",
"config")
95AllowDefaultMakeOption = bool(int(
"-1" if __debug__
or not getattr(sys,
"frozen",
False)
else int(os.getenv(
"pyx_default_make_opt",
"0"))) == -1)
98logger = logging.getLogger(__name__)
106 Base class of all supported subsystems.
116@six.add_metaclass(abc.ABCMeta)
119 Inherited class to NT projects without any presets.
124 Initialization of NT class object.
126 super(NT, self).
__init__(*args, **kwargs)
133@six.add_metaclass(abc.ABCMeta)
136 Inherited class to POSIX projects without any presets.
141 Initialization of POSIX class object.
143 super(POSIX, self).
__init__(*args, **kwargs)
150 copyfile(os.path.join(Path2Config,
"stm_makefile"), os.path.join(self.
scrtdir,
"Makefile"))
154 def __create__(self, **kwargs):
156 Unified create function replacing all create commands of ALL classes when used with Mingx64 or on Linux. All builds are solely
157 defined by one unified Makefile. in these cases.
161 from PyXMake.VTL
import GetPreprocessingCommand
162 from numpy.distutils.fcompiler
import gnu
163 from numpy.distutils
import ccompiler
164 from numpy.f2py
import crackfortran, auxfuncs
165 from numpy.distutils
import misc_util
166 from packaging.version
import parse
172 self.
environ = copy.deepcopy(getattr(os.environ,
"_data",{}))
175 if Utility.GetPlatform()
in [
"windows"]
and not Utility.GetExecutable(
"choco"):
176 os.environ[
"pyx_user_install"] =
"chocolatey"
177 os.system(
" ".join([sys.executable,os.path.abspath(__install__.__file__)]))
180 os.environ[
"PATH"] = os.pathsep.join([os.getenv(
"PATH"),os.path.join(os.path.dirname(os.path.abspath(__install__.__file__)),
"bin",
"chocolatey")])
184 msys2_base_path, msys2_compiler_path, msys2_shell_initialization = self.setup(mingw = Utility.GetExecutable(
"choco"))
186 if self.hasFoss
and (
"fpp" in getattr(self,
"precmd",
"")
and not Utility.GetExecutable(
"fpp")):
195 if Utility.GetPlatform()
in [
"windows"]:
raise ImportError
198 msys2_compiler_path =
""
199 msys2_shell_initialization =
""
203 from re.RegexFlag
import MULTILINE
206 from re
import MULTILINE
212 if self.MakeObjectKind
in [
'Py2X',
"f2py"]:
213 self.incdirs.append(os.path.join(os.getcwd(),
"tmp",
"Release"))
216 os.environ[
"pyx_compiler"] = os.getenv(
"pyx_compiler").replace(ntpath.sep,posixpath.sep)
218 if Utility.GetPlatform()
in [
"windows"]:
220 os.environ[
"pyx_ldflags"] = delimn.join([
"-L"+os.path.join(msys2_base_path,
"mingw64",
"lib"),
"-L"+msys2_compiler_path]) + delimn
221 if parse(np.__version__) >= parse(
"1.22.0"): os.environ[
"pyx_ldflags"] = delimn.join([os.getenv(
"pyx_ldflags",
""),
"-D__STDC_NO_THREADS__"]) + delimn
224 for x
in [
'-I"'+x+
'" ' for x
in self.incdirs]: os.environ[
"pyx_ldflags"] = os.getenv(
"pyx_ldflags",
"") + x
227 for x
in [
'-L"'+x+
'" ' for x
in self.
libdirs]: os.environ[
"pyx_ldflags"] = os.getenv(
"pyx_ldflags",
"") + x
230 for x
in [
'-l'+x+
' ' for x
in self.libs]: os.environ[
"pyx_ldflags"] = os.getenv(
"pyx_ldflags",
"") + x
233 os.environ[
"pyx_ldflags"] = os.getenv(
"pyx_ldflags",
"").replace(
"\\",
"/")
238 command = self.
precmdprecmd.split(delimn); command.insert(-2,
"-D__GFORTRAN__");
247 for source
in os.getenv(
"pyx_source").split(delimn):
248 Make.F2CPreprocessing(source)
249 except FileNotFoundError:
254 except UnicodeError:
pass
257 os.environ[
"pyx_cflags"] = delimn.join([os.getenv(
"pyx_cflags",
""),delimn.join([x
for x
in self.makecmd.split(delimn)
if x.startswith(
"-D")])])
261 command = msys2_shell_initialization
263 if Utility.GetPlatform() !=
"windows": command = delimn.join([
';export PYX_BUILDID="'+os.environ[
"pyx_buildid"]+
'"',
';export PYX_SOURCE="'+os.environ[
"pyx_source"]+
'"',
";bash"])
266 if self.MakeObjectKind
in [
'Py2X',
"f2py"]:
268 for x
in [ccompiler, crackfortran, gnu, misc_util]:
270 if Utility.IsDockerContainer()
and Utility.GetPlatform()
in [
"linux"]
and not os.access(x.__file__, os.W_OK):
271 Permission = str(oct(stat.S_IMODE(os.lstat(x.__file__).st_mode)));
272 subprocess.check_call([
"sudo",
"chmod",
"777",x.__file__])
275 os.environ[
"pyx_cflags"] += delimn +
"-ffree-line-length-0"
276 if self.makecmd.find(
"-fixed") != -1:
277 os.environ[
"pyx_cflags"] += delimn +
"-f%s-form" %
"fixed"
279 os.environ[
"pyx_cflags"] += delimn +
"-f%s-form" %
"free"
282 if self.
verbose >= 2: os.environ[
"pyx_ldflags"] += delimn +
"--verbose"
283 else: os.environ[
"pyx_ldflags"] += delimn +
"--quiet"
286 if Utility.GetPlatform() !=
"windows":
288 command = command.split(delimn); compiler = Utility.PathLeaf(os.getenv(
"pyx_compiler"))
289 command.insert(0,
'export PYX_COMPILER="'+compiler.replace(os.path.splitext(compiler)[1],
"")+
'"');
290 command.insert(0,
'export PYX_CFLAGS="'+os.getenv(
"pyx_cflags")+
'"')
291 command.insert(0,
'export PYX_LDFLAGS="'+os.getenv(
"pyx_ldflags")+
'"')
292 command.insert(0,
'export LD_RUN_PATH="'+os.pathsep.join(self.
libdirs)+
'"')
293 command.insert(0,
'export NPY_DISTUTILS_APPEND_FLAGS=1')
294 command = delimn.join(command)
298 with tempfile.NamedTemporaryFile(mode=
'w+')
as __:
300 with open(gnu.__file__,
"r")
as f: gnustream = f.read()
301 with open(misc_util.__file__,
"r")
as f: utilstream = f.read();
302 with open(auxfuncs.__file__,
"r")
as f: auxstream = f.read();
303 with open(crackfortran.__file__,
"r")
as f: crackstream = f.read();
304 with open(ccompiler.__file__,
"r")
as f: ccompstream = f.read()
306 with open(gnu.__file__,
"w")
as f:
308 target =
"v >= '4.'"; replace =
"int(v.split('.')[0]) >= int('4')";
309 pattern = re.compile(target,MULTILINE); _ = gnustream;
311 if Utility.GetPlatform()
in [
"windows"]: _ = gnustream.replace(
'["<F90>", "-Wall", "-g"],',
'["<F90>", "-Wall", "-g","-static","-static-libgcc","-static-libgfortran"],')
312 if re.search(pattern,_)
and not parse(np.__version__) >= parse(
"1.19.0"):
314 print(
"==================================")
315 print(
"On-the-fly patching of numpy version %s" % np.__version__)
316 print(
"==================================")
317 _ = re.sub(pattern,replace,_)
320 with open(misc_util.__file__,
"w")
as f:
322 if utilstream.find(str(
"import textwrap")) != -1:
323 _ = utilstream.replace(str(
"import textwrap"),str(
"import textwrap, io"))
324 else: _ = utilstream.replace(str(
"import os"),str(
"import os, io"))
326 _ = _.replace(str(
"open(source, 'r')"),str(
'io.open(source, "r", encoding="utf-8")')); f.write(_)
327 with open(crackfortran.__file__,
"w")
as f:
329 _ = crackstream.replace(str(
"import fileinput"),str(
"import fileinput, io"))
330 _ = _.replace(str(
"fileinput.FileInput(ffile)"),str(
"fileinput.FileInput(ffile,openhook=fileinput.hook_encoded('utf-8'))"))
332 if sys.version_info <= (3,0): _ = _.replace(str(
r'\xa0'),str(
r'\t'))
334 if self.makecmd.find(
"-fixed") != -1
and parse(np.__version__) >= parse(
"1.26.0"):
336 _ = _.replace(str(
"sourcecodeform = 'free'"),str(
"sourcecodeform = 'fix'"));
338 _ = _.replace(str(
"open(file, 'r')"),str(
'io.open(file, "r", encoding="utf-8")')); f.write(_)
340 if sys.version_info <= (3,0):
341 with open(auxfuncs.__file__,
"w")
as f:
343 _ = auxstream.replace(str(
"if isinstance(rules[k], str)"),str(
"if isinstance(rules[k], basestring)"))
344 _ = _.replace(
"ret[k] = replace(rules[k], d)",
"ret[k] = str(replace(str(rules[k]), d))")
348 if parse(np.__version__) < parse(
"2.0.0"):
349 with open(ccompiler.__file__,
"w")
as f:
351 _ = ccompstream.replace(
"ccomp = self.compiler_so",
"self.compiler_so += ['-fpermissive','-fno-strict-aliasing']; ccomp = self.compiler_so")
355 if kwargs.get(
"use_default_encoding",sys.version_info <= (3,0)):
357 with open(misc_util.__file__,
"w")
as f: f.write(utilstream)
358 with open(crackfortran.__file__,
"w")
as f: f.write(crackstream)
359 with open(auxfuncs.__file__,
"w")
as f: f.write(auxstream)
362 params = {}
if not Utility.IsDockerContainer()
else {
"shell":
True,
"collect":
True}
364 environment = os.environ.copy();
366 if sys.version_info <= (3, 0): params.update({
"env":environment})
368 if Utility.GetPlatform()
in [
"windows"]
and not Utility.IsDockerContainer():
369 params.update({
"replace":
""})
370 command = delimn.join([command,
"-c",
'"make f2py"'])
372 Utility.Popen(command, verbosity=self.
verbose, **params)
377 with open(gnu.__file__,
"w")
as f: f.write(gnustream)
378 with open(misc_util.__file__,
"w")
as f: f.write(utilstream)
379 with open(crackfortran.__file__,
"w")
as f: f.write(crackstream)
380 with open(ccompiler.__file__,
"w")
as f: f.write(ccompstream)
381 with open(auxfuncs.__file__,
"w")
as f: f.write(auxstream)
384 print(
"==================================")
385 print(
"Restoring numpy version %s" % np.__version__)
386 print(
"==================================")
388 if os.path.exists(
"tmp")
or os.path.exists(os.getenv(
"pyx_buildid")):
390 shutil.rmtree(
"tmp"); shutil.rmtree(os.getenv(
"pyx_buildid"))
391 except (FileNotFoundError, OSError)
as _:
pass
394 if Utility.IsDockerContainer()
and Utility.GetPlatform
in [
"linux"]: subprocess.check_call([
"sudo",
"chmod",Permission,gnu.__file__])
396 elif self.MakeObjectKind
in [
'Fortran',
"CCxx"]:
398 if self.makecmd.find(
"-fixed") != -1:
399 os.environ[
"pyx_cflags"] += delimn +
"-ffixed-line-length-132 -f%s-form" %
"fixed"
400 elif self.MakeObjectKind
in [
'Fortran']:
401 os.environ[
"pyx_cflags"] += delimn +
"-ffree-line-length-0 -f%s-form" %
"free"
404 if Utility.GetPlatform() !=
"windows":
405 command = command.split(delimn);
406 command.insert(0,
'export PYX_CFLAGS="'+os.getenv(
"pyx_cflags")+
'"')
407 command.insert(0,
'export PYX_LDFLAGS="'+os.getenv(
"pyx_ldflags")+
'"')
408 command = delimn.join(command)
411 command = delimn.join([command,
"-c",
'"make"'])
412 Utility.Popen(command, verbosity=self.
verbose, replace=
"")
418 _ = list(self.
temps);
419 if ".mod" in _: _.remove(
".mod");
420 self.
temps = tuple(_)
423 Utility.DeleteFilesbyEnding(self.
temps)
426 for x
in os.listdir(os.getcwd()):
429 if os.path.isfile(x)
and not x.startswith(
"."): shutil.move(x,os.path.join(getattr(self,
"outlibs",self.
outdir),x))
433 if hasattr(self,
"outlibs")
and hasattr(self,
"outmodule"):
437 if any([x.endswith((
".mod",
".h"))
for x
in os.listdir(os.getcwd())]): os.makedirs(self.
outmodule, exist_ok=
True)
438 for x
in os.listdir(os.getcwd()):
439 if x.endswith((
".mod",
".h")): shutil.move(x,os.path.join(self.
outmodule,x))
442 os.environ.pop(
"pyx_cflags",
"")
443 os.environ.pop(
"pyx_ldflags",
"")
446 for k, v
in getattr(self,
"environ",{}).items():
448 if hasattr(k,
"decode"): k = k.decode()
449 if hasattr(v,
"decode"): v = v.decode()
450 os.environ.update({k:v})
458 Parent class for all make objects.
461 def __init__(self, BuildID, Srcs, scratch=os.getcwd(), verbose=0, *args, **kwargs):
463 Low-level initialization of parent class.
471 self.
srcs.append(Srcs)
472 self.
srcs = list(Utility.ArbitraryFlattening(self.
srcs))
474 self.
bare =
not BuildID
and not self.
srcs
476 self.
stype = kwargs.get(
"stype",
'Fortran')
485 self.
hasFoss = kwargs.get(
"foss", Utility.GetExecutable(
"choco")
or Utility.GetPlatform()
in [
"linux"]
or kwargs.get(
"bash",
False))
497 if os.path.exists(os.path.join(PyXMakePath,
'Paths.log')):
498 with open(os.path.join(PyXMakePath,
'Paths.log'))
as f:
499 content = f.readlines()
500 content = [x.strip()
for x
in content][20]
528 self.
setarch =
True if kwargs.get(
'arch',
None)
in [
'x86',
'x64']
else False
531 self.
msvsc = kwargs.get(
"msvsc",
'vs2015')
532 os.environ[
'pyx_msvsc'] = self.
msvsc
535 if 'win' in sys.platform:
537 if ((
'32bit' in platform.architecture()
and not self.
setarch)
or (self.
setarch and kwargs.get(
'arch',
None) ==
"x86")):
539 os.environ[
'pyx_proc'] =
'x86'
540 os.environ[
'pyx_intel'] =
'ia32'
544 elif ((
'64bit' in platform.architecture()
and not self.
setarch)
or (self.
setarch and kwargs.get(
'arch',
None) ==
"x64")):
546 os.environ[
'pyx_proc'] =
'amd64'
547 os.environ[
'pyx_intel'] =
'intel64'
551 if kwargs.get(
"initialize",
True):
557 elif Utility.IsDockerContainer()
and Utility.GetPlatform()
in [
"linux"]:
559 os.environ[
"pyx_intel"] =
"intel64_lin"
561 self.
intelpath = os.path.join(Utility.AsDrive(
"opt"),
"intel",
"psxe_runtime",
"linux")
565 elif 'linux' in sys.platform:
567 os.environ[
"pyx_intel"] =
""
576 if os.path.exists(os.path.join(self.
intelpath,
"mkl",
"include")):
578 mkl_include_path = os.path.join(self.
intelpath,
"mkl",
"include")
579 self.
incdirs.append(mkl_include_path)
581 if os.path.exists(os.path.join(self.
intelpath,
"mkl")):
583 mkl_lib_path = os.path.join(self.
intelpath,
"mkl",
"lib",os.environ[
'pyx_intel'])
584 mkl_compiler_path = os.path.join(self.
intelpath,
"compiler",
"lib",os.environ[
'pyx_intel'])
585 self.
libdirs.extend([mkl_lib_path, mkl_compiler_path])
588 if os.path.exists(os.path.join(self.
intelpath,
"bin",os.environ[
'pyx_intel'])):
589 os.environ[
"PATH"] =
";".join([os.getenv(
"PATH",
""),os.path.join(self.
intelpath,
"bin",os.environ[
'pyx_intel'])])
593 for path
in mkl_paths: self.
_mkl_includes.extend([x
for x
in os.listdir(path)
if (os.path.isfile(os.path.join(path,x))
and x.endswith((
".f90",
".F90",
".for",
".FOR",
".f",
".F",
".f77",
".F77")))])
604 Request compatibility with Mingw64 and Linux.
607 if kwargs.get(
"bash", self.
hasFoss):
617 delattr(self,
"__create__")
624 Default parser object for command line interface
626 @author: Marc Garbade
629 parser = argparse.ArgumentParser(add_help=
False)
631 parser.add_argument(
'name', type=str, nargs=1, help=
"Name of the project")
632 parser.add_argument(
'source', type=str, nargs=1, help=
"Absolute path to the source file directory.")
633 parser.add_argument(
'-f',
'--files', nargs=
'+', default=[], help=
"Source file or list of all source files in the order of compilation")
634 parser.add_argument(
"-o",
"--output", type=str, nargs=1, help=
"Absolute path to output directory. Defaults to current project folder.")
635 parser.add_argument(
'-i',
'--include', nargs=
'+', default=[], help=
"Additional directories and files required for the build.")
636 parser.add_argument(
'-s',
'--scratch', nargs=
'+', default=[], help=
"Default scratch folder for the build. Defaults to current workspace.")
637 parser.add_argument(
"-v",
"--verbosity", type=str, nargs=1, help=
"Level of verbosity. Defaults to 0 - meaning no output. Max value is 2.")
644 Detach current console window from parent window.
646 @author: Marc Garbade
651 DETACHED_PROCESS = 0x00000008
652 CREATE_NEW_PROCESS_GROUP = subprocess.CREATE_NEW_PROCESS_GROUP
653 kwargs.update(creationflags=DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP)
654 elif sys.version_info < (3, 2):
655 kwargs.update(preexec_fn=os.setsid)
657 kwargs.update(start_new_session=
True)
664 Replace incompatible Fortran PreProcessing directives with its C++ counterparts.
670 from re.RegexFlag
import MULTILINE
673 from re
import MULTILINE
675 def NegationDirective(matchobj):
677 Replace .not. with ! (e.g. .not. defined will be !defined)
680 if matchobj.group(1) ==
".NOT. ":
683 newString +=
"defined(%s)" % matchobj.group(2)
686 def LowerDirective(matchobj):
688 All initial directives are given in lower cases.
690 return "#" + matchobj.group()[1:].lower()
693 decorator = re.compile(
"^!DEC\$ (?=IF|ELSE|ENDIF|END IF)",MULTILINE)
694 addition = re.compile(
"^#(.*?)\.AND\.(.*?)", MULTILINE)
695 either = re.compile(
"^#(.*?)\.OR\.(.*?)", MULTILINE)
696 negation = re.compile(
"(\.NOT\. )?DEFINED\(([A-Za-z0-9_]+)\)", MULTILINE)
697 conditionals = re.compile(
"^#(IF|ENDIF|END IF|ELSE)",MULTILINE)
698 space = re.compile(
"^#(end if)",MULTILINE)
704 with io.open(PreprocessingFile,
"r")
as f: stream = f.read()
707 if Utility.GetPlatform()
in [
"windows"]:
710 with io.open(PreprocessingFile,
"r", encoding=
'cp1252')
as f: stream = f.read()
713 with io.open(PreprocessingFile,
"r",encoding=
"utf-8")
as f: stream = f.read()
716 with io.open(PreprocessingFile,
"r",encoding=
"utf-8")
as f: stream = f.read()
719 stream = decorator.sub(
"#",stream)
720 stream = addition.sub(
"#\g<1>&&\g<2>", stream)
721 stream = either.sub(
"#\g<1>||\g<2>", stream)
722 stream = negation.sub(NegationDirective, stream)
723 stream = conditionals.sub(LowerDirective, stream)
724 stream = space.sub(
"#endif",stream)
729 with io.open(PreprocessingFile,
"w",encoding=
"utf-8")
as f: f.write(stream)
732 with open(PreprocessingFile,
"w")
as f: f.write(stream)
736 Define additional include directories containing modules or source files as comma separated list.
744 Define additional directories containing 3rd party libraries as comma separated list.
746 self.
libdirs.append(dependencies)
752 Define which non-default libraries should be used during linking.
754 self.
libs.append(libs)
755 self.
libs = list(Utility.ArbitraryFlattening(self.
libs))
760 Define a new source directory. Input is read from workspace by default.
766 self.
srcdir = os.path.abspath(os.getcwd())
771 Define a new output directory. Output is written to the workspace by default.
777 self.
outdir = os.path.abspath(os.getcwd())
785 Load an additional environment file prior to execution of all commands.
788 os.environ[
'pyx_environment'] = os.path.join(path,script)
789 if path.rsplit(
"\\",1)[1] ==
"bin":
790 self.
intelpath = path[::-1].replace(
"bin"[::-1],
"",1)[::-1]
796 if all(x
in inc
for x
in [
"mkl",
"include"]):
801 if all(x
in lib
for x
in [
"mkl",
"lib"])
or all(x
in lib
for x
in [
"compiler",
"lib"]):
805 mkl_include_path = os.path.join(self.
intelpath,
"mkl",
"include")
806 mkl_lib_path = os.path.join(self.
intelpath,
"mkl",
"lib",os.environ[
'pyx_intel'])
807 mkl_compiler_path = os.path.join(self.
intelpath,
"compiler",
"lib",os.environ[
'pyx_intel'])
809 self.
incdirs.append(mkl_include_path)
810 self.
libdirs.extend([mkl_lib_path, mkl_compiler_path])
814 replace = {'!DEC$ IF':
'#IF',
'!DEC$ ELSE':
'#ELSE',
'!DEC$ ENDIF':
'#ENDIF'}):
816 Assemble command string for the pre-build event.
822 if not Utility.IsNotEmpty(os.path.splitext(self.
buildname)[1]):
831 collsrcfile = Utility.GetTemporaryFileName(filename=
"coll" +
"_", extension=inend)
832 presrcfile = Utility.GetTemporaryFileName(filename=
"pre",extension=outend)
835 search_dir = [self.
srcdir]
837 search_dir.extend(self.
incdirs)
843 for subdir
in search_dir:
845 if not os.path.exists(subdir):
continue
846 src_files = os.listdir(subdir)
847 file_names = [x
for x
in src_files
if x
in copyfiles]
848 for inputfile
in file_names:
849 full_file_name = os.path.join(subdir, inputfile)
850 if (os.path.isfile(full_file_name)):
851 shutil.copy(full_file_name, os.getcwd())
860 Utility.ConcatenateFiles(collsrcfile, self.
srcs, self.
srcdir, ending=inend)
863 Utility.ReplaceTextinFile(collsrcfile, presrcfile, replace, source=self.
scrtdir)
866 Make.F2CPreprocessing(presrcfile)
869 if any(x
in cmdstring
for x
in [
"cpp",
"fpp"]):
870 cmdstring += delimn + delimn.join([
'-I"'+x+
'" ' for x
in self.
incdirs])
873 cmdstring +=
' %s %s' % (presrcfile, self.
buildname)
883 def Build(self, cmdstring, **kwargs):
885 Assemble command string for the main build event.
891 if not self.MakeObjectKind.lower()
in [
"doxygen"]:
894 includes = [
'-I"'+x+
'" ' for x
in self.
incdirs]
899 dependencies = [
'-L"'+x+
'" ' for x
in self.
libdirs]
900 for x
in dependencies:
904 libs = [
'-l'+x+
' ' for x
in self.
libs]
916 Assemble command string for the post-build event.
925 Provide a dictionary with substrings to replace in the given input.
927 @note: Defaults to replace architecture and platform identifiers
929 result = copy.deepcopy(string)
930 replacements = kwargs.get(
"replace",{
'{arch}': Utility.GetArchitecture(),
"{platform}":Utility.GetPlatform()})
931 for key, value
in replacements.items():
932 result = result.replace(key, value)
933 result = Utility.GetSanitizedDataFromCommand([result], is_path=
False)[-1]
939 Initialize a predefined compiler tool chain of all requirements are met.
941 @note: Only meaningful on NT systems.
944 try:
from packaging.version
import Version
as StrictVersion
945 except ImportError:
from distutils.version
import StrictVersion
950 if Utility.GetPlatform()
not in [
"windows"]:
return
953 if kwargs.get(
"mingw",
False):
955 _, choco_base_path = Utility.GetExecutable(
"choco", get_path=
True)
957 if "bin" not in os.listdir(os.path.dirname(choco_base_path)): choco_base_path = os.path.join(choco_base_path,
'..',
'..')
958 else: choco_base_path = os.path.join(choco_base_path,
'..')
959 choco_base_path = os.path.normpath(choco_base_path)
960 content = open(os.path.join(choco_base_path,
"logs",
"choco.summary.log"),
"r").readlines()
962 try: _, msys2_base_path = next(iter([x
for x
in content
if all([y
in x.lower()
for y
in [
"msys64",
"software installed to"]])])).split(
"Software installed to")
964 except StopIteration: _, msys2_base_path = next(iter([x
for x
in content
if all([y
in x.lower()
for y
in [
"msys64",
"installing to"]])])).split(
"Installing to:")
966 try: msys2_base_path = Utility.GetSanitizedDataFromCommand(
"r"+msys2_base_path.strip(), allowed_exceptions=(ValueError,))[0]
967 except SyntaxError: msys2_base_path = msys2_base_path.strip()
968 msys2_base_path = os.path.normpath(msys2_base_path)
970 msys2_compiler_version = sorted(os.listdir(os.path.join(msys2_base_path,
"mingw64",
"lib",
"gcc",
"x86_64-w64-mingw32")),key=StrictVersion)[-1]
971 msys2_compiler_path = os.path.join(msys2_base_path,
"mingw64",
"lib",
"gcc",
"x86_64-w64-mingw32",msys2_compiler_version)
973 msys2_shell_initialization = delimn.join([os.path.join(msys2_base_path,
"msys2_shell.cmd"),
"-defterm",
"-mingw64",
"-no-start",
"-full-path",
"-here"])
975 return (msys2_base_path, msys2_compiler_path, msys2_shell_initialization)
977 elif kwargs.get(
"msvsc",
'vs2015')
in [
"vs2015",
"vs2017",
"vs2019",
"vs2022"]:
979 intel_compiler_path =
""
981 msvsc_shell_initialization =
r'"'+os.path.join(PyXMakePath,
"Build",
"cmd",
"windows",
"iniCompiler.bat")+
'"'
983 if not any([Utility.GetExecutable(x)
for x
in [
"ifx",
"ifort"]])
and not os.path.exists(os.path.join(Utility.GetPyXMakePath(),
"Paths.log")):
985 allprograms = os.path.join(os.environ[
'ALLUSERSPROFILE'],
"Microsoft",
"Windows",
"Start Menu",
"Programs")
987 for root, _, files
in Utility.PathWalk(allprograms):
988 if "intel" not in root.lower():
continue
989 if not any(x.lower().endswith(
"lnk")
for x
in files)
or not any(
"compiler" in x.lower()
for x
in files):
continue
990 intellink = os.path.abspath(os.path.join(root,sorted(files)[-1]))
992 try: command = Utility.GetLink(intellink)
994 except UnboundLocalError:
return (
None, intel_compiler_path, msvsc_shell_initialization )
995 intelpath = next(iter(x
for x
in command.split(
'"')
if "compiler" in x.lower()))
997 if not os.getenv(
"pyx_intel",
"")
and not os.getenv(
"pyx_msvsc",
""):
998 os.environ[
"pyx_intel"], os.environ[
"pyx_msvsc"] = [x.replace(
'"',
"")
for x
in command.split(delimn)[-2:]]
1000 os.environ[
"pyx_environment"] = intelpath
1002 intel_compiler_path = os.path.abspath(os.path.join(intelpath, os.path.pardir, os.path.pardir))
1004 data = Utility.GetEnvironmentFromCommand(os.path.join(Utility.GetPyXMakePath(),
"Build",
"cmd",
"windows",
"iniCompiler.bat"))
1006 os.environ.update(data)
1009 if any([Utility.GetExecutable(x)
for x
in [
"ifx",
"ifort"]]): os.environ[
"pyx_environment"] =
"unset"
1011 return (
None, intel_compiler_path, msvsc_shell_initialization )
1017 Assemble command string for the post-build event.
1020 if hasattr(cls,
"parse"): cls.parse(command=sys.argv, **kwargs)
1021 else: RuntimeWarning(
"Class %s has no associated default parsing feature. Skipping." % str(cls.
__name____name__))
1026 Execute make command
1029 settings = {
"verbosity": self.
verbose,
"collect":
not "cmake" in self.exe
or Utility.GetPlatform()
in [
"linux"]}
1040 vault = [x
for x
in os.listdir(os.getcwd())
if x
not in self.
temps]
1042 for key
in os.environ.keys():
1044 if Utility.GetPlatform() ==
"windows" and self.
verbose >= 3
and len(os.environ[key]) >= 2048:
1045 warnings.warn(
"Environment variable %s" % key +
" is exceeding the character limit")
1050 Utility.Popen(self.
precmd, **settings)
1056 if getattr(self,
"mkl_dependency",
""):
1058 for x
in getattr(self,
"_mkl_includes",[]):
1060 with open(
"pyx_bridge_"+str(x),
"a+")
as mkl_include: mkl_include.write(
" include '%s' \n" % str(x))
1061 command = self.
iniCompiler +
" "+
'ifort -c "%s"' % str(
"pyx_bridge_"+str(x))
1062 Utility.Popen(command, **settings)
1066 env = os.environ.copy();
1068 if not "python" in self.
makecmd: env.pop(
"PYTHONPATH",
"")
1069 Utility.Popen(self.
makecmd, env=env, **settings)
1075 Utility.Popen(self.
postcmd, **settings)
1084 if self.
outdir != os.getcwd():
1085 for f
in os.listdir(os.getcwd()):
1087 if f
in vault:
continue
1091 copyfile(os.path.join(os.getcwd(),f), os.path.join(self.
outdir,f))
1094 copyfile(os.path.join(os.getcwd(),f), os.path.join(self.
outdir,f))
1100 Utility.DeleteFilesbyEnding(self.
temps)
1107 Inherited class to build projects without any presets.
1111 Initialization of Custom class object.
1113 super(Custom, self).
__init__(*args, **kwargs)
1121 if self.
srcs[-1]
in [
"CMakeLists.txt"]:
1122 settings = {
"search_paths": os.pathsep.join([os.getenv(
"PATH",os.getcwd()),os.path.join(sys.prefix,
"scripts")]) }
1124 self.
exe = [
"cmake" if not Utility.GetExecutable(
"cmake", **settings)
else
1125 Utility.InQuotes(Utility.GetExecutable(
"cmake",get_path=
True, **settings)[-1]) ][0]
1127 if Utility.GetPlatform()
in [
"windows"]
and Utility.GetExecutable(
"choco")
and self.
hasFosshasFosshasFoss:
1128 self.
exe = Utility.GetPathConversion(self.
exe,
"linux")
1135 os.environ[
"ABQ_ENV_FILE"] =
"abaqus_v6.env"
1136 os.environ[
"pyx_abaqus"] = os.getenv(
"pyx_abaqus",
"abaqus")
1148 def Build(self, cmdstring, **kwargs):
1150 Assemble command string for the main build event.
1157 os.environ[
"INCLUDE"] = os.pathsep.join(list(self.
incdirs)) + os.pathsep + os.pathsep.join((os.environ.get(
"MSMPI_INC",
""), os.environ.get(
"INCLUDE",
"")))
1160 os.environ[
"LIB"] = os.pathsep.join(self.
libdirs) + os.pathsep + os.pathsep.join((os.environ.get(
"MSMPI_LIB64",
""), os.environ.get(
"LIB",
"")))
1163 os.environ[
"PATH"] = os.pathsep.join([self.
srcdir,self.
scrtdir]) + os.pathsep + os.getenv(
"PATH",
"")
1166 if "cmake" in self.
exe:
1169 command =
"%s" % self.
exe
1171 if not self.
hasFosshasFosshasFoss and Utility.GetPlatform()
in [
"windows"]: command +=
' -B build -S '"%s"'' % os.path.abspath(self.
srcdir)
1172 else: command +=
" -B build -S '%s'" % os.path.abspath(self.
srcdir)
1174 command += cmdstring.replace(
"cmake",
" ")
1178 if any(isinstance(x,six.string_types)
for x
in getattr(self,
"copyfiles",[])):
1179 command +=
" -DCMAKE_INSTALL_PREFIX='%s'" % os.path.abspath(self.
outdir)
1182 cpus = str(multiprocessing.cpu_count()//2)
1188 if self.
hasFosshasFosshasFoss: command +=
" -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DCMAKE_Fortran_COMPILER=gfortran"
1191 if self.
verbose >= 2: command +=
" -DCMAKE_VERBOSE_MAKEFILE=On"
1194 if kwargs.get(
"append",[]): command += delimn + delimn.join(kwargs.get(
"append"))
1198 command +=
' -DCMAKE_BUILD_TYPE=Release'
1200 command +=
' -DCMAKE_INCLUDE_PATH="%s"' % os.path.join(PyXMakePath,
"VTL",
"make")
1202 settings = {
"search_paths":os.pathsep.join([os.path.join(sys.prefix,
"Scripts"),os.getenv(
"PATH",
"")])}
1204 if Utility.GetExecutable(
"pythonsed",**settings):
1205 command +=
' -DSED="%s"' % Utility.GetExecutable(
"pythonsed", get_path=
True, **settings)[-1]
1206 elif Utility.GetExecutable(
"choco"):
1208 settings = {
"search_paths":os.pathsep.join([os.path.join(Make.setup(mingw = Utility.GetExecutable(
"choco"))[0],
"usr",
"bin"),os.getenv(
"PATH",
"")])}
1209 command +=
' -DSED="%s"' % Utility.GetExecutable(
"sed", get_path=
True, **settings)[-1]
1212 elif Utility.GetExecutable(
"sed"):
pass
1217 command +=
' -Wno-dev -G "NMake Makefiles"'
1219 if Utility.GetExecutable(
"oneapi-cli")
and Utility.GetExecutable(
"ifort"): command +=
" -DCMAKE_Fortran_COMPILER=ifort"
1223 self.
precmdprecmd = delimn.join([batch,
'%s' % command])
1225 self.
postcmdpostcmd = delimn.join([batch,
'%s' %
"%s --install build" % self.
exe])
1227 elif Utility.GetPlatform()
in [
"windows"]
and Utility.GetExecutable(
"choco"):
1228 command +=
" -G 'MinGW Makefiles'"
1230 msys2_shell = delimn.join([self.
setup(mingw=
True)[-1],
"-c"])
1232 self.
precmdprecmd = delimn.join([msys2_shell,
'"%s"' % command])
1233 self.
makecmdmakecmd = delimn.join([msys2_shell,
'"%s"' %
"%s --build build -j %s" % (self.
exe, cpus)])
1234 self.
postcmdpostcmd = delimn.join([msys2_shell,
'"%s"' %
"%s --install build" % self.
exe])
1238 self.
precmdprecmd = shlex.split(command, posix=
not os.name.lower()
in [
"nt"])
1239 self.
makecmdmakecmd = shlex.split(
"%s --build build -j %s" % (self.
exe, cpus), posix=
not os.name.lower()
in [
"nt"])
1240 self.
postcmdpostcmd = shlex.split(
"%s --install build" % self.
exe, posix=
not os.name.lower()
in [
"nt"])
1246 if self.
msvsc.lower()
in [
"vs2015",
"vs2017",
"vs2019",
"vs2022"]:
1247 self.
libs.extend([
"msvcrt",
"vcruntime",
"ucrt",
"legacy_stdio_definitions"])
1249 if Utility.GetExecutable(
"oneapi-cli"): self.
libs.remove(
"msvcrt")
1252 pyx_libs = [
"'"+x+
".lib'" for x
in sorted(set(self.
libs), key=self.
libs.index)]
1255 os.environ[
"pyx_libs"] =
",".join(pyx_libs)
1269 Execute the current class as a CLI command.
1272 from PyXMake.VTL
import cmake
1274 command = kwargs.get(
"command",sys.argv)
1276 parser = argparse.ArgumentParser(description=
'CLI wrapper options for CMAKE with more sensible default settings.')
1277 parser.add_argument(
'name', type=str, nargs=1, help=
"Name of the project")
1278 parser.add_argument(
'source', type=str, nargs=1, help=
"Absolute path to the source file directory.")
1279 parser.add_argument(
'-s',
'--scratch', nargs=
'+', default=[], help=
"Default scratch folder for CMake. Defaults to current workspace.")
1280 parser.add_argument(
"-o",
"--output", type=str, nargs=1, help=
"Absolute path to output directory. Defaults to current project folder.")
1281 parser.add_argument(
"-v",
"--verbosity", type=str, nargs=1, help=
"Level of verbosity. Defaults to 0 - meaning no output. Max value is 2.")
1282 parser.add_argument(
"--foss", type=Utility.GetBoolean, const=
True, default=
True, nargs=
'?',
1283 help=
"Toggle to enforce free-open source builds. Defaults to True.")
1288 args, unknown = parser.parse_known_args(command[1:])
1290 project = args.name[0];
1292 source = args.source[0] ;
1294 try: output = args.output[0]
1295 except: output =
None
1297 try: scratch = args.scratch[0]
1298 except: scratch = os.path.abspath(os.getcwd())
1300 try: verbosity = int(args.verbosity[0])
1301 except: verbosity = 0
1303 try: foss = args.foss[0]
1304 except: foss = Utility.GetPlatform()
in [
"linux"]
1306 settings = {
"source":source,
"output":output,
"scratch":scratch,
1307 "verbosity":verbosity,
"foss": foss}
1309 append = [x
for x
in unknown
if not any(y
in x
for y
in vars(args).keys())]
1310 if append: settings.update({
"append":append})
1312 except Exception
as _:
1314 from PyCODAC.Tools.Utility
import GetPyCODACPath
1316 if AllowDefaultMakeOption:
1318 BuildID =
"mcd_core";
1320 cmake(BuildID, source=os.path.join(GetPyCODACPath(),
"Core",
"config"), foss=kwargs.pop(
"foss",
True))
1323 cmake(project, **settings)
1330 Inherited class to build projects using Intel C/C++.
1334 Initialization of C/C++ class object.
1336 super(CCxx, self).
__init__(*args, **kwargs)
1341 self.
exe =
'cl.exe'; os.environ[
"pyx_compiler"] =
"gcc"
1344 self.
isStaticisStatic =
True if kwargs.get(
'lib',
'static')
not in [
'shared',
'SHARED',
'Shared']
else False
1352 self.
exe +=
' -c %s' % (
' '.join(self.
srcs))
1374 self.
incdirs.append(os.path.join(PyXMakePath,
"VTL",
"make"))
1378 os.environ[
"pyx_buildid"], os.environ[
"pyx_source"] = (self.
libname,
' '.join([x
for x
in self.
srcs if os.path.splitext(x)[1].lower()
in (
".c",
".cpp",
".h",
".hpp",
"Makefile")]))
1383 Define output directories for modules and libraries.
1389 def Build(self, cmdstring, **kwargs):
1391 Assemble command strings for the main build event.
1397 includes = [
' -I"'+x+
'" ' for x
in self.
incdirs]
1403 librarian =
'link -dll -fixed:no -defaultlib:libcmt.lib -nodefaultlib:msvcrt.lib '
1425 Execute the current class as a CLI command.
1428 from PyXMake.VTL
import cxx
1430 command = kwargs.pop(
"command",sys.argv)
1432 parser = argparse.ArgumentParser(description=
"Build a sCxx project from console.")
1433 parser.add_argument(
'name', type=str, nargs=1, help=
"Name of the project")
1434 parser.add_argument(
'source', type=str, nargs=1, help=
"Absolute path to the source file directory.")
1435 parser.add_argument(
'-f',
'--files', nargs=
'+', default=[], help=
"Source file or list of all source files in the order of compilation")
1436 parser.add_argument(
"-o",
"--output", type=str, nargs=1, help=
"Absolute path to output directory. Defaults to current project folder.")
1437 parser.add_argument(
'-i',
'--include', nargs=
'+', default=[], help=
"Additional directories and files required for the build.")
1438 parser.add_argument(
'-s',
'--scratch', nargs=
'+', default=[], help=
"Default scratch folder for the build. Defaults to current workspace.")
1439 parser.add_argument(
"-v",
"--verbosity", type=str, nargs=1, help=
"Level of verbosity. Defaults to 0 - meaning no output. Max value is 2.")
1440 parser.add_argument(
"--incremental", type=Utility.GetBoolean, const=
True, default=
False, nargs=
'?',
1441 help=
"Toggle between incremental and non-incremental build. Defaults to False.")
1446 args, _ = parser.parse_known_args(command[1:])
1448 project = args.name[0]
1450 source = args.source[0] ;
1452 try: files = args.files
1455 try: output = args.output[0]
1456 except: output = os.path.abspath(os.getcwd())
1461 include = Utility.GetSanitizedDataFromCommand(args.include)
1463 except: include = []
1465 try: incremental = args.incremental[0]
1466 except: incremental =
False
1468 try: scratch = args.scratch[0]
1469 except: scratch = os.path.abspath(os.getcwd())
1471 try: verbosity = int(args.verbosity[0])
1472 except: verbosity = 0
1474 settings = {
"files":files,
"incremental": incremental,
"include": include,
1475 "source":source,
"output":output,
"scratch":scratch,
1476 "verbosity":verbosity}
1478 except Exception
as _:
1480 if AllowDefaultMakeOption:
1484 BuildID =
"muesli"; cxx(BuildID, foss=
False, **kwargs)
1488 from PyCODAC.Plugin.DispLam
import __path__
as DispLamPath
1489 disp_src = os.path.join(DispLamPath[0],
"src",
"displam"); disp_bin=os.path.join(DispLamPath[0],
"bin",Utility.GetPlatform())
1490 cxx(
"displam", os.listdir(disp_src), source=disp_src, output=disp_bin, verbosity=0, **kwargs)
1493 else: cxx(project, **settings)
1498 Execute make command
1514 for y
in dependencies:
1518 linklist = [
' '+x+
'.lib ' for x
in self.
libs]
1528 except Exception
as _:
pass
1549 Inherited class to build projects using Intel Fortran.
1553 Initialization of Fortran class object.
1555 super(Fortran, self).
__init__(*args, **kwargs)
1560 self.
isStaticisStatic =
True if kwargs.get(
'lib',
'static')
not in [
'shared',
'SHARED',
'Shared']
else False
1565 mkl_interface_lib =
"mkl_intel_c"
1567 mkl_interface_lib =
"mkl_intel_lp64"
1570 self.
libslibs.append([mkl_interface_lib,
"mkl_intel_thread",
"mkl_core",
"libiomp5md"])
1599 os.environ[
"pyx_buildid"], os.environ[
"pyx_source"] = (self.
libname,
' '.join([x
for x
in self.
srcs if os.path.splitext(x)[1].lower()
in (
".for",
".f95",
".f",
".f90")]))
1604 Define output directories for modules and libraries.
1607 if modulepath
is None:
1616 replace = {'!DEC$ IF':
'#IF',
'!DEC$ ELSE':
'#ELSE',
'!DEC$ ENDIF':
'#ENDIF'},
1617 decorator=
"!DEC$ ATTRIBUTES DLLEXPORT::"):
1619 Assemble command string for the pre-build event.
1622 delimn =
" "; validater =
"bind"
1625 _preprocessing = copy.deepcopy(getattr(self,
"precmd",
None))
1628 Make.Preprocessing(self,
"custom", inend, outend, copyfiles, replace)
1637 except FileNotFoundError:
pass
1644 Inputfile = os.path.join(os.getcwd(),presrcfile)
1646 with open(Inputfile)
as infile, open(Outputfile,
'w')
as outfile:
1650 xname, xline = line.partition(
'="')[0], line.partition(
'="')[2]
1651 if xline !=
'' and validater
in xname.lower():
1652 outfile.write(decorator+xline.partition(
'"')[0]+
"\n")
1660 Assemble command string for the pre-build event.
1663 makedir = os.path.join(PyXMakePath,
"VTL",
"make")
1681 def Build(self, cmdstring, **kwargs):
1683 Assemble command strings for the main build event.
1685 sep =
" "; multi_objects = []
1695 includes = [
' -I"'+x+
'" ' for x
in self.
incdirs]
1701 librarian =
'link -dll -fixed:no -defaultlib:libcmt.lib -nodefaultlib:msvcrt.lib '
1719 makefile = sep.join([x
for x
in self.
srcs if os.path.splitext(x)[1].lower()
in (
".for",
".f95",
".f",
".f90")])
1720 multi_objects = [os.path.splitext(x)[0]+
".obj" for x
in self.
srcs if os.path.splitext(x)[1].lower()
in (
".for",
".f95",
".f",
".f90")]
1724 self.
makecmdmakecmd +=
'ifort -c '+ makefile + cmd + cmdstring +
' && '
1726 if not multi_objects:
1738 Execute make command
1754 for y
in dependencies:
1758 linklist = [
' '+x+
'.lib ' for x
in self.
libslibs]
1766 if f.endswith(
'.mod')
and not kwargs.get(
"combine",
False):
1790 sep =
' '; librarian =
'lib '; ext =
'.lib'
1792 multi_libs = [os.path.join(self.
outlibsoutlibs,x)
for x
in [list(Utility.ArbitraryFlattening(x[2]))
for x
in Utility.PathWalk(self.
outlibsoutlibs)][0]
if x.startswith(mergedid)]
1802 for lib
in multi_libs:
1816 Inherited class to build projects using PyReq.
1820 Initialization of PyReq class object.
1822 @note Creates a list of all 3rd party dependencies of a package using PyReq.
1824 super(PyReq, self).
__init__(*args, **kwargs)
1841 Assemble command string for the pre-build event.
1852 Execute the current class as a CLI command.
1855 from PyXMake.VTL
import pyreq
1857 command = kwargs.get(
"command",sys.argv)
1859 parser = argparse.ArgumentParser(description=
'CLI wrapper options for dependency detection tool.')
1860 parser.add_argument(
'name', type=str, nargs=1, help=
"Name of the project")
1861 parser.add_argument(
'--source', type=str, nargs=1, help=
"Absolute path to project folder.")
1862 parser.add_argument(
"--output", type=str, nargs=1, help=
"Absolute path to output directory. Defaults to current project folder.")
1863 parser.add_argument(
"--file", type=str, nargs=1, help=
"Output file name. Defaults to requirements.txt")
1864 parser.add_argument(
"--check", type=Utility.GetBoolean, const=
True, default=
True, nargs=
'?',
1865 help=
"Check public PyPi repository to verify the results. Defaults to True.")
1866 parser.add_argument(
'--command', nargs=argparse.REMAINDER, help=
"Additional command line parameters.")
1873 args, _ = parser.parse_known_args(command[1:])
1875 project = args.name[0]
1877 try: source = args.source[0] ;
1880 handle = importlib.import_module(project)
1881 source = os.path.abspath(handle.__path__[0])
1883 try: output = args.output[0]
1884 except: output = os.path.abspath(os.getcwd())
1886 try: check = args.check[0]
1887 except: check =
True
1889 try: filename = args.file[0]
1890 except: filename =
'requirements.txt'
1892 try: command = args.command[0]
1893 except: command = delimn.join([
"--ignore",
"cmd,bin,Core,Plugin",
"--no-pin"])
1895 except Exception
as _:
1897 if AllowDefaultMakeOption:
1901 from PyXMake
import PyXMakePath;
from PyCODAC
import PyCODACPath
1903 pyreq(
"PyXMake", source=PyXMakePath,
1904 compargs=delimn.join([
"--ignore",
"cmd,bin",
"--no-pin"]), output=os.getcwd(), check=
True)
1906 pyreq(
"PyCODAC", source=PyCODACPath,
1907 compargs=delimn.join([
"--ignore",
"cmd,bin,Core,Plugin",
"--no-pin"]), output=os.getcwd(), check=
True)
1910 pyreq(
"DELiS", source=os.path.join(PyCODACPath,
"Plugin",
"DELiS",
"src",
"delis"),
1911 compargs=delimn.join([
"--no-pin"]), output=os.getcwd())
1915 pyreq(
"Smetana", source=os.path.join(PyCODACPath,
"Plugin",
"Smetana",
"src",
"smetana"),
1916 compargs=delimn.join([
"--ignore",
"gopak,curvefit,test,static",
"--no-pin"]), output=os.getcwd())
1919 else: pyreq(project, source, output, check=check, filename=filename, compargs=command)
1924 Execute make command
1927 sys.setrecursionlimit(kwargs.get(
"recursion_limit",5000))
1928 delimn =
" "; linebreak =
"\n"
1941 data = Utility.GetRequirements(self.
srcdir, getattr(self,
"compargs",
"--no-pin").split(delimn), **kwargs)
1945 with open(os.path.join(self.
outdiroutdir,kwargs.get(
"filename",self.
buildid+
".md")),
"w+")
as output:
1946 output.write(linebreak.join(str(item)
for item
in data))
1956 Inherited class to build projects using Py2X.
1960 Initialization of Py2X class object.
1962 @note Currently uses f2py - but should be build with Py2X (DLR) in the future
1964 super(Py2X, self).
__init__(*args, **kwargs)
1975 self.
no_mkl = kwargs.get(
"no_mkl", self.
hasFosshasFoss and (Utility.GetExecutable(
"choco")
or Utility.GetPlatform()
in [
"linux",
"cygwin",
"msys",
"darwin"]))
1987 self.
path2exe = sys.executable.replace(
"\python.exe",
"")
1995 old_numpy_call = os.path.join(self.
path2exe,
"Scripts",
"f2py.py")
1996 new_numpy_call = os.path.join(self.
path2exe,
"Scripts",
"f2py.exe")
1998 if os.path.exists(old_numpy_call):
1999 self.
exe +=
'"{}"'.format(old_numpy_call)
2000 os.environ[
"pyx_compiler"] =
" ".join([sys.executable,old_numpy_call])
2001 elif os.path.exists(old_numpy_call):
2002 self.
exe =
'"{}"'.format(new_numpy_call)
2003 os.environ[
"pyx_compiler"] = new_numpy_call
2006 from numpy
import f2py
2009 os.environ.update({
"PATH":os.pathsep.join([os.getenv(
"PATH")]+
2010 [os.path.join(f2py.__path__[0].split(os.path.sep+
"lib")[0],
"bin")]+
2011 [os.path.join(os.path.dirname(x),
"Scripts")
if Utility.GetPlatform()
in [
"windows"]
else
2012 os.path.join(os.path.dirname(x),
"bin")
for x
in sys.path
if x.endswith(
"lib")])})
2014 found, self.
exe = Utility.GetExecutable(
"f2py", get_path=
True)
2016 if not found:
raise RuntimeError(
"f2py could not be found on the system.")
2018 os.environ[
"pyx_compiler"] = self.
exe
2019 self.
exe =
'"{}"'.format(self.
exe)
2026 mkl_interface_lib =
"mkl_intel_c"
2028 mkl_interface_lib =
"mkl_intel_lp64"
2032 if version.parse(np.__version__) >= version.parse(
"1.26.0"):
2039 self.
libslibslibs.append([mkl_interface_lib,
"mkl_intel_thread",
"mkl_core",
"libiomp5md"])
2043 if Utility.IsDockerContainer()
and Utility.GetPlatform()
not in [
"windows",
"msys"]: self.
libslibslibs.append([
"gomp",
"ifcore"])
2051 prefix =
"Library" if Utility.GetPlatform()
in [
"windows"]
else ""
2053 base = os.path.dirname(os.path.dirname(os.getenv(
"pyx_compiler", sys.prefix)))
2055 self.
libdirslibdirs.extend([os.path.join(x,prefix,
"lib")
for x
in (sys.prefix, base)])
2062 c_files = [x
for x
in self.
srcs if os.path.splitext(x)[1].lower()
in (
".for",
".f95",
".f",
".f90")]
2080 if Utility.IsDockerContainer()
and not self.
barebare:
2081 for proc
in psutil.process_iter():
2082 if os.getpid() == proc.pid:
2085 for key, value
in proc.as_dict().items():
2088 proc_delimn =
" "; processName = proc.name(); processID = proc.pid;
2089 print(
"==================================")
2090 print(
"Found existing child process @ %s" % proc_delimn.join([str(processName),
':::',str(processID)]))
2091 print(
"The process is aborted for compilation")
2092 print(
"==================================")
2093 except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
2110 Inspect the content of a given f2py package. Returns all qualified modules with their respective functions
2113 def condition(x):
return kwargs.get(
"custom_condition",
not x.startswith(
"_")
and not x.endswith(
"__"))
2115 all_modules = [x
for x
in dir(package)
if condition(x)]
2117 return [
".".join([package.__name__,x,y])
for x
in all_modules
for y
in dir(getattr(package, x))
if condition(y)]
2120 def show(package, feature, **kwargs):
2122 Inspect the documentation content of a given f2py package feature by default.
2123 Optional, define callback to return any other existing attribute.
2126 delimn =
"."; anchor = feature.split(
".");
2128 def rgetattr(obj, attr, *args):
2130 Get an attribute from a nested object.
2132 @note: https://stackoverflow.com/questions/31174295/getattr-and-setattr-on-nested-subobjects-chained-properties
2134 def _getattr(obj, attr):
2136 Wrapper of existing getattr function
2138 try: result = getattr(obj, attr, *args)
2140 relative =
"."*(anchor.index(str(attr))-1)+str(attr)
2141 result = importlib.import_module(relative, package=
".".join(anchor[0:relative.count(
".")+1]))
2143 return functools.reduce(_getattr, [obj] + attr.split(
'.'))
2145 module = importlib.import_module(package.__name__)
2147 attributes = delimn.join([x
for x
in feature.split(delimn)
if x
not in [package.__name__]])
2149 return getattr(rgetattr(module, attributes),kwargs.get(
"callback",
"__doc__"))
if (attributes
and attributes
not in [delimn])
else getattr(module,kwargs.get(
"callback",
"__doc__"))
2154 Get callback of any Python object.
2157 return Py2X.show(*args,callback=
"__call__")
2162 Execute the current class as a CLI command.
2165 from PyXMake.VTL
import py2x
2167 command = kwargs.get(
"command",sys.argv)
2169 parser = argparse.ArgumentParser(description=
"Build a shared Fortran library for current Python executable")
2170 parser.add_argument(
'name', type=str, nargs=1, help=
"Name of the project")
2171 parser.add_argument(
'source', type=str, nargs=1, help=
"Absolute path to the source file directory.")
2172 parser.add_argument(
'-f',
'--files', nargs=
'+', default=[], help=
"Source file or list of all source files in the order of compilation")
2173 parser.add_argument(
"-o",
"--output", type=str, nargs=1, help=
"Absolute path to output directory. Defaults to current project folder.")
2174 parser.add_argument(
'-i',
'--include', nargs=
'+', default=[], help=
"Additional directories and files required for the build.")
2175 parser.add_argument(
'-s',
'--scratch', nargs=
'+', default=[], help=
"Default scratch folder for the build. Defaults to current workspace.")
2176 parser.add_argument(
"-v",
"--verbosity", type=str, nargs=1, help=
"Level of verbosity. Defaults to 0 - meaning no output. Max value is 2.")
2177 parser.add_argument(
"--format", type=str, nargs=1, help=
"Toggle between fixed and free format code style. Defaults to Fixed.")
2178 parser.add_argument(
"--incremental", type=Utility.GetBoolean, const=
True, default=
False, nargs=
'?',
2179 help=
"Toggle between incremental and non-incremental build. Defaults to False.")
2180 parser.add_argument(
"--foss", type=Utility.GetBoolean, const=
True, default=
True, nargs=
'?',
2181 help=
"Toggle to enforce free-open source builds. Defaults to True.")
2186 args, _ = parser.parse_known_args(command[1:])
2188 project = args.name[0]
2190 source = args.source[0] ;
2192 try: files = args.files
2195 try: output = args.output[0]
2196 except: output = os.path.abspath(os.getcwd())
2198 try: scratch = args.scratch[0]
2199 except: scratch = os.path.abspath(os.getcwd())
2204 include = Utility.GetSanitizedDataFromCommand(args.include)
2206 except: include = []
2208 try: fformat = args.format[0]
2209 except: fformat =
"fixed"
2211 try: incremental = args.incremental[0]
2212 except: incremental =
False
2214 try: verbosity = int(args.verbosity[0])
2215 except: verbosity = 0
2217 try: foss = args.check[0]
2220 settings = {
"files":files,
"incremental": incremental,
"include": include,
2221 "source":source,
"output":output,
"scratch":scratch,
2222 "format":fformat,
"foss":foss,
2223 "verbosity":verbosity}
2225 except Exception
as _:
2227 from PyXMake
import VTL
2229 if AllowDefaultMakeOption:
2231 __arch = Utility.GetArchitecture()
2232 __foss = Utility.IsDockerContainer()
or Utility.GetPlatform()
in [
"linux"]
2235 from PyCODAC.Tools.Utility
import GetPyCODACPath
2237 __mcd_core_path = os.path.join(GetPyCODACPath(),
"Core")
2240 __mcd_core_path =
""
2244 ErrorHandling.InputError(20)
2248 files=VTL.GetSourceCode(1),
2249 source=os.path.join(__mcd_core_path,
"external",
"boxbeam"),
2250 libs=[],include=[],dependency=[],verbosity=2,
2252 output=os.path.join(os.path.join(__mcd_core_path,
"bin",Utility.GetPlatform(),__arch)), foss=__foss)
2256 files=VTL.GetSourceCode(2),
2257 source=os.path.join(__mcd_core_path,
"external",
"beos"),
2258 libs=[],include=[],dependency=[],
2260 output=os.path.join(os.path.join(__mcd_core_path,
"bin",Utility.GetPlatform(),__arch)), foss=__foss)
2262 BuildID =
"mcd_core"; py2x(BuildID, foss=__foss)
2264 fformat = settings.pop(
"format")
2266 py2x(project, command=VTL.GetBuildCommand(0, _format=fformat), **settings)
2272 Inherited class to build projects using PyInstaller.
2276 Initialization of PyInstaller class object.
2278 @note Creates stand-alone application of Python scripts using PyInstaller.
2280 super(PyInstaller, self).
__init__(*args, **kwargs)
2285 self.
buildtype = kwargs.get(
"type",
"onefile")
2298 Encrypt byte-code by using user-supplied or randomly generated key.
2301 @param encrypt: Boolean
2304 self.
key_string = kwargs.get(
"key_string",
''.join(random.choice(string.ascii_uppercase + string.ascii_lowercase + string.digits)
for _
in range(16)))
2309 Assemble command string for the pre-build event.
2317 def Build(self, mode="onefile", **kwargs):
2319 Switch build mode. Defaults to one single file.
2324 from PyInstaller.compat
import is_py27
2326 is_py27 = sys.version_info[0] == 2
2328 from PyInstaller.compat
import is_py35, is_py36, is_py37
2331 from setuptools
import __version__
as set_version
2332 from PyInstaller
import __version__
as pyi_version
2343 self.
makecmdmakecmdmakecmd.append(
"--icon=%s" % kwargs.get(
"icon",os.path.join(Path2Config,
"stm_logo.ico")))
2346 if version.parse(
"45.0.0") < version.parse(set_version) < version.parse(
"49.0.0"):
2349 if version.parse(set_version) >= version.parse(
"64.0.0"): self.
makecmdmakecmdmakecmd.insert(1,
'--hidden-import=%s' %
"requests")
2352 if Utility.GetPlatform()
in [
"windows"]:
2354 if Utility.GetExecutable(
"upx"): self.
makecmdmakecmdmakecmd.append(
"--upx-dir=%s" % Utility.GetExecutable(
"upx", get_path=
True)[-1])
2356 elif os.path.exists(os.path.join(PyXMakePath,
"Build",
"bin",
"upx")): self.
makecmdmakecmdmakecmd.append(
"--upx-dir=%s" % os.path.join(PyXMakePath,
"Build",
"bin",
"upx"))
2360 excludes = [
"python2.dll",
"python27.dll",
"qwindows.dll"]
2362 excludes = [x
for x
in os.listdir(os.path.dirname(sys.executable))
if x.endswith((
".dll"))]
2364 excludes = [x
for x
in os.listdir(os.path.dirname(sys.executable))
if x.endswith((
".dll"))]
2366 excludes = [
"python3.dll",
"python37.dll",
"ucrtbase.dll",
"qwindows.dll"]
2373 if version.parse(scipy.__version__) <= version.parse(
"1.6.3"): excludes.extend(Utility.ArbitraryFlattening([x[-1]
for x
in os.walk(scipy.__path__[0])]))
2376 upx_exclude = [
"--upx-exclude=%s" % x
for x
in excludes]
2382 add_compile = list(Utility.ArbitraryFlattening(kwargs.get(
"add_compile",[])))
2385 if hasattr(self,
"incdirs"):
2387 if os.path.exists(data.split(os.path.pathsep)[0]):
2388 new_path = data.split(os.path.pathsep)[0]
2390 if Utility.PathLeaf(new_path).endswith(
".py")
and Utility.PathLeaf(new_path)
in add_compile:
2391 py_compile.compile(new_path,os.path.join(self.
scrtdirscrtdir,Utility.PathLeaf(new_path)+
"c"))
2393 new_path = os.path.join(self.
scrtdirscrtdir,Utility.PathLeaf(new_path)+
"c")
2394 data = os.path.pathsep.join([new_path,data.split(os.path.pathsep)[1]])
2397 for path
in sys.path:
2398 new_path = os.path.join(path,data.split(os.path.pathsep)[0])
2399 if os.path.exists(new_path)
and os.path.isdir(new_path):
2401 if not kwargs.get(
"add_plain",
False):
2402 for root, _, files
in Utility.PathWalk(new_path):
2404 if any(x
in root
for x
in [
".git",
".svn"]):
2408 if not file.endswith((
".pdf"))
and not any(x
in file
for x
in [
".cpython"]):
2409 base_path = data.split(os.path.pathsep)[-1]; sub_path = root.split(base_path)[-1]
2410 sub_struct =os.path.join(base_path,sub_path.lstrip(os.path.sep),
".")
2412 if len(data.split(os.path.pathsep)) != 1:
2413 save_path = os.path.join(data.split(os.path.pathsep)[-1],
".")
2415 save_path = sub_struct
2417 if file.endswith(
".py")
and os.path.exists(os.path.join(new_path,file+
"c")):
2419 elif file.endswith(
".py")
and file
in add_compile:
2421 py_compile.compile(os.path.join(new_path.split(data.split(os.path.pathsep)[0])[0],sub_struct.rstrip(
"."),file),
2422 os.path.join(new_path.split(data.split(os.path.pathsep)[0])[0],sub_struct.rstrip(
"."),file+
"c"))
2425 self.
makecmdmakecmdmakecmd.insert(1,
'--add-data=%s' % os.path.pathsep.join([os.path.join(new_path.split(
2426 data.split(os.path.pathsep)[0])[0],sub_struct.rstrip(
"."),file),save_path]))
2429 self.
makecmdmakecmdmakecmd.insert(1,
'--add-data=%s' % os.path.pathsep.join([new_path,data.split(os.path.pathsep)[-1]]))
2432 elif os.path.exists(new_path)
and os.path.isfile(new_path):
2433 if Utility.PathLeaf(new_path).endswith(
".py")
and Utility.PathLeaf(new_path)
in add_compile:
2434 py_compile.compile(new_path,os.path.join(self.
scrtdirscrtdir,Utility.PathLeaf(new_path)+
"c"))
2436 new_path = os.path.join(self.
scrtdirscrtdir,Utility.PathLeaf(new_path)+
"c")
2437 self.
makecmdmakecmdmakecmd.insert(1,
'--add-data=%s' % os.path.pathsep.join([new_path,os.path.join(os.path.dirname(data.split(os.path.pathsep)[-1]),
".")]))
2443 if hasattr(self,
"scrtdir"):
2448 if hasattr(self,
"outdir"):
2452 if hasattr(self,
"libdirs"):
2457 if hasattr(self,
"key_string")
and version.parse(pyi_version) <= version.parse(
"6.0.0"):
2467 if hasattr(self,
"verbose"):
2479 Execute the current class as a CLI command.
2482 from PyXMake.VTL
import app
2484 command = kwargs.get(
"command",sys.argv)
2485 parser = argparse.ArgumentParser(description=
"Build a stand-alone python application.")
2486 parser.add_argument(
'name', type=str, nargs=1, help=
"Name of the project")
2487 parser.add_argument(
'source', type=str, nargs=1, help=
"Absolute path to the source file directory.")
2488 parser.add_argument(
'-f',
'--file', nargs=
'+', default=[], help=
"Main entry point file.")
2489 parser.add_argument(
'-i',
'--include', nargs=
'+', default=[], help=
"Additional files and folders required by the final executable.")
2490 parser.add_argument(
'-d',
'--dependency', nargs=
'+', default=[], help=
"Additional search paths to resolve dependencies.")
2491 parser.add_argument(
"-o",
"--output", type=str, nargs=1, help=
"Absolute path to output directory. Defaults to current project folder.")
2492 parser.add_argument(
'-s',
'--scratch', nargs=
'+', default=[], help=
"Default scratch folder for the build. Defaults to current workspace.")
2493 parser.add_argument(
"-v",
"--verbosity", type=str, nargs=1, help=
"Level of verbosity. Defaults to 0 - meaning no output. Max value is 2.")
2494 parser.add_argument(
"-m",
"--mode", type=str, nargs=1, default=
"onefile", help=
"Build type. Can be toggled between 'onefile' and 'onedir'.")
2495 parser.add_argument(
'--icon', type=str, nargs=1, help=
"Absolute path to a custom icon for the executable. Format: *.ico")
2496 parser.add_argument(
"--encryption", type=Utility.GetBoolean, const=
True, default=
False, nargs=
'?',
2497 help=
"Toggle between encryption and non-encryption build. Defaults to False.")
2502 args, _ = parser.parse_known_args(command[1:])
2504 project = args.name[0]
2506 source = args.source[0] ;
2508 try: file = args.file
2511 try: output = args.output[0]
2512 except: output = os.path.abspath(os.getcwd())
2514 try: encryption = args.encryption[0]
2515 except: encryption =
False
2517 try: scratch = args.scratch[0]
2518 except: scratch = os.path.abspath(os.getcwd())
2520 try: include = args.include[0]
2521 except: include = []
2523 try: dependency= args.dependency[0]
2524 except: dependency = []
2526 try: mode = args.mode[0]
2527 except: mode =
"onefile"
2529 try: verbosity = int(args.verbosity[0])
2530 except: verbosity = 0
2532 try: icon = str(args.icon[0])
2535 settings = {
"script":file,
2536 "source":source,
"output":output,
"scratch":scratch,
2537 "mode":mode,
"encryption": encryption,
2538 "verbosity":verbosity,
"icon":icon}
2540 if include: settings.update({
"include":include})
2541 if dependency: settings.update({
"dependency":dependency})
2543 except Exception
as _:
2546 if AllowDefaultMakeOption: app(str(BuildID.lower()), mode=
"onedir")
2548 else: app(project, **settings)
2553 Execute make command
2556 import PyInstaller.__main__
as pyi
2559 sys.setrecursionlimit(kwargs.get(
"recursion_limit",int(os.getenv(
"pyx_recursion_limit",5000))))
2579 shutil.rmtree(
'build', ignore_errors=
True)
2588 Inherited class to build projects using NSIS.
2592 Initialization of PyInstaller class object.
2594 @note Creates a portable installer of a source folder using NSIS.
2596 super(NSIS, self).
__init__(*args, **kwargs)
2607 self.
path2exe = os.path.join(PyXMakePath,
"Build",
"bin",
"nsis",
"App",
"NSIS")
2612 if Utility.GetExecutable(
"makensis"):
2620 def FTP(self, user, key, upload_file, host='ftp.dlr.de', path="/public/download/nightly"):
2622 Define settings to establish a FTP connection.
2629 with open(upload_file,
'rb')
as file:
2630 self.
ftp_client.storbinary(
"STOR %s" % Utility.PathLeaf(upload_file), file)
2636 Execute the current class as a CLI command.
2639 from PyXMake.VTL
import bundle
2641 command = kwargs.get(
"command",sys.argv)
2643 parser = argparse.ArgumentParser(description=
"Create a portable distribution using a compressed archive or NSIS")
2644 parser.add_argument(
'name', type=str, nargs=1, help=
"Name of the resulting archive(s).")
2645 parser.add_argument(
'source', type=str, nargs=1, help=
"Absolute path to distribution folder.")
2646 parser.add_argument(
'-f',
'--files', nargs=
'+', default=[], help=
"Source file or list of all source files used in the creation of the documentation.")
2647 parser.add_argument(
"-o",
"--output", type=str, nargs=1, help=
"Absolute path to output directory. Defaults to current working directory.")
2648 parser.add_argument(
"-e",
"--exclude", nargs=
'+', default=[], help=
"File extensions to be ignored during the process")
2649 parser.add_argument(
'-s',
'--scratch', nargs=
'+', default=[], help=
"Default scratch folder for the build. Defaults to current workspace.")
2650 parser.add_argument(
"-v",
"--verbosity", type=str, nargs=1, help=
"Level of verbosity. Defaults to 0 - meaning no output. Max value is 2.")
2651 parser.add_argument(
"--use_nsis", type=Utility.GetBoolean, const=
True, default=
False, nargs=
'?', help=
"Create an archive using NSIS. Defaults to False.")
2652 parser.add_argument(
'--extensions', nargs=argparse.REMAINDER,
2654 All archive extensions. Defaults to tar.gz. List given as string separated by commas.
2655 Possible values are <zip>, <tar>, <tar.gz>, <bz2>.
2664 args, _ = parser.parse_known_args(command[1:])
2666 project = args.name[0]
2668 source = args.source[0] ;
2670 try: files = args.files
2673 try: output = args.output[0]
2674 except: output = os.path.abspath(os.getcwd())
2676 try: check = args.use_nsis[0]
2677 except: check =
False
2679 try: scratch = args.scratch[0]
2680 except: scratch = os.path.abspath(os.getcwd())
2682 try: excludes = args.exclude[0]
2683 except: excludes = [
".git",
".svn",
"__pycache__"]
2685 try: extensions= args.extensions[0]
2686 except: extensions = delimn.join([
"tar",
"tar.gz",
"tar.bz2",
"zip"])
2687 finally: extensions = extensions.split(delimn)
2689 settings = {
"source":source,
"output":output,
"extensions":extensions,
"files":files,
2690 "scratch": scratch,
"excludes":excludes,
"use_nsis": check}
2692 except Exception
as _:
2694 if AllowDefaultMakeOption:
2696 BuildID =
"PyCODAC"; bundle(str(BuildID.lower()), use_nsis=Utility.GetExecutable(
"makensis"))
2698 else: bundle(project, **settings)
2703 Execute make command
2705 space =
" "; point =
"."; newline =
'\n'
2708 script = [
"Unicode true"]
2709 script.append(
"!define MULTIUSER_EXECUTIONLEVEL user")
2712 script.append(
"!define ZIP2EXE_COMPRESSOR_LZMA")
2713 script.append(
"!define ZIP2EXE_INSTALLDIR `$EXEDIR`")
2714 script.append(
"!include `${NSISDIR}\Contrib\zip2exe\Base.nsh`")
2715 script.append(
"!include `${NSISDIR}\Contrib\zip2exe\Modern.nsh`")
2716 if kwargs.get(
"install_path",
""):
2717 script.append(
"InstallDir '%s'" % kwargs.get(
"install_path",
"$Desktop"))
2718 script.append(
"!insertmacro SECTION_BEGIN")
2719 script.append(
"SetOutPath $INSTDIR")
2722 script.append(
"File /r /x *.nsh `%s`" % os.path.join(kwargs.get(
"assembly_path", self.
srcdirsrcdir),src))
2723 script.append(
"!insertmacro SECTION_END")
2724 script.append(
'Icon "%s"' % kwargs.get(
"icon",os.path.join(Path2Config,
"stm_logo.ico")))
2725 script.append(
"RequestExecutionLevel user")
2730 MakeFile = Utility.GetTemporaryFileName(extension=
".nsh")
2733 with open(MakeFile,
"w")
as f:
2734 f.write(newline.join(script))
2752 if kwargs.get(
"upload",
False)
and not hasattr(self,
"ftp_client"):
2753 user = kwargs.get(
"user",os.getenv(
"username",
"")); key = kwargs.get(
"key",
"")
2757 print(
"==================================")
2758 print(
"Uploaded result to given FTP server")
2759 print(
"==================================")
2768 Inherited class to automatically build a documentation using Doxygen.
2772 Initialization of doxygen class object.
2774 super(Doxygen, self).
__init__(*args,**kwargs)
2778 os.environ[
'dox_pyjava'] =
'NO'
2779 os.environ[
'dox_fortran'] =
'NO'
2780 os.environ[
'dox_ccpp'] =
'NO'
2781 os.environ[
'dox_pdflatex'] =
'NO'
2785 self.
path2exe = os.path.join(PyXMakePath,
"Build",
"bin",
"doxygen")
2792 if Utility.GetPlatform() ==
"linux": remove =
"rm -rf"
2795 if Utility.GetExecutable(
"doxygen"):
2796 _, doxy_path = Utility.GetExecutable(
"doxygen",get_path=
True)
2797 self.
path2exe = os.path.dirname(doxy_path)
2798 self.
exe = Utility.PathLeaf(doxy_path)
2801 Utility.Popen(
" ".join([os.path.join(self.
path2exe,self.
exe),
"-u",os.path.join(Path2Config,
"stm_doc_config")]),verbosity=0)
2807 os.environ[
'dox_fortran'] =
'YES'
2813 os.environ[
'dox_ccpp'] =
'YES'
2817 temp = []; delimn =
" "
2820 os.environ[
'dox_pyjava'] =
'YES'
2821 paths = list(Utility.ArbitraryFlattening(temp))
2825 for x
in os.listdir(y):
2826 if x.endswith((
".java",
".py")):
2827 if not any([z ==
"__init__.py" for z
in os.listdir(y)])
and x.endswith((
".py")):
2830 open(os.path.join(y,
"__init__.py"),
'a+').close()
2837 if y
in [os.path.dirname(k)
for k
in list(filter(os.path.isfile, self.
tempstempstemps))]:
2845 path = os.path.dirname(x)
2846 if os.path.exists(os.path.join(path,
"__init__.py")):
2866 os.environ[
"dox_version"] = str(1.0)
2867 os.environ[
'dox_images'] = Path2Config
2868 os.environ[
'dox_footer'] = os.path.join(Path2Config,
"stm_doc_footer.html")
2869 os.environ[
'dox_logo'] = os.path.join(Path2Config,
"stm_logo.png")
2870 os.environ[
'dox_pyfilter'] = (sys.executable+
" "+os.path.join(Path2Config,
"stm_pyfilter.py"))
if Utility.GetPlatform()
in [
"windows",
"nt"]
else (os.path.join(Path2Config,
"stm_pyfilter.py"))
2873 if not sys.executable
in os.getenv(
"PATH",
"")
and not Utility.GetPlatform()
in [
"windows",
"nt"]:
2874 os.environ[
'PATH'] = os.pathsep.join([sys.executable,os.getenv(
"PATH",
"")]);
2875 os.chmod(os.path.join(Path2Config,
"stm_pyfilter.py"), stat.S_IWOTH); os.chmod(os.path.join(Path2Config,
"stm_pyfilter.py"), stat.S_IXOTH)
2878 if not all([os.getenv(x)
for x
in (
"dox_hue",
"dox_sat",
"dox_gamma")]):
2879 from PyXMake.Build.config.stm_color
import DLRBlue
as dox_color
2880 os.environ[
'dox_hue'], os.environ[
'dox_sat'], os.environ[
'dox_gamma'] = [str(int(round(x)))
for x
in np.multiply([360.,100.,100],
2881 np.array(colorsys.rgb_to_hsv(*(value/255
for value
in
2882 ImageColor.getcolor(dox_color,
"RGB")))))]
2890 def Settings(self, brief, header, outdir='', **kwargs):
2892 Define environment variables for the default configuration file.
2900 os.environ[
'dox_brief'] = brief
2901 os.environ[
'dox_header'] = header
2905 if kwargs.get(
"version",
None): os.environ[
'dox_version'] = kwargs.get(
"version")
2906 if kwargs.get(
"icon",
None):
2908 user_defined_image = kwargs.get(
"icon")
2910 temporary_optimized_image =os.path.join(tempfile.mkdtemp(),
"doxygen_icon%s" % os.path.splitext(user_defined_image)[-1])
2912 base_width = kwargs.get(
"base_width",Image.open(os.path.join(os.getenv(
"dox_images"),
"stm_logo.png")).size[0])
2914 icon = Utility.GetResizedImage(user_defined_image, base_width)
2916 icon.save(temporary_optimized_image, optimize=
True, quality=95, **icon.info)
2918 os.environ[
"dox_logo"], os.environ[
"dox_icon"] = (temporary_optimized_image,)*2
2920 if kwargs.get(
"color",
""):
2922 os.environ[
'dox_hue'], os.environ[
'dox_sat'], os.environ[
'dox_gamma'] = [str(x)
for x
in np.multiply([360.,100.,100],
2923 np.array(colorsys.rgb_to_hsv(*(value/255
for value
in
2924 ImageColor.getcolor(kwargs.get(
"color"),
"RGB")))))]
2930 Execute the current class as a CLI command.
2933 from PyXMake.VTL
import doxygen
2935 command = kwargs.get(
"command",sys.argv)
2937 parser = argparse.ArgumentParser(description=
'CLI wrapper options for Doxygen with more sensible default settings.')
2938 parser.add_argument(
'name', type=str, nargs=1, help=
"Name of the project")
2939 parser.add_argument(
'source', type=str, nargs=1, help=
"Absolute path to the source file directory.")
2940 parser.add_argument(
'-t',
'--title', nargs=
'+', default=[], help=
"Header used in the documentation. If not given, defaults are created from the project name.")
2941 parser.add_argument(
'-f',
'--files', nargs=
'+', default=[], help=
"Source file or list of all source files used in the creation of the documentation.")
2942 parser.add_argument(
'-s',
'--scratch', nargs=
'+', default=[], help=
"Default scratch folder for Doxygen. Defaults to current workspace.")
2943 parser.add_argument(
"-o",
"--output", type=str, nargs=1, help=
"Absolute path to output directory. Defaults to current project folder.")
2944 parser.add_argument(
"-c",
"--config", type=str, nargs=1, help=
"Absolute path to user-supplied Doxygen configuration file. Can be left blank.")
2945 parser.add_argument(
'-l',
'--logo', nargs=
'+', default=[], help=
"Top level logo used by Doxygen. Defaults to structural mechanics department logo.")
2946 parser.add_argument(
"-v",
"--verbosity", type=str, nargs=1, help=
"Level of verbosity. Defaults to 0 - meaning no output. Max value is 2.")
2947 parser.add_argument(
"-ta",
"--tag", type=str, nargs=1, help=
"Documentation version tag. Defaults to 1.0 if not set.")
2948 parser.add_argument(
"-fo",
"--format", type=str, nargs=1, help=
"Toggle between Java, Fortran and Python code base. Defaults to Fortran.")
2949 parser.add_argument(
"-fi",
"--filter", type=str, nargs=1, help=
"JSON configuration string for this operation")
2950 parser.add_argument(
'--icon', type=str, nargs=1, help=argparse.SUPPRESS)
2955 args, _ = parser.parse_known_args(command[1:])
2957 project = args.name[0];
2959 source = args.source[0] ;
2963 header = [Utility.ArbitraryEval(x)
for x
in args.title]
2964 except: header = [project.title(),
"%s Developer Guide" % project.title()]
2966 try: output = args.output[0]
2967 except: output = os.path.abspath(os.getcwd())
2969 try: scratch = args.scratch[0]
2970 except: scratch = os.path.abspath(os.getcwd())
2972 try: fformat = args.format[0]
2973 except: fformat =
"Fortran"
2975 scfilter = {
"exclude":
True,
"startswith":(
".",
"__")}
2977 try: scfilter.update(json.loads(Utility.ArbitraryEval(args.filter[0])))
2982 files = [Utility.ArbitraryEval(x)
for x
in args.files]
2985 index = 0
if fformat !=
"Fortran" else -1
2986 files = [x[index]
for x
in Utility.PathWalk(os.path.abspath(source), **scfilter)]
2988 try: config = args.config[0];
2989 except: config = os.path.join(Path2Config,
"stm_doc_config")
2991 try: icon = args.logo[0]
2992 except: icon = getattr(args,
"icon", [
None] )
2993 if icon: icon = os.path.abspath(next(iter(icon)))
2995 try: tag = args.tag[0]
2996 except: tag = str(1.0)
2998 try: verbosity = int(args.verbosity[0])
2999 except: verbosity = 0
3001 settings = {
"title":header,
3003 "ftype":fformat,
"config":config,
3004 "source":source,
"output":output,
"scratch":scratch,
3005 "verbosity":verbosity,
3006 "icon":icon,
"version":tag}
3008 except Exception
as _:
3010 from PyXMake
import VTL
3011 from PyCODAC.Tools.Utility
import GetPyCODACPath
3013 if AllowDefaultMakeOption:
3015 BuildID =
"pyx_core"
3016 doxygen(BuildID, [
"PyXMake",
"PyXMake Developer Guide"],
3017 [x[0]
for x
in Utility.PathWalk(PyXMakePath, startswith=(
".",
"__"), contains=(
"doc",
"bin",
"config"), endswith=(
"make",
"scratch",
"examples"))],
"Python",
3018 output=os.path.join(PyXMakePath,
"VTL",
"doc",
"pyx_core"))
3020 BuildID =
"pyc_core"
3021 doxygen(BuildID, [
"PyCODAC",
"PyCODAC Developer Guide"],
3022 [x[0]
for x
in Utility.PathWalk(GetPyCODACPath(), startswith=(
".",
"__"),
3023 contains=(
"DELiS",
"Smetana",
"PyXMake",
"external",
"doc",
"cmd",
"bin",
"include",
"lib",
"config",
"fetch"),
3024 endswith=(
"VTL",
"make",
"scratch",
"examples",
"src",
"config",
"solver"))],
"Python",
3025 output=os.path.join(GetPyCODACPath(),
"VTL",
"doc",
"pyc_core"))
3027 BuildID =
"mcd_subbuck"
3028 doxygen(BuildID, [
"SubBuck",
"SubLaminate Buckling Developer Guide"],
3029 [x[0]
for x
in Utility.PathWalk(os.path.join(Utility.AsDrive(
"D"),
"03_Workspaces",
"01_Eclipse",
"mcd_subbuckling"))],
"Java",
3030 output=os.path.join(GetPyCODACPath(),
"VTL",
"doc",
"mcd_subbuckling"))
3032 BuildID =
"mcd_mapper"
3033 doxygen(BuildID, [
"Mapper",
"Damage Mapping Developer Guide"],
3034 [x[0]
for x
in Utility.PathWalk(os.path.join(Utility.AsDrive(
"D"),
"03_Workspaces",
"01_Eclipse",
"mcd_mapper"))],
"Java",
3035 output=os.path.join(GetPyCODACPath(),
"VTL",
"doc",
"mcd_mapper"))
3037 BuildID =
"box_core"
3038 doxygen(BuildID, [
"BoxBeam",
"BoxBeam Developer Guide"], VTL.GetSourceCode(1),
3039 source=os.path.join(os.path.join(GetPyCODACPath(),
"Core"),
"external",
"boxbeam"),
3040 output=os.path.join(GetPyCODACPath(),
"Plugin",
"BoxBeam",
"VTL",
"doc",
"box_core"))
3042 BuildID =
'mcd_core'
3046 doxygen(project, **settings)
3053 Inherited class to automatically build a documentation using Latex
3057 class __property(object):
3058 def __init__(self, getter): self.getter= getter
3059 def __get__(self, instance, owner):
return self.getter(owner)
3062 base_url = os.getenv(
"pyx_overleaf_url",
"https://overleaf.fa-services.intra.dlr.de")
3065 secret =
"pyc_overleaf_secret" if os.getenv(
"pyc_overleaf_secret",
"")
else "pyx_overleaf_secret"
3068 try: secret = open(os.getenv(secret,os.path.join(os.path.expanduser(
"~"),
"Keys",
"Keepass",
"fa_overleaf_access")),
"r").read()
3073 Initialization of Latex class object.
3076 if len(args) < 2: args += (
"",)
3078 super(Latex, self).
__init__(*args,**kwargs)
3083 from six
import exec_
3085 from sphinx
import package_dir
3088 silent_install = kwargs.get(
"silent_install",
False)
3092 if silent_install: exec_(open(__install__.__file__).read(),{
"__name__":
"__main__",
"__file__":__install__.__file__})
3095 os.environ[
"PATH"] += os.pathsep + os.pathsep.join([os.path.join(os.path.dirname(sys.executable),
"Scripts")])
3097 os.environ[
"TEXINPUTS"] = os.getenv(
"TEXINPUTS",
"")
3099 os.environ[
"TEXINPUTS"] += os.pathsep + os.pathsep.join([os.path.join(package_dir,
"texinputs"),os.path.join(PyXMakePath,
"Build",
"config")])
3109 if os.path.exists(self.
srcs[0]):
3114 if kwargs.get(
"secret",
None): Latex.secret = kwargs.get(
"secret")
3124 API access token defined as a protected class property for backwards compatibility.
3125 Works for both Python 2 and 3. Only meaningful when a remote Latex instance shall be called.
3127 if not getattr(self,
"_auth",{}):
3130 result = self.
session(*base64.b64decode(self.
secret).decode(
'utf-8').split(
":",1), base_url=self.
base_url, use_cache=
False) ;
3131 self.
_auth = result[-1] ;
3138 Define environment variables for the default configuration file.
3141 os.environ[
"TEXINPUTS"] += os.pathsep + os.pathsep.join([str(value)
for value
in kwargs.values()])
3147 Create all required session tokens for an active Overleaf instance.
3149 status_code = 500; result = {}
3151 if kwargs.get(
"use_cache",
True):
return [200,copy.deepcopy(getattr(cls,
"auth",{}))]
3154 from bs4
import BeautifulSoup
3156 session = requests.Session()
3157 email, password = args
3159 login_url =
"{}/login".format(kwargs.get(
"base_url", cls.
base_url)
or cls.
base_url)
3161 r = session.get(login_url); csrf = BeautifulSoup(r.text,
'html.parser').find(
'input', {
'name' :
'_csrf' })[
'value']
3162 r = session.post(login_url, {
'_csrf' : csrf ,
'email' : email ,
'password' : password })
3164 r.json(); status_code = 403;
3165 result =
"The given credentials could not be verified."
3167 return [status_code, result]
3171 r = session.get(login_url); csrf = BeautifulSoup(r.text,
'html.parser').find(
'input', {
'name' :
'_csrf' })[
'value']
3173 if r.status_code == 200:
3174 status_code = r.status_code; result = {
"Cookie":r.headers.pop(
"Set-Cookie").split(ntpath.pathsep)[0],
"_csrf":csrf}
3176 r.raise_for_status()
3180 return [status_code, result]
3183 def show(cls,ProjectID, *args, **kwargs):
3185 Show all build files from an Overleaf project remotely given its ID.
3187 @note: Rebuilds the project in the process.
3190 code, result = cls.
session(*args, **kwargs)
3191 if code != 200:
return [code, result]
3193 header = result; header.update({
'Content-Type':
'application/json;charset=utf-8' })
3195 project_url =
"{}/project".format(kwargs.get(
"base_url", cls.
base_url)
or cls.
base_url)
3197 requests.delete(posixpath.join(project_url,ProjectID,
"output"),headers={
"X-Csrf-Token" if k ==
"_csrf" else k:v
for k,v
in result.items()})
3199 r = requests.post(posixpath.join(project_url,ProjectID,
"compile"),params={
"auto_compile":
True}, headers=header,
3200 data=json.dumps({
"check":
"silent",
"incrementalCompilesEnabled":
True,
"_csrf":header.pop(
"_csrf")}))
3202 if r.status_code == 200:
return r.json()[
"outputFiles"]
3206 def rename(cls, ProjectID, ProjectName, *args, **kwargs):
3208 Rename an Overleaf project remotely given its ID.
3211 code, result = cls.
session(*args, **kwargs)
3212 if code != 200:
return [code, result]
3214 header = result; header.update({
'Content-Type':
'application/json;charset=utf-8' })
3216 data = {
"_csrf":result.pop(
"_csrf")}
3217 data.update({
"newProjectName":str(ProjectName)})
3219 project_url =
"{}/project".format(kwargs.get(
"base_url", cls.
base_url)
or cls.
base_url)
3221 r = requests.post(posixpath.join(project_url,ProjectID,
"rename"), headers=result, data=json.dumps(data))
3223 if r.status_code == 200:
return {
"success":
True,
"message":r.text}
3229 Upload a given archive to an active Overleaf instance creating a new project.
3234 code, result = cls.
session(*args, **kwargs)
3235 if code != 200:
return [code, result]
3237 upload_url =
"{}/project/new/upload".format(kwargs.get(
"base_url", cls.
base_url)
or cls.
base_url)
3238 filename = os.path.basename(archive)
3239 mime =
"application/zip"
3240 files = {
"qqfile": (filename, open(archive,
"rb"), mime),
"name": (
None, filename)}
3242 "_csrf":result.pop(
"_csrf"),
3243 "qquid": str(uuid.uuid4()),
3244 "qqfilename": filename,
3245 "qqtotalfilesize": os.path.getsize(archive),
3248 r = requests.post(upload_url,params=params, files=files, headers=result)
3250 r.raise_for_status(); response = r.json()
3251 except Exception:
pass
3253 if not "success" in response:
raise Exception(
"Uploading of %s failed." % archive )
3255 cls.
rename(r.json()[
"project_id"], str(filename.split(
".")[0]).title(), *args, **kwargs)
3262 Download the complete archive or final pdf from an Overleaf project given its ID.
3265 code, result = cls.
session(*args, **kwargs)
3266 if code != 200:
return [code, result]
3268 endpoint = posixpath.join(
"download",
"zip")
3270 if kwargs.get(
"output_format",
"zip")
in [
"pdf"]:
3272 endpoint = [x[
"url"]
for x
in cls.
show(ProjectID, *args, **kwargs)
3273 if str(x[
"url"]).endswith(
"output.pdf")][0]
3276 endpoint = next(iter([ posixpath.join(
"user",endpoint.split(
"user")[-1].replace(posixpath.sep,
"",1))
3277 if "user" in endpoint.split(posixpath.sep)[:4]
3278 else posixpath.join(
"build",endpoint.split(
"build")[-1].replace(posixpath.sep,
"",1)) ] ))
3280 project_url =
"{}/project".format(kwargs.get(
"base_url", cls.
base_url)
or cls.
base_url)
3282 r = requests.get(posixpath.join(project_url,ProjectID,endpoint), headers=result , stream=
True)
3284 output = os.path.abspath(
".".join([os.path.join(os.getcwd(),ProjectID),endpoint[-3:]]))
3286 with open(output,
"wb")
as f:
3287 for chunk
in r.iter_content(chunk_size=1024):
3288 if chunk: f.write(chunk)
3295 Delete an Overleaf project given its ID.
3298 forever = kwargs.get(
"forever",
False)
3300 code, result = cls.
session(*args, **kwargs)
3301 if code != 200:
return [code, result]
3303 header = result; header.update({
'Content-Type':
'application/json;charset=utf-8' })
3305 project_url =
"{}/project".format(kwargs.get(
"base_url", cls.
base_url)
or cls.
base_url)
3307 r = requests.delete(posixpath.join(project_url,ProjectID), data=json.dumps({
"forever": forever,
"_csrf":header.pop(
"_csrf")}), headers=header)
3308 r.raise_for_status()
3310 return {
"success":
True,
"message":r.text}
3315 Execute the current class as a CLI command.
3318 from PyXMake.VTL
import latex
3320 command = kwargs.pop(
"command",sys.argv)
3322 parser = argparse.ArgumentParser(description=
"Compile a TeXfile using MikTeX or Overleaf with custom templates.")
3323 parser.add_argument(
'name', type=str, nargs=1, help=
"Name of the project")
3324 parser.add_argument(
'source', type=str, nargs=1, metavar=
"main.tex", help=
"Absolute path to the main source file. Must be either a Texfile or an archive.")
3325 parser.add_argument(
'-a',
'--api', type=str, nargs=1, default=
"texworks", help=
"Additional files required for the process.")
3326 parser.add_argument(
'-i',
'--include', nargs=
'+', default=[], help=
"Additional files required for the compilation process.")
3327 parser.add_argument(
"-v",
"--verbosity", type=str, nargs=1, help=
"Level of verbosity. Defaults to 0 - meaning no output. Max value is 2.")
3332 args, _ = parser.parse_known_args(command[1:])
3334 project = args.name[0];
3336 source = args.source[0] ;
3338 try: config = args.api[0]
3339 except: config =
"texworks"
3341 try: scratch = args.scratch[0]
3342 except: scratch = os.path.abspath(os.getcwd())
3347 include = Utility.GetSanitizedDataFromCommand(args.include)
3349 except: include = []
3351 try: verbosity = int(args.verbosity[0])
3352 except: verbosity = 2
3354 settings = {
"file":source,
"API":config,
"include":include,
"scratch":scratch,
"verbosity": verbosity}
3357 except Exception
as _:
3359 if AllowDefaultMakeOption:
3361 with Utility.TemporaryDirectory():
3365 from urllib.request
import urlretrieve
3367 BuildID =
"elsevier"
3368 filename =
"elsarticle.zip"
3369 url =
"https://mirrors.ctan.org/macros/latex/contrib/elsarticle.zip"
3371 settings = copy.deepcopy(kwargs)
3373 if os.getenv(
"CI_USER",
"")
and os.getenv(
"CI_PASSWORD",
""):
3374 settings.update({
"secret": Utility.GetDockerEncoding(os.getenv(
"CI_USER"),os.getenv(
"CI_PASSWORD"))})
3376 urlretrieve(url, filename); latex(BuildID, filename, API=
"Overleaf", **settings)
3379 latex(project, **settings)
3382 def create(self, API="TeXworks", GUI=True, **kwargs):
3384 Compile an existing project and/or start the graphical user interface.
3388 os.environ[
"TEXINPUTS"] += os.pathsep + os.pathsep.join([str(include)
for include
in self.
incdirsincdirs])
3391 if API.lower()
in [
"overleaf"]:
3393 archive = os.path.abspath(self.
srcs[0])
3397 shutil.copy(archive, os.getcwd())
3399 result = self.
upload(archive)
3402 ProjectID = result[
"project_id"]
3404 self.
download(ProjectID, output_format=
"pdf")
3408 if not kwargs.get(
"keep",
False): self.
delete(ProjectID)
3410 result_file = [x
for x
in os.listdir()
if x.endswith(
".pdf")][0]
3413 except Exception
as e: print(e.args())
3416 elif API.lower()
in [
"texworks"]:
3417 if os.path.exists(self.
srcs[0]):
3418 command.append(self.
srcs[0])
3420 if GUI
or not os.path.exists(self.
srcs[0]):
3422 command.insert(0,
"texworks.exe")
3423 subprocess.Popen(command, close_fds =
True, **Make.Detach())
3425 with tempfile.TemporaryDirectory(dir=self.
scrtdirscrtdir)
as temp:
3429 output = os.path.splitext(Utility.PathLeaf(command[-1]))[0] +
".pdf"
3431 command[0:0] = [
"texify.exe",
"--pdf",
"--tex-option=-shell-escape",
"--synctex=1",
"--clean"]
3435 shutil.copyfile(output, os.path.join(self.
outdiroutdir,output))
3439 else:
raise NotImplementedError
3443 def __new(cls, ProjectName=None, *args, **kwargs):
3445 Create a new project within the current session
3448 forever = kwargs.get(
"forever",
False)
3450 code, result = cls.
session(*args, **kwargs)
3451 if code != 200:
return [code, result]
3453 if not ProjectName: ProjectID = str(getattr(cls,
"buildid",ProjectName))
3454 if not ProjectID:
raise ValueError
3456 header = result; header.update({
'Content-Type':
'application/json;charset=utf-8' })
3458 project_url =
"{}/project/new".format(kwargs.get(
"base_url", cls.
base_url)
or cls.
base_url)
3461 "_csrf": header.pop(
"_csrf"),
3462 "template": kwargs.get(
"template",
"template"),
3463 "projectName": ProjectID,
3467 r = requests.post(project_url, data=json.dumps(data), headers=header)
3468 r.raise_for_status()
3470 return {
"success":
True,
"message":r.text,
"response":r.json()}
3479 Inherited class to automatically build a coverage report using Coverage.
3483 Initialization of coverage class object.
3486 try: self.
isDecorator = kwargs.pop(
"__as_decorator",any(line.startswith(
'@')
for line
in inspect.stack(context=2)[1].code_context))
3491 super(Coverage, self).
__init__(*args,**kwargs)
3503 Implement an executable variant if class is used as a decorator.
3507 isPytest = self.
kwargs.pop(
"autorun",
False)
or self.
show()
3509 @functools.wraps(fn)
3510 def decorated(*args, **kwargs):
3512 Execute this part with given *args and **kwargs and the underlying function
3515 if isPytest
and not getattr(decorated,
"has_run",
False):
3516 compare = self.
kwargs.pop(
"result",
None);
3519 except Exception
as e:
raise e
3522 if compare:
assert result == compare
3524 decorated.has_run =
True
3526 result = fn(*args, **kwargs)
3532 except TypeError:
pass
3534 if not hasattr(decorated,
"has_run"): decorated.has_run =
False
3540 Get a boolean value if this function is called within an active test environment
3543 return str(
"pytest")
in sys.modules
or str(
"PYTEST_CURRENT_TEST")
in os.environ
3548 Provide a test case for the given method as a decorator.
3550 kwargs.update({
"__as_decorator":
True})
3552 if getattr(sys,
'frozen',
False)
and hasattr(sys,
'_MEIPASS'):
3553 def decorator(func):
return func
3556 else:
return cls(*args,**kwargs)
3561 Execute the current class as a CLI command.
3564 from PyXMake.VTL
import coverage
3566 command = kwargs.get(
"command",sys.argv)
3568 parser = argparse.ArgumentParser(description=
'CLI wrapper options for Coverage with more sensible default settings.')
3569 parser.add_argument(
'name', type=str, nargs=1, help=
"Name of the project")
3570 parser.add_argument(
'source', type=str, nargs=1, help=
"Absolute path to the source file directory.")
3571 parser.add_argument(
'-i',
'--include', nargs=
'+', default=[], help=
"Additional files defining test cases required for test coverage.")
3572 parser.add_argument(
"-o",
"--output", type=str, nargs=1, help=
"Absolute path to output directory. Defaults to current project folder.")
3573 parser.add_argument(
"-e",
"--exclude", nargs=
'+', default=[], help=
"Full paths to be ignored from the coverage.")
3574 parser.add_argument(
"-v",
"--verbosity", type=str, nargs=1, help=
"Level of verbosity. Defaults to 0 - meaning no output. Max value is 2.")
3579 args, _ = parser.parse_known_args(command[1:])
3581 project = args.name[0];
3583 source = os.path.abspath(args.source[0]) ;
3588 include = Utility.GetSanitizedDataFromCommand(args.include)
3590 except: include = []
3592 try: output = args.output[0]
3593 except: output = os.path.abspath(os.getcwd())
3598 exclude = Utility.GetSanitizedDataFromCommand(args.exclude)
3599 except: exclude = []
3601 try: verbosity = int(args.verbosity[0])
3602 except: verbosity = 0
3604 source = [r
for r, _, f
in Utility.PathWalk(source)
if any(x
in [
"__init__.py"]
for x
in f)][0]
3606 settings = {
"source":source,
"output":output,
"include":include,
"exclude_paths":exclude,
"verbosity":verbosity}
3609 except Exception
as _:
3611 if AllowDefaultMakeOption:
3617 coverage(project, **settings)
3620 def Build(self, command=["--cov-fail-under=10","--cov-report=term-missing","--cov-report=html","--cov-report=xml","--junit-xml=junit.xml", "-W ignore::pytest.PytestAssertRewriteWarning
"], **kwargs):
3622 Assemble command strings for the main build event.
3632 Execute make command
3636 sys_arg_recovery = copy.deepcopy(sys.argv);
3638 try: sys.argv[1:] = []
3639 except IndexError:
pass
3641 sys_path_recovery = copy.deepcopy(sys.path)
3643 _ = [ sys.path.pop(i)
for i, x
in enumerate(sys.path)
if x.endswith(
"VTL") ]
3645 try:
import pytest_cov
as _
3646 except:
raise ImportError
3651 from ..
import PyXMakePath
3654 if not hasattr(self,
"makecmd"): self.
BuildBuild(**kwargs)
3663 config = kwargs.get(
"config",
None)
3664 configfiles = [
"pytest.ini",
"pyproject.toml",
"tox.ini",
"setup.cfg"]
3667 if any(x
in os.listdir(os.getcwd())
for x
in configfiles)
and not config:
3669 for i, x
in enumerate(configfiles):
3670 if os.path.exists(x):
break
3672 config = os.path.abspath(os.path.join(os.getcwd(),configfiles[i]))
3675 test_directory =
"tests"
3678 with Utility.TemporaryDirectory(), Utility.TemporaryEnvironment():
3679 os.mkdir(test_directory);
3681 [shutil.copy(x,os.path.join(os.getcwd(),test_directory,Utility.PathLeaf(x)))
for x
in self.
incdirsincdirs if os.path.isfile(x)]
3683 for file
in os.listdir(os.path.join(os.getcwd(),test_directory)):
3684 with open(os.path.join(test_directory,delimn.join([
"test",Utility.PathLeaf(file)])),
"w")
as f:
3685 f.write(
"import runpy" +
"\n")
3686 f.write(
'def test_script():'+
"\n")
3687 f.write(
" try: runpy.run_path('%s', run_name='__main__')" % str(os.path.join(test_directory,file)).replace(ntpath.sep,ntpath.sep*2) +
"\n")
3688 f.write(
" except SystemExit as exception: exitcode = exception.code" +
"\n")
3689 f.write(
" else: exitcode = 0" +
"\n")
3691 [shutil.copy(os.path.join(self.
srcdirsrcdir,x),os.path.join(os.getcwd(),test_directory))
for x
in os.listdir(self.
srcdirsrcdir)
3692 if os.path.isfile(os.path.join(self.
srcdirsrcdir,x))
and x.startswith(
"test_")]
3695 with open(os.path.join(test_directory,delimn.join([
"test",Utility.PathLeaf(os.path.dirname(path)),
".py"])),
"w")
as f:
3696 f.write(
"import os; import pkgutil;"+
"\n")
3697 f.write(
'os.environ.update(%s)' % str(os.environ.copy()) +
"\n")
3698 f.write(
'__all__ = [] ; __path__ = ["%s"];' % os.path.dirname(path).replace(ntpath.sep,ntpath.sep*2) +
"\n")
3699 f.write(
'def test_import():'+
"\n")
3700 f.write(
' for loader, module_name, is_pkg in pkgutil.walk_packages(__path__):'+
"\n")
3701 f.write(
' __all__.append(module_name); '+
"\n")
3702 f.write(
' _module = loader.find_module(module_name).load_module(module_name);'+
"\n")
3703 f.write(
' globals()[module_name] = _module'+
"\n")
3706 with open(
".coveragerc",
"w")
as f:
3707 f.write(
"[run]"+
"\n");
3709 if kwargs.get(
"exclude_paths",[]): f.write(
"omit = "+
"\n");
3710 for x
in kwargs.get(
"exclude_paths",[]):
3712 if os.path.isfile(x): path = str(x)
3713 else: path = str(x) + os.path.sep +
"*"
3715 f.write(
" *%s" % path +
"\n");
3717 f.write(
"[report]"+
"\n");
3718 f.write(
"exclude_also ="+
"\n");
3719 f.write(
" def __repr__"+
"\n");
3720 f.write(
" if self.debug:"+
"\n");
3721 f.write(
" if settings.DEBUG"+
"\n");
3722 f.write(
" raise AssertionError"+
"\n");
3723 f.write(
" raise NotImplementedError"+
"\n");
3724 f.write(
" if 0:"+
"\n");
3725 f.write(
" except"+
"\n");
3726 f.write(
" if __name__ == .__main__.:"+
"\n");
3727 f.write(
" if TYPE_CHECKING:"+
"\n");
3728 f.write(
" class .*\bProtocol\):"+
"\n");
3729 f.write(
" @(abc\.)?abstractmethod"+
"\n");
3733 if config: shutil.copy(config, os.path.abspath(os.getcwd()))
3735 else: command.extend([
"--rootdir=%s" % os.path.join(os.getcwd())])
3737 command.extend([
"--cov-config=.coveragerc"])
3739 command.extend([
"--import-mode=importlib"])
3741 command.extend([
'--override-ini="testpaths=%s"' % str(test_directory)])
3746 command.extend([os.path.join(os.getcwd(),test_directory)]); pytest.main(command)
3748 result = [x
for x
in os.listdir(os.getcwd())
if x.startswith((
"coverage",
"htmlcov",
"junit",))]
3752 if os.path.isdir(x):
3755 finally: shutil.copytree(x,os.path.join(self.
outdiroutdir,x));
3757 else: shutil.copy(x, os.path.join(self.
outdiroutdir,x))
3759 sys.argv = sys_arg_recovery
3761 sys.path = sys_path_recovery
3768 Inherited class to automatically build a documentation using Sphinx.
3772 Initialization of sphinx class object.
3774 super(Sphinx, self).
__init__(*args,**kwargs)
3779 from six
import exec_
3781 exec_(open(__install__.__file__).read(),{
"__name__":
"__main__",
"__file__":__install__.__file__})
3784 os.environ[
"PATH"] += os.pathsep + os.pathsep.join([os.path.join(os.path.dirname(sys.executable),
"Scripts")])
3788 self.
path2exe = os.path.join(os.path.dirname(sys.executable),
"Scripts")
3795 os.environ[
"sphinx_project"] = str(self.
buildid)
3798 os.environ[
"sphinx_master"] = str(self.
srcs[0])
3801 from PyXMake.Build.config.stm_color
import DLRBlue
as sphinx_color
3802 os.environ[
"sphinx_color"] = sphinx_color
3812 Define environment variables for the default configuration file.
3816 for key, value
in kwargs.items():
3817 os.environ[delimn.join([
"sphinx",str(key)])] = str(value)
3823 Execute the current class as a CLI command.
3826 from PyXMake.VTL
import sphinx
3828 command = kwargs.get(
"command",sys.argv)
3830 parser = argparse.ArgumentParser(description=
'CLI wrapper options for Sphinx with more sensible default settings.')
3831 parser.add_argument(
'name', type=str, nargs=1, help=
"Name of the project")
3832 parser.add_argument(
'source', type=str, nargs=1, help=
"Absolute path to the source file directory.")
3833 parser.add_argument(
'-f',
'--file', nargs=
'+', default=[], help=
"Top level input file used in the creation of the documentation.")
3834 parser.add_argument(
'-l',
'--logo', nargs=
'+', default=[], help=
"Top level logo in SVG format.")
3835 parser.add_argument(
'-i',
'--include', nargs=
'+', default=[], help=
"Additional files defining test cases required for test coverage.")
3836 parser.add_argument(
'-s',
'--scratch', nargs=
'+', default=[], help=
"Default scratch folder for Sphinx. Defaults to current workspace.")
3837 parser.add_argument(
"-o",
"--output", type=str, nargs=1, help=
"Absolute path to output directory. Defaults to current project folder.")
3838 parser.add_argument(
'-t',
'--theme', type=str, nargs=1, help=
"An installed Sphinx theme. Defaults to 'Read the docs' theme.")
3839 parser.add_argument(
"-v",
"--verbosity", type=str, nargs=1, help=
"Level of verbosity. Defaults to 0 - meaning no output. Max value is 2.")
3840 parser.add_argument(
'--icon', type=str, nargs=1, help=argparse.SUPPRESS)
3845 args, _ = parser.parse_known_args(command[1:])
3847 project = Utility.GetSanitizedDataFromCommand(args.name, is_path=
False)[0]
3849 mainfile = args.file[0];
3851 source = os.path.abspath(args.source[0]) ;
3856 include = Utility.GetSanitizedDataFromCommand(args.include)
3858 except: include = []
3860 try: output = args.output[0]
3861 except: output = os.path.abspath(os.getcwd())
3863 try: scratch = args.scratch[0]
3864 except: scratch = os.path.abspath(os.getcwd())
3866 try: icon = args.logo[0]
3867 except: icon = getattr(args,
"icon", [
None] )
3868 if icon: icon = os.path.abspath(next(iter(icon)))
3870 try: theme = args.theme[0]
3871 except: theme =
None
3873 try: verbosity = int(args.verbosity[0])
3874 except: verbosity = 2
3876 settings = {
"source":source,
"output":output,
"include":include,
"scratch": scratch,
"verbosity":verbosity,
"logo":icon}
3878 if theme: settings.update({
"html_theme":theme})
3881 except Exception
as _:
3883 sphinx(
"Composite Damage Analysis Code",
"codac")
3886 sphinx(project, mainfile, **settings)
3891 Execute make command
3893 from distutils.dir_util
import copy_tree
3896 self.
SPHINXOPTS = os.getenv(
'sphinx_opts',
'')
3897 self.
SPHINXBUILD = os.getenv(
'sphinx_build',
'sphinx-build')
3898 self.
PAPER = os.getenv(
'sphinx_paper',
None)
3901 self.
BUILDDIR = os.getenv(
'sphinx_builddir', Utility.PathLeaf(tempfile.NamedTemporaryFile().name))
3902 self.
TEMPDIR = os.getenv(
'sphinx_templates',
"_templates")
3903 self.
STATICEDIR = os.getenv(
'sphinx_static',
"_static")
3906 os.environ[
'sphinx_static'] = self.
STATICEDIR; os.environ[
'sphinx_templates'] = self.
TEMPDIR
3909 os.environ[
"sphinx_include"] = os.getenv(
"sphinx_include",
"")
3910 os.environ[
"sphinx_include"] += os.pathsep + os.pathsep.join(self.
incdirsincdirs)
3914 User-friendly check for sphinx-build
3916 with open(os.devnull,
'w')
as devnull:
3918 if subprocess.call([self.
SPHINXBUILD,
'--version'],stdout=devnull, stderr=devnull) == 0:
3920 except FileNotFoundError:
3923 "The '{0}' command was not found. Make sure you have Sphinx "
3924 "installed, then set the SPHINXBUILD environment variable "
3925 "to point to the full path of the '{0}' executable. "
3926 "Alternatively you can add the directory with the "
3927 "executable to your PATH. If you don't have Sphinx "
3928 "installed, grab it from http://sphinx-doc.org/)"
3933 def build(builder, success_msg=None, extra_opts=None, outdir=None,doctrees=True):
3937 builddir = os.path.join(self.
BUILDDIR or outdir)
3939 command.extend([
'-c', os.getenv(
'sphinx_config',self.
SOURCEDIR)])
3941 command = command[:len(command)-2]
3943 command.extend([
'-d', os.path.join(self.
BUILDDIR,
'doctrees')])
3945 command.extend(extra_opts)
3949 print(
'Build finished. ' + success_msg.format(self.
outdiroutdir or builddir))
3951 def buildmethod(function):
3953 Decorator function for each build option
3968 Remove the build directory
3970 shutil.rmtree(self.
BUILDDIR, ignore_errors=
True)
3975 Make standalone HTML files
3977 return build(
'html',
'The HTML pages are in {}.')
3982 Make HTML files named index.html in directories
3984 return build(
'dirhtml',
'The HTML pages are in {}')
3989 Make a single large HTML file
3991 return build(
'singlehtml',
'The HTML page is in {}.')
3998 return build(
'pickle',
'Now you can process the pickle files.')
4005 return build(
'json',
'Now you can process the JSON files.')
4010 Make HTML files and a HTML help project
4012 return build(
'htmlhelp',
'Now you can run HTML Help Workshop with the .hhp project file in {}.')
4017 Make HTML files and a qthelp project
4019 return build(
'qthelp',
'Now you can run "qcollectiongenerator" with the '
4020 '.qhcp project file in {0}, like this: \n'
4021 '# qcollectiongenerator {0}/RinohType.qhcp\n'
4022 'To view the help file:\n'
4023 '# assistant -collectionFile {0}/RinohType.qhc')
4028 Make HTML files and a Devhelp project
4030 return build(
'devhelp',
'To view the help file:\n'
4031 '# mkdir -p $HOME/.local/share/devhelp/RinohType\n'
4032 '# ln -s {} $HOME/.local/share/devhelp/RinohType\n'
4040 return self.build(
'epub',
'The epub file is in {}.')
4045 Make a PDF using rinohtype
4047 return self.build(
'rinoh',
'The PDF file is in {}.')
4052 Make LaTeX files, you can set PAPER=a4 or PAPER=letter
4054 extra_opts = [
'-D',
'latex_paper_size={}'.format(self.
PAPER)]
if self.
PAPER else None
4055 return build(
'latex',
'The LaTeX files are in {}.\n'
4056 "Run 'make' in that directory to run these through "
4057 "(pdf)latex (use the 'latexpdf' target to do that "
4058 "automatically).", extra_opts)
4063 Make LaTeX files and run them through pdflatex
4066 print(
'Running LaTeX files through pdflatex...')
4067 builddir = os.path.join(self.
BUILDDIR,
'latex')
4068 subprocess.call([
'make',
'-C', builddir,
'all-pdf'])
4069 print(
'pdflatex finished; the PDF files are in {}.'.format(builddir))
4074 Make LaTeX files and run them through platex/dvipdfmx
4077 print(
'Running LaTeX files through platex and dvipdfmx...')
4078 builddir = os.path.join(self.
BUILDDIR,
'latex')
4079 subprocess.call([
'make',
'-C', builddir,
'all-pdf-ja'])
4080 print(
'pdflatex finished; the PDF files are in {}.'.format(builddir))
4087 return build(
'text',
'The text files are in {}.')
4094 return build(
'man',
'The manual pages are in {}.')
4101 return build(
'texinfo',
'The Texinfo files are in {}.\n'
4102 "Run 'make' in that directory to run these "
4103 "through makeinfo (use the 'info' target to do "
4104 "that automatically).")
4109 Make Texinfo files and run them through makeinfo
4112 print(
'Running Texinfo files through makeinfo...')
4113 builddir = os.path.join(self.
BUILDDIR,
'texinfo')
4114 subprocess.call([
'make',
'-C', builddir,
'info'])
4115 print(
'makeinfo finished; the Info files are in {}.'.format(builddir))
4120 Make PO message catalogs
4122 return build(
'gettext',
'The message catalogs are in {}.', outdir=
'locale',doctrees=
False)
4127 Make an overview of all changed/added/deprecated items
4129 return build(
'changes',
'The overview file is in {}.')
4134 Make Docutils-native XML files
4136 return build(
'xml',
'The XML files are in {}.')
4141 Make pseudoxml-XML files for display purposes
4143 return self.build(
'pseudoxml',
'The pseudo-XML files are in {}.')
4148 Check all external links for integrity
4150 return build(
'linkcheck',
'Look for any errors in the above output or in {}/output.txt.')
4155 Run all doctests embedded in the documentation (if enabled)
4157 return build(
'doctest',
'Look at the results in {}/output.txt.')
4164 print(
"Please use '{} <target>' where <target> is one of" .format(sys.argv[0]))
4165 width = max(len(name)
for name
in self.
BuildOption)
4167 print(
' {name:{width}} {descr}'.format(name=name, width=width, descr=target.__doc__))
4172 args = [
'default']
or sys.argv[1:]
4177 temp = Utility.PathLeaf(tempfile.NamedTemporaryFile().name)
4179 shutil.copytree(os.path.abspath(self.
SOURCEDIR), os.path.abspath(temp), ignore=shutil.ignore_patterns(
".git",
".svn")); self.
SOURCEDIR = temp
4181 for x
in os.getenv(
"sphinx_include",
"").split(os.pathsep):
4182 try: subprocess.call([
"sphinx-apidoc",
"-o",os.path.join(temp,
"_advanced",Utility.PathLeaf(os.path.dirname(x)).lower()),x])
4185 if not os.path.exists(os.path.join(temp,
"conf.py")):
4187 copyfile(os.path.join(PyXMakePath,
"Build",
"config",
"stm_conf.py"), os.path.join(temp,
"conf.py"))
4189 if not os.path.exists(os.path.join(temp,
"_static")):
4190 os.mkdir(os.path.join(temp,
'_static')); copyfile(os.path.join(PyXMakePath,
"Build",
"config",
"stm_style.css"), os.path.join(temp,
"_static",
"style.css"))
4192 if not os.path.exists(os.path.join(temp,
"_templates")):
4193 os.mkdir(os.path.join(temp,
'_templates')); copyfile(os.path.join(PyXMakePath,
"Build",
"config",
"stm_layout.html"), os.path.join(temp,
"_templates",
"layout.html"))
4197 if not kwargs.get(
"keep_doctree",
False):
4199 shutil.rmtree(os.path.join(self.
BUILDDIR,
"doctrees"))
4212 Inherited class for all builds using SSH connection.
4216 Initialization of SSH class object.
4218 super(SSH, self).
__init__(*args, **kwargs)
4221 setattr(self, str(Fortran.Wrapper.__name__), MethodType(Fortran.Wrapper, self))
4269 Define output directories for modules and libraries. Output written to the workspace is DELETED.
4272 if modulepath
is None:
4273 modulepath = libpath
4280 def Settings(self, user, key="", host='129.247.54.37', port=22, use_cache=True, **kwargs):
4282 Define settings to establish a SSH connection.
4286 if kwargs.get(
"client",
None):
4288 sftp = self.
ssh_client.open_sftp(); sftp.chdir(
".")
4289 self.
workspace = kwargs.get(
"workspace",posixpath.join(sftp.getcwd(),
"")); sftp.close()
4293 self.
workspace = kwargs.get(
"workspace",posixpath.join(Utility.AsDrive(
'home',posixpath.sep),user)+posixpath.sep)
4296 self.
ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
4298 password = kwargs.pop(
"password",
"");
4301 if password:
raise ValueError
4303 try: self.
ssh_client.connect(hostname=host, port=port, username=user, key_filename=key, timeout=kwargs.get(
"timeout",
None))
4304 except paramiko.ssh_exception.SSHException:
4305 self.
ssh_client.connect(hostname=host, port=port, username=user, key_filename=key, timeout=kwargs.get(
"timeout",
None),
4306 disabled_algorithms=kwargs.get(
"disabled",{
"pubkeys":[
"rsa-sha2-512",
"rsa-sha2-256"]}))
4307 except socket.timeout:
raise TimeoutError
4312 except:
raise ModuleNotFoundError
4314 try: self.
ssh_client.connect(hostname=host, port=port, username=user, password=keyring.get_password(user, user))
4317 if not password: password = getpass.getpass()
4318 keyring.set_password(user, user, password)
4319 finally: self.
ssh_client.connect(hostname=host, port=port, username=user, password=keyring.get_password(user, user))
4321 if not password: password = getpass.getpass()
4322 self.
ssh_client.connect(hostname=host, port=port, username=user, password=password)
4327 Load an additional environment file prior to execution of all commands.
4331 if any([str(posixpath.join(path,bash)).startswith(
"module"),args.startswith(
"module")]): source =
""
4332 self.
environment +=
" ".join([source,posixpath.join(path,bash),args])+
"; "
4337 Assemble command string for the post-build event.
4343 def Build(self, cmdstring, run= "ifort", path="", lib= "", linkedIn="", **kwargs):
4345 Assemble command strings for the main build event.
4368 c_files = [x
for x
in self.
srcssrcs if os.path.splitext(x)[1].lower()
in (
".for",
".f95",
".f",
".f90")]
4369 cmd +=
' %s ' % (
' '.join(c_files))
4372 if self.
exe in (
"f2py")
and self.
exe:
4375 self.
libslibs.extend([
"mkl_rt",
"iomp5",
"pthread",
"m",
"dl"])
4378 for x
in [
' -l'+x+
' ' for x
in self.
libslibs if x]:
4382 if self.
exe and self.
exe not in (
"custom"):
4388 if self.
exe not in (
"ifort",
"gcc",
"g++"):
4391 elif self.
exe ==
"ifort":
4396 self.
linkcmd = posixpath.join(
"",
"ar")+
" -rc "
4401 Define settings to establish SSH connection.
4406 includes = [
':"'+x+
'"' for x
in self.
incdirs]
4421 linklist = [
'ar -x "'+x+
'" && ' for x
in self.
linkedIn]
4460 if self.
exe not in (
"ifort",
"gcc",
"g++",
"custom"):
4461 sftp.put(os.path.join(Path2Config,
".f2py_f2cmap"), posixpath.join(self.
workspace,
".f2py_f2cmap"))
4468 if not kwargs.get(
"combine",
False):
4474 if Utility.IsNotEmpty(target):
4475 self.
command+=
' "'+target+
'"'
4480 if Utility.IsNotEmpty(self.
linkcmd):
4483 elif self.
exe in [
"custom"]:
4484 sarch = 1; scopy = 1
4487 sarch = 1; scopy = 0
4505 posixpath.join(self.
workspace,
"intel")+
'; rm -f '+
4506 posixpath.join(self.
workspace,
".f2py_f2cmap") +
4507 " rm -f %s " % (
' '.join([posixpath.join(self.
workspace,cs)
for cs
in self.
srcssrcs])),
4513 if kwargs.get(
"combine",
False):
4514 librarian =
'ar'; ext =
'.a'; decomp =
" && "+librarian+
" -x "
4515 mergedid =
"lib"+posixpath.basename(self.
outmodule.rstrip(
"/"))
4517 multi_libs = [x
for x
in [x.rstrip(
"\n")
for x
in stdout.readlines()
if x.startswith(mergedid)]]
4526 self.
postcmdpostcmd += librarian +
" -x " + decomp.join(multi_libs) +
" && "
4530 for lib
in multi_libs:
4541setattr(sys.modules[__name__],
"Robot", Coverage)
4543setattr(sys.modules[__name__],
"CMake", Custom)
4545if __name__ ==
'__main__':
Base class for all C/C++ build events inherited from Make.
incremental
Define if the input should be compiled exactly as provided.
__init__(self, *args, **kwargs)
str MakeObjectKind
String identifier of current instance.
libname
Name of library, assembled using BuildID.
bool isStatic
Static or dynamic link library flag.
OutputPath(self, libpath=os.getcwd())
str exe
The executable command used in the main build event.
compargs
Used defined command line options.
Build(self, cmdstring, **kwargs)
# pragma no cover isStatic
list linkedIn
List of libraries which should be statically linked in.
buildname
Temporary build name.
str linkcmd
Intel Linker command.
outlibs
Output path for library files.
str makecmd
Intel Compiler command.
tuple temps
Blank version of tuple to store temporary file names scheduled for removal.
list libdirs
Blank version of list containing library directories without initially specifying MKL.
Base class for all Coverage build events.
str MakeObjectKind
String identifier of current instance.
__init__(self, *args, **kwargs)
add(cls, *args, **kwargs)
Build(self, command=["--cov-fail-under=10","--cov-report=term-missing","--cov-report=html","--cov-report=xml","--junit-xml=junit.xml", "-W ignore::pytest.PytestAssertRewriteWarning"], **kwargs)
Base class for all custom build events inherited from Make.
buildname
Immutable settings for Custom object.
str MakeObjectKind
String identifier of current instance.
str exe
The executable command used in all build events.
str makecmd
Command line arguments passed in by the user.
temps
Command line arguments passed in by the user.
__init__(self, *args, **kwargs)
# pragma no cover hasFoss
str compargs
Command line arguments passed in by the user.
Base class for all Doxygen build events.
path2exe
Path to Doxygen executable.
list incdirs
Blank version of list containing library directories without initially specifying MKL.
outdir
Output directory of current job.
str stype
Type of source file.
__init__(self, *args, **kwargs)
temps
Tuple of temporary files scheduled for removal.
str exe
Executable of Doxygen.
Settings(self, brief, header, outdir='', **kwargs)
str buildname
Temporary build name of current job.
str MakeObjectKind
String identifier of current instance.
Base class for all Fortran build events.
str makecmd
Intel Compiler command.
compargs
Used defined command line options.
OutputPath(self, modulepath=None, libpath=os.getcwd())
list libdirs
Blank version of list containing library directories without initially specifying MKL.
Build(self, cmdstring, **kwargs)
list linkedIn
List of libraries which should be statically linked in.
Preprocessing(self, inend='', outend='', copyfiles=[], replace={'!DEC$ IF':'#IF','!DEC$ ELSE':'#ELSE','!DEC$ ENDIF':'#ENDIF'}, decorator="!DEC$ ATTRIBUTES DLLEXPORT::")
Wrapper(self, module_name, source_name=None)
__init__(self, *args, **kwargs)
tuple buildname
Temporary build name.
tuple linkcmd
Intel Linker command.
bool isStatic
Static or dynamic link library flag.
str intermediate_wrapper
Wrapper interface file for 3rd party FORTRAN code.
outlibs
Output path for library files.
str MakeObjectKind
String identifier of current instance.
outmodule
Output path for module or header files.
tuple libname
Name of library, assembled using BuildID.
Base class for all Latex build events.
str MakeObjectKind
String identifier of current instance.
show(cls, ProjectID, *args, **kwargs)
upload(cls, archive, *args, **kwargs)
delete(cls, ProjectID, *args, **kwargs)
srcdir
Set default source and output directories for Latex build objects.
__init__(self, *args, **kwargs)
str path2exe
Path to Latex executable.
list incdirs
Blank version of list containing library directories without initially specifying MKL.
session(cls, *args, **kwargs)
rename(cls, ProjectID, ProjectName, *args, **kwargs)
create(self, API="TeXworks", GUI=True, **kwargs)
str exe
Executable of Latex.
download(cls, ProjectID, *args, **kwargs)
Abstract base class for all make objects.
Postprocessing(self, cmdstring='')
scrtdir
Current scratch directory
_, self.intelpath, self.iniCompiler intelpath
Path to Intel Fortran Compiler (read from Paths.log or empty).
compargs
Command line arguments passed in by the user.
list copyfiles
List of files to be copied to the output directory after finish.
OutputPath(self, path, files="")
__posix__(self, **kwargs)
verbose
Level of verbosity of the current build object.
AddDependencyPath(self, dependencies)
bool setarch
Define the architecture for the build directly by using the keyword argument "arch".
buildid
Base string of build object.
list srcs
Source file or folders.
outdir
Default search directory for output.
str precmd
Command executed during pre-build event.
__init__(self, BuildID, Srcs, scratch=os.getcwd(), verbose=0, *args, **kwargs)
msvsc
Default version of Microsoft visual studio used by the Intel Fortran Compiler.
str architecture
Processor architecture.
str postcmd
Post build command.
Preprocessing(self, cmdstring='', inend='', outend='', copyfiles=[], replace={'!DEC$ IF':'#IF','!DEC$ ELSE':'#ELSE','!DEC$ ENDIF':'#ENDIF'})
hasFoss
Toggle between free open source software and commercial 3rd party libraries.
Environment(self, path, script="ifortvars.bat")
Build(self, cmdstring, **kwargs)
F2CPreprocessing(PreprocessingFile)
list incdirs
List of include directories.
tuple temps
Tuple of data to be removed after job completion.
list libdirs
List of library directories.
str iniCompiler
Default initialization of compiler script.
list libs
List of actual libraries (by name) used during linking.
str makecmd
Command executed during build event.
sanitize(string, **kwargs)
AddIncludePath(self, includes)
srcdir
Default search directory for source files.
Base class for all NSIS build events.
srcdir
Adding option to deactivate NSIS and instead use a compressed archive directly.
FTP(self, user, key, upload_file, host='ftp.dlr.de', path="/public/download/nightly")
buildid
Adding option to deactivate NSIS and instead use a compressed archive directly.
__init__(self, *args, **kwargs)
path2exe
Path to NSIS executable.
str exe
Executable of NSIS.
makecmd
Adding option to deactivate NSIS and instead use a compressed archive directly.
outdir
Adding option to deactivate NSIS and instead use a compressed archive directly.
verbose
Adding option to deactivate NSIS and instead use a compressed archive directly.
str MakeObjectKind
String identifier of current instance.
ftp_client
Remote workspace.
Abstract base class for all NT subclasses.
str SystemObjectKind
String identifier of current instance.
__init__(self, *args, **kwargs)
Abstract base class for all system subclasses.
str SystemObjectKind
String identifier of current instance.
__init__(self, *args, **kwargs)
Abstract base class for all POSIX subclasses.
outdir
Accept both OutLibs and OutDir variable.
__create__(self, **kwargs)
scrtdir
Overwrite create method in all subclasses to use a predefined MakeFile for all builds.
__init__(self, *args, **kwargs)
str SystemObjectKind
String identifier of current instance.
temps
Overwrite create method in all subclasses to use a predefined MakeFile for all builds.
Base class for all Py2X (for now only f2py) build events.
str exe
The executable command used in the main build event.
no_static_mkl
Define whether Intel's MKL should be statically or dynamically linked.
show(package, feature, **kwargs)
str path2exe
Absolute system path to Python executable.
no_append_arch
Define whether the architecture shall be appended to the build name.
__init__(self, *args, **kwargs)
inspect(package, **kwargs)
str MakeObjectKind
String identifier of current instance.
no_mkl
Define whether Intel's MKL should be discarded Defaults to False on NT systems.
incremental
Define if the input should be compiled exactly as provided.
copyfile(os.path.join(Path2Config,), os.path.join(self.scrtdir,)) bare
Iterate through all active processes matching the current BuildID and kill them.
str buildname
Temporary build name of current job.
parse(cls, *args, **kwargs)
temps
Tuple of temporary files deleted after job completion.
Base class for all PyInstaller build events.
Build(self, mode="onefile", **kwargs)
__init__(self, *args, **kwargs)
Encryption(self, encrypt, **kwargs)
str MakeObjectKind
String identifier of current instance.
Preprocessing(self, cmdstring='')
precmd
Command executed during pre-build event.
Base class for all PyReq build events.
str precmd
Command executed during pre-build event.
__init__(self, *args, **kwargs)
Preprocessing(self, cmdstring='')
str MakeObjectKind
String identifier of current instance.
Base class for all build events requiring a SSH connection.
list libdirs
Blank version of list containing library directories.
str MakeObjectKind
String identifier of current instance.
str environment
Load an additional library prior to execution of all commands.
str intermediate_wrapper
Wrapper interface file for 3rd party FORTRAN code.
tuple temps
Blank version of tuple to store temporary file names scheduled for removal.
incremental
Define if the input should be compiled exactly as provided.
Settings(self, user, key="", host='129.247.54.37', port=22, use_cache=True, **kwargs)
outmodule
Output path for module or header files.
__init__(self, *args, **kwargs)
workspace
Remote workspace.
Postprocessing(self, cmdstring="")
list linkedIn
List of libraries which should be statically linked in.
outlibs
Output path for library files.
str makecmd
Remote (Intel) Compiler command.
str buildname
Temporary build name.
Environment(self, path="", bash="", args="", method="source")
str postcmd
Command executed during post-build event.
str export
Environment variables to be set prior to the execution of the build command.
path2exe
(Intel Fortran) Compiler Path
str linkcmd
Remote Linker command.
ssh_client
Remote workspace.
str libname
Name of library, assembled using BuildID.
OutputPath(self, libpath, modulepath=None)
Base class for all Sphinx build events.
path2exe
Path to Sphinx executable.
__init__(self, *args, **kwargs)
str exe
Executable of Sphinx.
BuildOption
Ordered dictionary containing all available options.
list incdirs
Blank version of list containing library directories without initially specifying MKL.
str MakeObjectKind
String identifier of current instance.
Module containing all relevant modules and scripts associated with the building process.