machine-root 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- machine_root-0.1.0/.gitignore +16 -0
- machine_root-0.1.0/LICENSE +9 -0
- machine_root-0.1.0/PKG-INFO +94 -0
- machine_root-0.1.0/README.md +79 -0
- machine_root-0.1.0/docs/raw/0000__machine-root.json +58 -0
- machine_root-0.1.0/docs/raw/0001__machineroot-package.json +124 -0
- machine_root-0.1.0/docs/raw/0002__help-output.txt +52 -0
- machine_root-0.1.0/pyproject.toml +27 -0
- machine_root-0.1.0/src/machineroot/__init__.py +32 -0
- machine_root-0.1.0/src/machineroot/__main__.py +144 -0
- machine_root-0.1.0/src/machineroot/_exceptions.py +10 -0
- machine_root-0.1.0/src/machineroot/_resolve.py +51 -0
- machine_root-0.1.0/zoo-project.json +9 -0
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
CC0 1.0 Universal
|
|
2
|
+
|
|
3
|
+
This work is dedicated to the public domain under the Creative Commons CC0 1.0
|
|
4
|
+
Universal Public Domain Dedication.
|
|
5
|
+
|
|
6
|
+
To the extent possible under law, the author(s) have waived all copyright and
|
|
7
|
+
related or neighboring rights to this work.
|
|
8
|
+
|
|
9
|
+
See https://creativecommons.org/publicdomain/zero/1.0/ for details.
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: machine-root
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A minimal shared registry for locating resources on a local machine
|
|
5
|
+
Project-URL: Homepage, https://github.com/LionKimbro/machine-root
|
|
6
|
+
Project-URL: Repository, https://github.com/LionKimbro/machine-root
|
|
7
|
+
Author: Lion Kimbro
|
|
8
|
+
License: CC0-1.0
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Classifier: License :: CC0 1.0 Universal (CC0 1.0) Public Domain Dedication
|
|
11
|
+
Classifier: Operating System :: OS Independent
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Requires-Python: >=3.11
|
|
14
|
+
Description-Content-Type: text/markdown
|
|
15
|
+
|
|
16
|
+
# machine-root
|
|
17
|
+
|
|
18
|
+
## The Problem
|
|
19
|
+
|
|
20
|
+
Programs, scripts, and AIs that run on a machine often need to locate resources - a project folder, a service registry, a configuration file. The usual solutions are fragile: hard-coded paths break when things move, environment variables require manual setup, and configuration systems are overkill for something this simple.
|
|
21
|
+
|
|
22
|
+
## The System
|
|
23
|
+
|
|
24
|
+
Machine Root is a minimal, shared registry for a local machine. It is a single JSON file - `machine-root.json` - that maps string keys to locations (typically filesystem paths):
|
|
25
|
+
|
|
26
|
+
```json
|
|
27
|
+
{
|
|
28
|
+
"zoo.projects": "C:/lion/zoo/projects",
|
|
29
|
+
"filetalk.registry": "C:/lion/filetalk/service-registry.json",
|
|
30
|
+
"librarian.main": "C:/lion/librarian/registry.json"
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Any program that knows the convention can read from the same registry. Keys are stable names; values are locations that can change. No metadata, no nesting, no configuration framework required.
|
|
35
|
+
|
|
36
|
+
### Resolution Order
|
|
37
|
+
|
|
38
|
+
When looking for `machine-root.json`, the system checks these locations in order and uses the first one found:
|
|
39
|
+
|
|
40
|
+
1. The path in the `MACHINE_ROOT` environment variable (if set and the file exists)
|
|
41
|
+
2. `./machine-root.json` (current working directory)
|
|
42
|
+
3. `~/machine-root.json` (user home directory)
|
|
43
|
+
4. Machine-level: `C:/machine-root.json` (Windows) or `/etc/machine-root.json` (Linux)
|
|
44
|
+
|
|
45
|
+
If none are found, operations fail clearly.
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## The Package
|
|
50
|
+
|
|
51
|
+
`machine-root` is a Python package that implements the Machine Root system. It provides a minimal API and a command-line tool for reading and writing the registry.
|
|
52
|
+
|
|
53
|
+
### Install
|
|
54
|
+
|
|
55
|
+
```
|
|
56
|
+
pip install machine-root
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Python API
|
|
60
|
+
|
|
61
|
+
```python
|
|
62
|
+
import machineroot
|
|
63
|
+
|
|
64
|
+
machineroot.locate() # path to the active machine-root.json
|
|
65
|
+
machineroot.keys() # list all keys
|
|
66
|
+
machineroot.get("zoo.projects") # get a value
|
|
67
|
+
machineroot.set("zoo.projects", "C:/lion/zoo/projects") # set a value
|
|
68
|
+
machineroot.delete("zoo.projects") # delete a key
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Errors:
|
|
72
|
+
|
|
73
|
+
- `MachineRootNotFoundError` - no `machine-root.json` could be found
|
|
74
|
+
- `MachineRootKeyError` - the requested key does not exist
|
|
75
|
+
|
|
76
|
+
### CLI
|
|
77
|
+
|
|
78
|
+
```
|
|
79
|
+
machine-root create
|
|
80
|
+
machine-root set zoo.projects C:/lion/zoo/projects
|
|
81
|
+
machine-root get zoo.projects
|
|
82
|
+
machine-root delete zoo.projects
|
|
83
|
+
machine-root keys
|
|
84
|
+
machine-root locate
|
|
85
|
+
machine-root help
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
The registry file must be created explicitly with `machine-root create`, which places it in the user's home directory. All other commands fail if the file does not exist.
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## License
|
|
93
|
+
|
|
94
|
+
CC0-1.0 - public domain.
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# machine-root
|
|
2
|
+
|
|
3
|
+
## The Problem
|
|
4
|
+
|
|
5
|
+
Programs, scripts, and AIs that run on a machine often need to locate resources - a project folder, a service registry, a configuration file. The usual solutions are fragile: hard-coded paths break when things move, environment variables require manual setup, and configuration systems are overkill for something this simple.
|
|
6
|
+
|
|
7
|
+
## The System
|
|
8
|
+
|
|
9
|
+
Machine Root is a minimal, shared registry for a local machine. It is a single JSON file - `machine-root.json` - that maps string keys to locations (typically filesystem paths):
|
|
10
|
+
|
|
11
|
+
```json
|
|
12
|
+
{
|
|
13
|
+
"zoo.projects": "C:/lion/zoo/projects",
|
|
14
|
+
"filetalk.registry": "C:/lion/filetalk/service-registry.json",
|
|
15
|
+
"librarian.main": "C:/lion/librarian/registry.json"
|
|
16
|
+
}
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Any program that knows the convention can read from the same registry. Keys are stable names; values are locations that can change. No metadata, no nesting, no configuration framework required.
|
|
20
|
+
|
|
21
|
+
### Resolution Order
|
|
22
|
+
|
|
23
|
+
When looking for `machine-root.json`, the system checks these locations in order and uses the first one found:
|
|
24
|
+
|
|
25
|
+
1. The path in the `MACHINE_ROOT` environment variable (if set and the file exists)
|
|
26
|
+
2. `./machine-root.json` (current working directory)
|
|
27
|
+
3. `~/machine-root.json` (user home directory)
|
|
28
|
+
4. Machine-level: `C:/machine-root.json` (Windows) or `/etc/machine-root.json` (Linux)
|
|
29
|
+
|
|
30
|
+
If none are found, operations fail clearly.
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## The Package
|
|
35
|
+
|
|
36
|
+
`machine-root` is a Python package that implements the Machine Root system. It provides a minimal API and a command-line tool for reading and writing the registry.
|
|
37
|
+
|
|
38
|
+
### Install
|
|
39
|
+
|
|
40
|
+
```
|
|
41
|
+
pip install machine-root
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Python API
|
|
45
|
+
|
|
46
|
+
```python
|
|
47
|
+
import machineroot
|
|
48
|
+
|
|
49
|
+
machineroot.locate() # path to the active machine-root.json
|
|
50
|
+
machineroot.keys() # list all keys
|
|
51
|
+
machineroot.get("zoo.projects") # get a value
|
|
52
|
+
machineroot.set("zoo.projects", "C:/lion/zoo/projects") # set a value
|
|
53
|
+
machineroot.delete("zoo.projects") # delete a key
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Errors:
|
|
57
|
+
|
|
58
|
+
- `MachineRootNotFoundError` - no `machine-root.json` could be found
|
|
59
|
+
- `MachineRootKeyError` - the requested key does not exist
|
|
60
|
+
|
|
61
|
+
### CLI
|
|
62
|
+
|
|
63
|
+
```
|
|
64
|
+
machine-root create
|
|
65
|
+
machine-root set zoo.projects C:/lion/zoo/projects
|
|
66
|
+
machine-root get zoo.projects
|
|
67
|
+
machine-root delete zoo.projects
|
|
68
|
+
machine-root keys
|
|
69
|
+
machine-root locate
|
|
70
|
+
machine-root help
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
The registry file must be created explicitly with `machine-root create`, which places it in the user's home directory. All other commands fail if the file does not exist.
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## License
|
|
78
|
+
|
|
79
|
+
CC0-1.0 - public domain.
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"document": {
|
|
3
|
+
"document-id": "machine-root.system.spec.v1",
|
|
4
|
+
"title": "Machine Root System Specification",
|
|
5
|
+
"tags": ["machineroot", "registry", "discovery", "system"],
|
|
6
|
+
"purpose": "Define a minimal system for locating named resources on a local machine.",
|
|
7
|
+
"conversation": "https://chatgpt.com/c/69c409a1-22e4-83e8-af6d-3272197ee231"
|
|
8
|
+
},
|
|
9
|
+
|
|
10
|
+
"vision": [
|
|
11
|
+
"Provide a single, simple way for programs, scripts, and AIs to locate important resources on a machine.",
|
|
12
|
+
"Avoid complex configuration systems by using a single JSON file with direct key-to-location mappings.",
|
|
13
|
+
"Enable systems to interoperate by agreeing on shared names for important locations."
|
|
14
|
+
],
|
|
15
|
+
|
|
16
|
+
"format": [
|
|
17
|
+
"The machine root file is a JSON object.",
|
|
18
|
+
"Each key is a string identifier.",
|
|
19
|
+
"Each value is a string representing a location (typically a filesystem path).",
|
|
20
|
+
"No additional structure is required.",
|
|
21
|
+
"The machine root file is named 'machine-root.json'."
|
|
22
|
+
],
|
|
23
|
+
|
|
24
|
+
"example": {
|
|
25
|
+
"zoo.projects": "C:/lion/zoo/projects",
|
|
26
|
+
"filetalk.registry": "C:/lion/filetalk/service-registry.json",
|
|
27
|
+
"librarian.main": "C:/lion/librarian/registry.json"
|
|
28
|
+
},
|
|
29
|
+
|
|
30
|
+
"resolution-process": {
|
|
31
|
+
"description": "The system resolves the machine root file by checking candidate locations in order. The first existing file found is used.",
|
|
32
|
+
"order": [
|
|
33
|
+
"If the MACHINE_ROOT environment variable is set and the referenced file exists, use it.",
|
|
34
|
+
"If a file named 'machine-root.json' exists in the current working directory, use it.",
|
|
35
|
+
"If a file named 'machine-root.json' exists in the user's home directory, use it.",
|
|
36
|
+
"If a file named 'machine-root.json' exists at the machine level, use it.",
|
|
37
|
+
"If none are found, resolution fails and the system should report that no machine root file is available."
|
|
38
|
+
],
|
|
39
|
+
"platform-notes": {
|
|
40
|
+
"windows": [
|
|
41
|
+
"User home directory is typically C:/Users/<username>/.",
|
|
42
|
+
"Machine-level path is typically C:/machine-root.json."
|
|
43
|
+
],
|
|
44
|
+
"linux": [
|
|
45
|
+
"User home directory is typically /home/<username>/ or as defined by $HOME.",
|
|
46
|
+
"Machine-level path is typically /etc/machine-root.json."
|
|
47
|
+
]
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
|
|
51
|
+
"principles": [
|
|
52
|
+
"Keep the format minimal and easy to parse.",
|
|
53
|
+
"Prefer stable names (keys) and allow locations (values) to change.",
|
|
54
|
+
"Do not embed metadata; use other files for richer descriptions.",
|
|
55
|
+
"Allow layering via resolution order (environment, local, user, machine).",
|
|
56
|
+
"Ensure the system is usable by both humans and simple programs."
|
|
57
|
+
]
|
|
58
|
+
}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
{
|
|
2
|
+
"document": {
|
|
3
|
+
"document-id": "machine-root.package.description.v1",
|
|
4
|
+
"title": "MachineRoot Python Package Description",
|
|
5
|
+
"tags": ["machineroot", "python", "registry", "cli", "api"],
|
|
6
|
+
"purpose": "Describe the Python package and CLI interface for interacting with the Machine Root system."
|
|
7
|
+
},
|
|
8
|
+
|
|
9
|
+
"overview": [
|
|
10
|
+
"The machineroot package provides a minimal interface for locating and interacting with the machine-root.json registry.",
|
|
11
|
+
"It supports both a Python API and a command-line interface.",
|
|
12
|
+
"The package enables programs, scripts, and AIs to resolve named resources on a machine using a shared registry."
|
|
13
|
+
],
|
|
14
|
+
|
|
15
|
+
"python-api": {
|
|
16
|
+
"description": "The Python API provides simple functions for resolving and modifying machine root entries.",
|
|
17
|
+
"functions": {
|
|
18
|
+
"get": {
|
|
19
|
+
"signature": "machineroot.get(key: str) -> str",
|
|
20
|
+
"description": "Return the value associated with the given key.",
|
|
21
|
+
"errors": [
|
|
22
|
+
"Raises MachineRootNotFoundError if no machine-root.json file can be resolved.",
|
|
23
|
+
"Raises MachineRootKeyError if the key does not exist."
|
|
24
|
+
]
|
|
25
|
+
},
|
|
26
|
+
"set": {
|
|
27
|
+
"signature": "machineroot.set(key: str, value: str) -> None",
|
|
28
|
+
"description": "Set or update the value for the given key in the active machine root file.",
|
|
29
|
+
"errors": [
|
|
30
|
+
"Raises MachineRootNotFoundError if no machine-root.json file can be resolved."
|
|
31
|
+
]
|
|
32
|
+
},
|
|
33
|
+
"delete": {
|
|
34
|
+
"signature": "machineroot.delete(key: str) -> None",
|
|
35
|
+
"description": "Delete the entry for the given key from the active machine root file.",
|
|
36
|
+
"errors": [
|
|
37
|
+
"Raises MachineRootNotFoundError if no machine-root.json file can be resolved.",
|
|
38
|
+
"Raises MachineRootKeyError if the key does not exist."
|
|
39
|
+
]
|
|
40
|
+
},
|
|
41
|
+
"keys": {
|
|
42
|
+
"signature": "machineroot.keys() -> List[str]",
|
|
43
|
+
"description": "Return a list of all keys in the active machine root file.",
|
|
44
|
+
"errors": [
|
|
45
|
+
"Raises MachineRootNotFoundError if no machine-root.json file can be resolved."
|
|
46
|
+
]
|
|
47
|
+
},
|
|
48
|
+
"locate": {
|
|
49
|
+
"signature": "machineroot.locate() -> str",
|
|
50
|
+
"description": "Return the path to the machine-root.json file currently in use.",
|
|
51
|
+
"errors": [
|
|
52
|
+
"Raises MachineRootNotFoundError if no machine-root.json file can be resolved."
|
|
53
|
+
]
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
|
|
57
|
+
"exceptions": {
|
|
58
|
+
"MachineRootError": {
|
|
59
|
+
"description": "Base exception for all MachineRoot-related errors."
|
|
60
|
+
},
|
|
61
|
+
"MachineRootNotFoundError": {
|
|
62
|
+
"base": "MachineRootError",
|
|
63
|
+
"description": "Raised when no machine-root.json file can be found."
|
|
64
|
+
},
|
|
65
|
+
"MachineRootKeyError": {
|
|
66
|
+
"base": "KeyError",
|
|
67
|
+
"description": "Raised when a key is not present in the machine-root.json file."
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
|
|
72
|
+
"cli": {
|
|
73
|
+
"description": "The package installs a command-line tool named 'machine-root'.",
|
|
74
|
+
"commands": {
|
|
75
|
+
"create": {
|
|
76
|
+
"usage": "machine-root create",
|
|
77
|
+
"description": "Create an empty machine-root.json file in the user's home directory. Fails if the file already exists."
|
|
78
|
+
},
|
|
79
|
+
"get": {
|
|
80
|
+
"usage": "machine-root get <key>",
|
|
81
|
+
"description": "Print the value associated with the given key. Fails if the file or key does not exist."
|
|
82
|
+
},
|
|
83
|
+
"set": {
|
|
84
|
+
"usage": "machine-root set <key> <value>",
|
|
85
|
+
"description": "Set or update the value for the given key. Fails if the file does not exist."
|
|
86
|
+
},
|
|
87
|
+
"delete": {
|
|
88
|
+
"usage": "machine-root delete <key>",
|
|
89
|
+
"description": "Delete the entry for the given key. Fails if the file or key does not exist."
|
|
90
|
+
},
|
|
91
|
+
"keys": {
|
|
92
|
+
"usage": "machine-root keys",
|
|
93
|
+
"description": "List all keys in the active machine root file. Fails if the file does not exist."
|
|
94
|
+
},
|
|
95
|
+
"locate": {
|
|
96
|
+
"usage": "machine-root locate",
|
|
97
|
+
"description": "Print the path to the machine-root.json file currently in use. Fails if no file exists."
|
|
98
|
+
},
|
|
99
|
+
"help": {
|
|
100
|
+
"usage": "machine-root help",
|
|
101
|
+
"description": "Display usage information and available commands."
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
|
|
106
|
+
"resolution": {
|
|
107
|
+
"description": "All API and CLI operations use the Machine Root resolution process to locate the active registry file.",
|
|
108
|
+
"notes": [
|
|
109
|
+
"The same resolution logic is used across both Python API and CLI.",
|
|
110
|
+
"The resolved file is the target for all read and write operations."
|
|
111
|
+
]
|
|
112
|
+
},
|
|
113
|
+
|
|
114
|
+
"design-principles": [
|
|
115
|
+
"Require explicit creation of the machine root file.",
|
|
116
|
+
"Fail clearly when the system is not initialized.",
|
|
117
|
+
"Provide specific exceptions for clarity and debuggability.",
|
|
118
|
+
"Keep the API surface minimal and obvious.",
|
|
119
|
+
"Ensure parity between CLI and Python API.",
|
|
120
|
+
"Favor direct key-value access over abstraction.",
|
|
121
|
+
"Make all operations fast and dependency-free.",
|
|
122
|
+
"Allow the system to be used interactively, programmatically, and by AIs."
|
|
123
|
+
]
|
|
124
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
machine-root — locate and manage the machine-root.json registry
|
|
2
|
+
|
|
3
|
+
USAGE
|
|
4
|
+
machine-root <command> [arguments]
|
|
5
|
+
|
|
6
|
+
COMMANDS
|
|
7
|
+
create
|
|
8
|
+
Create an empty machine-root.json file in the user's home directory.
|
|
9
|
+
Fails if the file already exists.
|
|
10
|
+
|
|
11
|
+
get <key>
|
|
12
|
+
Print the value associated with <key>.
|
|
13
|
+
Fails if the registry file or key does not exist.
|
|
14
|
+
|
|
15
|
+
set <key> <value>
|
|
16
|
+
Set or update the value for <key>.
|
|
17
|
+
Fails if the registry file does not exist.
|
|
18
|
+
|
|
19
|
+
delete <key>
|
|
20
|
+
Delete the entry for <key>.
|
|
21
|
+
Fails if the registry file or key does not exist.
|
|
22
|
+
|
|
23
|
+
keys
|
|
24
|
+
List all keys in the registry.
|
|
25
|
+
Fails if the registry file does not exist.
|
|
26
|
+
|
|
27
|
+
locate
|
|
28
|
+
Print the path to the active machine-root.json file.
|
|
29
|
+
Fails if no registry file can be found.
|
|
30
|
+
|
|
31
|
+
help
|
|
32
|
+
Show this help message.
|
|
33
|
+
|
|
34
|
+
RESOLUTION ORDER
|
|
35
|
+
1. MACHINE_ROOT environment variable
|
|
36
|
+
2. ./machine-root.json
|
|
37
|
+
3. ~/machine-root.json
|
|
38
|
+
4. Machine-level file
|
|
39
|
+
- Windows: C:/machine-root.json
|
|
40
|
+
- Linux: /etc/machine-root.json
|
|
41
|
+
|
|
42
|
+
EXAMPLES
|
|
43
|
+
machine-root create
|
|
44
|
+
machine-root set zoo.projects C:/lion/zoo/projects
|
|
45
|
+
machine-root get zoo.projects
|
|
46
|
+
machine-root keys
|
|
47
|
+
machine-root locate
|
|
48
|
+
|
|
49
|
+
NOTES
|
|
50
|
+
- The registry file must be created explicitly using 'machine-root create'.
|
|
51
|
+
- All commands fail if the registry file is not found.
|
|
52
|
+
- Keys are simple strings; values are typically filesystem paths.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "machine-root"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
requires-python = ">=3.11"
|
|
9
|
+
license = { text = "CC0-1.0" }
|
|
10
|
+
description = "A minimal shared registry for locating resources on a local machine"
|
|
11
|
+
readme = "README.md"
|
|
12
|
+
authors = [{ name = "Lion Kimbro" }]
|
|
13
|
+
classifiers = [
|
|
14
|
+
"License :: CC0 1.0 Universal (CC0 1.0) Public Domain Dedication",
|
|
15
|
+
"Programming Language :: Python :: 3",
|
|
16
|
+
"Operating System :: OS Independent",
|
|
17
|
+
]
|
|
18
|
+
|
|
19
|
+
[project.urls]
|
|
20
|
+
Homepage = "https://github.com/LionKimbro/machine-root"
|
|
21
|
+
Repository = "https://github.com/LionKimbro/machine-root"
|
|
22
|
+
|
|
23
|
+
[project.scripts]
|
|
24
|
+
machine-root = "machineroot.__main__:main"
|
|
25
|
+
|
|
26
|
+
[tool.hatch.build.targets.wheel]
|
|
27
|
+
packages = ["src/machineroot"]
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
from ._exceptions import MachineRootError, MachineRootNotFoundError, MachineRootKeyError
|
|
2
|
+
from ._resolve import locate as _locate_path, read_registry, write_registry
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def locate():
|
|
6
|
+
return str(_locate_path())
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def get(key):
|
|
10
|
+
data, _ = read_registry()
|
|
11
|
+
if key not in data:
|
|
12
|
+
raise MachineRootKeyError(key)
|
|
13
|
+
return data[key]
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def set(key, value):
|
|
17
|
+
data, path = read_registry()
|
|
18
|
+
data[key] = value
|
|
19
|
+
write_registry(data, path)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def keys():
|
|
23
|
+
data, _ = read_registry()
|
|
24
|
+
return list(data.keys())
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def delete(key):
|
|
28
|
+
data, path = read_registry()
|
|
29
|
+
if key not in data:
|
|
30
|
+
raise MachineRootKeyError(key)
|
|
31
|
+
del data[key]
|
|
32
|
+
write_registry(data, path)
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import pathlib
|
|
2
|
+
import sys
|
|
3
|
+
|
|
4
|
+
import machineroot
|
|
5
|
+
from machineroot._exceptions import MachineRootError, MachineRootNotFoundError
|
|
6
|
+
from machineroot._resolve import kFILENAME, locate as _locate_path
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
kHELP = """\
|
|
10
|
+
machine-root — locate and manage the machine-root.json registry
|
|
11
|
+
|
|
12
|
+
USAGE
|
|
13
|
+
machine-root <command> [arguments]
|
|
14
|
+
|
|
15
|
+
COMMANDS
|
|
16
|
+
create
|
|
17
|
+
Create an empty machine-root.json file in the user's home directory.
|
|
18
|
+
Fails if the file already exists.
|
|
19
|
+
|
|
20
|
+
get <key>
|
|
21
|
+
Print the value associated with <key>.
|
|
22
|
+
Fails if the registry file or key does not exist.
|
|
23
|
+
|
|
24
|
+
set <key> <value>
|
|
25
|
+
Set or update the value for <key>.
|
|
26
|
+
Fails if the registry file does not exist.
|
|
27
|
+
|
|
28
|
+
delete <key>
|
|
29
|
+
Delete the entry for <key>.
|
|
30
|
+
Fails if the registry file or key does not exist.
|
|
31
|
+
|
|
32
|
+
keys
|
|
33
|
+
List all keys in the registry.
|
|
34
|
+
Fails if the registry file does not exist.
|
|
35
|
+
|
|
36
|
+
locate
|
|
37
|
+
Print the path to the active machine-root.json file.
|
|
38
|
+
Fails if no registry file can be found.
|
|
39
|
+
|
|
40
|
+
help
|
|
41
|
+
Show this help message.
|
|
42
|
+
|
|
43
|
+
RESOLUTION ORDER
|
|
44
|
+
1. MACHINE_ROOT environment variable
|
|
45
|
+
2. ./machine-root.json
|
|
46
|
+
3. ~/machine-root.json
|
|
47
|
+
4. Machine-level file
|
|
48
|
+
- Windows: C:/machine-root.json
|
|
49
|
+
- Linux: /etc/machine-root.json
|
|
50
|
+
|
|
51
|
+
EXAMPLES
|
|
52
|
+
machine-root create
|
|
53
|
+
machine-root set zoo.projects C:/lion/zoo/projects
|
|
54
|
+
machine-root get zoo.projects
|
|
55
|
+
machine-root keys
|
|
56
|
+
machine-root locate
|
|
57
|
+
|
|
58
|
+
NOTES
|
|
59
|
+
- The registry file must be created explicitly using 'machine-root create'.
|
|
60
|
+
- All commands fail if the registry file is not found.
|
|
61
|
+
- Keys are simple strings; values are typically filesystem paths.
|
|
62
|
+
"""
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def run_create():
|
|
66
|
+
path = pathlib.Path.home() / kFILENAME
|
|
67
|
+
if path.exists():
|
|
68
|
+
print(f"error: {path} already exists.", file=sys.stderr)
|
|
69
|
+
sys.exit(1)
|
|
70
|
+
import json
|
|
71
|
+
tmp = pathlib.Path(str(path) + ".tmp")
|
|
72
|
+
with open(tmp, "w", encoding="utf-8") as f:
|
|
73
|
+
json.dump({}, f, indent=2)
|
|
74
|
+
f.write("\n")
|
|
75
|
+
tmp.replace(path)
|
|
76
|
+
print(f"Created {path}")
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def run_get(key):
|
|
80
|
+
print(machineroot.get(key))
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def run_set(key, value):
|
|
84
|
+
machineroot.set(key, value)
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def run_delete(key):
|
|
88
|
+
machineroot.delete(key)
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def run_keys():
|
|
92
|
+
for k in machineroot.keys():
|
|
93
|
+
print(k)
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def run_locate():
|
|
97
|
+
print(machineroot.locate())
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def run_help():
|
|
101
|
+
print(kHELP, end="")
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def main():
|
|
105
|
+
args = sys.argv[1:]
|
|
106
|
+
|
|
107
|
+
if not args or args[0] == "help":
|
|
108
|
+
run_help()
|
|
109
|
+
return
|
|
110
|
+
|
|
111
|
+
cmd = args[0]
|
|
112
|
+
|
|
113
|
+
try:
|
|
114
|
+
if cmd == "create":
|
|
115
|
+
run_create()
|
|
116
|
+
elif cmd == "get":
|
|
117
|
+
if len(args) < 2:
|
|
118
|
+
print("error: get requires a key.", file=sys.stderr)
|
|
119
|
+
sys.exit(1)
|
|
120
|
+
run_get(args[1])
|
|
121
|
+
elif cmd == "set":
|
|
122
|
+
if len(args) < 3:
|
|
123
|
+
print("error: set requires a key and a value.", file=sys.stderr)
|
|
124
|
+
sys.exit(1)
|
|
125
|
+
run_set(args[1], args[2])
|
|
126
|
+
elif cmd == "delete":
|
|
127
|
+
if len(args) < 2:
|
|
128
|
+
print("error: delete requires a key.", file=sys.stderr)
|
|
129
|
+
sys.exit(1)
|
|
130
|
+
run_delete(args[1])
|
|
131
|
+
elif cmd == "keys":
|
|
132
|
+
run_keys()
|
|
133
|
+
elif cmd == "locate":
|
|
134
|
+
run_locate()
|
|
135
|
+
else:
|
|
136
|
+
print(f"error: unknown command '{cmd}'. Run 'machine-root help' for usage.", file=sys.stderr)
|
|
137
|
+
sys.exit(1)
|
|
138
|
+
except MachineRootError as e:
|
|
139
|
+
print(f"error: {e}", file=sys.stderr)
|
|
140
|
+
sys.exit(1)
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
if __name__ == "__main__":
|
|
144
|
+
main()
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import os
|
|
3
|
+
import pathlib
|
|
4
|
+
|
|
5
|
+
from ._exceptions import MachineRootNotFoundError
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
kFILENAME = "machine-root.json"
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def locate():
|
|
12
|
+
# 1. MACHINE_ROOT environment variable
|
|
13
|
+
env = os.environ.get("MACHINE_ROOT")
|
|
14
|
+
if env:
|
|
15
|
+
p = pathlib.Path(env)
|
|
16
|
+
if p.exists():
|
|
17
|
+
return p
|
|
18
|
+
|
|
19
|
+
# 2. Current working directory
|
|
20
|
+
p = pathlib.Path.cwd() / kFILENAME
|
|
21
|
+
if p.exists():
|
|
22
|
+
return p
|
|
23
|
+
|
|
24
|
+
# 3. User home directory
|
|
25
|
+
p = pathlib.Path.home() / kFILENAME
|
|
26
|
+
if p.exists():
|
|
27
|
+
return p
|
|
28
|
+
|
|
29
|
+
# 4. Machine-level
|
|
30
|
+
if os.name == "nt":
|
|
31
|
+
p = pathlib.Path("C:/") / kFILENAME
|
|
32
|
+
else:
|
|
33
|
+
p = pathlib.Path("/etc") / kFILENAME
|
|
34
|
+
if p.exists():
|
|
35
|
+
return p
|
|
36
|
+
|
|
37
|
+
raise MachineRootNotFoundError("No machine-root.json file could be found.")
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def read_registry():
|
|
41
|
+
p = locate()
|
|
42
|
+
with open(p, "r", encoding="utf-8") as f:
|
|
43
|
+
return json.load(f), p
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def write_registry(data, path):
|
|
47
|
+
tmp = pathlib.Path(str(path) + ".tmp")
|
|
48
|
+
with open(tmp, "w", encoding="utf-8") as f:
|
|
49
|
+
json.dump(data, f, indent=2)
|
|
50
|
+
f.write("\n")
|
|
51
|
+
tmp.replace(path)
|