mgraphctl 0.1.0__tar.gz → 0.2.1__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.
Potentially problematic release.
This version of mgraphctl might be problematic. Click here for more details.
- {mgraphctl-0.1.0 → mgraphctl-0.2.1}/PKG-INFO +21 -3
- {mgraphctl-0.1.0 → mgraphctl-0.2.1}/README.md +17 -1
- {mgraphctl-0.1.0 → mgraphctl-0.2.1}/pyproject.toml +5 -3
- {mgraphctl-0.1.0 → mgraphctl-0.2.1}/pyproject.toml.orig +5 -3
- {mgraphctl-0.1.0 → mgraphctl-0.2.1}/src/mgraphctl/__init__.py +1 -1
- {mgraphctl-0.1.0 → mgraphctl-0.2.1}/src/mgraphctl/config.py +6 -1
- {mgraphctl-0.1.0 → mgraphctl-0.2.1}/src/mgraphctl/http.py +2 -2
- {mgraphctl-0.1.0 → mgraphctl-0.2.1}/src/mgraphctl/render.py +2 -2
- {mgraphctl-0.1.0 → mgraphctl-0.2.1}/LICENSE +0 -0
- {mgraphctl-0.1.0 → mgraphctl-0.2.1}/src/mgraphctl/__main__.py +0 -0
- {mgraphctl-0.1.0 → mgraphctl-0.2.1}/src/mgraphctl/auth.py +0 -0
- {mgraphctl-0.1.0 → mgraphctl-0.2.1}/src/mgraphctl/cli.py +0 -0
- {mgraphctl-0.1.0 → mgraphctl-0.2.1}/src/mgraphctl/commands/__init__.py +0 -0
- {mgraphctl-0.1.0 → mgraphctl-0.2.1}/src/mgraphctl/commands/api.py +0 -0
- {mgraphctl-0.1.0 → mgraphctl-0.2.1}/src/mgraphctl/commands/calendar.py +0 -0
- {mgraphctl-0.1.0 → mgraphctl-0.2.1}/src/mgraphctl/commands/chats.py +0 -0
- {mgraphctl-0.1.0 → mgraphctl-0.2.1}/src/mgraphctl/commands/config_cmd.py +0 -0
- {mgraphctl-0.1.0 → mgraphctl-0.2.1}/src/mgraphctl/commands/groups.py +0 -0
- {mgraphctl-0.1.0 → mgraphctl-0.2.1}/src/mgraphctl/commands/mail.py +0 -0
- {mgraphctl-0.1.0 → mgraphctl-0.2.1}/src/mgraphctl/commands/mailbox.py +0 -0
- {mgraphctl-0.1.0 → mgraphctl-0.2.1}/src/mgraphctl/commands/meetings.py +0 -0
- {mgraphctl-0.1.0 → mgraphctl-0.2.1}/src/mgraphctl/commands/onedrive.py +0 -0
- {mgraphctl-0.1.0 → mgraphctl-0.2.1}/src/mgraphctl/commands/onenote.py +0 -0
- {mgraphctl-0.1.0 → mgraphctl-0.2.1}/src/mgraphctl/commands/org.py +0 -0
- {mgraphctl-0.1.0 → mgraphctl-0.2.1}/src/mgraphctl/commands/people.py +0 -0
- {mgraphctl-0.1.0 → mgraphctl-0.2.1}/src/mgraphctl/commands/planner.py +0 -0
- {mgraphctl-0.1.0 → mgraphctl-0.2.1}/src/mgraphctl/commands/presence.py +0 -0
- {mgraphctl-0.1.0 → mgraphctl-0.2.1}/src/mgraphctl/commands/search.py +0 -0
- {mgraphctl-0.1.0 → mgraphctl-0.2.1}/src/mgraphctl/commands/sharepoint.py +0 -0
- {mgraphctl-0.1.0 → mgraphctl-0.2.1}/src/mgraphctl/commands/teams.py +0 -0
- {mgraphctl-0.1.0 → mgraphctl-0.2.1}/src/mgraphctl/commands/todo.py +0 -0
- {mgraphctl-0.1.0 → mgraphctl-0.2.1}/src/mgraphctl/commands/top.py +0 -0
- {mgraphctl-0.1.0 → mgraphctl-0.2.1}/src/mgraphctl/errors.py +0 -0
- {mgraphctl-0.1.0 → mgraphctl-0.2.1}/src/mgraphctl/fixtures.py +0 -0
- {mgraphctl-0.1.0 → mgraphctl-0.2.1}/src/mgraphctl/graph/__init__.py +0 -0
- {mgraphctl-0.1.0 → mgraphctl-0.2.1}/src/mgraphctl/graph/calendar.py +0 -0
- {mgraphctl-0.1.0 → mgraphctl-0.2.1}/src/mgraphctl/graph/chats.py +0 -0
- {mgraphctl-0.1.0 → mgraphctl-0.2.1}/src/mgraphctl/graph/files.py +0 -0
- {mgraphctl-0.1.0 → mgraphctl-0.2.1}/src/mgraphctl/graph/groups.py +0 -0
- {mgraphctl-0.1.0 → mgraphctl-0.2.1}/src/mgraphctl/graph/mail.py +0 -0
- {mgraphctl-0.1.0 → mgraphctl-0.2.1}/src/mgraphctl/graph/mailbox.py +0 -0
- {mgraphctl-0.1.0 → mgraphctl-0.2.1}/src/mgraphctl/graph/meetings.py +0 -0
- {mgraphctl-0.1.0 → mgraphctl-0.2.1}/src/mgraphctl/graph/onedrive.py +0 -0
- {mgraphctl-0.1.0 → mgraphctl-0.2.1}/src/mgraphctl/graph/onenote.py +0 -0
- {mgraphctl-0.1.0 → mgraphctl-0.2.1}/src/mgraphctl/graph/org.py +0 -0
- {mgraphctl-0.1.0 → mgraphctl-0.2.1}/src/mgraphctl/graph/people.py +0 -0
- {mgraphctl-0.1.0 → mgraphctl-0.2.1}/src/mgraphctl/graph/planner.py +0 -0
- {mgraphctl-0.1.0 → mgraphctl-0.2.1}/src/mgraphctl/graph/presence.py +0 -0
- {mgraphctl-0.1.0 → mgraphctl-0.2.1}/src/mgraphctl/graph/search.py +0 -0
- {mgraphctl-0.1.0 → mgraphctl-0.2.1}/src/mgraphctl/graph/sharepoint.py +0 -0
- {mgraphctl-0.1.0 → mgraphctl-0.2.1}/src/mgraphctl/graph/teams.py +0 -0
- {mgraphctl-0.1.0 → mgraphctl-0.2.1}/src/mgraphctl/graph/todo.py +0 -0
- {mgraphctl-0.1.0 → mgraphctl-0.2.1}/src/mgraphctl/graph/users.py +0 -0
- {mgraphctl-0.1.0 → mgraphctl-0.2.1}/src/mgraphctl/html.py +0 -0
- {mgraphctl-0.1.0 → mgraphctl-0.2.1}/src/mgraphctl/odata.py +0 -0
- {mgraphctl-0.1.0 → mgraphctl-0.2.1}/src/mgraphctl/resolve.py +0 -0
- {mgraphctl-0.1.0 → mgraphctl-0.2.1}/src/mgraphctl/token_store.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mgraphctl
|
|
3
|
-
Version: 0.1
|
|
3
|
+
Version: 0.2.1
|
|
4
4
|
Summary: Microsoft Graph CLI behind the mgraphctl Claude Code skill
|
|
5
5
|
Keywords: microsoft-graph,microsoft-365,outlook,teams,sharepoint,onedrive,cli
|
|
6
6
|
Author: Sviatoslav Sviridov
|
|
@@ -13,6 +13,7 @@ Classifier: Intended Audience :: Developers
|
|
|
13
13
|
Classifier: Intended Audience :: End Users/Desktop
|
|
14
14
|
Classifier: Operating System :: OS Independent
|
|
15
15
|
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
17
|
Classifier: Programming Language :: Python :: 3.11
|
|
17
18
|
Classifier: Programming Language :: Python :: 3.12
|
|
18
19
|
Classifier: Programming Language :: Python :: 3.13
|
|
@@ -25,7 +26,8 @@ Requires-Dist: typer>=0.27,<1
|
|
|
25
26
|
Requires-Dist: markdownify>=1.2,<2
|
|
26
27
|
Requires-Dist: keyring>=24,<26
|
|
27
28
|
Requires-Dist: tzdata ; sys_platform == 'win32'
|
|
28
|
-
Requires-
|
|
29
|
+
Requires-Dist: tomli>=2,<3 ; python_full_version < '3.11'
|
|
30
|
+
Requires-Python: >=3.10, <3.14
|
|
29
31
|
Project-URL: Homepage, https://github.com/svd/mgraphctl
|
|
30
32
|
Project-URL: Source, https://github.com/svd/mgraphctl
|
|
31
33
|
Project-URL: Changelog, https://github.com/svd/mgraphctl/blob/main/CHANGELOG.md
|
|
@@ -118,6 +120,22 @@ uv run --project <plugin> --frozen --no-dev mgraphctl login
|
|
|
118
120
|
Every other command reads the cached sign-in silently and never opens a browser or a device-code
|
|
119
121
|
prompt — a missing or expired token fails with an actionable hint instead.
|
|
120
122
|
|
|
123
|
+
## Commands
|
|
124
|
+
|
|
125
|
+
All 123 verbs are documented inside the skill, and `--help` works at every level.
|
|
126
|
+
|
|
127
|
+
| Where | What |
|
|
128
|
+
|---|---|
|
|
129
|
+
| [`skills/mgraphctl/SKILL.md`](skills/mgraphctl/SKILL.md) | the skill itself: setup, a cheat-sheet of every noun and its verbs, recipes, guardrails, exit codes |
|
|
130
|
+
| [`skills/mgraphctl/reference/commands.md`](skills/mgraphctl/reference/commands.md) | the conventions every verb shares — argument resolution, the list envelope, paging defaults, exit codes, environment variables — and the index of the files below |
|
|
131
|
+
| [`skills/mgraphctl/reference/commands/`](skills/mgraphctl/reference/commands/) | one file per noun (`mail.md`, `calendar.md`, `teams.md`, …): each verb's options, the Graph call it makes and the scopes it needs |
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
${CLAUDE_PLUGIN_ROOT}/mgraphctl --help
|
|
135
|
+
${CLAUDE_PLUGIN_ROOT}/mgraphctl mail --help
|
|
136
|
+
${CLAUDE_PLUGIN_ROOT}/mgraphctl mail list --help
|
|
137
|
+
```
|
|
138
|
+
|
|
121
139
|
## Where things live
|
|
122
140
|
|
|
123
141
|
- Virtual environment: under `${CLAUDE_PLUGIN_DATA}` when Claude Code sets it, otherwise
|
|
@@ -215,7 +233,7 @@ uv run ruff format src tests
|
|
|
215
233
|
The test suite runs entirely offline against recorded fixtures — no Microsoft 365 account or
|
|
216
234
|
network access is needed to run it.
|
|
217
235
|
|
|
218
|
-
CI (`.github/workflows/ci.yml`) runs the suite on Python 3.
|
|
236
|
+
CI (`.github/workflows/ci.yml`) runs the suite on Python 3.10–3.13, ruff, `uv lock --check` and a
|
|
219
237
|
credential scan on every push. Releases are annotated `mgraphctl--vX.Y.Z` tags on `main`, cut with
|
|
220
238
|
`claude plugin tag`; the tag publishes the package to PyPI and a GitHub Release. See `VERSIONING.md`.
|
|
221
239
|
|
|
@@ -84,6 +84,22 @@ uv run --project <plugin> --frozen --no-dev mgraphctl login
|
|
|
84
84
|
Every other command reads the cached sign-in silently and never opens a browser or a device-code
|
|
85
85
|
prompt — a missing or expired token fails with an actionable hint instead.
|
|
86
86
|
|
|
87
|
+
## Commands
|
|
88
|
+
|
|
89
|
+
All 123 verbs are documented inside the skill, and `--help` works at every level.
|
|
90
|
+
|
|
91
|
+
| Where | What |
|
|
92
|
+
|---|---|
|
|
93
|
+
| [`skills/mgraphctl/SKILL.md`](skills/mgraphctl/SKILL.md) | the skill itself: setup, a cheat-sheet of every noun and its verbs, recipes, guardrails, exit codes |
|
|
94
|
+
| [`skills/mgraphctl/reference/commands.md`](skills/mgraphctl/reference/commands.md) | the conventions every verb shares — argument resolution, the list envelope, paging defaults, exit codes, environment variables — and the index of the files below |
|
|
95
|
+
| [`skills/mgraphctl/reference/commands/`](skills/mgraphctl/reference/commands/) | one file per noun (`mail.md`, `calendar.md`, `teams.md`, …): each verb's options, the Graph call it makes and the scopes it needs |
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
${CLAUDE_PLUGIN_ROOT}/mgraphctl --help
|
|
99
|
+
${CLAUDE_PLUGIN_ROOT}/mgraphctl mail --help
|
|
100
|
+
${CLAUDE_PLUGIN_ROOT}/mgraphctl mail list --help
|
|
101
|
+
```
|
|
102
|
+
|
|
87
103
|
## Where things live
|
|
88
104
|
|
|
89
105
|
- Virtual environment: under `${CLAUDE_PLUGIN_DATA}` when Claude Code sets it, otherwise
|
|
@@ -181,7 +197,7 @@ uv run ruff format src tests
|
|
|
181
197
|
The test suite runs entirely offline against recorded fixtures — no Microsoft 365 account or
|
|
182
198
|
network access is needed to run it.
|
|
183
199
|
|
|
184
|
-
CI (`.github/workflows/ci.yml`) runs the suite on Python 3.
|
|
200
|
+
CI (`.github/workflows/ci.yml`) runs the suite on Python 3.10–3.13, ruff, `uv lock --check` and a
|
|
185
201
|
credential scan on every push. Releases are annotated `mgraphctl--vX.Y.Z` tags on `main`, cut with
|
|
186
202
|
`claude plugin tag`; the tag publishes the package to PyPI and a GitHub Release. See `VERSIONING.md`.
|
|
187
203
|
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "mgraphctl"
|
|
3
|
-
version = "0.1
|
|
3
|
+
version = "0.2.1"
|
|
4
4
|
description = "Microsoft Graph CLI behind the mgraphctl Claude Code skill"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
license = "MIT"
|
|
7
7
|
license-files = ["LICENSE"]
|
|
8
|
-
requires-python = ">=3.
|
|
8
|
+
requires-python = ">=3.10,<3.14"
|
|
9
9
|
keywords = [
|
|
10
10
|
"microsoft-graph",
|
|
11
11
|
"microsoft-365",
|
|
@@ -22,6 +22,7 @@ classifiers = [
|
|
|
22
22
|
"Intended Audience :: End Users/Desktop",
|
|
23
23
|
"Operating System :: OS Independent",
|
|
24
24
|
"Programming Language :: Python :: 3",
|
|
25
|
+
"Programming Language :: Python :: 3.10",
|
|
25
26
|
"Programming Language :: Python :: 3.11",
|
|
26
27
|
"Programming Language :: Python :: 3.12",
|
|
27
28
|
"Programming Language :: Python :: 3.13",
|
|
@@ -36,6 +37,7 @@ dependencies = [
|
|
|
36
37
|
"markdownify>=1.2,<2",
|
|
37
38
|
"keyring>=24,<26",
|
|
38
39
|
"tzdata; sys_platform == 'win32'",
|
|
40
|
+
"tomli>=2,<3; python_version < '3.11'",
|
|
39
41
|
]
|
|
40
42
|
|
|
41
43
|
[[project.authors]]
|
|
@@ -70,7 +72,7 @@ module-name = "mgraphctl"
|
|
|
70
72
|
|
|
71
73
|
[tool.ruff]
|
|
72
74
|
line-length = 100
|
|
73
|
-
target-version = "
|
|
75
|
+
target-version = "py310"
|
|
74
76
|
extend-exclude = ["docs"]
|
|
75
77
|
|
|
76
78
|
[tool.ruff.lint]
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "mgraphctl"
|
|
3
|
-
version = "0.1
|
|
3
|
+
version = "0.2.1"
|
|
4
4
|
description = "Microsoft Graph CLI behind the mgraphctl Claude Code skill"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
license = "MIT"
|
|
7
7
|
license-files = ["LICENSE"]
|
|
8
8
|
authors = [{ name = "Sviatoslav Sviridov", email = "sviridov@gmail.com" }]
|
|
9
|
-
requires-python = ">=3.
|
|
9
|
+
requires-python = ">=3.10,<3.14"
|
|
10
10
|
keywords = ["microsoft-graph", "microsoft-365", "outlook", "teams", "sharepoint", "onedrive", "cli"]
|
|
11
11
|
classifiers = [
|
|
12
12
|
"Development Status :: 4 - Beta",
|
|
@@ -15,6 +15,7 @@ classifiers = [
|
|
|
15
15
|
"Intended Audience :: End Users/Desktop",
|
|
16
16
|
"Operating System :: OS Independent",
|
|
17
17
|
"Programming Language :: Python :: 3",
|
|
18
|
+
"Programming Language :: Python :: 3.10",
|
|
18
19
|
"Programming Language :: Python :: 3.11",
|
|
19
20
|
"Programming Language :: Python :: 3.12",
|
|
20
21
|
"Programming Language :: Python :: 3.13",
|
|
@@ -29,6 +30,7 @@ dependencies = [
|
|
|
29
30
|
"markdownify>=1.2,<2",
|
|
30
31
|
"keyring>=24,<26",
|
|
31
32
|
"tzdata; sys_platform == 'win32'",
|
|
33
|
+
"tomli>=2,<3; python_version < '3.11'",
|
|
32
34
|
]
|
|
33
35
|
|
|
34
36
|
[project.urls]
|
|
@@ -55,7 +57,7 @@ module-name = "mgraphctl"
|
|
|
55
57
|
|
|
56
58
|
[tool.ruff]
|
|
57
59
|
line-length = 100
|
|
58
|
-
target-version = "
|
|
60
|
+
target-version = "py310"
|
|
59
61
|
# Markdown under docs/ holds illustrative Python blocks; ruff must not rewrite them.
|
|
60
62
|
extend-exclude = ["docs"]
|
|
61
63
|
|
|
@@ -5,12 +5,17 @@ from __future__ import annotations
|
|
|
5
5
|
|
|
6
6
|
import os
|
|
7
7
|
import re
|
|
8
|
-
import
|
|
8
|
+
import sys
|
|
9
9
|
from collections.abc import Iterable
|
|
10
10
|
from dataclasses import dataclass
|
|
11
11
|
from pathlib import Path
|
|
12
12
|
from typing import Any
|
|
13
13
|
|
|
14
|
+
if sys.version_info >= (3, 11):
|
|
15
|
+
import tomllib
|
|
16
|
+
else: # tomllib is stdlib from 3.11; on 3.10 the same parser ships as tomli
|
|
17
|
+
import tomli as tomllib
|
|
18
|
+
|
|
14
19
|
from mgraphctl import __version__
|
|
15
20
|
|
|
16
21
|
CLIENT_ID_DEFAULT = "00000000-0000-0000-0000-000000000000"
|
|
@@ -14,7 +14,7 @@ import time
|
|
|
14
14
|
import uuid
|
|
15
15
|
from collections.abc import Callable, Mapping
|
|
16
16
|
from dataclasses import dataclass, field, replace
|
|
17
|
-
from datetime import
|
|
17
|
+
from datetime import datetime, timezone
|
|
18
18
|
from pathlib import Path
|
|
19
19
|
from typing import Any, Literal
|
|
20
20
|
from urllib.parse import urlsplit
|
|
@@ -399,7 +399,7 @@ class GraphClient:
|
|
|
399
399
|
return float(min(int(value), config.RETRY_AFTER_CAP))
|
|
400
400
|
with contextlib.suppress(TypeError, ValueError):
|
|
401
401
|
when = email.utils.parsedate_to_datetime(value)
|
|
402
|
-
seconds = (when - datetime.now(
|
|
402
|
+
seconds = (when - datetime.now(timezone.utc)).total_seconds()
|
|
403
403
|
return max(0.0, min(seconds, config.RETRY_AFTER_CAP))
|
|
404
404
|
base = self.retry_base_ms / 1000
|
|
405
405
|
return min(2**attempt * base, config.BACKOFF_CAP) + random.uniform(0, base)
|
|
@@ -13,7 +13,7 @@ import sys
|
|
|
13
13
|
import time
|
|
14
14
|
from collections.abc import Callable
|
|
15
15
|
from dataclasses import dataclass
|
|
16
|
-
from datetime import
|
|
16
|
+
from datetime import date, datetime, timedelta, timezone
|
|
17
17
|
from pathlib import Path
|
|
18
18
|
from typing import Any
|
|
19
19
|
from zoneinfo import ZoneInfo, ZoneInfoNotFoundError
|
|
@@ -343,7 +343,7 @@ def parse_graph_dt(value: str | None) -> datetime | None:
|
|
|
343
343
|
dt = datetime.fromisoformat(text)
|
|
344
344
|
except ValueError:
|
|
345
345
|
return None
|
|
346
|
-
return dt if dt.tzinfo is not None else dt.replace(tzinfo=
|
|
346
|
+
return dt if dt.tzinfo is not None else dt.replace(tzinfo=timezone.utc)
|
|
347
347
|
|
|
348
348
|
|
|
349
349
|
def fmt_dt(value: str | None, tz: str) -> str:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|