magmascript 2.2.0__tar.gz → 2.3.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.
Files changed (83) hide show
  1. {magmascript-2.2.0 → magmascript-2.3.0}/PKG-INFO +1 -1
  2. {magmascript-2.2.0 → magmascript-2.3.0}/magmascript/domains/mc1/client.py +5 -1
  3. magmascript-2.3.0/magmascript/domains/mc1/tools.py +127 -0
  4. {magmascript-2.2.0 → magmascript-2.3.0}/magmascript.egg-info/PKG-INFO +1 -1
  5. {magmascript-2.2.0 → magmascript-2.3.0}/pyproject.toml +1 -1
  6. magmascript-2.2.0/magmascript/domains/mc1/tools.py +0 -82
  7. {magmascript-2.2.0 → magmascript-2.3.0}/LICENSE +0 -0
  8. {magmascript-2.2.0 → magmascript-2.3.0}/README.md +0 -0
  9. {magmascript-2.2.0 → magmascript-2.3.0}/magmascript/__init__.py +0 -0
  10. {magmascript-2.2.0 → magmascript-2.3.0}/magmascript/cli.py +0 -0
  11. {magmascript-2.2.0 → magmascript-2.3.0}/magmascript/core/__init__.py +0 -0
  12. {magmascript-2.2.0 → magmascript-2.3.0}/magmascript/core/cache.py +0 -0
  13. {magmascript-2.2.0 → magmascript-2.3.0}/magmascript/core/commands.py +0 -0
  14. {magmascript-2.2.0 → magmascript-2.3.0}/magmascript/core/config.py +0 -0
  15. {magmascript-2.2.0 → magmascript-2.3.0}/magmascript/core/exceptions.py +0 -0
  16. {magmascript-2.2.0 → magmascript-2.3.0}/magmascript/core/github.py +0 -0
  17. {magmascript-2.2.0 → magmascript-2.3.0}/magmascript/core/output.py +0 -0
  18. {magmascript-2.2.0 → magmascript-2.3.0}/magmascript/core/registry.py +0 -0
  19. {magmascript-2.2.0 → magmascript-2.3.0}/magmascript/core/rpc.py +0 -0
  20. {magmascript-2.2.0 → magmascript-2.3.0}/magmascript/core/runner.py +0 -0
  21. {magmascript-2.2.0 → magmascript-2.3.0}/magmascript/domains/__init__.py +0 -0
  22. {magmascript-2.2.0 → magmascript-2.3.0}/magmascript/domains/archive/__init__.py +0 -0
  23. {magmascript-2.2.0 → magmascript-2.3.0}/magmascript/domains/archive/client.py +0 -0
  24. {magmascript-2.2.0 → magmascript-2.3.0}/magmascript/domains/gh/__init__.py +0 -0
  25. {magmascript-2.2.0 → magmascript-2.3.0}/magmascript/domains/gh/client.py +0 -0
  26. {magmascript-2.2.0 → magmascript-2.3.0}/magmascript/domains/gh/tools.py +0 -0
  27. {magmascript-2.2.0 → magmascript-2.3.0}/magmascript/domains/lastfm/__init__.py +0 -0
  28. {magmascript-2.2.0 → magmascript-2.3.0}/magmascript/domains/lastfm/client.py +0 -0
  29. {magmascript-2.2.0 → magmascript-2.3.0}/magmascript/domains/mb/__init__.py +0 -0
  30. {magmascript-2.2.0 → magmascript-2.3.0}/magmascript/domains/mb/client.py +0 -0
  31. {magmascript-2.2.0 → magmascript-2.3.0}/magmascript/domains/mc1/__init__.py +0 -0
  32. {magmascript-2.2.0 → magmascript-2.3.0}/magmascript/domains/mcp/__init__.py +0 -0
  33. {magmascript-2.2.0 → magmascript-2.3.0}/magmascript/domains/mcp/client.py +0 -0
  34. {magmascript-2.2.0 → magmascript-2.3.0}/magmascript/domains/mcp/tools.py +0 -0
  35. {magmascript-2.2.0 → magmascript-2.3.0}/magmascript/domains/media/__init__.py +0 -0
  36. {magmascript-2.2.0 → magmascript-2.3.0}/magmascript/domains/media/client.py +0 -0
  37. {magmascript-2.2.0 → magmascript-2.3.0}/magmascript/domains/media/providers/__init__.py +0 -0
  38. {magmascript-2.2.0 → magmascript-2.3.0}/magmascript/domains/media/providers/archive.py +0 -0
  39. {magmascript-2.2.0 → magmascript-2.3.0}/magmascript/domains/media/providers/met_museum.py +0 -0
  40. {magmascript-2.2.0 → magmascript-2.3.0}/magmascript/domains/media/providers/openverse.py +0 -0
  41. {magmascript-2.2.0 → magmascript-2.3.0}/magmascript/domains/media/providers/pexels.py +0 -0
  42. {magmascript-2.2.0 → magmascript-2.3.0}/magmascript/domains/media/providers/pixabay.py +0 -0
  43. {magmascript-2.2.0 → magmascript-2.3.0}/magmascript/domains/media/providers/smithsonian.py +0 -0
  44. {magmascript-2.2.0 → magmascript-2.3.0}/magmascript/domains/media/tools.py +0 -0
  45. {magmascript-2.2.0 → magmascript-2.3.0}/magmascript/domains/pi/__init__.py +0 -0
  46. {magmascript-2.2.0 → magmascript-2.3.0}/magmascript/domains/pi/client.py +0 -0
  47. {magmascript-2.2.0 → magmascript-2.3.0}/magmascript/domains/pi/tools.py +0 -0
  48. {magmascript-2.2.0 → magmascript-2.3.0}/magmascript/domains/rights/__init__.py +0 -0
  49. {magmascript-2.2.0 → magmascript-2.3.0}/magmascript/domains/rights/client.py +0 -0
  50. {magmascript-2.2.0 → magmascript-2.3.0}/magmascript/domains/rights/tools.py +0 -0
  51. {magmascript-2.2.0 → magmascript-2.3.0}/magmascript/domains/scores/__init__.py +0 -0
  52. {magmascript-2.2.0 → magmascript-2.3.0}/magmascript/domains/scores/client.py +0 -0
  53. {magmascript-2.2.0 → magmascript-2.3.0}/magmascript/domains/scores/tools.py +0 -0
  54. {magmascript-2.2.0 → magmascript-2.3.0}/magmascript/domains/search/__init__.py +0 -0
  55. {magmascript-2.2.0 → magmascript-2.3.0}/magmascript/domains/search/client.py +0 -0
  56. {magmascript-2.2.0 → magmascript-2.3.0}/magmascript/lang/__init__.py +0 -0
  57. {magmascript-2.2.0 → magmascript-2.3.0}/magmascript/lang/ast_nodes.py +0 -0
  58. {magmascript-2.2.0 → magmascript-2.3.0}/magmascript/lang/builtins.py +0 -0
  59. {magmascript-2.2.0 → magmascript-2.3.0}/magmascript/lang/domain_bridge.py +0 -0
  60. {magmascript-2.2.0 → magmascript-2.3.0}/magmascript/lang/environment.py +0 -0
  61. {magmascript-2.2.0 → magmascript-2.3.0}/magmascript/lang/interpreter.py +0 -0
  62. {magmascript-2.2.0 → magmascript-2.3.0}/magmascript/lang/lexer.py +0 -0
  63. {magmascript-2.2.0 → magmascript-2.3.0}/magmascript/lang/parser.py +0 -0
  64. {magmascript-2.2.0 → magmascript-2.3.0}/magmascript/lang/pygments_mgs.py +0 -0
  65. {magmascript-2.2.0 → magmascript-2.3.0}/magmascript/lang/tokens.py +0 -0
  66. {magmascript-2.2.0 → magmascript-2.3.0}/magmascript/lang/util.py +0 -0
  67. {magmascript-2.2.0 → magmascript-2.3.0}/magmascript/repl.py +0 -0
  68. {magmascript-2.2.0 → magmascript-2.3.0}/magmascript.egg-info/SOURCES.txt +0 -0
  69. {magmascript-2.2.0 → magmascript-2.3.0}/magmascript.egg-info/dependency_links.txt +0 -0
  70. {magmascript-2.2.0 → magmascript-2.3.0}/magmascript.egg-info/entry_points.txt +0 -0
  71. {magmascript-2.2.0 → magmascript-2.3.0}/magmascript.egg-info/requires.txt +0 -0
  72. {magmascript-2.2.0 → magmascript-2.3.0}/magmascript.egg-info/top_level.txt +0 -0
  73. {magmascript-2.2.0 → magmascript-2.3.0}/setup.cfg +0 -0
  74. {magmascript-2.2.0 → magmascript-2.3.0}/tests/test_cache.py +0 -0
  75. {magmascript-2.2.0 → magmascript-2.3.0}/tests/test_classes.py +0 -0
  76. {magmascript-2.2.0 → magmascript-2.3.0}/tests/test_cli.py +0 -0
  77. {magmascript-2.2.0 → magmascript-2.3.0}/tests/test_commands.py +0 -0
  78. {magmascript-2.2.0 → magmascript-2.3.0}/tests/test_domain_bridge.py +0 -0
  79. {magmascript-2.2.0 → magmascript-2.3.0}/tests/test_import.py +0 -0
  80. {magmascript-2.2.0 → magmascript-2.3.0}/tests/test_lang.py +0 -0
  81. {magmascript-2.2.0 → magmascript-2.3.0}/tests/test_mcp_client.py +0 -0
  82. {magmascript-2.2.0 → magmascript-2.3.0}/tests/test_rpc.py +0 -0
  83. {magmascript-2.2.0 → magmascript-2.3.0}/tests/test_try_catch.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: magmascript
3
- Version: 2.2.0
3
+ Version: 2.3.0
4
4
  Summary: Scripting toolkit with domain-first subcommands
5
5
  Author: Jake McCoy
6
6
  License-Expression: MIT
@@ -73,7 +73,11 @@ class MC1Client:
73
73
  'Write-Host \\"UPTIME:$((Get-Date) - $os.LastBootUpTime)\\"; '
74
74
  'Write-Host \\"MEMORY:$([math]::Round($os.TotalVisibleMemorySize/1MB, 1))GB/$([math]::Round(($os.TotalVisibleMemorySize - $os.FreePhysicalMemory)/1MB, 1))GB\\"; '
75
75
  'Write-Host \\"CPU:$($cpu.LoadPercentage)%\\"; '
76
- 'Write-Host \\"DISK:$([math]::Round($disk.FreeSpace/$disk.Size*100, 1))% free\\"'
76
+ 'Write-Host \\"DISK:$([math]::Round($disk.FreeSpace/$disk.Size*100, 1))% free\\"; '
77
+ 'Write-Host \\"DISK_FREE_GB:$([math]::Round($disk.FreeSpace/1GB, 1))GB\\"; '
78
+ 'Write-Host \\"CPU_NAME:$($cpu.Name)\\"; '
79
+ 'Write-Host \\"CPU_CORES:$($cpu.NumberOfCores)\\"; '
80
+ 'Write-Host \\"OS_VERSION:$($os.Caption)\\"'
77
81
  '"'
78
82
  )
79
83
  return parse_system_info(stdout)
@@ -0,0 +1,127 @@
1
+ """Typed result dataclasses for the MC1 domain."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from dataclasses import dataclass, field
6
+
7
+
8
+ @dataclass
9
+ class MC1ServiceStatus:
10
+ """Status of a Windows service."""
11
+
12
+ name: str
13
+ status: str
14
+ ok: bool
15
+
16
+
17
+ @dataclass
18
+ class MC1SystemInfo:
19
+ """MC1 system info."""
20
+
21
+ hostname: str
22
+ uptime: str
23
+ memory: str
24
+ cpu_load: str
25
+ disk_free: str
26
+ disk_free_gb: str = ""
27
+ cpu_name: str = ""
28
+ cpu_cores: str = ""
29
+ os_version: str = ""
30
+
31
+
32
+ # ---------------------------------------------------------------------------
33
+ # Uptime formatting
34
+ # ---------------------------------------------------------------------------
35
+
36
+
37
+ def _format_uptime(raw: str) -> str:
38
+ """Parse .NET TimeSpan string (e.g. '1.03:05:36.7441121') into human-readable form.
39
+
40
+ Format: 'D.HH:MM:SS.fffffff' → '1 day, 3 hours, 5 minutes'
41
+ """
42
+ try:
43
+ # Split on '.' for days, then ':' for time
44
+ parts = raw.split(".", 1)
45
+ days = int(parts[0]) if parts[0].isdigit() else 0
46
+
47
+ if len(parts) > 1:
48
+ time_parts = parts[1].split(":")
49
+ hours = int(time_parts[0]) if len(time_parts) > 0 else 0
50
+ minutes = int(time_parts[1]) if len(time_parts) > 1 else 0
51
+ else:
52
+ hours = 0
53
+ minutes = 0
54
+
55
+ segments = []
56
+ if days > 0:
57
+ segments.append(f"{days} day{'s' if days != 1 else ''}")
58
+ if hours > 0:
59
+ segments.append(f"{hours} hour{'s' if hours != 1 else ''}")
60
+ if minutes > 0 or not segments:
61
+ segments.append(f"{minutes} min{'s' if minutes != 1 else ''}")
62
+
63
+ return ", ".join(segments)
64
+ except (ValueError, IndexError):
65
+ return raw
66
+
67
+
68
+ # ---------------------------------------------------------------------------
69
+ # Parsers
70
+ # ---------------------------------------------------------------------------
71
+
72
+
73
+ def parse_service_list(text: str) -> list[MC1ServiceStatus]:
74
+ """Parse PowerShell Get-Service output into MC1ServiceStatus list.
75
+
76
+ Expected format (from the PowerShell command):
77
+ AmdPpkgSvc: Running
78
+ AppIDSvc: Running
79
+ """
80
+ results = []
81
+ for line in text.splitlines():
82
+ line = line.strip()
83
+ if ":" in line:
84
+ name, status = line.split(":", 1)
85
+ name = name.strip()
86
+ status = status.strip()
87
+ results.append(MC1ServiceStatus(
88
+ name=name,
89
+ status=status,
90
+ ok=status.lower() == "running",
91
+ ))
92
+ return results
93
+
94
+
95
+ def parse_system_info(text: str) -> MC1SystemInfo:
96
+ """Parse the output of the combined system info command.
97
+
98
+ Expected format:
99
+ HOSTNAME:MC1
100
+ UPTIME:07:33:06.0140847
101
+ MEMORY:31.7GB/7.6GB
102
+ CPU:4%
103
+ DISK:93.2% free
104
+ DISK_FREE_GB:776.9GB
105
+ CPU_NAME:AMD Ryzen 7 8700F 8-Core Processor
106
+ CPU_CORES:8
107
+ OS_VERSION:Microsoft Windows 11 Home
108
+ """
109
+ info = {
110
+ "hostname": "", "uptime": "", "memory": "", "cpu_load": "",
111
+ "disk_free": "", "disk_free_gb": "", "cpu_name": "",
112
+ "cpu_cores": "", "os_version": "",
113
+ }
114
+ for line in text.splitlines():
115
+ line = line.strip()
116
+ if ":" in line:
117
+ key, val = line.split(":", 1)
118
+ key = key.lower().strip()
119
+ val = val.strip()
120
+ if key in info:
121
+ info[key] = val
122
+
123
+ # Format uptime from raw TimeSpan to human-readable
124
+ if info["uptime"]:
125
+ info["uptime"] = _format_uptime(info["uptime"])
126
+
127
+ return MC1SystemInfo(**info)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: magmascript
3
- Version: 2.2.0
3
+ Version: 2.3.0
4
4
  Summary: Scripting toolkit with domain-first subcommands
5
5
  Author: Jake McCoy
6
6
  License-Expression: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "magmascript"
7
- version = "2.2.0"
7
+ version = "2.3.0"
8
8
  description = "Scripting toolkit with domain-first subcommands"
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -1,82 +0,0 @@
1
- """Typed result dataclasses for the MC1 domain."""
2
-
3
- from __future__ import annotations
4
-
5
- from dataclasses import dataclass
6
-
7
-
8
- @dataclass
9
- class MC1ServiceStatus:
10
- """Status of a Windows service."""
11
-
12
- name: str
13
- status: str
14
- ok: bool
15
-
16
-
17
- @dataclass
18
- class MC1SystemInfo:
19
- """MC1 system info."""
20
-
21
- hostname: str
22
- uptime: str
23
- memory: str
24
- cpu_load: str
25
- disk_free: str
26
-
27
-
28
- # ---------------------------------------------------------------------------
29
- # Parsers
30
- # ---------------------------------------------------------------------------
31
-
32
-
33
- def parse_service_list(text: str) -> list[MC1ServiceStatus]:
34
- """Parse PowerShell Get-Service output into MC1ServiceStatus list.
35
-
36
- Expected format (from the PowerShell command):
37
- AmdPpkgSvc: Running
38
- AppIDSvc: Running
39
- """
40
- results = []
41
- for line in text.splitlines():
42
- line = line.strip()
43
- if ":" in line:
44
- name, status = line.split(":", 1)
45
- name = name.strip()
46
- status = status.strip()
47
- results.append(MC1ServiceStatus(
48
- name=name,
49
- status=status,
50
- ok=status.lower() == "running",
51
- ))
52
- return results
53
-
54
-
55
- def parse_system_info(text: str) -> MC1SystemInfo:
56
- """Parse the output of the combined system info command.
57
-
58
- Expected format:
59
- HOSTNAME:MC1
60
- UPTIME:07:33:06.0140847
61
- MEMORY:31.7GB/7.6GB
62
- CPU:4%
63
- DISK:93.2% free
64
- """
65
- info = {"hostname": "", "uptime": "", "memory": "", "cpu_load": "", "disk_free": ""}
66
- for line in text.splitlines():
67
- line = line.strip()
68
- if ":" in line:
69
- key, val = line.split(":", 1)
70
- key = key.lower().strip()
71
- val = val.strip()
72
- if key == "hostname":
73
- info["hostname"] = val
74
- elif key == "uptime":
75
- info["uptime"] = val
76
- elif key == "memory":
77
- info["memory"] = val
78
- elif key == "cpu":
79
- info["cpu_load"] = val
80
- elif key == "disk":
81
- info["disk_free"] = val
82
- return MC1SystemInfo(**info)
File without changes
File without changes
File without changes