code: def pull(
      self,
      service_name,
      pull_leaf=True,
      using_docker=False,
      ignore_pull_failures=True,
  ):
      def _pull(service):
          args = ["pull"]
          if service["image"] in self.pull_memory:
              return
  
          if using_docker:
              try:
                  self._execute_docker(*args, service["image"])
              except Exception as e:
                  if ignore_pull_failures:
                      # better --ignore-pull-failures handling
                      print(e)
                  else:
                      raise
          else:
              if ignore_pull_failures:
                  args.append("--ignore-pull-failures")
              self._execute_compose(*args, service["name"])
  
          self.pull_memory.add(service["image"])
  
      service = self.config.get(service_name)
      for ancestor in service["ancestors"]:
          _pull(self.config.get(ancestor))
      if pull_leaf:
          _pull(service)
  
imports: import os
  import shlex
  import subprocess
  from io import StringIO
  from dotenv import dotenv_values
  from ruamel.yaml import YAML
  from ..utils.command import Command, default_bin
  from ..utils.source import arrow_path
  from ..compat import _ensure_path
label_desc: Use image node_id 5 for calling the DockerCompose obj's underlying member method code with example usage: obj.pull(service_name, pull_leaf, using_docker, ignore_pull_failures) without return types