code: def pull(self, dryrun=False):
      self.singularity.check()
      if self.is_local:
          return
      if dryrun:
          logger.info(f"Singularity image {self.url} will be pulled.")
          return
      logger.debug(f"Singularity image location: {self.path}")
      if not os.path.exists(self.path):
          logger.info(f"Pulling singularity image {self.url}.")
          try:
              p = subprocess.check_output(
                  [
                      "singularity",
                      "pull",
                      "--name",
                      f"{self.hash}.simg",
                      self.url,
                  ],
                  cwd=self._img_dir,
                  stderr=subprocess.STDOUT,
              )
          except subprocess.CalledProcessError as e:
              raise WorkflowError(
                  "Failed to pull singularity image "
                  "from {}:\n{}".format(self.url, e.stdout.decode())
              )
  
imports: from pathlib import Path
  import subprocess
  import shutil
  import os
  import hashlib
  from snakemake.common import get_snakemake_searchpaths, is_local_file, parse_uri
  from snakemake.exceptions import WorkflowError
  from snakemake.logging import logger
  from snakemake_interface_common.utils import lazy_property
label_desc: Use image node_id 4 for calling the Image obj's underlying member method code with example usage: obj.pull(dryrun) without return types