Exemplo n.º 1
0
    def callable_to_dict(c):
        """
        Turn a callable function of class into a dictionary

        Used for conversion to JSON

        Parameters
        ----------
        c : callable (function or class with __call__)
            the function to be turned into a dict representation

        Returns
        -------
        dict
            the dict representation of the callable
        """
        f_module = c.__module__
        root_module = f_module.split('.')[0]

        # is_class = isinstance(c, (type, types.ClassType))

        # try saving known external classes of functions, e.g. `msmbuilder`
        if root_module in ObjectJSON.safe_modules:
            # only store the function/class and the module
            return {
                '_module': c.__module__,
                '_name': c.__name__
            }

        # if the easy way did not work, try saving it using bytecode
        if ObjectJSON.allow_marshal and callable(c):
            # use marshal
            global_vars = ObjectJSON._find_var(c, opcode.opmap['LOAD_GLOBAL'])
            import_vars = ObjectJSON._find_var(c, opcode.opmap['IMPORT_NAME'])

            all_builtins = dir(builtins)

            global_vars = list(set(
                [var for var in global_vars if var not in all_builtins]))
            import_vars = list(set(import_vars))

            err = ''

            if len(global_vars) > 0:
                err += 'The function you try to save relies on globally set ' \
                       'variables and these cannot be saved since storage ' \
                       'has no access to the global scope which includes ' \
                       'imports! \n\n'
                err += 'We require that the following globals: ' + \
                       str(global_vars) + ' either\n'
                err += '\n1. be replaced by constants'
                err += '\n2. be defined inside your function,' + \
                       '\n\n' + '\n'.join(
                           map(lambda x: ' ' * 8 + x + '= ...', global_vars)
                       ) + '\n'
                err += '\n3. imports need to be "re"-imported inside your ' \
                       'function' + \
                       '\n\n' + '\n'.join(
                           map(lambda x: ' ' * 8 + 'import ' + x, global_vars)
                       ) + '\n'
                err += '\n4. be passed as an external parameter ' \
                       '(not for imports!)'
                err += '\n\n        my_cv = FunctionCV("cv_name", ' + \
                       c.func_name + ', \n' + \
                       ',\n'.join(
                           map(lambda x: ' ' * 20 + x + '=' + x, global_vars)
                       ) + ')' + '\n'
                err += '\n    and change your function definition like this'
                err += '\n\n        def ' + \
                       c.func_name + '(snapshot, ...,  ' + \
                       '\n' + ',\n'.join(
                           map(lambda x: ' ' * 16 + x, global_vars)
                       ) + '):'

            unsafe_modules = [
                module for module in import_vars
                if module not in ObjectJSON.safe_modules
            ]

            if ObjectJSON.prevent_unsafe_modules and len(unsafe_modules) > 0:
                if len(err) > 0:
                    err += '\n\n'

                err += 'The function you try to save requires the following' \
                       ' modules to be installed: ' + str(unsafe_modules) + \
                       ' which are not marked as safe! '
                err += 'You can change the list of safe modules using '
                err += '\n\n        ObjectJSON.safe_modules.extend(['
                err += '\n' + ',\n'.join(
                       map(lambda x: ' ' * 12 + x, unsafe_modules)
                )
                err += '\n        ])'
                err += '\n\n'
                err += 'include the import statement in your function like'
                err += '\n\n' + '\n'.join(
                    [' ' * 8 + 'import ' + v for v in unsafe_modules])

            if len(err) > 0:
                raise RuntimeError('Cannot store function! \n\n' +
                                   word_wrap(err, 60))

            return {
                '_marshal': ObjectJSON._to_marshal(c),
                '_global_vars': global_vars,
                '_module_vars': import_vars
            }

        raise RuntimeError('Locally defined classes are not storable yet')
Exemplo n.º 2
0
    def callable_to_dict(c):
        """
        Turn a callable function of class into a dictionary

        Used for conversion to JSON

        Parameters
        ----------
        c : callable (function or class with __call__)
            the function to be turned into a dict representation

        Returns
        -------
        dict
            the dict representation of the callable
        """
        f_module = c.__module__
        root_module = f_module.split('.')[0]

        # is_class = isinstance(c, (type, types.ClassType))

        # try saving known external classes of functions, e.g. `msmbuilder`
        if root_module in ObjectJSON.safe_modules:
            # only store the function/class and the module
            return {'_module': c.__module__, '_name': c.__name__}

        # if the easy way did not work, try saving it using bytecode
        if ObjectJSON.allow_marshal and callable(c):
            # use marshal
            global_vars = ObjectJSON._find_var(c, opcode.opmap['LOAD_GLOBAL'])
            import_vars = ObjectJSON._find_var(c, opcode.opmap['IMPORT_NAME'])

            all_builtins = dir(builtins)

            global_vars = list(
                set([var for var in global_vars if var not in all_builtins]))
            import_vars = list(set(import_vars))

            err = ''

            if len(global_vars) > 0:
                err += 'The function you try to save relies on globally set ' \
                       'variables and these cannot be saved since storage ' \
                       'has no access to the global scope which includes ' \
                       'imports! \n\n'
                err += 'We require that the following globals: ' + \
                       str(global_vars) + ' either\n'
                err += '\n1. be replaced by constants'
                err += '\n2. be defined inside your function,' + \
                       '\n\n' + '\n'.join(
                           map(lambda x: ' ' * 8 + x + '= ...', global_vars)
                       ) + '\n'
                err += '\n3. imports need to be "re"-imported inside your ' \
                       'function' + \
                       '\n\n' + '\n'.join(
                           map(lambda x: ' ' * 8 + 'import ' + x, global_vars)
                       ) + '\n'
                err += '\n4. be passed as an external parameter ' \
                       '(not for imports!)'
                err += '\n\n        my_cv = FunctionCV("cv_name", ' + \
                       get_name(c) + ', \n' + \
                       ',\n'.join(
                           map(lambda x: ' ' * 20 + x + '=' + x, global_vars)
                       ) + ')' + '\n'
                err += '\n    and change your function definition like this'
                err += '\n\n        def ' + \
                       get_name(c) + '(snapshot, ...,  ' + \
                       '\n' + ',\n'.join(
                           map(lambda x: ' ' * 16 + x, global_vars)
                       ) + '):'

            unsafe_modules = [
                module for module in import_vars
                if module not in ObjectJSON.safe_modules
            ]

            if ObjectJSON.prevent_unsafe_modules and len(unsafe_modules) > 0:
                if len(err) > 0:
                    err += '\n\n'

                err += 'The function you try to save requires the following' \
                       ' modules to be installed: ' + str(unsafe_modules) + \
                       ' which are not marked as safe! '
                err += 'You can change the list of safe modules using '
                err += '\n\n        ObjectJSON.safe_modules.extend(['
                err += '\n' + ',\n'.join(
                    map(lambda x: ' ' * 12 + x, unsafe_modules))
                err += '\n        ])'
                err += '\n\n'
                err += 'include the import statement in your function like'
                err += '\n\n' + '\n'.join(
                    [' ' * 8 + 'import ' + v for v in unsafe_modules])

            if len(err) > 0:
                raise RuntimeError('Cannot store function! \n\n' +
                                   word_wrap(err, 60))

            return {
                '_marshal': ObjectJSON._to_marshal(c),
                '_global_vars': global_vars,
                '_module_vars': import_vars
            }

        raise RuntimeError('Locally defined classes are not storable yet')