code: async def _handle_local_charms(self, bundle):
          
          apps, args = [], []
  
          default_series = bundle.get('series')
          apps_dict = bundle.get('applications', bundle.get('services', {}))
          for app_name in self.applications:
              app_dict = apps_dict[app_name]
              charm_dir = os.path.abspath(os.path.expanduser(app_dict['charm']))
              if not os.path.isdir(charm_dir):
                  continue
              series = (
                  app_dict.get('series') or
                  default_series or
                  get_charm_series(charm_dir)
              )
              if not series:
                  raise JujuError(
                      "Couldn't determine series for charm at {}. "
                      "Add a 'series' key to the bundle.".format(charm_dir))
  
              # Keep track of what we need to update. We keep a list of apps
              # that need to be updated, and a corresponding list of args
              # needed to update those apps.
              apps.append(app_name)
              args.append((charm_dir, series))
  
          if apps:
              # If we have apps to update, spawn all the coroutines concurrently
              # and wait for them to finish.
              charm_urls = await asyncio.gather(*[
                  self.model.add_local_charm_dir(*params)
                  for params in args
              ], loop=self.model.loop)
              # Update the 'charm:' entry for each app with the new 'local:' url.
              for app_name, charm_url in zip(apps, charm_urls):
                  apps_dict[app_name]['charm'] = charm_url
  
          return bundle
docs: Search for references to local charms (i.e. filesystem paths)
          in the bundle. Upload the local charms to the model, and replace
          the filesystem paths with appropriate 'local:' paths in the bundle.
  
          Return the modified bundle.
  
          :param dict bundle: Bundle dictionary
          :return: Modified bundle dictionary