예제 #1
0
    def _write_executable_f90(self, execname, lines):
        """Appends the Fortran code to write the wrapper executable to the specified 'lines' list.

        :arg execname: the name of the executable in the self.module.executables to write.
        """
        executable = self.module.executables[execname]

        #The 14 in the formatting indent comes from 4 spaces, 2 from "_c", 1 from the spacing
        #between 'subroutine' and name of the executable, 10 from subroutine, 1 from the ("
        cparams = present_params(_ctypes_ex_parameters(executable),
                                 len(execname) + 14)
        lines.append("  subroutine {}_c({}) BIND(C)".format(execname, cparams))
        #Next, we add the variables declarations, the call to the original executable and then
        #the handling of the output variables.
        lines.append("    " + "\n    ".join(_ctypes_ex_variables(executable)))
        lines.append("    " + "\n    ".join(_ctypes_ex_compatvars(executable)))

        #Add assignment/allocate statements for the intent(in*) paramaters *local* variable
        #declarations so that we can match the signature exactly.
        lines.extend(_ctypes_ex_assign(executable))

        if type(executable).__name__ == "Subroutine":
            prefix = "call "
        else:
            prefix = "{}_f = ".format(execname)

        spacing = len(list(prefix)) + len(list(execname)) + 4
        lines.append("    {}{}({})".format(
            prefix, execname, present_params(executable.paramorder, spacing,
                                             90)))
        lines.append("")
        lines.extend(_ctypes_ex_clean(executable))

        lines.append("  end subroutine {}_c\n".format(execname))
예제 #2
0
파일: ftypes.py 프로젝트: feifzhou/fortpy
    def _write_executable_f90(self, execname, lines):
        """Appends the Fortran code to write the wrapper executable to the specified 'lines' list.

        :arg execname: the name of the executable in the self.module.executables to write.
        """
        executable = self.module.executables[execname]
            
        #The 14 in the formatting indent comes from 4 spaces, 2 from "_c", 1 from the spacing
        #between 'subroutine' and name of the executable, 10 from subroutine, 1 from the ("
        cparams = present_params(_ctypes_ex_parameters(executable), len(execname) + 14)
        lines.append("  subroutine {}_c({}) BIND(C)".format(execname, cparams))
        #Next, we add the variables declarations, the call to the original executable and then
        #the handling of the output variables.
        lines.append("    " + "\n    ".join(_ctypes_ex_variables(executable)))
        lines.append("    " + "\n    ".join(_ctypes_ex_compatvars(executable)))

        #Add assignment/allocate statements for the intent(in*) paramaters *local* variable
        #declarations so that we can match the signature exactly.
        lines.extend(_ctypes_ex_assign(executable))
                
        if type(executable).__name__  == "Subroutine":
            prefix = "call "
        else:
            prefix = "{}_f = ".format(execname)
            
        spacing = len(list(prefix)) + len(list(execname)) + 4
        lines.append("    {}{}({})".format(prefix, execname,
                                           present_params(executable.paramorder, spacing, 90)))
        lines.append("")
        lines.extend(_ctypes_ex_clean(executable))

        lines.append("  end subroutine {}_c\n".format(execname))
예제 #3
0
파일: ftypes.py 프로젝트: feifzhou/fortpy
    def _write_executable_py(self, execname, lines):
        """Writes the python executable definition for interacting with ctypes.

        :arg execname: the name of the executable to write.
        :arg lines: the lines of python code are appended to this list.
        """
        executable = self.module.executables[execname]
            
        #The 5 in the formatting indent comes from 1 space, 3 from the 'def'
        #and 1 from '('.
        inparams = []
        for p in executable.ordered_parameters:
            if "in" in p.direction:
                inparams.append(p.lname)
        pyparams = present_params(inparams, len(execname) + 5, linecont=", ")
        lines.append("def {}({}):".format(execname.lower(), pyparams))
        tab = "    "

        #Next, we want to append the docstring information from the XML tags
        #that were parsed by fortpy.
        docs = ['"""']
        summary = self._format_docstring(executable.summary)
        if len(summary) > 0:
            docs[0] += summary[0]
            docs.extend(summary[1::])
            docs.append("")
        else:
            docs[0] += "No XML documentation summary."
        for p in executable.ordered_parameters:
            doc = ":arg {}: {}; {}".format(p.name, p.strtype, p.summary)
            docs.extend(self._format_docstring(doc))

        lines.extend([tab + l for l in docs])
        lines.append(tab + '"""')

        pathstr = '{}libpath = path.join(path.dirname(__file__), "{}")'
        lines.append(pathstr.format(tab, self.libname))
        methparams = '"{}_c", "{}_c", libpath, True'.format(self.module.name, execname)
        lines.append("{}method = static_symbol({})".format(tab, methparams))
        argtypes = _py_ex_argtype(executable)
        spacing = len(tab) + 6 + 8 + 3
        lines.append("{}method.argtypes = [{}]".format(tab, present_params(argtypes, spacing,
                                                                           linecont=", ")))
        lines.append("")
        lparams = []
        _py_code_variables(lines, executable, lparams, tab)
        #This is the line that calls the shared library executable.
        methparams = present_params(lparams, len(tab) + 5, linecont=", ")
        lines.append("{}method({})\n".format(tab, methparams))

        #Now we clean up the output variables to turn them into numpy arrays etc.
        constructor = '{}result = FtypesResult("{}", "{}", "{}")'
        lines.append(constructor.format(tab, self.module.name, execname, type(executable).__name__))
        count = _py_code_clean(lines, tab, executable)
        
        if count > 0:
            lines.append("")
            lines.append("{}return result\n".format(tab))
        else:
            lines.append("{}return None\n".format(tab))
예제 #4
0
def generate(parser, coderoot, stagedir, compiler=None, debug=False, profile=False,
             strict=False, docompile=True):
    """Generates the f90 module file for all members referenced in the parser's
    modules list.
    """
    import fortpy
    from fortpy.utility import get_fortpy_templates_dir
    from fortpy.testing.elements import AutoClasser
    
    members = _find_members(parser, coderoot)
    folder = "filename"
    classers = [AutoClasser(m, folder, m.name, [], coderoot, True) for m in members]
    
    from os import path
    templates = get_fortpy_templates_dir()
    statpath = path.join(templates, "fpy_auxiliary.f90")
    with open(statpath) as f:
        static = f.read()
        
    from fortpy.printing.formatting import present_params
    xnames, modcode, routines, modules = _generate_single(classers)

    from fortpy.code import order_module_dependencies
    modules = order_module_dependencies(modules, parser)

    from os import mkdir, path
    if docompile:
        auxdir = path.join(stagedir, "fortpy.aux")
        if not path.isdir(auxdir):
            mkdir(auxdir)
    else:
        auxdir = coderoot

    if docompile and not _should_recompile(auxdir, parser, modules, compiler):
        msg.okay("The current version of fpy_auxiliary.f90 is up-to-date.")
        from fortpy.testing.compilers import replace
        target = replace(auxdir + ".[c]", compiler)
        return (0, True, target)
    
    static = static.replace("__auxsave__", present_params(xnames, 21))
    static = static.replace("__aux_uses__", '\n'.join(modcode))        
    static = static.replace("__version__", fortpy.__version__)
    static = static.replace("__fxauxsave__", '\n'.join(routines))

    xnames, modcode, routines, dmods = _generate_single(classers, False)
    static = static.replace("__auxread__", present_params(xnames, 21))
    static = static.replace("__fxauxread__", '\n'.join(routines))

    fortpath = path.join(auxdir, "fpy_auxiliary.f90")
    with open(fortpath, 'w') as f:
        f.write(static)

    if docompile:
        _prepare_dir(parser, modules, auxdir)
        return _compile(auxdir, compiler, debug, profile)
예제 #5
0
파일: ftypes.py 프로젝트: feifzhou/fortpy
def _py_check_optional(parameter, tab, assign):
    """Returns the code to check for actual values when an out parameter is pure 
    out/optional and doesn't have anything changed.

    :arg assign: the actual variable assignment value if the conditions pass.
    """
    if parameter.direction == "(out)":
        result = []
        checks = ["{0}_{1:d}.value==0".format(parameter.lname, i) for i in range(parameter.D)]
        spacing = len(tab) + 2 + 3 + 3 + 2
        result.append("{}if not all([{}]):".format(tab, present_params(checks, spacing, linecont=", ")))
        for line in assign:
            if assign is not None:
                result.append("{0}{1}".format(tab, line))
        result.append("{}else:".format(tab))
        result.append('{0}{0}result.add("{1}", None)'.format(tab, parameter.lname))
        return '\n'.join(result)
    else:
        return '\n'.join(assign)
예제 #6
0
파일: genf90.py 프로젝트: halvorlu/fortpy
def fpy_interface(fpy, static, interface, typedict):
    """Splices the full list of subroutines and the module procedure list
    into the static.f90 file.

    :arg static: the string contents of the static.f90 file.
    :arg interface: the name of the interface *field* being replaced.
    :arg typedict: the dictionary of dtypes and their kind and suffix combos. 
    """
    modprocs = []
    subtext = []
    for dtype, combos in list(typedict.items()):
        for tcombo in combos:
            kind, suffix = tcombo
            xnames, sub = fpy_interface_sub(fpy, dtype, kind, suffix)
            modprocs.extend(xnames)
            subtext.append(sub)
        subtext.append("\n")

    #Next, chunk the names of the module procedures into blocks of five
    #so that they display nicely for human readability.
    from fortpy.printing.formatting import present_params
    splice = static.replace(interface, present_params(modprocs, 21))
    return splice.replace(interface.replace("py", "xpy"), ''.join(subtext))
예제 #7
0
def fpy_interface(fpy, static, interface, typedict):
    """Splices the full list of subroutines and the module procedure list
    into the static.f90 file.

    :arg static: the string contents of the static.f90 file.
    :arg interface: the name of the interface *field* being replaced.
    :arg typedict: the dictionary of dtypes and their kind and suffix combos. 
    """
    modprocs = []
    subtext = []
    for dtype, combos in list(typedict.items()):
        for tcombo in combos:
            kind, suffix = tcombo
            xnames, sub = fpy_interface_sub(fpy, dtype, kind, suffix)
            modprocs.extend(xnames)
            subtext.append(sub)
        subtext.append("\n")

    #Next, chunk the names of the module procedures into blocks of five
    #so that they display nicely for human readability.
    from fortpy.printing.formatting import present_params
    splice = static.replace(interface, present_params(modprocs, 21))
    return splice.replace(interface.replace("py", "xpy"), ''.join(subtext))
예제 #8
0
def _py_check_optional(parameter, tab, assign):
    """Returns the code to check for actual values when an out parameter is pure 
    out/optional and doesn't have anything changed.

    :arg assign: the actual variable assignment value if the conditions pass.
    """
    if parameter.direction == "(out)":
        result = []
        checks = [
            "{0}_{1:d}.value==0".format(parameter.lname, i)
            for i in range(parameter.D)
        ]
        spacing = len(tab) + 2 + 3 + 3 + 2
        result.append("{}if not all([{}]):".format(
            tab, present_params(checks, spacing, linecont=", ")))
        for line in assign:
            if assign is not None:
                result.append("{0}{1}".format(tab, line))
        result.append("{}else:".format(tab))
        result.append('{0}{0}result.add("{1}", None)'.format(
            tab, parameter.lname))
        return '\n'.join(result)
    else:
        return '\n'.join(assign)
예제 #9
0
    def _write_executable_py(self, execname, lines):
        """Writes the python executable definition for interacting with ctypes.

        :arg execname: the name of the executable to write.
        :arg lines: the lines of python code are appended to this list.
        """
        executable = self.module.executables[execname]

        #The 5 in the formatting indent comes from 1 space, 3 from the 'def'
        #and 1 from '('.
        inparams = []
        for p in executable.ordered_parameters:
            if "in" in p.direction:
                inparams.append(p.lname)
        pyparams = present_params(inparams, len(execname) + 5, linecont=", ")
        lines.append("def {}({}):".format(execname.lower(), pyparams))
        tab = "    "

        #Next, we want to append the docstring information from the XML tags
        #that were parsed by fortpy.
        docs = ['"""']
        summary = self._format_docstring(executable.summary)
        if len(summary) > 0:
            docs[0] += summary[0]
            docs.extend(summary[1::])
            docs.append("")
        else:
            docs[0] += "No XML documentation summary."
        for p in executable.ordered_parameters:
            doc = ":arg {}: {}; {}".format(p.name, p.strtype, p.summary)
            docs.extend(self._format_docstring(doc))

        lines.extend([tab + l for l in docs])
        lines.append(tab + '"""')

        pathstr = '{}libpath = path.join(path.dirname(__file__), "{}")'
        lines.append(pathstr.format(tab, self.libname))
        methparams = '"{}_c", "{}_c", libpath, True'.format(
            self.module.name, execname)
        lines.append("{}method = static_symbol({})".format(tab, methparams))
        argtypes = _py_ex_argtype(executable)
        spacing = len(tab) + 6 + 8 + 3
        lines.append("{}method.argtypes = [{}]".format(
            tab, present_params(argtypes, spacing, linecont=", ")))
        lines.append("")
        lparams = []
        _py_code_variables(lines, executable, lparams, tab)
        #This is the line that calls the shared library executable.
        methparams = present_params(lparams, len(tab) + 5, linecont=", ")
        lines.append("{}method({})\n".format(tab, methparams))

        #Now we clean up the output variables to turn them into numpy arrays etc.
        constructor = '{}result = FtypesResult("{}", "{}", "{}")'
        lines.append(
            constructor.format(tab, self.module.name, execname,
                               type(executable).__name__))
        count = _py_code_clean(lines, tab, executable)

        if count > 0:
            lines.append("")
            lines.append("{}return result\n".format(tab))
        else:
            lines.append("{}return None\n".format(tab))