my-cli-utilities 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.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) [year] [fullname]
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,82 @@
1
+ Metadata-Version: 2.4
2
+ Name: my-cli-utilities
3
+ Version: 0.1.0
4
+ Summary: A suite of CLI utilities for account pool and device spy services.
5
+ Author-email: Swain Zheng <swain.zheng@xxxx.com>
6
+ License: MIT License
7
+ Project-URL: Homepage, https://github.com/yourusername/my-cli-utilities
8
+ Project-URL: Bug Tracker, https://github.com/yourusername/my-cli-utilities/issues
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Operating System :: OS Independent
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Topic :: Utilities
14
+ Requires-Python: >=3.8
15
+ Description-Content-Type: text/markdown
16
+ License-File: LICENSE
17
+ Requires-Dist: httpx>=0.20
18
+ Requires-Dist: fire>=0.4
19
+ Requires-Dist: requests>=2.20
20
+ Dynamic: license-file
21
+
22
+ # Account Pool CLI
23
+
24
+ A simple CLI tool to interact with the account pool service, allowing you to fetch account details.
25
+
26
+ ## Installation
27
+
28
+ To install the Account Pool CLI, run the following command in your terminal:
29
+
30
+ ```bash
31
+ pip install .
32
+ ```
33
+
34
+ (If you publish it to PyPI, you would use `pip install account-pool-cli`)
35
+
36
+ ## Usage
37
+
38
+ Once installed, you can use the `ap` command:
39
+
40
+ ### Get account info by main number
41
+
42
+ ```bash
43
+ ap info <main_number> [--env_name <environment_name>]
44
+ ```
45
+ Example:
46
+ ```bash
47
+ ap info 1234567890
48
+ ap info +1234567890 --env_name specific_env
49
+ ```
50
+ `env_name` defaults to `webaqaxmn` if not provided.
51
+
52
+ ### Get a random account
53
+
54
+ ```bash
55
+ ap get_random_account <account_type> [--env_name <environment_name>]
56
+ ```
57
+ Example:
58
+ ```bash
59
+ ap get_random_account "QQ"
60
+ ap get_random_account "YOUR_ACCOUNT_TYPE" --env_name specific_env
61
+ ```
62
+
63
+ ### Get account info by ID
64
+
65
+ ```bash
66
+ ap get_account_by_id <account_id> [--env_name <environment_name>]
67
+ ```
68
+ Example:
69
+ ```bash
70
+ ap get_account_by_id "60c72b2f9b1d8f001f8e4d3a"
71
+ ap get_account_by_id "60c72b2f9b1d8f001f8e4d3b" --env_name specific_env
72
+ ```
73
+
74
+ ## Development
75
+
76
+ To set up for development:
77
+
78
+ 1. Clone the repository.
79
+ 2. Create a virtual environment: `python -m venv .venv`
80
+ 3. Activate it: `source .venv/bin/activate` (on Linux/macOS) or `.venv\Scripts\activate` (on Windows)
81
+ 4. Install dependencies: `pip install -r requirements-dev.txt` (You'll need to create this file if you have dev-specific dependencies like `pytest`)
82
+ 5. Install the package in editable mode: `pip install -e .`
@@ -0,0 +1,61 @@
1
+ # Account Pool CLI
2
+
3
+ A simple CLI tool to interact with the account pool service, allowing you to fetch account details.
4
+
5
+ ## Installation
6
+
7
+ To install the Account Pool CLI, run the following command in your terminal:
8
+
9
+ ```bash
10
+ pip install .
11
+ ```
12
+
13
+ (If you publish it to PyPI, you would use `pip install account-pool-cli`)
14
+
15
+ ## Usage
16
+
17
+ Once installed, you can use the `ap` command:
18
+
19
+ ### Get account info by main number
20
+
21
+ ```bash
22
+ ap info <main_number> [--env_name <environment_name>]
23
+ ```
24
+ Example:
25
+ ```bash
26
+ ap info 1234567890
27
+ ap info +1234567890 --env_name specific_env
28
+ ```
29
+ `env_name` defaults to `webaqaxmn` if not provided.
30
+
31
+ ### Get a random account
32
+
33
+ ```bash
34
+ ap get_random_account <account_type> [--env_name <environment_name>]
35
+ ```
36
+ Example:
37
+ ```bash
38
+ ap get_random_account "QQ"
39
+ ap get_random_account "YOUR_ACCOUNT_TYPE" --env_name specific_env
40
+ ```
41
+
42
+ ### Get account info by ID
43
+
44
+ ```bash
45
+ ap get_account_by_id <account_id> [--env_name <environment_name>]
46
+ ```
47
+ Example:
48
+ ```bash
49
+ ap get_account_by_id "60c72b2f9b1d8f001f8e4d3a"
50
+ ap get_account_by_id "60c72b2f9b1d8f001f8e4d3b" --env_name specific_env
51
+ ```
52
+
53
+ ## Development
54
+
55
+ To set up for development:
56
+
57
+ 1. Clone the repository.
58
+ 2. Create a virtual environment: `python -m venv .venv`
59
+ 3. Activate it: `source .venv/bin/activate` (on Linux/macOS) or `.venv\Scripts\activate` (on Windows)
60
+ 4. Install dependencies: `pip install -r requirements-dev.txt` (You'll need to create this file if you have dev-specific dependencies like `pytest`)
61
+ 5. Install the package in editable mode: `pip install -e .`
@@ -0,0 +1,226 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ import httpx
4
+ import asyncio
5
+ import fire
6
+ import json
7
+ import random
8
+
9
+
10
+ class AccountPoolCli:
11
+ """
12
+ A CLI tool to interact with the Account Pool service.
13
+ Provides commands to fetch random accounts, specific account details by ID,
14
+ or specific account details by main number.
15
+ env_name defaults to 'webaqaxmn' if not provided for relevant commands.
16
+ """
17
+
18
+ async def _fetch_random_account_async(self, env_name: str, account_type: str):
19
+ # Base part of the URL
20
+ base_url = "https://account-pool-mthor.int.rclabenv.com/accounts"
21
+ # Dictionary of query parameters; httpx will automatically handle URL encoding for these
22
+ params = {"envName": env_name, "accountType": account_type}
23
+ try:
24
+ async with httpx.AsyncClient() as client:
25
+ # Pass query conditions using the params argument
26
+ response = await client.get(base_url, params=params)
27
+ response.raise_for_status() # If the request fails (status code 4xx or 5xx), an HTTPStatusError exception will be raised
28
+ print(f"Request successful! Status code: {response.status_code}")
29
+ # Assume the response is in JSON format
30
+ try:
31
+ parsed_json = response.json() # Parse JSON first
32
+ accounts_list = parsed_json.get(
33
+ "accounts"
34
+ ) # More safely get the 'accounts' list
35
+
36
+ if accounts_list: # Check if the list exists and is not empty
37
+ random_account = random.choice(
38
+ accounts_list
39
+ ) # Randomly select an account
40
+ print("Randomly selected account information:")
41
+ # Print the entire randomly selected account dictionary (user previously changed to print the whole object)
42
+ print(json.dumps(random_account, indent=2, ensure_ascii=False))
43
+ else:
44
+ print(
45
+ "No matching accounts found, or the 'accounts' list is empty."
46
+ )
47
+
48
+ except (
49
+ json.JSONDecodeError,
50
+ TypeError,
51
+ KeyError,
52
+ ) as e: # Removed IndexError because we now check the list first
53
+ print(f"Failed to parse JSON or extract account information: {e}")
54
+ print("Attempting to print raw response text:")
55
+ print(response.text)
56
+ if not isinstance(e, json.JSONDecodeError):
57
+ try:
58
+ print(
59
+ "Parsed JSON structure (may be incomplete or not as expected):"
60
+ )
61
+ print(
62
+ json.dumps(
63
+ response.json(), indent=2, ensure_ascii=False
64
+ )
65
+ )
66
+ except Exception as dump_e:
67
+ print(
68
+ f"Error occurred while trying to print parsed JSON: {dump_e}"
69
+ )
70
+
71
+ except httpx.HTTPStatusError as exc:
72
+ print(
73
+ f"Request failed, HTTP status code: {exc.response.status_code}, Error message: {exc.response.text}"
74
+ )
75
+ except httpx.RequestError as exc:
76
+ print(f"An error occurred during the request: {exc}")
77
+
78
+ def get_random_account(self, account_type: str, env_name: str = "webaqaxmn"):
79
+ """
80
+ Fetches a random account from the Account Pool based on environment and account type.
81
+
82
+ Args:
83
+ account_type (str): Account type (e.g., \'\'\'kamino2(CI-Common-4U,mThor,brand=1210,packageId=26,packageVersion=1,pipeline=rc+glp)\'\'\').
84
+ env_name (str, optional): Environment name. Defaults to "webaqaxmn".
85
+ """
86
+ asyncio.run(self._fetch_random_account_async(env_name, account_type))
87
+
88
+ async def _fetch_account_by_id_async(self, account_id: str, env_name: str):
89
+ # Construct URL with account_id in the path and env_name as a query parameter
90
+ url = f"https://account-pool-mthor.int.rclabenv.com/accounts/{account_id}"
91
+ params = {"envName": env_name}
92
+
93
+ print(
94
+ f"Fetching details for account ID {account_id} in env {env_name}..."
95
+ ) # Added print for clarity
96
+ try:
97
+ async with httpx.AsyncClient() as client:
98
+ response = await client.get(url, params=params)
99
+ response.raise_for_status() # Raise an exception for bad status codes
100
+ print(
101
+ f"Request for ID {account_id} successful! Status code: {response.status_code}"
102
+ )
103
+ try:
104
+ account_details = response.json()
105
+ print("Account details:")
106
+ # Print the formatted JSON response
107
+ print(json.dumps(account_details, indent=2, ensure_ascii=False))
108
+ except json.JSONDecodeError as e:
109
+ print(f"Failed to parse JSON response for ID {account_id}: {e}")
110
+ print("Raw response text:")
111
+ print(response.text)
112
+ except httpx.HTTPStatusError as exc:
113
+ print(
114
+ f"Request for ID {account_id} failed, HTTP status code: {exc.response.status_code}, Error message: {exc.response.text}"
115
+ )
116
+ print("Raw response text (on error):")
117
+ print(exc.response.text)
118
+ except httpx.RequestError as exc:
119
+ print(f"An error occurred during the request for ID {account_id}: {exc}")
120
+
121
+ def get_account_by_id(self, account_id: str, env_name: str = "webaqaxmn"):
122
+ """
123
+ Fetches specific account details by its ID and environment name.
124
+
125
+ Args:
126
+ account_id (str): The _id of the account to fetch.
127
+ env_name (str, optional): Environment name. Defaults to "webaqaxmn".
128
+ """
129
+ asyncio.run(self._fetch_account_by_id_async(account_id, env_name))
130
+
131
+ async def _fetch_info_by_main_number_async(self, main_number: str, env_name: str):
132
+ # Ensure main_number is treated as a string for string operations
133
+ main_number_str = str(main_number)
134
+ # Automatically prepend '+' if not present
135
+ if not main_number_str.startswith("+"):
136
+ main_number_str = "+" + main_number_str
137
+
138
+ base_url = "https://account-pool-mthor.int.rclabenv.com/accounts"
139
+ params_initial_lookup = {"envName": env_name, "mainNumber": main_number_str}
140
+ print(
141
+ f"Looking up account ID for main number {main_number_str} in env {env_name}..."
142
+ )
143
+ try:
144
+ async with httpx.AsyncClient() as client:
145
+ response_initial = await client.get(
146
+ base_url, params=params_initial_lookup
147
+ )
148
+ response_initial.raise_for_status()
149
+ try:
150
+ parsed_json = response_initial.json()
151
+ accounts_list = parsed_json.get("accounts")
152
+ if accounts_list:
153
+ account_summary = accounts_list[0]
154
+ retrieved_account_id = account_summary.get("_id")
155
+ if retrieved_account_id:
156
+ print(
157
+ f"Found account ID: {retrieved_account_id}. Fetching details..."
158
+ )
159
+ await self._fetch_account_by_id_async(
160
+ retrieved_account_id, env_name
161
+ )
162
+ else:
163
+ print(
164
+ f"Account found for main number {main_number_str}, but it does not contain an '_id' field."
165
+ )
166
+ print("Account summary found:")
167
+ print(
168
+ json.dumps(
169
+ account_summary, indent=2, ensure_ascii=False
170
+ )
171
+ )
172
+ else:
173
+ print(
174
+ f"No account found for main number {main_number_str} in environment {env_name}."
175
+ )
176
+ except (json.JSONDecodeError, TypeError, KeyError, IndexError) as e:
177
+ print(
178
+ f"Failed to parse JSON or extract account ID from initial lookup: {e}"
179
+ )
180
+ print("Attempting to print raw response text from initial lookup:")
181
+ print(response_initial.text)
182
+ if not isinstance(e, json.JSONDecodeError):
183
+ try:
184
+ print(
185
+ "Parsed JSON structure from initial lookup (may be incomplete or not as expected):"
186
+ )
187
+ print(
188
+ json.dumps(
189
+ response_initial.json(),
190
+ indent=2,
191
+ ensure_ascii=False,
192
+ )
193
+ )
194
+ except Exception as dump_e:
195
+ print(
196
+ f"Error occurred while trying to print parsed JSON from initial lookup: {dump_e}"
197
+ )
198
+ except httpx.HTTPStatusError as exc:
199
+ print(
200
+ f"Initial lookup for main number {main_number_str} failed, HTTP status code: {exc.response.status_code}, Error message: {exc.response.text}"
201
+ )
202
+ print("Raw response text (on error):")
203
+ print(exc.response.text)
204
+ except httpx.RequestError as exc:
205
+ print(
206
+ f"An error occurred during the initial lookup for main number {main_number_str}: {exc}"
207
+ )
208
+
209
+ def info(self, main_number: str, env_name: str = "webaqaxmn"):
210
+ """
211
+ Fetches specific account details by its mainNumber.
212
+ This first looks up the account by mainNumber to get its _id, then fetches full details using the _id.
213
+ If main_number is provided without a leading '+', it will be added automatically.
214
+
215
+ Args:
216
+ main_number (str): The mainNumber of the account to fetch (e.g., 12495002020 or +12495002020).
217
+ env_name (str, optional): Environment name. Defaults to "webaqaxmn".
218
+ """
219
+ asyncio.run(self._fetch_info_by_main_number_async(main_number, env_name))
220
+
221
+
222
+ def main_cli_function():
223
+ fire.Fire(AccountPoolCli)
224
+
225
+ if __name__ == "__main__":
226
+ main_cli_function()
@@ -0,0 +1,165 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+
4
+ import json
5
+ import fire
6
+ import httpx
7
+
8
+ BASE_URL = "https://device-spy-mthor.int.rclabenv.com"
9
+ HOSTS_ENDPOINT = BASE_URL + "/api/v1/hosts"
10
+ ALL_DEVICES_ENDPOINT = BASE_URL + "/api/v1/hosts/get_all_devices"
11
+ LABELS_ENDPOINT = BASE_URL + "/api/v1/labels/"
12
+ DEVICE_ASSETS_ENDPOINT = BASE_URL + "/api/v1/device_assets/"
13
+
14
+
15
+ class DeviceSpyCli:
16
+ """A CLI tool to interact with the Device Spy service.
17
+
18
+ This tool allows you to query various details about devices and hosts
19
+ managed by the Device Spy system.
20
+ """
21
+
22
+ def _get_device_location_from_assets(self, udid):
23
+ try:
24
+ with httpx.Client() as client:
25
+ response = client.get(DEVICE_ASSETS_ENDPOINT)
26
+ response.raise_for_status()
27
+ device_assets = response.json().get("data", [])
28
+ for device_asset in device_assets:
29
+ if device_asset.get("udid") == udid:
30
+ return device_asset.get("location")
31
+ except httpx.RequestError as e:
32
+ print(f"Error fetching device assets: {e}")
33
+ except json.JSONDecodeError:
34
+ print("Error decoding JSON from device assets response.")
35
+ return None
36
+
37
+ def _get_host_alias(self, host_ip):
38
+ try:
39
+ with httpx.Client() as client:
40
+ response = client.get(HOSTS_ENDPOINT)
41
+ response.raise_for_status()
42
+ hosts = response.json().get("data", [])
43
+ for host in hosts:
44
+ if host.get("hostname") == host_ip:
45
+ return host.get("alias")
46
+ except httpx.RequestError as e:
47
+ print(f"Error fetching hosts: {e}")
48
+ except json.JSONDecodeError:
49
+ print("Error decoding JSON from hosts response.")
50
+ return None
51
+
52
+ def info(self, udid: str):
53
+ """Queries and displays detailed information for a specific device.
54
+
55
+ Args:
56
+ udid (str): The Unique Device Identifier (UDID) of the device to query.
57
+ """
58
+ try:
59
+ with httpx.Client() as client:
60
+ response = client.get(ALL_DEVICES_ENDPOINT)
61
+ response.raise_for_status()
62
+ devices = response.json().get("data", [])
63
+ for device_data in devices:
64
+ if udid == device_data.get("udid"):
65
+ device_info = device_data.copy()
66
+ original_hostname = device_info.get("hostname")
67
+
68
+ device_info["hostname"] = self._get_host_alias(
69
+ original_hostname
70
+ )
71
+
72
+ if device_info.get("platform") == "android":
73
+ device_info["ip_port"] = (
74
+ f"{original_hostname}:{device_info.get('adb_port')}"
75
+ )
76
+
77
+ location = self._get_device_location_from_assets(udid)
78
+ if location:
79
+ device_info["location"] = location
80
+
81
+ keys_to_delete = ["is_simulator", "remote_control", "adb_port"]
82
+
83
+ for key in keys_to_delete:
84
+ if key in device_info:
85
+ del device_info[key]
86
+
87
+ print(json.dumps(device_info, indent=2, ensure_ascii=False))
88
+ return
89
+ print(f"Device with UDID '{udid}' not found.")
90
+ except httpx.RequestError as e:
91
+ print(f"Error fetching all devices: {e}")
92
+ except json.JSONDecodeError:
93
+ print("Error decoding JSON from all devices response.")
94
+
95
+ def available_devices(self, platform: str):
96
+ """Lists available (not locked, not simulator) devices for a given platform.
97
+
98
+ Args:
99
+ platform (str): The platform to filter by (e.g., "android", "ios").
100
+ """
101
+ try:
102
+ with httpx.Client() as client:
103
+ response = client.get(ALL_DEVICES_ENDPOINT)
104
+ response.raise_for_status()
105
+ all_devices = response.json().get("data", [])
106
+ avail_devices_udids = []
107
+
108
+ for device in all_devices:
109
+ if (
110
+ not device.get("is_locked")
111
+ and not device.get("is_simulator")
112
+ and device.get("platform") == platform
113
+ ):
114
+ avail_devices_udids.append(device.get("udid"))
115
+
116
+ result = {
117
+ "count": len(avail_devices_udids),
118
+ "udids": avail_devices_udids,
119
+ }
120
+ print(json.dumps(result, indent=2, ensure_ascii=False))
121
+
122
+ except httpx.RequestError as e:
123
+ print(f"Error fetching available devices: {e}")
124
+ except json.JSONDecodeError:
125
+ print("Error decoding JSON from available devices response.")
126
+
127
+ def get_host_ip(self, query_string: str):
128
+ """Finds host IP address(es) based on a query string.
129
+
130
+ The query string is matched against host information fields like alias or hostname.
131
+
132
+ Args:
133
+ query_string (str): The string to search for within host information.
134
+ """
135
+ try:
136
+ with httpx.Client() as client:
137
+ response = client.get(HOSTS_ENDPOINT)
138
+ response.raise_for_status()
139
+ hosts = response.json().get("data", [])
140
+ found_host_ips = []
141
+ for host in hosts:
142
+ for value in host.values():
143
+ if query_string.lower() in str(value).lower():
144
+ found_host_ips.append(host.get("hostname"))
145
+ break
146
+
147
+ if not found_host_ips:
148
+ print(f"No host found matching '{query_string}'.")
149
+ elif len(found_host_ips) == 1:
150
+ print(found_host_ips[0])
151
+ else:
152
+ print(json.dumps(found_host_ips, indent=2))
153
+
154
+ except httpx.RequestError as e:
155
+ print(f"Error fetching hosts for IP lookup: {e}")
156
+ except json.JSONDecodeError:
157
+ print("Error decoding JSON from hosts response for IP lookup.")
158
+
159
+
160
+ def main_ds_function():
161
+ fire.Fire(DeviceSpyCli)
162
+
163
+
164
+ # if __name__ == '__main__':
165
+ # main_ds_function() # Keep this commented out for library use
@@ -0,0 +1,82 @@
1
+ Metadata-Version: 2.4
2
+ Name: my-cli-utilities
3
+ Version: 0.1.0
4
+ Summary: A suite of CLI utilities for account pool and device spy services.
5
+ Author-email: Swain Zheng <swain.zheng@xxxx.com>
6
+ License: MIT License
7
+ Project-URL: Homepage, https://github.com/yourusername/my-cli-utilities
8
+ Project-URL: Bug Tracker, https://github.com/yourusername/my-cli-utilities/issues
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Operating System :: OS Independent
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Topic :: Utilities
14
+ Requires-Python: >=3.8
15
+ Description-Content-Type: text/markdown
16
+ License-File: LICENSE
17
+ Requires-Dist: httpx>=0.20
18
+ Requires-Dist: fire>=0.4
19
+ Requires-Dist: requests>=2.20
20
+ Dynamic: license-file
21
+
22
+ # Account Pool CLI
23
+
24
+ A simple CLI tool to interact with the account pool service, allowing you to fetch account details.
25
+
26
+ ## Installation
27
+
28
+ To install the Account Pool CLI, run the following command in your terminal:
29
+
30
+ ```bash
31
+ pip install .
32
+ ```
33
+
34
+ (If you publish it to PyPI, you would use `pip install account-pool-cli`)
35
+
36
+ ## Usage
37
+
38
+ Once installed, you can use the `ap` command:
39
+
40
+ ### Get account info by main number
41
+
42
+ ```bash
43
+ ap info <main_number> [--env_name <environment_name>]
44
+ ```
45
+ Example:
46
+ ```bash
47
+ ap info 1234567890
48
+ ap info +1234567890 --env_name specific_env
49
+ ```
50
+ `env_name` defaults to `webaqaxmn` if not provided.
51
+
52
+ ### Get a random account
53
+
54
+ ```bash
55
+ ap get_random_account <account_type> [--env_name <environment_name>]
56
+ ```
57
+ Example:
58
+ ```bash
59
+ ap get_random_account "QQ"
60
+ ap get_random_account "YOUR_ACCOUNT_TYPE" --env_name specific_env
61
+ ```
62
+
63
+ ### Get account info by ID
64
+
65
+ ```bash
66
+ ap get_account_by_id <account_id> [--env_name <environment_name>]
67
+ ```
68
+ Example:
69
+ ```bash
70
+ ap get_account_by_id "60c72b2f9b1d8f001f8e4d3a"
71
+ ap get_account_by_id "60c72b2f9b1d8f001f8e4d3b" --env_name specific_env
72
+ ```
73
+
74
+ ## Development
75
+
76
+ To set up for development:
77
+
78
+ 1. Clone the repository.
79
+ 2. Create a virtual environment: `python -m venv .venv`
80
+ 3. Activate it: `source .venv/bin/activate` (on Linux/macOS) or `.venv\Scripts\activate` (on Windows)
81
+ 4. Install dependencies: `pip install -r requirements-dev.txt` (You'll need to create this file if you have dev-specific dependencies like `pytest`)
82
+ 5. Install the package in editable mode: `pip install -e .`
@@ -0,0 +1,13 @@
1
+ LICENSE
2
+ README.md
3
+ pyproject.toml
4
+ account_pool_cli/__init__.py
5
+ account_pool_cli/cli.py
6
+ device_spy_cli/__init__.py
7
+ device_spy_cli/cli.py
8
+ my_cli_utilities.egg-info/PKG-INFO
9
+ my_cli_utilities.egg-info/SOURCES.txt
10
+ my_cli_utilities.egg-info/dependency_links.txt
11
+ my_cli_utilities.egg-info/entry_points.txt
12
+ my_cli_utilities.egg-info/requires.txt
13
+ my_cli_utilities.egg-info/top_level.txt
@@ -0,0 +1,3 @@
1
+ [console_scripts]
2
+ ap = account_pool_cli.cli:main_cli_function
3
+ ds = device_spy_cli.cli:main_ds_function
@@ -0,0 +1,3 @@
1
+ httpx>=0.20
2
+ fire>=0.4
3
+ requests>=2.20
@@ -0,0 +1,2 @@
1
+ account_pool_cli
2
+ device_spy_cli
@@ -0,0 +1,38 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "my-cli-utilities"
7
+ version = "0.1.0"
8
+ authors = [
9
+ { name="Swain Zheng", email="swain.zheng@xxxx.com" },
10
+ ]
11
+ description = "A suite of CLI utilities for account pool and device spy services."
12
+ readme = "README.md"
13
+ requires-python = ">=3.8"
14
+ license = {text = "MIT License"}
15
+ classifiers = [
16
+ "Programming Language :: Python :: 3",
17
+ "Operating System :: OS Independent",
18
+ "Development Status :: 3 - Alpha",
19
+ "Intended Audience :: Developers",
20
+ "Topic :: Utilities",
21
+ ]
22
+ dependencies = [
23
+ "httpx>=0.20",
24
+ "fire>=0.4",
25
+ "requests>=2.20"
26
+ ]
27
+
28
+ [project.urls]
29
+ "Homepage" = "https://github.com/yourusername/my-cli-utilities"
30
+ "Bug Tracker" = "https://github.com/yourusername/my-cli-utilities/issues"
31
+
32
+ [project.scripts]
33
+ ap = "account_pool_cli.cli:main_cli_function"
34
+ ds = "device_spy_cli.cli:main_ds_function"
35
+
36
+ [tool.setuptools.packages.find]
37
+ include = ["account_pool_cli*", "device_spy_cli*"]
38
+ exclude = ["plists*" ]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+