Repository: DataBiosphere/toil

Issue:
Feature request: more informative naming for function wrapping jobs
I make most toil jobs with `addChildJobFn()` and `addFollowOnJobFn()` rather than creating `Job` subclasses, as I find this interface much cleaner usually.  

The downside is that in the Toil logs, and in the `_toil_worker` command arguments (that I may check with `top`), every single Job created this way  is is called `JobFunctionWrappingJob`.  I'm probably wrong, but I don't think this was always the case.  But anyway, would it be possible to have a name that incorporates the name of the function that's actually being wrapped?  
Thanks!

┆Issue is synchronized with this [Jira Story](https://ucsc-cgl.atlassian.net/browse/TOIL-988)
┆Issue Number: TOIL-988



Discussion:
I'm sure this is possible. We might even have had it like that in the past. I think we just need to look at the function we're wrapping and steal its name.
➤ Melaina Legaspi commented:

William Gao investigate to confirm if this is fixed by Adam Novak 's PR #3887
➤ Melaina Legaspi commented:

William Gao add this to https://github.com/DataBiosphere/toil/blob/1f0930b7b9ecc31ca556d15ab07ff836ba85eb23/docs/appendices/architecture.rst ( https://github.com/DataBiosphere/toil/blob/1f0930b7b9ecc31ca556d15ab07ff836ba85eb23/docs/appendices/architecture.rst|smart-link )

Resolving patch:
diff --git a/src/toil/job.py b/src/toil/job.py
--- a/src/toil/job.py
+++ b/src/toil/job.py
@@ -433,7 +433,7 @@ def __init__(
         Create a new JobDescription.
 
         :param requirements: Dict from string to number, string, or bool
-            describing the resource requirments of the job. 'cores', 'memory',
+            describing the resource requirements of the job. 'cores', 'memory',
             'disk', and 'preemptable' fields, if set, are parsed and broken out
             into properties. If unset, the relevant property will be
             unspecified, and will be pulled from the assigned Config object if
@@ -872,7 +872,6 @@ def pre_update_hook(self) -> None:
         logger.debug("New job version: %s", self)
 
 
-
 class ServiceJobDescription(JobDescription):
     """
     A description of a job that hosts a service.
@@ -910,6 +909,7 @@ def onRegistration(self, jobStore):
         self.terminateJobStoreID = jobStore.getEmptyFileStoreID()
         self.errorJobStoreID = jobStore.getEmptyFileStoreID()
 
+
 class CheckpointJobDescription(JobDescription):
     """
     A description of a job that is a checkpoint.
@@ -957,6 +957,7 @@ def restartCheckpoint(self, jobStore: "AbstractJobStore") -> List[str]:
                 # If the subtree of successors is not complete restart everything
                 logger.debug("Checkpoint job has unfinished successor jobs, deleting children: %s, followOns: %s, services: %s " %
                              (self.childIDs, self.followOnIDs, self.serviceTree.keys()))
+
                 # Delete everything on the stack, as these represent successors to clean
                 # up as we restart the queue
                 def recursiveDelete(jobDesc):
@@ -980,6 +981,7 @@ def recursiveDelete(jobDesc):
                 jobStore.update_job(self)
         return successorsDeleted
 
+
 class Job:
     """
     Class represents a unit of work in toil.
@@ -1026,7 +1028,6 @@ def __init__(
         jobName = self.__class__.__name__
         displayName = displayName if displayName else jobName
 
-
         # Build a requirements dict for the description
         requirements = {'memory': memory, 'cores': cores, 'disk': disk,
                         'preemptable': preemptable}
@@ -1459,8 +1460,8 @@ def encapsulate(self, name=None):
         return EncapsulatedJob(self, unitName=name)
 
     ####################################################
-    #The following function is used for passing return values between
-    #job run functions
+    # The following function is used for passing return values between
+    # job run functions
     ####################################################
 
     def rv(self, *path) -> Any:
@@ -1525,7 +1526,7 @@ def _disablePromiseRegistration(self):
         self._promiseJobStore = None
 
     ####################################################
-    #Cycle/connectivity checking
+    # Cycle/connectivity checking
     ####################################################
 
     def checkJobGraphForDeadlocks(self):
@@ -1697,7 +1698,7 @@ def checkNewCheckpointsAreLeafVertices(self):
                     raise JobGraphDeadlockException("New checkpoint job %s is not a leaf in the job graph" % y)
 
     ####################################################
-    #Deferred function system
+    # Deferred function system
     ####################################################
 
     def defer(self, function, *args, **kwargs):
@@ -2018,7 +2019,7 @@ def getTopologicalOrderingOfJobs(self):
         return ordering
 
     ####################################################
-    #Storing Jobs into the JobStore
+    # Storing Jobs into the JobStore
     ####################################################
 
     def _register(self, jobStore):
@@ -2411,8 +2412,6 @@ def _runner(
         # That and the new child/follow-on relationships will need to be
         # recorded later by an update() of the JobDescription.
 
-
-
     def _jobName(self):
         """
         :rtype : string, used as identifier of the job class in the stats report.
@@ -2504,7 +2503,7 @@ def getUserScript(self):
         return self.userFunctionModule
 
     def _jobName(self):
-        return ".".join((self.__class__.__name__,self.userFunctionModule.name,self.userFunctionName))
+        return ".".join((self.__class__.__name__, self.userFunctionModule.name, self.userFunctionName))
 
 
 class JobFunctionWrappingJob(FunctionWrappingJob):
diff --git a/src/toil/jobStores/fileJobStore.py b/src/toil/jobStores/fileJobStore.py
--- a/src/toil/jobStores/fileJobStore.py
+++ b/src/toil/jobStores/fileJobStore.py
@@ -61,7 +61,7 @@ class FileJobStore(AbstractJobStore):
     JOB_NAME_DIR_PREFIX = 'kind-'
 
     # 10Mb RAM chunks when reading/writing files
-    BUFFER_SIZE = 10485760 # 10Mb
+    BUFFER_SIZE = 10485760  # 10Mb
 
     def __init__(self, path, fanOut=1000):
         """
@@ -795,7 +795,6 @@ def _get_arbitrary_jobs_dir_for_name(self, jobNameSlug):
 
         """
 
-
         if len(os.listdir(self.jobsDir)) > self.fanOut:
             # Make sure that we don't over-fill the root with too many unique job names.
             # Go in a subdirectory tree, and then go by job name and make another tree.


Test patch:
diff --git a/src/toil/test/docs/scripts/example_alwaysfail.py b/src/toil/test/docs/scripts/example_alwaysfail.py
--- a/src/toil/test/docs/scripts/example_alwaysfail.py
+++ b/src/toil/test/docs/scripts/example_alwaysfail.py
@@ -33,5 +33,5 @@ def explode(job):
     raise RuntimeError('Boom!')
 
 
-if __name__=="__main__":
+if __name__ == "__main__":
     main()
diff --git a/src/toil/test/docs/scripts/example_cachingbenchmark.py b/src/toil/test/docs/scripts/example_cachingbenchmark.py
--- a/src/toil/test/docs/scripts/example_cachingbenchmark.py
+++ b/src/toil/test/docs/scripts/example_cachingbenchmark.py
@@ -33,7 +33,7 @@ def main():
     parser = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
 
     parser.add_argument('--minSleep', type=int, default=1,
-        help="Minimum seconds to sleep")
+                        help="Minimum seconds to sleep")
 
     Job.Runner.addToilOptions(parser)
 
@@ -51,8 +51,8 @@ def main():
 def root(job, options):
     # Make a file
     with job.fileStore.writeGlobalFileStream() as (stream, file_id):
-        stream.write(('This is a test of the Toil file caching system. ' +
-            'Had this been an actual file, its contents would have been more interesting.').encode('utf-8'))
+        stream.write(("This is a test of the Toil file caching system. "
+                      "Had this been an actual file, its contents would have been more interesting.").encode('utf-8'))
 
     child_rvs = []
     for i in range(100):
@@ -62,6 +62,7 @@ def root(job, options):
     # Collect all their views into a report
     return job.addFollowOnJobFn(report, child_rvs).rv()
 
+
 def poll(job, options, file_id, number, cores=0.1, disk='200M', memory='512M'):
 
     # Wait a random amount of time before grabbing the file for others to cache it
@@ -84,7 +85,7 @@ def poll(job, options, file_id, number, cores=0.1, disk='200M', memory='512M'):
 
     # Return a tuple representing our view of the file.
     # Drop hostname since hostnames are unique per pod.
-    return (stats.st_dev, stats.st_ino)
+    return stats.st_dev, stats.st_ino
 
 
 def report(job, views):
@@ -101,5 +102,5 @@ def report(job, views):
     return '\n'.join(report)
 
 
-if __name__=="__main__":
+if __name__ == "__main__":
     main()
diff --git a/src/toil/test/docs/scripts/tutorial_arguments.py b/src/toil/test/docs/scripts/tutorial_arguments.py
--- a/src/toil/test/docs/scripts/tutorial_arguments.py
+++ b/src/toil/test/docs/scripts/tutorial_arguments.py
@@ -10,7 +10,8 @@ def __init__(self, message):
     def run(self, fileStore):
         return "Hello, world!, here's a message: %s" % self.message
 
-if __name__=="__main__":
+
+if __name__ == "__main__":
     parser = Job.Runner.getDefaultArgumentParser()
     options = parser.parse_args()
     options.logLevel = "OFF"
diff --git a/src/toil/test/docs/scripts/tutorial_discoverfiles.py b/src/toil/test/docs/scripts/tutorial_discoverfiles.py
--- a/src/toil/test/docs/scripts/tutorial_discoverfiles.py
+++ b/src/toil/test/docs/scripts/tutorial_discoverfiles.py
@@ -7,6 +7,7 @@
 
 class discoverFiles(Job):
     """Views files at a specified path using ls."""
+
     def __init__(self, path, *args, **kwargs):
         self.path = path
         super().__init__(*args, **kwargs)
@@ -15,6 +16,7 @@ def run(self, fileStore):
         if os.path.exists(self.path):
             subprocess.check_call(["ls", self.path])
 
+
 def main():
     options = Job.Runner.getDefaultArgumentParser().parse_args()
     options.clean = "always"
@@ -32,5 +34,6 @@ def main():
         else:
             toil.restart()
 
+
 if __name__ == '__main__':
     main()
diff --git a/src/toil/test/docs/scripts/tutorial_docker.py b/src/toil/test/docs/scripts/tutorial_docker.py
--- a/src/toil/test/docs/scripts/tutorial_docker.py
+++ b/src/toil/test/docs/scripts/tutorial_docker.py
@@ -9,10 +9,10 @@
                       working_dir=os.getcwd(),
                       parameters=['ls', '-lha'])
 
-if __name__=="__main__":
+if __name__ == "__main__":
     options = Job.Runner.getDefaultOptions("./toilWorkflowRun")
     options.logLevel = "INFO"
     options.clean = "always"
 
     with Toil(options) as toil:
-       toil.start(align)
+        toil.start(align)
diff --git a/src/toil/test/docs/scripts/tutorial_dynamic.py b/src/toil/test/docs/scripts/tutorial_dynamic.py
--- a/src/toil/test/docs/scripts/tutorial_dynamic.py
+++ b/src/toil/test/docs/scripts/tutorial_dynamic.py
@@ -9,7 +9,8 @@ def binaryStringFn(job, depth, message=""):
     else:
         job.log(f"Binary string: {message}")
 
-if __name__=="__main__":
+
+if __name__ == "__main__":
     options = Job.Runner.getDefaultOptions("./toilWorkflowRun")
     options.logLevel = "INFO"
     options.clean = "always"
diff --git a/src/toil/test/docs/scripts/tutorial_encapsulation.py b/src/toil/test/docs/scripts/tutorial_encapsulation.py
--- a/src/toil/test/docs/scripts/tutorial_encapsulation.py
+++ b/src/toil/test/docs/scripts/tutorial_encapsulation.py
@@ -1,7 +1,7 @@
 from toil.common import Toil
 from toil.job import Job
 
-if __name__=="__main__":
+if __name__ == "__main__":
     # A is a job with children and follow-ons, for example:
     A = Job()
     A.addChild(Job())
diff --git a/src/toil/test/docs/scripts/tutorial_encapsulation2.py b/src/toil/test/docs/scripts/tutorial_encapsulation2.py
--- a/src/toil/test/docs/scripts/tutorial_encapsulation2.py
+++ b/src/toil/test/docs/scripts/tutorial_encapsulation2.py
@@ -1,7 +1,7 @@
 from toil.common import Toil
 from toil.job import Job
 
-if __name__=="__main__":
+if __name__ == "__main__":
     # A
     A = Job()
     A.addChild(Job())
diff --git a/src/toil/test/docs/scripts/tutorial_helloworld.py b/src/toil/test/docs/scripts/tutorial_helloworld.py
--- a/src/toil/test/docs/scripts/tutorial_helloworld.py
+++ b/src/toil/test/docs/scripts/tutorial_helloworld.py
@@ -3,7 +3,8 @@
 
 
 def helloWorld(message, memory="1G", cores=1, disk="1G"):
-    return "Hello, world!, here's a message: %s" % message
+    return f"Hello, world!, here's a message: {message}"
+
 
 if __name__ == "__main__":
     parser = Job.Runner.getDefaultArgumentParser()
diff --git a/src/toil/test/docs/scripts/tutorial_invokeworkflow.py b/src/toil/test/docs/scripts/tutorial_invokeworkflow.py
--- a/src/toil/test/docs/scripts/tutorial_invokeworkflow.py
+++ b/src/toil/test/docs/scripts/tutorial_invokeworkflow.py
@@ -8,9 +8,10 @@ def __init__(self, message):
         self.message = message
 
     def run(self, fileStore):
-        return "Hello, world!, here's a message: %s" % self.message
+        return f"Hello, world!, here's a message: {self.message}"
 
-if __name__=="__main__":
+
+if __name__ == "__main__":
     options = Job.Runner.getDefaultOptions("./toilWorkflowRun")
     options.logLevel = "OFF"
     options.clean = "always"
diff --git a/src/toil/test/docs/scripts/tutorial_invokeworkflow2.py b/src/toil/test/docs/scripts/tutorial_invokeworkflow2.py
--- a/src/toil/test/docs/scripts/tutorial_invokeworkflow2.py
+++ b/src/toil/test/docs/scripts/tutorial_invokeworkflow2.py
@@ -8,9 +8,10 @@ def __init__(self, message):
         self.message = message
 
     def run(self, fileStore):
-        self.log(f"Hello, world!, I have a message: {self.message}")
+        return f"Hello, world!, I have a message: {self.message}"
 
-if __name__=="__main__":
+
+if __name__ == "__main__":
     options = Job.Runner.getDefaultOptions("./toilWorkflowRun")
     options.logLevel = "INFO"
     options.clean = "always"
@@ -18,6 +19,7 @@ def run(self, fileStore):
     with Toil(options) as toil:
         if not toil.options.restart:
             job = HelloWorld("Woot!")
-            toil.start(job)
+            output = toil.start(job)
         else:
-            toil.restart()
+            output = toil.restart()
+    print(output)
diff --git a/src/toil/test/docs/scripts/tutorial_jobfunctions.py b/src/toil/test/docs/scripts/tutorial_jobfunctions.py
--- a/src/toil/test/docs/scripts/tutorial_jobfunctions.py
+++ b/src/toil/test/docs/scripts/tutorial_jobfunctions.py
@@ -5,7 +5,8 @@
 def helloWorld(job, message):
     job.log(f"Hello world, I have a message: {message}")
 
-if __name__=="__main__":
+
+if __name__ == "__main__":
     options = Job.Runner.getDefaultOptions("./toilWorkflowRun")
     options.logLevel = "INFO"
     options.clean = "always"
diff --git a/src/toil/test/docs/scripts/tutorial_managing.py b/src/toil/test/docs/scripts/tutorial_managing.py
--- a/src/toil/test/docs/scripts/tutorial_managing.py
+++ b/src/toil/test/docs/scripts/tutorial_managing.py
@@ -4,13 +4,14 @@
 
 class LocalFileStoreJob(Job):
     def run(self, fileStore):
-        # self.TempDir will always contain the name of a directory within the allocated disk space reserved for the job
+        # self.tempDir will always contain the name of a directory within the allocated disk space reserved for the job
         scratchDir = self.tempDir
 
         # Similarly create a temporary file.
         scratchFile = fileStore.getLocalTempFile()
 
-if __name__=="__main__":
+
+if __name__ == "__main__":
     options = Job.Runner.getDefaultOptions("./toilWorkflowRun")
     options.logLevel = "INFO"
     options.clean = "always"
@@ -18,6 +19,6 @@ def run(self, fileStore):
     # Create an instance of FooJob which will have at least 2 gigabytes of storage space.
     j = LocalFileStoreJob(disk="2G")
 
-    #Run the workflow
+    # Run the workflow
     with Toil(options) as toil:
         toil.start(j)
diff --git a/src/toil/test/docs/scripts/tutorial_managing2.py b/src/toil/test/docs/scripts/tutorial_managing2.py
--- a/src/toil/test/docs/scripts/tutorial_managing2.py
+++ b/src/toil/test/docs/scripts/tutorial_managing2.py
@@ -5,8 +5,8 @@
 
 
 def globalFileStoreJobFn(job):
-    job.log("The following example exercises all the methods provided"
-            " by the toil.fileStores.abstractFileStore.AbstractFileStore class")
+    job.log("The following example exercises all the methods provided "
+            "by the toil.fileStores.abstractFileStore.AbstractFileStore class")
 
     # Create a local temporary file.
     scratchFile = job.fileStore.getLocalTempFile()
@@ -33,7 +33,7 @@ def globalFileStoreJobFn(job):
 
     # Read the second file again using a stream.
     with job.fileStore.readGlobalFileStream(fileID2) as fH:
-        print(fH.read()) #This prints "Out brief candle"
+        print(fH.read())  # This prints "Out brief candle"
 
     # Delete the first file from the global file-store.
     job.fileStore.deleteGlobalFile(fileID)
@@ -41,7 +41,8 @@ def globalFileStoreJobFn(job):
     # It is unnecessary to delete the file keyed by fileID2 because we used the cleanup flag,
     # which removes the file after this job and all its successors have run (if the file still exists)
 
-if __name__=="__main__":
+
+if __name__ == "__main__":
     options = Job.Runner.getDefaultOptions("./toilWorkflowRun")
     options.logLevel = "INFO"
     options.clean = "always"
diff --git a/src/toil/test/docs/scripts/tutorial_multiplejobs.py b/src/toil/test/docs/scripts/tutorial_multiplejobs.py
--- a/src/toil/test/docs/scripts/tutorial_multiplejobs.py
+++ b/src/toil/test/docs/scripts/tutorial_multiplejobs.py
@@ -5,7 +5,8 @@
 def helloWorld(job, message, memory="2G", cores=2, disk="3G"):
     job.log(f"Hello world, I have a message: {message}")
 
-if __name__=="__main__":
+
+if __name__ == "__main__":
     options = Job.Runner.getDefaultOptions("./toilWorkflowRun")
     options.logLevel = "INFO"
     options.clean = "always"
@@ -14,6 +15,7 @@ def helloWorld(job, message, memory="2G", cores=2, disk="3G"):
     j2 = Job.wrapJobFn(helloWorld, "second or third")
     j3 = Job.wrapJobFn(helloWorld, "second or third")
     j4 = Job.wrapJobFn(helloWorld, "last")
+
     j1.addChild(j2)
     j1.addChild(j3)
     j1.addFollowOn(j4)
diff --git a/src/toil/test/docs/scripts/tutorial_multiplejobs2.py b/src/toil/test/docs/scripts/tutorial_multiplejobs2.py
--- a/src/toil/test/docs/scripts/tutorial_multiplejobs2.py
+++ b/src/toil/test/docs/scripts/tutorial_multiplejobs2.py
@@ -5,7 +5,8 @@
 def helloWorld(job, message, memory="2G", cores=2, disk="3G"):
     job.log(f"Hello world, I have a message: {message}")
 
-if __name__=="__main__":
+
+if __name__ == "__main__":
     options = Job.Runner.getDefaultOptions("./toilWorkflowRun")
     options.logLevel = "INFO"
     options.clean = "always"
diff --git a/src/toil/test/docs/scripts/tutorial_multiplejobs3.py b/src/toil/test/docs/scripts/tutorial_multiplejobs3.py
--- a/src/toil/test/docs/scripts/tutorial_multiplejobs3.py
+++ b/src/toil/test/docs/scripts/tutorial_multiplejobs3.py
@@ -5,7 +5,8 @@
 def helloWorld(job, message, memory="2G", cores=2, disk="3G"):
     job.log(f"Hello world, I have a message: {message}")
 
-if __name__=="__main__":
+
+if __name__ == "__main__":
     options = Job.Runner.getDefaultOptions("./toilWorkflowRun")
     options.logLevel = "INFO"
     options.clean = "always"
diff --git a/src/toil/test/docs/scripts/tutorial_promises.py b/src/toil/test/docs/scripts/tutorial_promises.py
--- a/src/toil/test/docs/scripts/tutorial_promises.py
+++ b/src/toil/test/docs/scripts/tutorial_promises.py
@@ -4,9 +4,10 @@
 
 def fn(job, i):
     job.log("i is: %s" % i, level=100)
-    return i+1
+    return i + 1
 
-if __name__=="__main__":
+
+if __name__ == "__main__":
     options = Job.Runner.getDefaultOptions("./toilWorkflowRun")
     options.logLevel = "INFO"
     options.clean = "always"
diff --git a/src/toil/test/docs/scripts/tutorial_promises2.py b/src/toil/test/docs/scripts/tutorial_promises2.py
--- a/src/toil/test/docs/scripts/tutorial_promises2.py
+++ b/src/toil/test/docs/scripts/tutorial_promises2.py
@@ -4,15 +4,17 @@
 
 def binaryStrings(job, depth, message=""):
     if depth > 0:
-        s = [ job.addChildJobFn(binaryStrings, depth-1, message + "0").rv(),
-              job.addChildJobFn(binaryStrings, depth-1, message + "1").rv() ]
+        s = [job.addChildJobFn(binaryStrings, depth - 1, message + "0").rv(),
+             job.addChildJobFn(binaryStrings, depth - 1, message + "1").rv()]
         return job.addFollowOnFn(merge, s).rv()
     return [message]
 
+
 def merge(strings):
     return strings[0] + strings[1]
 
-if __name__=="__main__":
+
+if __name__ == "__main__":
     options = Job.Runner.getDefaultOptions("./toilWorkflowRun")
     options.loglevel = "OFF"
     options.clean = "always"
diff --git a/src/toil/test/docs/scripts/tutorial_quickstart.py b/src/toil/test/docs/scripts/tutorial_quickstart.py
--- a/src/toil/test/docs/scripts/tutorial_quickstart.py
+++ b/src/toil/test/docs/scripts/tutorial_quickstart.py
@@ -3,9 +3,10 @@
 
 
 def helloWorld(message, memory="2G", cores=2, disk="3G"):
-    return "Hello, world!, here's a message: %s" % message
+    return f"Hello, world!, here's a message: {message}"
 
-if __name__=="__main__":
+
+if __name__ == "__main__":
     options = Job.Runner.getDefaultOptions("./toilWorkflowRun")
     options.logLevel = "OFF"
     options.clean = "always"
@@ -13,4 +14,4 @@ def helloWorld(message, memory="2G", cores=2, disk="3G"):
     hello_job = Job.wrapFn(helloWorld, "Woot")
 
     with Toil(options) as toil:
-        print(toil.start(hello_job)) #Prints Hello, world!, ...
+        print(toil.start(hello_job))  # prints "Hello, world!, ..."
diff --git a/src/toil/test/docs/scripts/tutorial_requirements.py b/src/toil/test/docs/scripts/tutorial_requirements.py
--- a/src/toil/test/docs/scripts/tutorial_requirements.py
+++ b/src/toil/test/docs/scripts/tutorial_requirements.py
@@ -5,21 +5,25 @@
 
 
 def parentJob(job):
-    downloadJob = Job.wrapJobFn(stageFn, "File://"+os.path.realpath(__file__), cores=0.1, memory='32M', disk='1M')
+    downloadJob = Job.wrapJobFn(stageFn, "file://" + os.path.realpath(__file__), cores=0.1, memory='32M', disk='1M')
     job.addChild(downloadJob)
 
-    analysis = Job.wrapJobFn(analysisJob, fileStoreID=downloadJob.rv(0),
+    analysis = Job.wrapJobFn(analysisJob,
+                             fileStoreID=downloadJob.rv(0),
                              disk=PromisedRequirement(downloadJob.rv(1)))
     job.addFollowOn(analysis)
 
+
 def stageFn(job, url, cores=1):
     importedFile = job.fileStore.import_file(url)
     return importedFile, importedFile.size
 
+
 def analysisJob(job, fileStoreID, cores=2):
     # now do some analysis on the file
     pass
 
+
 if __name__ == "__main__":
     options = Job.Runner.getDefaultOptions("./toilWorkflowRun")
     options.logLevel = "INFO"
diff --git a/src/toil/test/docs/scripts/tutorial_services.py b/src/toil/test/docs/scripts/tutorial_services.py
--- a/src/toil/test/docs/scripts/tutorial_services.py
+++ b/src/toil/test/docs/scripts/tutorial_services.py
@@ -3,7 +3,6 @@
 
 
 class DemoService(Job.Service):
-
     def start(self, fileStore):
         # Start up a database/service here
         # Return a value that enables another process to connect to the database
@@ -18,17 +17,21 @@ def stop(self, fileStore):
         # Cleanup the database here
         pass
 
+
 j = Job()
 s = DemoService()
 loginCredentialsPromise = j.addService(s)
 
+
 def dbFn(loginCredentials):
     # Use the login credentials returned from the service's start method to connect to the service
     pass
 
+
 j.addChildFn(dbFn, loginCredentialsPromise)
 
-if __name__=="__main__":
+
+if __name__ == "__main__":
     options = Job.Runner.getDefaultOptions("./toilWorkflowRun")
     options.logLevel = "INFO"
     options.clean = "always"
diff --git a/src/toil/test/docs/scripts/tutorial_staging.py b/src/toil/test/docs/scripts/tutorial_staging.py
--- a/src/toil/test/docs/scripts/tutorial_staging.py
+++ b/src/toil/test/docs/scripts/tutorial_staging.py
@@ -6,7 +6,7 @@
 
 class HelloWorld(Job):
     def __init__(self, id):
-        Job.__init__(self,  memory="2G", cores=2, disk="3G")
+        Job.__init__(self, memory="2G", cores=2, disk="3G")
         self.inputFileID = id
 
     def run(self, fileStore):
@@ -16,7 +16,7 @@ def run(self, fileStore):
         return outputFileID
 
 
-if __name__=="__main__":
+if __name__ == "__main__":
     options = Job.Runner.getDefaultOptions("./toilWorkflowRun")
     options.logLevel = "INFO"
     options.clean = "always"