python313Packages.nixpkgs-plugin-update: init from maintainer script (#453943)

This commit is contained in:
Wolfgang Walther
2025-10-22 06:43:40 +00:00
committed by GitHub
13 changed files with 110 additions and 50 deletions

View File

@@ -4,7 +4,7 @@
with pkgs; with pkgs;
let let
pyEnv = python3.withPackages (ps: [ ps.gitpython ]); pyEnv = python3.withPackages (ps: [ ps.nixpkgs-plugin-update ]);
in in
mkShell { mkShell {

View File

@@ -13,12 +13,9 @@ import os
import sys import sys
from pathlib import Path from pathlib import Path
# Import plugin update library from maintainers/scripts/pluginupdate.py import nixpkgs_plugin_update
ROOT = Path(os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))) # type: ignore ROOT = Path(os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))) # type: ignore
sys.path.insert(
0, os.path.join(ROOT.parent.parent.parent.parent.parent, "maintainers", "scripts")
)
import pluginupdate
GET_PLUGINS = f"""with import <localpkgs> {{ }}; GET_PLUGINS = f"""with import <localpkgs> {{ }};
let let
@@ -53,10 +50,10 @@ lib.mapAttrs parse generated"""
HEADER = "# This file has been @generated by ./pkgs/applications/editors/kakoune/plugins/update.py. Do not edit!" HEADER = "# This file has been @generated by ./pkgs/applications/editors/kakoune/plugins/update.py. Do not edit!"
class KakouneEditor(pluginupdate.Editor): class KakouneEditor(nixpkgs_plugin_update.Editor):
def generate_nix( def generate_nix(
self, self,
plugins: list[tuple[pluginupdate.PluginDesc, pluginupdate.Plugin]], plugins: list[tuple[nixpkgs_plugin_update.PluginDesc, nixpkgs_plugin_update.Plugin]],
outfile: str, outfile: str,
): ):
with open(outfile, "w+") as f: with open(outfile, "w+") as f:
@@ -88,7 +85,7 @@ in lib.fix' (lib.extends overrides packages)
print(f"updated {outfile}") print(f"updated {outfile}")
def update(self, args): def update(self, args):
pluginupdate.update_plugins(self, args) nixpkgs_plugin_update.update_plugins(self, args)
def main(): def main():

View File

@@ -27,12 +27,11 @@ from typing import List, Tuple
log = logging.getLogger("vim-updater") log = logging.getLogger("vim-updater")
# Import plugin update library from maintainers/scripts/pluginupdate.py
ROOT = Path(os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))) ROOT = Path(os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))))
import importlib import importlib
import pluginupdate import nixpkgs_plugin_update
from pluginupdate import PluginDesc, run_nix_expr from nixpkgs_plugin_update import PluginDesc, run_nix_expr
treesitter = importlib.import_module("nvim-treesitter.update") treesitter = importlib.import_module("nvim-treesitter.update")
@@ -44,15 +43,15 @@ HEADER = (
NIXPKGS_NVIMTREESITTER_FOLDER = "pkgs/applications/editors/vim/plugins/nvim-treesitter" NIXPKGS_NVIMTREESITTER_FOLDER = "pkgs/applications/editors/vim/plugins/nvim-treesitter"
class VimEditor(pluginupdate.Editor): class VimEditor(nixpkgs_plugin_update.Editor):
nvim_treesitter_updated = False nvim_treesitter_updated = False
def generate_nix( def generate_nix(
self, plugins: List[Tuple[PluginDesc, pluginupdate.Plugin]], outfile: str self, plugins: List[Tuple[PluginDesc, nixpkgs_plugin_update.Plugin]], outfile: str
): ):
log.info("Generating nix code") log.info("Generating nix code")
log.debug("Loading nvim-treesitter revision from nix...") log.debug("Loading nvim-treesitter revision from nix...")
nvim_treesitter_rev = pluginupdate.run_nix_expr( nvim_treesitter_rev = nixpkgs_plugin_update.run_nix_expr(
"(import <localpkgs> { }).vimPlugins.nvim-treesitter.src.rev", "(import <localpkgs> { }).vimPlugins.nvim-treesitter.src.rev",
self.nixpkgs, self.nixpkgs,
timeout=10, timeout=10,
@@ -64,7 +63,7 @@ class VimEditor(pluginupdate.Editor):
log.debug("Loading list of lua plugins...") log.debug("Loading list of lua plugins...")
luaPlugins = run_nix_expr(GET_PLUGINS_LUA, self.nixpkgs, timeout=30) luaPlugins = run_nix_expr(GET_PLUGINS_LUA, self.nixpkgs, timeout=30)
def _isNeovimPlugin(plug: pluginupdate.Plugin) -> bool: def _isNeovimPlugin(plug: nixpkgs_plugin_update.Plugin) -> bool:
""" """
Whether it's a neovim-only plugin Whether it's a neovim-only plugin
We can check if it's available in lua packages We can check if it's available in lua packages
@@ -103,7 +102,7 @@ class VimEditor(pluginupdate.Editor):
print(f"updated {outfile}") print(f"updated {outfile}")
def plugin2nix( def plugin2nix(
self, pdesc: PluginDesc, plugin: pluginupdate.Plugin, isNeovim: bool self, pdesc: PluginDesc, plugin: nixpkgs_plugin_update.Plugin, isNeovim: bool
) -> str: ) -> str:
if isNeovim: if isNeovim:
raise RuntimeError(f"Plugin {plugin.name} is already packaged in `luaPackages`, please use that") raise RuntimeError(f"Plugin {plugin.name} is already packaged in `luaPackages`, please use that")
@@ -129,7 +128,7 @@ class VimEditor(pluginupdate.Editor):
return content return content
def update(self, args): def update(self, args):
pluginupdate.update_plugins(self, args) nixpkgs_plugin_update.update_plugins(self, args)
# TODO this should probably be skipped when running outside a nixpkgs checkout # TODO this should probably be skipped when running outside a nixpkgs checkout
if self.nvim_treesitter_updated: if self.nvim_treesitter_updated:

View File

@@ -24,8 +24,8 @@ buildPythonApplication {
]; ];
pythonPath = [ pythonPath = [
python3Packages.gitpython
python3Packages.requests python3Packages.requests
python3Packages.nixpkgs-plugin-update
]; ];
dontUnpack = true; dontUnpack = true;
@@ -43,12 +43,12 @@ buildPythonApplication {
neovim-unwrapped neovim-unwrapped
nurl nurl
] ]
}" --prefix PYTHONPATH : "${./.}:${../../../../../../maintainers/scripts/pluginupdate-py}" ) }" --prefix PYTHONPATH : "${./.}" )
wrapPythonPrograms wrapPythonPrograms
''; '';
shellHook = '' shellHook = ''
export PYTHONPATH=pkgs/applications/editors/vim/plugins:maintainers/scripts/pluginupdate-py:$PYTHONPATH export PYTHONPATH=pkgs/applications/editors/vim/plugins:$PYTHONPATH
''; '';
passthru.updateScript = writeShellScript "updateScript" '' passthru.updateScript = writeShellScript "updateScript" ''

View File

@@ -5,7 +5,6 @@
lib, lib,
nix-prefetch-scripts, nix-prefetch-scripts,
luarocks-nix, luarocks-nix,
pluginupdate,
lua5_1, lua5_1,
lua5_2, lua5_2,
lua5_3, lua5_3,
@@ -41,18 +40,15 @@ python3Packages.buildPythonApplication {
]; ];
dependencies = [ dependencies = [
python3Packages.gitpython python3Packages.nixpkgs-plugin-update
]; ];
postFixup = '' postFixup = ''
echo "pluginupdate folder ${pluginupdate}"
wrapProgram $out/bin/luarocks-packages-updater \ wrapProgram $out/bin/luarocks-packages-updater \
--prefix PYTHONPATH : "${pluginupdate}" \
--prefix PATH : "${path}" --prefix PATH : "${path}"
''; '';
shellHook = '' shellHook = ''
export PYTHONPATH="maintainers/scripts/pluginupdate-py:$PYTHONPATH"
export PATH="${path}:$PATH" export PATH="${path}:$PATH"
''; '';

View File

@@ -18,8 +18,8 @@ from dataclasses import dataclass
from multiprocessing.dummy import Pool from multiprocessing.dummy import Pool
from pathlib import Path from pathlib import Path
import pluginupdate import nixpkgs_plugin_update
from pluginupdate import FetchConfig, update_plugins from nixpkgs_plugin_update import FetchConfig, update_plugins
class ColoredFormatter(logging.Formatter): class ColoredFormatter(logging.Formatter):
@@ -88,7 +88,7 @@ class LuaPlugin:
# rename Editor to LangUpdate/ EcosystemUpdater # rename Editor to LangUpdate/ EcosystemUpdater
class LuaEditor(pluginupdate.Editor): class LuaEditor(nixpkgs_plugin_update.Editor):
def create_parser(self): def create_parser(self):
parser = super().create_parser() parser = super().create_parser()
parser.set_defaults(proc=1) parser.set_defaults(proc=1)

View File

@@ -0,0 +1,42 @@
{
lib,
buildPythonPackage,
uv-build,
gitpython,
ruff,
mypy,
}:
buildPythonPackage {
pname = "nixpkgs-plugin-update";
version = "0.1.0";
format = "pyproject";
src = ./nixpkgs-plugin-update;
build-system = [ uv-build ];
dependencies = [
gitpython
];
nativeCheckInputs = [
ruff
mypy
];
postInstallCheck = ''
ruff check
mypy
'';
meta = {
description = "Library for updating plugin collections in Nixpkgs";
license = lib.licenses.mit;
maintainers = [
lib.maintainers.teto
lib.maintainers.perchun
lib.maintainers.khaneliman
];
};
}

View File

@@ -0,0 +1,14 @@
uv.lock
.ruff_cache/
.mypy_cache/
# Python-generated files
__pycache__/
*.py[oc]
build/
dist/
wheels/
*.egg-info
# Virtual environments
.venv

View File

@@ -0,0 +1,20 @@
[project]
name = "nixpkgs-plugin-update"
version = "0.1.0"
requires-python = ">=3.12"
dependencies = [
"gitpython>=3.1.45",
]
[build-system]
requires = ["uv_build>=0.8.19"]
build-backend = "uv_build"
[dependency-groups]
dev = [
"mypy>=1.18.2",
"ruff>=0.14.1",
]
[tool.mypy]
packages = ["nixpkgs_plugin_update"]

View File

@@ -3,13 +3,6 @@
# - pkgs/applications/editors/kakoune/plugins/update.py # - pkgs/applications/editors/kakoune/plugins/update.py
# - pkgs/development/lua-modules/updater/updater.py # - pkgs/development/lua-modules/updater/updater.py
# format:
# $ nix run nixpkgs#ruff maintainers/scripts/pluginupdate.py
# type-check:
# $ nix run nixpkgs#python3.pkgs.mypy maintainers/scripts/pluginupdate.py
# linted:
# $ nix run nixpkgs#python3.pkgs.flake8 -- --ignore E501,E265 maintainers/scripts/pluginupdate.py
import argparse import argparse
import csv import csv
import functools import functools
@@ -104,7 +97,7 @@ class Repo:
self._branch = branch self._branch = branch
# Redirect is the new Repo to use # Redirect is the new Repo to use
self.redirect: "Repo | None" = None self.redirect: "Repo | None" = None
self.token = "dummy_token" self.token: str | None = "dummy_token"
@property @property
def name(self): def name(self):
@@ -141,7 +134,7 @@ class Repo:
loaded = json.loads(data) loaded = json.loads(data)
return loaded return loaded
def prefetch(self, ref: str | None) -> str: def prefetch(self, ref: str) -> str:
log.info("Prefetching %s", self.uri) log.info("Prefetching %s", self.uri)
loaded = self._prefetch(ref) loaded = self._prefetch(ref)
return loaded["sha256"] return loaded["sha256"]
@@ -202,12 +195,12 @@ class RepoGitHub(Repo):
latest_entry = root.find(ATOM_ENTRY) latest_entry = root.find(ATOM_ENTRY)
assert latest_entry is not None, f"No commits found in repository {self}" assert latest_entry is not None, f"No commits found in repository {self}"
commit_link = latest_entry.find(ATOM_LINK) commit_link = latest_entry.find(ATOM_LINK)
assert commit_link is not None, f"No link tag found feed entry {xml}" assert commit_link is not None, f"No link tag found feed entry {xml!r}"
url = urlparse(commit_link.get("href")) url = urlparse(commit_link.get("href"))
updated_tag = latest_entry.find(ATOM_UPDATED) updated_tag = latest_entry.find(ATOM_UPDATED)
assert ( assert (
updated_tag is not None and updated_tag.text is not None updated_tag is not None and updated_tag.text is not None
), f"No updated tag found feed entry {xml}" ), f"No updated tag found feed entry {xml!r}"
updated = datetime.strptime(updated_tag.text, "%Y-%m-%dT%H:%M:%SZ") updated = datetime.strptime(updated_tag.text, "%Y-%m-%dT%H:%M:%SZ")
return Path(str(url.path)).name, updated return Path(str(url.path)).name, updated
@@ -372,7 +365,7 @@ class Editor:
self.default_out = default_out or root.joinpath("generated.nix") self.default_out = default_out or root.joinpath("generated.nix")
self.deprecated = deprecated or root.joinpath("deprecated.json") self.deprecated = deprecated or root.joinpath("deprecated.json")
self.cache_file = cache_file or f"{name}-plugin-cache.json" self.cache_file = cache_file or f"{name}-plugin-cache.json"
self.nixpkgs_repo = None self.nixpkgs_repo: git.Repo | None = None
def add(self, args): def add(self, args):
"""CSV spec""" """CSV spec"""
@@ -403,6 +396,7 @@ class Editor:
autocommit = not args.no_commit autocommit = not args.no_commit
if autocommit: if autocommit:
assert editor.nixpkgs_repo is not None
commit( commit(
editor.nixpkgs_repo, editor.nixpkgs_repo,
"{drv_name}: init at {version}".format( "{drv_name}: init at {version}".format(
@@ -788,11 +782,10 @@ def make_repo(uri: str, branch) -> Repo:
# dumb check to see if it's of the form owner/repo (=> github) or https://... # dumb check to see if it's of the form owner/repo (=> github) or https://...
res = urlparse(uri) res = urlparse(uri)
if res.netloc in ["github.com", ""]: if res.netloc in ["github.com", ""]:
res = res.path.strip("/").split("/") owner, repo = res.path.strip("/").split("/")
repo = RepoGitHub(res[0], res[1], branch) return RepoGitHub(owner, repo, branch)
else: else:
repo = Repo(uri.strip(), branch) return Repo(uri.strip(), branch)
return repo
def get_cache_path(cache_file_name: str) -> Path | None: def get_cache_path(cache_file_name: str) -> Path | None:
@@ -928,7 +921,7 @@ def update_plugins(editor: Editor, args):
All input arguments are grouped in the `Editor`.""" All input arguments are grouped in the `Editor`."""
log.info("Start updating plugins") log.info("Start updating plugins")
if args.proc > 1 and args.github_token == None: if args.proc > 1 and args.github_token is None:
log.warning( log.warning(
"You have enabled parallel updates but haven't set a github token.\n" "You have enabled parallel updates but haven't set a github token.\n"
"You may be hit with `HTTP Error 429: too many requests` as a consequence." "You may be hit with `HTTP Error 429: too many requests` as a consequence."
@@ -966,6 +959,7 @@ def update_plugins(editor: Editor, args):
if redirects: if redirects:
update() update()
if autocommit: if autocommit:
assert editor.nixpkgs_repo is not None
commit( commit(
editor.nixpkgs_repo, editor.nixpkgs_repo,
f"{editor.attr_path}: resolve github repository redirects", f"{editor.attr_path}: resolve github repository redirects",

View File

@@ -5817,10 +5817,6 @@ with pkgs;
luarocks = luaPackages.luarocks; luarocks = luaPackages.luarocks;
luarocks-nix = luaPackages.luarocks-nix; luarocks-nix = luaPackages.luarocks-nix;
luarocks-packages-updater = callPackage ../by-name/lu/luarocks-packages-updater/package.nix {
pluginupdate = ../../maintainers/scripts/pluginupdate-py;
};
toluapp = callPackage ../development/tools/toluapp { toluapp = callPackage ../development/tools/toluapp {
lua = lua5_1; # doesn't work with any other :( lua = lua5_1; # doesn't work with any other :(
}; };

View File

@@ -10588,6 +10588,8 @@ self: super: with self; {
nix-prefetch-github = callPackage ../development/python-modules/nix-prefetch-github { }; nix-prefetch-github = callPackage ../development/python-modules/nix-prefetch-github { };
nixpkgs-plugin-update = callPackage ../development/python-modules/nixpkgs-plugin-update { };
nixpkgs-pytools = callPackage ../development/python-modules/nixpkgs-pytools { }; nixpkgs-pytools = callPackage ../development/python-modules/nixpkgs-pytools { };
nixpkgs-updaters-library = callPackage ../development/python-modules/nixpkgs-updaters-library { }; nixpkgs-updaters-library = callPackage ../development/python-modules/nixpkgs-updaters-library { };