@@ -0,0 +1,2017 @@
+# -*- coding: utf-8 -*-%0A%0A%22%22%22%0ATasks that provide common and often used functionality.%0A%22%22%22%0A%0A%0A__all__ = %5B%22PutLocalFile%22%5D%0A%0A%0Aimport os%0Afrom abc import abstractmethod%0A%0Aimport luigi%0A%0Afrom law.task.base import Task%0Afrom law.target.local import LocalFileTarget%0Afrom law.target.collection import SiblingFileCollection%0Afrom law.decorator import log%0A%0A%0Aclass PutLocalFile(Task):%0A%0A    path = luigi.Parameter(description=%22path to the file to put%22)%0A    replicas = luigi.IntParameter(default=0, description=%22number of replicas to put, uses %22%0A        %22replica_format when %3E 0 for creating target basenames, default: 0%22)%0A%0A    replica_format = %22%7Bname%7D.%7Bi%7D%7Bext%7D%22%0A%0A    def get_file_target(self):%0A        # when self.path is set, return a target around it%0A        # otherwise assume self.requires() returns a task with a single local target%0A        return LocalFileTarget(self.path) if self.path else self.input()%0A%0A    @abstractmethod%0A    def single_output(self):%0A        pass%0A%0A    def output(self):%0A        output = self.single_output()%0A        if self.replicas %3C= 0:%0A            return output%0A%0A        # prepare replica naming%0A        name, ext = os.path.splitext(output.basename)%0A        basename = lambda i: self.replica_format.format(name=name, ext=ext, i=i)%0A%0A        # return the replicas in a SiblingFileCollection%0A        output_dir = output.parent%0A        return SiblingFileCollection(%5B%0A            output_dir.child(basename(i), %22f%22) for i in range(self.replicas)%0A        %5D)%0A%0A    @log%0A    def run(self):%0A        output = self.output()%0A        src = self.get_file_target()%0A%0A        # single output or replicas?%0A        if not isinstance(output, SiblingFileCollection):%0A            output.copy_from_local(src, cache=False)%0A        else:%0A            # upload all replicas%0A            for i, replica in enumerate(output.targets):%0A                replica.copy_from_local(src, cache=False)%0A                self.publish_message(%22uploaded replica %25d%22 %25 (i + 1))%0A                self.set_progress_percentage(100. * (i + 1) / self.replicas)%0A

Add generic file upload task with replica support, close #28.