machine-root 0.1.0__py3-none-any.whl

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.
@@ -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,9 @@
1
+ machineroot/__init__.py,sha256=9iMItU6DcDiSs1W8NgeGDuecXMPYe0z1XMaECFsi6kQ,720
2
+ machineroot/__main__.py,sha256=onRzIo8JvsuiAZNN9Y-jWC07NJbs5RarUCywvPu_fL8,3625
3
+ machineroot/_exceptions.py,sha256=F3_MyAp_6KP5krcDxlXTaFRSusUWdkRLbVmBLAO7_jQ,181
4
+ machineroot/_resolve.py,sha256=z4yZQelGTDw1hXciKikDRWTzg3UM02sfsyL-87dgjtk,1163
5
+ machine_root-0.1.0.dist-info/METADATA,sha256=kfXfC_6x59z90jhqkeykEA2NggRLXQ7trADgYTmBBps,3084
6
+ machine_root-0.1.0.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
7
+ machine_root-0.1.0.dist-info/entry_points.txt,sha256=I0gmRNltiMgr6aSGfaaSLi-EtcNG7WtONtDw7XXtX0M,59
8
+ machine_root-0.1.0.dist-info/licenses/LICENSE,sha256=J3cutLOIV6T_qvfoxvKVoFemyzMQtnMARm5jpL5TYI4,335
9
+ machine_root-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.29.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ machine-root = machineroot.__main__:main
@@ -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,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,10 @@
1
+ class MachineRootError(Exception):
2
+ pass
3
+
4
+
5
+ class MachineRootNotFoundError(MachineRootError):
6
+ pass
7
+
8
+
9
+ class MachineRootKeyError(MachineRootError, KeyError):
10
+ pass
@@ -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)