code: def copy(self):
          
  
          metadata = {}
          # grab all the keys into a list so if something is added
          # in another thread it probably doesn't stomp on our loop
          for key in list(self.metadata.keys()):
              try:
                  metadata[key] = copy.deepcopy(self.metadata[key])
              except RuntimeError:
                  # multiple threads
                  log.warning('key {} changed during copy'.format(key))
  
          # copy the core data
          copied = type(self)(entities=copy.deepcopy(self.entities),
                              vertices=copy.deepcopy(self.vertices),
                              metadata=metadata)
  
          cache = {}
          # try to copy the cache over to the new object
          try:
              # save dict keys before doing slow iteration
              keys = list(self._cache.cache.keys())
              # run through each key and copy into new cache
              for k in keys:
                  cache[k] = copy.deepcopy(self._cache.cache[k])
          except RuntimeError:
              # if we have multiple threads this may error and is NBD
              log.debug('unable to copy cache')
          except BaseException:
              # catch and log errors we weren't expecting
              log.error('unable to copy cache', exc_info=True)
          copied._cache.cache = cache
          copied._cache.id_set()
  
          return copied
docs: Get a copy of the current mesh
  
          Returns
          ---------
          copied: Path object, copy of self