eeroctl 1.7.1__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.
Files changed (45) hide show
  1. eeroctl/__init__.py +19 -0
  2. eeroctl/commands/__init__.py +32 -0
  3. eeroctl/commands/activity.py +237 -0
  4. eeroctl/commands/auth.py +471 -0
  5. eeroctl/commands/completion.py +142 -0
  6. eeroctl/commands/device.py +492 -0
  7. eeroctl/commands/eero/__init__.py +12 -0
  8. eeroctl/commands/eero/base.py +224 -0
  9. eeroctl/commands/eero/led.py +154 -0
  10. eeroctl/commands/eero/nightlight.py +235 -0
  11. eeroctl/commands/eero/updates.py +82 -0
  12. eeroctl/commands/network/__init__.py +18 -0
  13. eeroctl/commands/network/advanced.py +191 -0
  14. eeroctl/commands/network/backup.py +162 -0
  15. eeroctl/commands/network/base.py +331 -0
  16. eeroctl/commands/network/dhcp.py +118 -0
  17. eeroctl/commands/network/dns.py +197 -0
  18. eeroctl/commands/network/forwards.py +115 -0
  19. eeroctl/commands/network/guest.py +162 -0
  20. eeroctl/commands/network/security.py +162 -0
  21. eeroctl/commands/network/speedtest.py +99 -0
  22. eeroctl/commands/network/sqm.py +194 -0
  23. eeroctl/commands/profile.py +671 -0
  24. eeroctl/commands/troubleshoot.py +317 -0
  25. eeroctl/context.py +254 -0
  26. eeroctl/errors.py +156 -0
  27. eeroctl/exit_codes.py +68 -0
  28. eeroctl/formatting/__init__.py +90 -0
  29. eeroctl/formatting/base.py +181 -0
  30. eeroctl/formatting/device.py +430 -0
  31. eeroctl/formatting/eero.py +591 -0
  32. eeroctl/formatting/misc.py +87 -0
  33. eeroctl/formatting/network.py +659 -0
  34. eeroctl/formatting/profile.py +443 -0
  35. eeroctl/main.py +161 -0
  36. eeroctl/options.py +429 -0
  37. eeroctl/output.py +739 -0
  38. eeroctl/safety.py +259 -0
  39. eeroctl/utils.py +181 -0
  40. eeroctl-1.7.1.dist-info/METADATA +115 -0
  41. eeroctl-1.7.1.dist-info/RECORD +45 -0
  42. eeroctl-1.7.1.dist-info/WHEEL +5 -0
  43. eeroctl-1.7.1.dist-info/entry_points.txt +3 -0
  44. eeroctl-1.7.1.dist-info/licenses/LICENSE +21 -0
  45. eeroctl-1.7.1.dist-info/top_level.txt +1 -0
eeroctl/__init__.py ADDED
@@ -0,0 +1,19 @@
1
+ """Command-line interface for Eero client.
2
+
3
+ This package provides the CLI for managing Eero networks.
4
+
5
+ Entry point: eeroctl.main:cli
6
+ """
7
+
8
+ from .main import cli, main
9
+
10
+ __version__ = "1.7.1"
11
+ __version_info__ = tuple(int(x) for x in __version__.split(".")[:3])
12
+
13
+
14
+ def get_version() -> str:
15
+ """Return the current version of eeroctl."""
16
+ return __version__
17
+
18
+
19
+ __all__ = ["cli", "main", "__version__", "__version_info__", "get_version"]
@@ -0,0 +1,32 @@
1
+ """New command structure for the Eero CLI.
2
+
3
+ This package contains the new noun-first command tree:
4
+ - auth: Authentication management
5
+ - network: Network configuration and settings
6
+ - eero: Mesh node management
7
+ - device: Connected device management
8
+ - profile: Profile/parental controls management
9
+ - activity: Network activity data (Eero Plus)
10
+ - troubleshoot: Diagnostics and troubleshooting
11
+ - completion: Shell completion
12
+ """
13
+
14
+ from .activity import activity_group
15
+ from .auth import auth_group
16
+ from .completion import completion_group
17
+ from .device import device_group
18
+ from .eero import eero_group
19
+ from .network import network_group
20
+ from .profile import profile_group
21
+ from .troubleshoot import troubleshoot_group
22
+
23
+ __all__ = [
24
+ "auth_group",
25
+ "network_group",
26
+ "eero_group",
27
+ "device_group",
28
+ "profile_group",
29
+ "activity_group",
30
+ "troubleshoot_group",
31
+ "completion_group",
32
+ ]
@@ -0,0 +1,237 @@
1
+ """Activity commands for the Eero CLI (Eero Plus feature).
2
+
3
+ Commands:
4
+ - eero activity summary: Network activity summary
5
+ - eero activity clients: Per-client activity
6
+ - eero activity history: Historical activity
7
+ - eero activity categories: Activity by category
8
+ """
9
+
10
+ import sys
11
+ from typing import Optional
12
+
13
+ import click
14
+ from eero import EeroClient
15
+ from rich.panel import Panel
16
+ from rich.table import Table
17
+
18
+ from ..context import ensure_cli_context
19
+ from ..errors import is_premium_error
20
+ from ..exit_codes import ExitCode
21
+ from ..options import apply_options, network_option, output_option
22
+ from ..utils import with_client
23
+
24
+
25
+ def _format_bytes(bytes_val: int) -> str:
26
+ """Format bytes into human-readable format."""
27
+ if bytes_val < 1024:
28
+ return f"{bytes_val} B"
29
+ elif bytes_val < 1024 * 1024:
30
+ return f"{bytes_val / 1024:.1f} KB"
31
+ elif bytes_val < 1024 * 1024 * 1024:
32
+ return f"{bytes_val / (1024 * 1024):.1f} MB"
33
+ else:
34
+ return f"{bytes_val / (1024 * 1024 * 1024):.2f} GB"
35
+
36
+
37
+ @click.group(name="activity")
38
+ @click.pass_context
39
+ def activity_group(ctx: click.Context) -> None:
40
+ """View network activity data (Eero Plus feature).
41
+
42
+ \b
43
+ Commands:
44
+ summary - Network activity summary
45
+ clients - Per-client activity
46
+ history - Historical activity
47
+ categories - Activity by category
48
+
49
+ \b
50
+ Note: Requires an active Eero Plus subscription.
51
+
52
+ \b
53
+ Examples:
54
+ eero activity summary
55
+ eero activity clients
56
+ eero activity history --period week
57
+ """
58
+ ensure_cli_context(ctx)
59
+
60
+
61
+ @activity_group.command(name="summary")
62
+ @output_option
63
+ @network_option
64
+ @click.pass_context
65
+ @with_client
66
+ async def activity_summary(
67
+ ctx: click.Context, client: EeroClient, output: Optional[str], network_id: Optional[str]
68
+ ) -> None:
69
+ """Show network activity summary."""
70
+ cli_ctx = apply_options(ctx, output=output, network_id=network_id)
71
+ console = cli_ctx.console
72
+
73
+ with cli_ctx.status("Getting network activity..."):
74
+ try:
75
+ activity_data = await client.get_activity(cli_ctx.network_id)
76
+ except Exception as e:
77
+ if is_premium_error(e):
78
+ console.print("[yellow]This feature requires Eero Plus subscription[/yellow]")
79
+ sys.exit(ExitCode.PREMIUM_REQUIRED)
80
+ raise
81
+
82
+ if cli_ctx.is_structured_output():
83
+ cli_ctx.render_structured(activity_data, "eero.activity.summary/v1")
84
+ else:
85
+ upload = activity_data.get("upload_bytes", 0)
86
+ download = activity_data.get("download_bytes", 0)
87
+ total = upload + download
88
+
89
+ content = (
90
+ f"[bold cyan]Download:[/bold cyan] {_format_bytes(download)}\n"
91
+ f"[bold cyan]Upload:[/bold cyan] {_format_bytes(upload)}\n"
92
+ f"[bold cyan]Total:[/bold cyan] {_format_bytes(total)}"
93
+ )
94
+ console.print(Panel(content, title="Network Activity Summary", border_style="blue"))
95
+
96
+
97
+ @activity_group.command(name="clients")
98
+ @output_option
99
+ @network_option
100
+ @click.pass_context
101
+ @with_client
102
+ async def activity_clients(
103
+ ctx: click.Context, client: EeroClient, output: Optional[str], network_id: Optional[str]
104
+ ) -> None:
105
+ """Show per-client activity data."""
106
+ cli_ctx = apply_options(ctx, output=output, network_id=network_id)
107
+ console = cli_ctx.console
108
+
109
+ with cli_ctx.status("Getting client activity..."):
110
+ try:
111
+ clients_data = await client.get_activity_clients(cli_ctx.network_id)
112
+ except Exception as e:
113
+ if is_premium_error(e):
114
+ console.print("[yellow]This feature requires Eero Plus subscription[/yellow]")
115
+ sys.exit(ExitCode.PREMIUM_REQUIRED)
116
+ raise
117
+
118
+ if cli_ctx.is_structured_output():
119
+ cli_ctx.render_structured(clients_data, "eero.activity.clients/v1")
120
+ else:
121
+ if not clients_data:
122
+ console.print("[yellow]No client activity data available[/yellow]")
123
+ return
124
+
125
+ table = Table(title="Client Activity")
126
+ table.add_column("Device", style="cyan")
127
+ table.add_column("Download", justify="right")
128
+ table.add_column("Upload", justify="right")
129
+ table.add_column("Total", justify="right")
130
+
131
+ for client_info in clients_data:
132
+ name = (
133
+ client_info.get("display_name")
134
+ or client_info.get("hostname")
135
+ or client_info.get("mac", "Unknown")
136
+ )
137
+ download = client_info.get("download_bytes", 0)
138
+ upload = client_info.get("upload_bytes", 0)
139
+ total = download + upload
140
+
141
+ table.add_row(
142
+ name, _format_bytes(download), _format_bytes(upload), _format_bytes(total)
143
+ )
144
+
145
+ console.print(table)
146
+
147
+
148
+ @activity_group.command(name="history")
149
+ @click.option(
150
+ "--period",
151
+ type=click.Choice(["hour", "day", "week", "month"]),
152
+ default="day",
153
+ help="Time period (default: day)",
154
+ )
155
+ @output_option
156
+ @network_option
157
+ @click.pass_context
158
+ @with_client
159
+ async def activity_history(
160
+ ctx: click.Context,
161
+ client: EeroClient,
162
+ period: str,
163
+ output: Optional[str],
164
+ network_id: Optional[str],
165
+ ) -> None:
166
+ """Show historical activity data.
167
+
168
+ \b
169
+ Options:
170
+ --period Time period: hour, day, week, month
171
+ """
172
+ cli_ctx = apply_options(ctx, output=output, network_id=network_id)
173
+ console = cli_ctx.console
174
+
175
+ with cli_ctx.status(f"Getting activity history ({period})..."):
176
+ try:
177
+ history_data = await client.get_activity_history(cli_ctx.network_id, period)
178
+ except Exception as e:
179
+ if is_premium_error(e):
180
+ console.print("[yellow]This feature requires Eero Plus subscription[/yellow]")
181
+ sys.exit(ExitCode.PREMIUM_REQUIRED)
182
+ raise
183
+
184
+ if cli_ctx.is_structured_output():
185
+ cli_ctx.render_structured(history_data, "eero.activity.history/v1")
186
+ else:
187
+ total_download = history_data.get("total_download_bytes", 0)
188
+ total_upload = history_data.get("total_upload_bytes", 0)
189
+ data_points = history_data.get("data_points", [])
190
+
191
+ content = (
192
+ f"[bold]Period:[/bold] {period}\n"
193
+ f"[bold cyan]Total Download:[/bold cyan] {_format_bytes(total_download)}\n"
194
+ f"[bold cyan]Total Upload:[/bold cyan] {_format_bytes(total_upload)}\n"
195
+ f"[bold]Data Points:[/bold] {len(data_points)}"
196
+ )
197
+ console.print(Panel(content, title=f"Activity History ({period})", border_style="blue"))
198
+
199
+
200
+ @activity_group.command(name="categories")
201
+ @output_option
202
+ @network_option
203
+ @click.pass_context
204
+ @with_client
205
+ async def activity_categories(
206
+ ctx: click.Context, client: EeroClient, output: Optional[str], network_id: Optional[str]
207
+ ) -> None:
208
+ """Show activity grouped by category."""
209
+ cli_ctx = apply_options(ctx, output=output, network_id=network_id)
210
+ console = cli_ctx.console
211
+
212
+ with cli_ctx.status("Getting activity categories..."):
213
+ try:
214
+ categories_data = await client.get_activity_categories(cli_ctx.network_id)
215
+ except Exception as e:
216
+ if is_premium_error(e):
217
+ console.print("[yellow]This feature requires Eero Plus subscription[/yellow]")
218
+ sys.exit(ExitCode.PREMIUM_REQUIRED)
219
+ raise
220
+
221
+ if cli_ctx.is_structured_output():
222
+ cli_ctx.render_structured(categories_data, "eero.activity.categories/v1")
223
+ else:
224
+ if not categories_data:
225
+ console.print("[yellow]No category data available[/yellow]")
226
+ return
227
+
228
+ table = Table(title="Activity by Category")
229
+ table.add_column("Category", style="cyan")
230
+ table.add_column("Usage", justify="right")
231
+
232
+ for category in categories_data:
233
+ name = category.get("name", "Unknown")
234
+ usage = category.get("bytes", 0)
235
+ table.add_row(name, _format_bytes(usage))
236
+
237
+ console.print(table)