Skip to content

Commit 8ab8bae

Browse files
committed
Make EventPath a read-only type.
1 parent 41a4e6f commit 8ab8bae

File tree

5 files changed

+143
-48
lines changed

5 files changed

+143
-48
lines changed

.github/workflows/lint.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ jobs:
1010
strategy:
1111
fail-fast: false
1212
matrix:
13-
python-version: ["3.11", "3.12"]
13+
python-version: ["3.11", "3.12", "3.13"]
1414

1515
steps:
1616

pyproject.toml

Lines changed: 20 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -7,36 +7,32 @@ build-backend = "hatchling.build"
77
[project]
88

99
name = "rubisco"
10-
1110
version = "0.1.0.post"
12-
13-
authors = [{ name = "ChenPi11", email = "[email protected]" }]
14-
11+
authors = [{name = "ChenPi11", email = "[email protected]"}]
1512
description = "C+++ Repository Utilities."
16-
1713
readme = "README.md"
18-
19-
license = { file = "LICENSE" }
20-
21-
requires-python = ">=3.10"
22-
14+
license = {file = "LICENSE"}
15+
requires-python = ">=3.11"
2316
classifiers = [
24-
"Programming Language :: Python :: 3",
25-
"License :: OSI Approved :: GNU General Public License v3 (GPLv3)",
26-
"Operating System :: OS Independent",
17+
"Programming Language :: Python :: 3",
18+
"License :: OSI Approved :: GNU General Public License v3 (GPLv3)",
19+
"Operating System :: OS Independent",
2720
]
2821

2922
dependencies = [
30-
"aiohttp >= 3.5.4",
31-
"beartype >= 0.20.1",
32-
"colorama >= 0.3.9",
33-
"json-five >= 0.5.1",
34-
"py7zr >= 0.16.1",
35-
"pyyaml >= 5.4.1",
36-
"requests >= 2.18.4",
37-
"rich >= 6.2.0",
38-
"rich-argparse >= 1.0.0",
39-
"pytest >= 6.2.4",
23+
"aiohttp >= 3.5.4",
24+
"beartype >= 0.20.1",
25+
"colorama >= 0.3.9",
26+
"json-five >= 0.5.1",
27+
"py7zr >= 0.16.1",
28+
"pyyaml >= 5.4.1",
29+
"requests >= 2.18.4",
30+
"rich >= 6.2.0",
31+
"rich-argparse >= 1.0.0",
32+
"GitPython >= 3.1.20",
33+
"pytest >= 6.2.4",
34+
"pygments >= 2.10.0",
35+
"prompt_toolkit >= 3.0.23",
4036
]
4137

4238
[project.urls]
@@ -50,5 +46,5 @@ exclude = [".github"]
5046

5147
[project.scripts]
5248

53-
rubisco = "rubisco.cli.main.main:main"
5449
ru = "rubisco.cli.main.main:main"
50+
rubisco = "rubisco.cli.main.main:main"

requirements.txt

Lines changed: 0 additions & 13 deletions
This file was deleted.

rubisco/kernel/command_event/event_path.py

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
"""
2525

2626
import os
27-
from pathlib import PurePath
27+
from pathlib import PurePosixPath
2828
from typing import TYPE_CHECKING, Any, Self
2929

3030
from rubisco.kernel.command_event.args import Option
@@ -42,36 +42,34 @@
4242
from rubisco.lib.variable.utils import make_pretty
4343

4444
if TYPE_CHECKING:
45-
from _typeshed import StrPath, Unused
45+
from _typeshed import StrPath
4646

4747
from rubisco.kernel.command_event.cmd_event import EventObject
4848

4949
__all__ = ["EventPath"]
5050

5151

52-
class EventPath(PurePath): # pylint: disable=R0904
52+
class EventPath(PurePosixPath): # pylint: disable=R0904
5353
"""A path object that represents an event.
5454
5555
See `EventObject` for more information.
5656
"""
5757

5858
_event: "EventObject | None" = None
5959

60-
def __init__(self, *args: "StrPath", **kwargs: "Unused") -> None:
60+
def __new__(cls, *args: "StrPath") -> Self:
6161
"""Initialize the EventPath class.
6262
6363
Args:
6464
*args: The arguments to pass to the super class.
65-
**kwargs: Never used.
6665
67-
"""
68-
if kwargs:
69-
msg = "Invalid argument."
70-
raise ValueError(msg)
66+
Returns:
67+
Self: The instance of the class.
7168
69+
"""
7270
if args and not str(args[0]).startswith("/"):
7371
args = ("/" + str(args[0]), *args[1:])
74-
super().__init__(*args)
72+
return super().__new__(cls, *args)
7573

7674
@property
7775
def event_object(self) -> "EventObject":
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
# -*- mode: python -*-
2+
# vi: set ft=python :
3+
4+
# Copyright (C) 2024 The C++ Plus Project.
5+
# This file is part of the Rubisco.
6+
#
7+
# Rubisco is free software: you can redistribute it and/or modify
8+
# it under the terms of the GNU General Public License as published
9+
# by the Free Software Foundation, either version 3 of the License,
10+
# or (at your option) any later version.
11+
#
12+
# Rubisco is distributed in the hope that it will be useful,
13+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
# GNU General Public License for more details.
16+
#
17+
# You should have received a copy of the GNU General Public License
18+
# along with this program. If not, see <https://www.gnu.org/licenses/>.
19+
20+
"""Test rubisco.kernel.command_event.event_types module.
21+
22+
This is a unittest generated by GitHub Copilot (Claude Sonnet 4), which is
23+
totally useless. If somebody see this file, please close it immediately, or
24+
create a issue or pull request to remove this file.
25+
"""
26+
27+
from typing import Any
28+
29+
import pytest
30+
31+
from rubisco.kernel.command_event.callback import EventCallback
32+
from rubisco.kernel.command_event.event_types import (
33+
EventObjectStat,
34+
EventObjectType,
35+
)
36+
37+
38+
class TestEventObjectStat:
39+
"""Test EventObjectStat dataclass."""
40+
41+
def test_event_object_stat_creation(self) -> None:
42+
"""Test EventObjectStat creation."""
43+
44+
def dummy_callback(
45+
options: list[Any],
46+
args: list[Any],
47+
) -> None:
48+
del options
49+
del args
50+
51+
callback = EventCallback(callback=dummy_callback, description="test")
52+
53+
stat = EventObjectStat(
54+
type=EventObjectType.FILE,
55+
description="Test file",
56+
dir_callbacks=[callback],
57+
)
58+
59+
if stat.type != EventObjectType.FILE:
60+
pytest.fail("stat.type` should be FILE.")
61+
if stat.description != "Test file":
62+
pytest.fail("`stat.description` should be 'Test file'.")
63+
if len(stat.dir_callbacks) != 1:
64+
pytest.fail("`stat.dir_callbacks` should have one callback.")
65+
66+
def test_event_object_stat_defaults(self) -> None:
67+
"""Test EventObjectStat with default values."""
68+
stat = EventObjectStat(
69+
type=EventObjectType.DIRECTORY,
70+
description="Test directory",
71+
)
72+
73+
if stat.type != EventObjectType.DIRECTORY:
74+
pytest.fail("`stat.type` should be `DIRECTORY`.")
75+
if stat.description != "Test directory":
76+
pytest.fail("`stat.description` should be 'Test directory'.")
77+
78+
def test_event_object_stat_with_alias(self) -> None:
79+
"""Test EventObjectStat with alias type."""
80+
stat = EventObjectStat(
81+
type=EventObjectType.ALIAS,
82+
description="Test alias",
83+
alias_to="/some/path",
84+
)
85+
86+
if stat.type != EventObjectType.ALIAS:
87+
pytest.fail("stat.type should be ALIAS")
88+
if stat.description != "Test alias":
89+
pytest.fail("stat.description should be 'Test alias'")
90+
if str(stat.alias_to) != "/some/path":
91+
pytest.fail("stat.alias_to should be '/some/path'")
92+
93+
def test_event_object_stat_with_mount_point(self) -> None:
94+
"""Test EventObjectStat with mount point type."""
95+
stat = EventObjectStat(
96+
type=EventObjectType.MOUNT_POINT,
97+
description="Test mount point",
98+
mount_to="/bin/ls",
99+
)
100+
101+
if stat.type != EventObjectType.MOUNT_POINT:
102+
pytest.fail("`stat.type` should be `MOUNT_POINT`.")
103+
if stat.description != "Test mount point":
104+
pytest.fail("`stat.description` should be 'Test mount point'.")
105+
if stat.mount_to != "/bin/ls":
106+
pytest.fail("`stat.mount_to` should be '/bin/ls'")
107+
108+
def test_event_object_stat_alias_validation(self) -> None:
109+
"""Test EventObjectStat alias validation."""
110+
with pytest.raises(ValueError, match="Alias must have an alias_to"):
111+
EventObjectStat(
112+
type=EventObjectType.ALIAS,
113+
description="Test alias without alias_to",
114+
)

0 commit comments

Comments
 (0)