-
-
Notifications
You must be signed in to change notification settings - Fork 14.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
nixos-render-docs-redirects: init (#357383)
Co-authored-by: Valentin Gagarin <valentin@gagarin.work>
- Loading branch information
1 parent
c808975
commit 836d207
Showing
8 changed files
with
300 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
{ lib, python3 }: | ||
|
||
python3.pkgs.buildPythonApplication { | ||
pname = "nixos-render-docs-redirects"; | ||
version = "0.0"; | ||
pyproject = true; | ||
|
||
src = ./src; | ||
|
||
build-system = with python3.pkgs; [ setuptools ]; | ||
|
||
nativeCheckInputs = with python3.pkgs; [ | ||
pytestCheckHook | ||
]; | ||
|
||
meta = { | ||
description = "Redirects manipulation for nixos manuals"; | ||
license = lib.licenses.mit; | ||
maintainers = with lib.maintainers; [ getpsyched ]; | ||
mainProgram = "redirects"; | ||
}; | ||
} |
130 changes: 130 additions & 0 deletions
130
pkgs/by-name/ni/nixos-render-docs-redirects/src/nixos_render_docs_redirects/__init__.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
import argparse | ||
import json | ||
import sys | ||
from pathlib import Path | ||
|
||
|
||
def add_content(redirects: dict[str, list[str]], identifier: str, path: str) -> dict[str, list[str]]: | ||
if identifier in redirects: | ||
raise IdentifierExists(identifier) | ||
|
||
# Insert the new identifier in alphabetical order | ||
new_redirects = list(redirects.items()) | ||
insertion_index = 0 | ||
for i, (key, _) in enumerate(new_redirects): | ||
if identifier > key: | ||
insertion_index = i + 1 | ||
else: | ||
break | ||
new_redirects.insert(insertion_index, (identifier, [f"{path}#{identifier}"])) | ||
return dict(new_redirects) | ||
|
||
|
||
def move_content(redirects: dict[str, list[str]], identifier: str, path: str) -> dict[str, list[str]]: | ||
if identifier not in redirects: | ||
raise IdentifierNotFound(identifier) | ||
redirects[identifier].insert(0, f"{path}#{identifier}") | ||
return redirects | ||
|
||
|
||
def rename_identifier( | ||
redirects: dict[str, list[str]], | ||
old_identifier: str, | ||
new_identifier: str | ||
) -> dict[str, list[str]]: | ||
if old_identifier not in redirects: | ||
raise IdentifierNotFound(old_identifier) | ||
if new_identifier in redirects: | ||
raise IdentifierExists(new_identifier) | ||
|
||
# To minimise the diff, we recreate the redirects mapping allowing | ||
# the new key to be updated in-place, preserving the index. | ||
new_redirects = {} | ||
current_path = "" | ||
for key, value in redirects.items(): | ||
if key == old_identifier: | ||
new_redirects[new_identifier] = value | ||
current_path = value[0].split('#')[0] | ||
continue | ||
new_redirects[key] = value | ||
new_redirects[new_identifier].insert(0, f"{current_path}#{new_identifier}") | ||
return new_redirects | ||
|
||
|
||
def remove_and_redirect( | ||
redirects: dict[str, list[str]], | ||
old_identifier: str, | ||
new_identifier: str | ||
) -> dict[str, list[str]]: | ||
if old_identifier not in redirects: | ||
raise IdentifierNotFound(old_identifier) | ||
if new_identifier not in redirects: | ||
raise IdentifierNotFound(new_identifier) | ||
redirects[new_identifier].extend(redirects.pop(old_identifier)) | ||
return redirects | ||
|
||
|
||
def main(): | ||
parser = argparse.ArgumentParser(description="redirects manipulation for nixos manuals") | ||
commands = parser.add_subparsers(dest="command", required=True) | ||
parser.add_argument("-f", "--file", type=Path, required=True) | ||
|
||
add_content_cmd = commands.add_parser("add-content") | ||
add_content_cmd.add_argument("identifier", type=str) | ||
add_content_cmd.add_argument("path", type=str) | ||
|
||
move_content_cmd = commands.add_parser("move-content") | ||
move_content_cmd.add_argument("identifier", type=str) | ||
move_content_cmd.add_argument("path", type=str) | ||
|
||
rename_id_cmd = commands.add_parser("rename-identifier") | ||
rename_id_cmd.add_argument("old_identifier", type=str) | ||
rename_id_cmd.add_argument("new_identifier", type=str) | ||
|
||
remove_redirect_cmd = commands.add_parser("remove-and-redirect") | ||
remove_redirect_cmd.add_argument("identifier", type=str) | ||
remove_redirect_cmd.add_argument("target_identifier", type=str) | ||
|
||
args = parser.parse_args() | ||
|
||
with open(args.file) as file: | ||
redirects = json.load(file) | ||
|
||
try: | ||
if args.command == "add-content": | ||
redirects = add_content(redirects, args.identifier, args.path) | ||
print(f"Added new identifier: {args.identifier}") | ||
|
||
elif args.command == "move-content": | ||
redirects = move_content(redirects, args.identifier, args.path) | ||
print(f"Moved '{args.identifier}' to the new path: {args.path}") | ||
|
||
elif args.command == "rename-identifier": | ||
redirects = rename_identifier(redirects, args.old_identifier, args.new_identifier) | ||
print(f"Renamed identifier from {args.old_identifier} to {args.new_identifier}") | ||
|
||
elif args.command == "remove-and-redirect": | ||
redirects = remove_and_redirect(redirects, args.identifier, args.target_identifier) | ||
print(f"Redirect from '{args.identifier}' to '{args.target_identifier}' added.") | ||
except Exception as error: | ||
print(error, file=sys.stderr) | ||
else: | ||
with open(args.file, "w") as file: | ||
json.dump(redirects, file, indent=2) | ||
file.write("\n") | ||
|
||
|
||
class IdentifierExists(Exception): | ||
def __init__(self, identifier: str): | ||
self.identifier = identifier | ||
|
||
def __str__(self): | ||
return f"The identifier '{self.identifier}' already exists." | ||
|
||
|
||
class IdentifierNotFound(Exception): | ||
def __init__(self, identifier: str): | ||
self.identifier = identifier | ||
|
||
def __str__(self): | ||
return f"The identifier '{self.identifier}' does not exist in the redirect mapping." |
16 changes: 16 additions & 0 deletions
16
pkgs/by-name/ni/nixos-render-docs-redirects/src/pyproject.toml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
[project] | ||
name = "nixos-render-docs-redirects" | ||
version = "0.0" | ||
description = "redirects manipulation for nixos manuals" | ||
classifiers = [ | ||
"Programming Language :: Python :: 3", | ||
"License :: OSI Approved :: MIT License", | ||
"Operating System :: OS Independent", | ||
] | ||
|
||
[project.scripts] | ||
redirects = "nixos_render_docs_redirects:main" | ||
|
||
[build-system] | ||
requires = ["setuptools"] | ||
build-backend = "setuptools.build_meta" |
1 change: 1 addition & 0 deletions
1
pkgs/by-name/ni/nixos-render-docs-redirects/src/tests/__init__.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
|
86 changes: 86 additions & 0 deletions
86
pkgs/by-name/ni/nixos-render-docs-redirects/src/tests/test_redirects.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
import unittest | ||
from nixos_render_docs_redirects import ( | ||
add_content, | ||
move_content, | ||
rename_identifier, | ||
remove_and_redirect, | ||
IdentifierExists, | ||
IdentifierNotFound, | ||
) | ||
|
||
|
||
class RedirectsTestCase(unittest.TestCase): | ||
def test_add_content(self): | ||
initial_redirects = { | ||
"bar": ["path/to/bar.html#bar"], | ||
"foo": ["path/to/foo.html#foo"], | ||
} | ||
final_redirects = { | ||
"bar": ["path/to/bar.html#bar"], | ||
"baz": ["path/to/baz.html#baz"], | ||
"foo": ["path/to/foo.html#foo"], | ||
} | ||
|
||
result = add_content(initial_redirects, "baz", "path/to/baz.html") | ||
self.assertEqual(list(result.items()), list(final_redirects.items())) | ||
|
||
with self.assertRaises(IdentifierExists): | ||
add_content(result, "foo", "another/path.html") | ||
|
||
|
||
def test_move_content(self): | ||
initial_redirects = { | ||
"foo": ["path/to/foo.html#foo"], | ||
"bar": ["path/to/bar.html#bar"], | ||
} | ||
final_redirects = { | ||
"foo": ["new/path.html#foo", "path/to/foo.html#foo"], | ||
"bar": ["path/to/bar.html#bar"], | ||
} | ||
|
||
result = move_content(initial_redirects, "foo", "new/path.html") | ||
self.assertEqual(list(result.items()), list(final_redirects.items())) | ||
|
||
with self.assertRaises(IdentifierNotFound): | ||
move_content(result, "baz", "path.html") | ||
|
||
|
||
def test_rename_identifier(self): | ||
initial_redirects = { | ||
"foo": ["path/to/foo.html#foo"], | ||
"bar": ["path/to/bar.html#bar"], | ||
"baz": ["path/to/baz.html#baz"], | ||
} | ||
final_redirects = { | ||
"foo": ["path/to/foo.html#foo"], | ||
"boo": ["path/to/bar.html#boo", "path/to/bar.html#bar"], | ||
"baz": ["path/to/baz.html#baz"], | ||
} | ||
|
||
result = rename_identifier(initial_redirects, "bar", "boo") | ||
self.assertEqual(list(result.items()), list(final_redirects.items())) | ||
|
||
with self.assertRaises(IdentifierNotFound): | ||
rename_identifier(result, "bar", "boo") | ||
with self.assertRaises(IdentifierExists): | ||
rename_identifier(result, "boo", "boo") | ||
|
||
|
||
def test_remove_and_redirect(self): | ||
initial_redirects = { | ||
"foo": ["new/path.html#foo", "path/to/foo.html#foo"], | ||
"bar": ["path/to/bar.html#bar"], | ||
"baz": ["path/to/baz.html#baz"], | ||
} | ||
final_redirects = { | ||
"bar": ["path/to/bar.html#bar", "new/path.html#foo", "path/to/foo.html#foo"], | ||
"baz": ["path/to/baz.html#baz"], | ||
} | ||
|
||
result = remove_and_redirect(initial_redirects, "foo", "bar") | ||
self.assertEqual(list(result.items()), list(final_redirects.items())) | ||
|
||
with self.assertRaises(IdentifierNotFound): | ||
remove_and_redirect(result, "foo", "bar") | ||
with self.assertRaises(IdentifierNotFound): | ||
remove_and_redirect(initial_redirects, "foo", "baz") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters