def set(self, attribute, specification, exact=False):
        """Set the named attribute from the specification given by the user.
        The value actually set may be different."""
        assert isinstance(attribute, basestring)
        assert isinstance(exact, (int, bool))
        if __debug__ and not exact:
            if attribute == 'requirements':
                assert (isinstance(specification, property_set.PropertySet)
                        or all(isinstance(s, basestring) for s in specification))
            elif attribute in (
            'usage-requirements', 'default-build', 'source-location', 'build-dir', 'id'):
                assert is_iterable_typed(specification, basestring)
        elif __debug__:
            assert (
                isinstance(specification, (property_set.PropertySet, type(None), basestring))
                    or all(isinstance(s, basestring) for s in specification)
            )
        if exact:
            self.__dict__[attribute] = specification

        elif attribute == "requirements":
            self.requirements = property_set.refine_from_user_input(
                self.requirements, specification,
                self.project_module, self.location)

        elif attribute == "usage-requirements":
            unconditional = []
            for p in specification:
                split = property.split_conditional(p)
                if split:
                    unconditional.append(split[1])
                else:
                    unconditional.append(p)

            non_free = property.remove("free", unconditional)
            if non_free:
                get_manager().errors()("usage-requirements %s have non-free properties %s" \
                                       % (specification, non_free))

            t = property.translate_paths(
                    property.create_from_strings(specification, allow_condition=True),
                    self.location)

            existing = self.__dict__.get("usage-requirements")
            if existing:
                new = property_set.create(existing.all() +  t)
            else:
                new = property_set.create(t)
            self.__dict__["usage-requirements"] = new


        elif attribute == "default-build":
            self.__dict__["default-build"] = property_set.create(specification)

        elif attribute == "source-location":
            source_location = []
            for path in specification:
                source_location.append(os.path.join(self.location, path))
            self.__dict__["source-location"] = source_location

        elif attribute == "build-dir":
            self.__dict__["build-dir"] = os.path.join(self.location, specification[0])

        elif attribute == "id":
            id = specification[0]
            if id[0] != '/':
                id = "/" + id
            self.manager.projects().register_id(id, self.project_module)
            self.__dict__["id"] = id

        elif not attribute in ["default-build", "location",
                               "source-location", "parent",
                               "projects-to-build", "project-root"]:
            self.manager.errors()(
"""Invalid project attribute '%s' specified
for project at '%s'""" % (attribute, self.location))
        else:
            self.__dict__[attribute] = specification
Set the named attribute from the specification given by the user.
        The value actually set may be different.