{"record":{"id":"086629c32e97750c","repo":"microsoft/qlib","slug":"notimplemented","errorCode":null,"errorMessage":"NotImplemented","messagePattern":"NotImplemented","errorType":"exception","errorClass":"NotImplementedError","httpStatus":null,"severity":"error","filePath":"qlib/utils/paral.py","lineNumber":146,"sourceCode":"\n        return decorator_func\n\n\n# # Outlines: Joblib enhancement\n# The code are for implementing following workflow\n# - Construct complex data structure nested with delayed joblib tasks\n#      - For example,  {\"job\": [<delayed_joblib_task>,  {\"1\": <delayed_joblib_task>}]}\n# - executing all the tasks and replace all the <delayed_joblib_task> with its return value\n\n# This will make it easier to convert some existing code to a parallel one\n\n\nclass DelayedTask:\n    def get_delayed_tuple(self):\n        \"\"\"get_delayed_tuple.\n        Return the delayed_tuple created by joblib.delayed\n        \"\"\"\n        raise NotImplementedError(\"NotImplemented\")\n\n    def set_res(self, res):\n        \"\"\"set_res.\n\n        Parameters\n        ----------\n        res :\n            the executed result of the delayed tuple\n        \"\"\"\n        self.res = res\n\n    def get_replacement(self):\n        \"\"\"return the object to replace the delayed task\"\"\"\n        raise NotImplementedError(\"NotImplemented\")\n\n\nclass DelayedTuple(DelayedTask):\n    def __init__(self, delayed_tpl):","sourceCodeStart":128,"sourceCodeEnd":164,"githubUrl":"https://github.com/microsoft/qlib/blob/79633dd9506ea689e5400dea0197717b5b3d74b7/qlib/utils/paral.py#L128-L164","documentation":"DelayedTask is a mixin in qlib.utils.paral for embedding joblib-delayed tasks inside nested data structures (dicts/lists) so Parallel can execute and replace them with results. The contract requires each subclass to return its (func, args, kwargs) delayed tuple from get_delayed_tuple(); the base class intentionally raises NotImplementedError. Hitting it means the base DelayedTask was used directly or a subclass omitted the method.","triggerScenarios":"Instantiating DelayedTask() itself, or a custom subclass without get_delayed_tuple, and passing it into qlib's run_loop_delayed / parallel execution utilities.","commonSituations":"Writing custom delayed-execution wrappers around qlib.utils.paral.run_loop_delayed; upgrading qlib where DelayedTask subclasses changed shape; copy-pasting an example that only shows set_res/get_replacement.","solutions":["Implement get_delayed_tuple() in your subclass, returning the tuple produced by joblib.delayed(func)(*args, **kwargs).","Prefer using joblib.delayed directly and qlib.utils.paral.run_loop_delayed, which accepts raw delayed objects without subclassing.","Never instantiate the DelayedTask base class itself; treat it as an interface."],"exampleFix":"// before\nclass MyTask(DelayedTask):\n    pass  # get_delayed_tuple inherited -> NotImplementedError\n\n// after\nfrom joblib import delayed\nclass MyTask(DelayedTask):\n    def get_delayed_tuple(self):\n        return delayed(self.func)(*self.args, **self.kwargs)","handlingStrategy":"type-guard","validationCode":"from qlib.utils.paral import DelayedTask\nassert type(task).get_delayed_tuple is not DelayedTask.get_delayed_tuple, 'implement get_delayed_tuple'","typeGuard":"def is_runnable_delayed(task) -> bool:\n    return type(task).get_delayed_tuple is not DelayedTask.get_delayed_tuple","tryCatchPattern":null,"preventionTips":["Use joblib.delayed directly with run_loop_delayed instead of subclassing DelayedTask when possible.","If subclassing, implement get_delayed_tuple first and unit-test it returns a (func, args, kwargs) delayed tuple."],"tags":["qlib","paral","joblib","notimplementederror","parallelism"],"backgroundTag":null,"analyzedSha":"79633dd9506ea689e5400dea0197717b5b3d74b7","analyzedAt":"2026-08-15T07:01:27.511Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}