code: def add_resource(self, value, name: str = 'default', context_attr: str = None,
                       types: Union[type, Sequence[type]] = ()) -> None:
          
          assert check_argument_types()
          self._check_closed()
          if isinstance(types, type):
              types = (types,)
          elif not types:
              types = (type(value),)
  
          if value is None:
              raise ValueError('"value" must not be None')
          if not resource_name_re.fullmatch(name):
              raise ValueError('"name" must be a nonempty string consisting only of alphanumeric '
                               'characters and underscores')
          if context_attr and getattr_static(self, context_attr, None) is not None:
              raise ResourceConflict('this context already has an attribute {!r}'.format(
                  context_attr))
          for resource_type in types:
              if (resource_type, name) in self._resources:
                  raise ResourceConflict(
                      'this context already contains a resource of type {} using the name {!r}'.
                      format(qualified_name(resource_type), name))
  
          resource = ResourceContainer(value, tuple(types), name, context_attr, False)
          for type_ in resource.types:
              self._resources[(type_, name)] = resource
  
          if context_attr:
              setattr(self, context_attr, value)
  
          # Notify listeners that a new resource has been made available
          self.resource_added.dispatch(types, name, False)
docs: Add a resource to this context.
  
          This will cause a ``resource_added`` event to be dispatched.
  
          :param value: the actual resource value
          :param name: name of this resource (unique among all its registered types within a single
              context)
          :param context_attr: name of the context attribute this resource will be accessible as
          :param types: type(s) to register the resource as (omit to use the type of ``value``)
          :raises asphalt.core.context.ResourceConflict: if the resource conflicts with an existing
              one in any way