Example #1
0
    def test_track_functions(self):
        assert _is_function(f1), "function got decorated unexpectedly"
        assert not _is_task(f1), "function got decorated unexpectedly"
        track_functions(f1, f2, f3)

        assert callable(f1), "function is not function anymore"
        assert _is_task(f1), "local function wasn't decorated"
        assert _is_task(
            module_to_track.f1), "function in module wasn't decorated"
        assert _is_task(f2)
        assert _is_task(f3)
Example #2
0
    def test_track_modules(self):
        assert _is_function(f4), "function got decorated unexpectedly"
        assert not _is_task(f4), "function got decorated unexpectedly"
        track_modules(module_to_track)

        assert callable(f4), "function is not function anymore"
        assert _is_task(f4), "local function wasn't decorated"
        assert callable(module_to_track.f4), "function is not function anymore"
        assert _is_task(
            module_to_track.f4), "function in module wasn't decorated"
        assert _is_task(module_to_track.f5)
        assert _is_function(module_to_track.task)
        assert not _is_task(module_to_track.task)
Example #3
0
    def _get_task_cls(self, task_name):
        from dbnd._core.utils.basics.load_python_module import load_python_module

        task_cls = self._get_registered_task_cls(task_name)
        if task_cls:
            return task_cls

        # we are going to check if we have override/definition in config
        config_task_type = config.get(task_name, "_type", None)
        if config_task_type:
            _validate_no_recursion_in_config(task_name, config_task_type,
                                             "_type")
            try:
                return self._get_task_cls(config_task_type)
            except Exception:
                logger.warning(
                    "Failed to load type required by [%s] using _type=%s",
                    task_name,
                    config_task_type,
                )
                raise
        config_task_type = config.get(task_name, "_from", None)
        if config_task_type:
            _validate_no_recursion_in_config(task_name, config_task_type,
                                             "_from")
            return self._get_task_cls(config_task_type)

        if "." in task_name:
            parts = task_name.split(".")
            possible_root_task = parts.pop()
            possible_module = ".".join(parts)

            # Try to load module and check again for existance
            load_python_module(possible_module, "task name '%s'" % task_name)

            task_cls = self._get_registered_task_cls(task_name)
            if task_cls:
                return task_cls

            # Check if task exists but user forgot to decorate method with @task
            task_module = sys.modules.get(possible_module)
            if task_module and hasattr(task_module, possible_root_task):
                user_func = getattr(task_module, possible_root_task)

                from dbnd._core.task_build.task_metaclass import TaskMetaclass

                # weird case of we didn't manage to find a class after it was loaded via _get_registered_task_cls
                # can happen if the function name is different from "task_family"
                if isinstance(user_func, TaskMetaclass):
                    return user_func

                if callable(user_func):
                    from dbnd._core.tracking.python_tracking import _is_task

                    if _is_task(user_func):
                        return user_func.task_cls
                    # Non-decorated function was found - decorate and return it
                    from dbnd._core.task_build import dbnd_decorator

                    decorated_task = dbnd_decorator.task(user_func)
                    setattr(task_module, possible_root_task, decorated_task)
                    logger.warning(
                        "Found non-decorated task: %s. "
                        "Please decorate this task with the proper symbol @pipeline / @task.\n"
                        "Auto-decorating and treating it as @task ...",
                        task_name,
                    )
                    return decorated_task.task

        if is_airflow_enabled():
            from dbnd_airflow.dbnd_task_executor.airflow_operator_as_dbnd import (
                AirflowDagAsDbndTask, )

            dag = self._get_aiflow_dag(task_name)
            if dag:
                return AirflowDagAsDbndTask
        return None