WIP: Pyclass installation
Changes to pyclasses don't trigger rebuilds in packages that use those pyclasses, noting that in the case of bugs, any affected packages may be misconfigured and won't get fixed until the next time they happen to be installed.
GLEP 33 gives some insight into how Gentoo handles this (it's a proposal on how to improve the system, but was never implemented). Basically eclasses are permanent and must always remain present in the tree as well as have the same interface. Changes are made by creating a new eclass and bumping the revision (in the name of the class), and then packages need to be individually modified with the new version of the eclass if they want to use it. I don't know what the Gentoo team would do if an eclass had a significant bug that affected the build result but didn't cause build failures.
Basic idea is that pyclasses get installed, and the installed version is used for inheritance, rather than the version which happens to be in the tree at the time. Installed packages which inherit from a particular pyclass will then depend on the exact version they were installed with (FIXME: Should this be recursive? If so, how?), provoking a rebuild if the pyclass is updated, since the version in the repository will instead depend on any version. Note that this would not include a dependency on the revision, to allow minor changes which don't affect installations to be made without causing rebuilds.
Shared functions are a different problem though. The way that occurs to me at the moment is define them on a dummy pyclass (i.e. only exists to define those functions), which can be inherited from to be able to call that function on
Note that pybuilds in the tree would inherit from pyclasses which are also in the tree. This would be necessary to allow them to load (i.e. so we can pull metadata from them) without having to install every pyclass in the tree first.
This would also fix a major issue with the ability to load pybuilds using only the vdb (i.e. to rebuild installed versions which have since been removed from the tree), as pyclasses would no longer be loaded from the tree for installed packages.
Should pyclasses be listed in
DEPEND? This would allow specific versions to be specified. What happens if a package depends on a specific version, but another package depends on a different version? Do we implement package slots to allow multiple versions to be installed simultaneously?
This might be wishful thinking, but it might be possible to define comparison operators on Pyclasses such that the following syntax could be used to declare a version:
class Mod(NexusMod >= "1.0"): ...
It would really depend on how pyclass versions are specified, as for the inheritance to work at all there would at the very least need to be a module which selects the newest version, and perhaps that module could export its selection function such that the newest version could then use comparison operators to turn itself into other versions. This behaviour would also need to work with the installed version too, which could make it relatively easy to allow multiple versions to be installed side by side.
I'd rather treat these as packages from the perspective of the dependency solver, so implementing slots seems like it might be the best way to allow multiple pyclasses to be installed side by side. The depcleaner could also then handle pyclasses which are no longer needed.
Update: The best way to handle versioning would be to require that pyclasses maintain a stable API, and changes which break an API should require a new pyclass (Appending/incrementing a number to the end, for example). That way each pybuild can opt-in to the version using the API which they use, and can guarantee that newer versions won't break the build file. The use of the
>= operator could still be useful if features (used by the pybuild in question) are added (without breaking the API) to a pyclass, as without any sort of version restriction the installed pyclass wouldn't necessarily get upgraded and the build might fail. If only
>= is used, then slots aren't necessary, as the newest version will always be sufficient to satisfy all version requirements.