xpipe_api 0.1.27__py3-none-any.whl → 0.1.28__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.
xpipe_api/clients.py CHANGED
@@ -19,7 +19,7 @@ class Client:
19
19
  base_url: str
20
20
  raise_errors: bool
21
21
  session: Optional[str] = None
22
- min_version: Version = Version("14.0")
22
+ min_version: Version = Version("15.2")
23
23
 
24
24
  def __init__(
25
25
  self, token: Optional[str] = None, base_url: Optional[str] = None, ptb: bool = False, raise_errors: bool = True
@@ -110,7 +110,7 @@ class Client:
110
110
  def get(self, *args, **kwargs) -> bytes:
111
111
  return self._get(*args, **kwargs).content
112
112
 
113
- def connection_query(self, categories: str = "*", connections: str = "*", types: str = "*") -> List[str]:
113
+ def connection_query(self, categories: str = "**", connections: str = "**", types: str = "*") -> List[str]:
114
114
  endpoint = f"{self.base_url}/connection/query"
115
115
  data = {"categoryFilter": categories, "connectionFilter": connections, "typeFilter": types}
116
116
  response = self.post(endpoint, json=data)
@@ -170,7 +170,7 @@ class Client:
170
170
  data = {"connection": connection}
171
171
  self.post(endpoint, json=data)
172
172
 
173
- def get_connections(self, categories: str = "*", connections: str = "*", types: str = "*") -> List[dict]:
173
+ def get_connections(self, categories: str = "**", connections: str = "**", types: str = "*") -> List[dict]:
174
174
  """Convenience method to chain connection/query with connection/info"""
175
175
  uuids = self.connection_query(categories, connections, types)
176
176
  return self.connection_info(uuids) if uuids else []
@@ -246,11 +246,13 @@ class AsyncClient(Client):
246
246
  session_token = parsed.get("sessionToken", None)
247
247
  if session_token:
248
248
  self.session = session_token
249
+ daemon_version = (await self.daemon_version())["version"]
250
+ assert (
251
+ daemon_version == "dev" or Version(daemon_version) >= self.min_version
252
+ ), f"xpipe_api requires XPipe of at least {self.min_version}"
249
253
  else:
250
254
  raise AuthFailedException(json.dumps(parsed))
251
- assert (
252
- Version((await self.daemon_version())["version"]) >= self.min_version
253
- ), f"xpipe_api requires XPipe of at least {self.min_version}"
255
+
254
256
 
255
257
  async def _post(self, *args, **kwargs) -> aiohttp.ClientResponse:
256
258
  if not self.session:
@@ -310,7 +312,7 @@ class AsyncClient(Client):
310
312
  resp = await self._get(*args, **kwargs)
311
313
  return await resp.read()
312
314
 
313
- async def connection_query(self, categories: str = "*", connections: str = "*", types: str = "*") -> List[str]:
315
+ async def connection_query(self, categories: str = "**", connections: str = "**", types: str = "*") -> List[str]:
314
316
  endpoint = f"{self.base_url}/connection/query"
315
317
  data = {"categoryFilter": categories, "connectionFilter": connections, "typeFilter": types}
316
318
  response = await self.post(endpoint, json=data)
@@ -370,7 +372,7 @@ class AsyncClient(Client):
370
372
  data = {"connection": connection}
371
373
  await self.post(endpoint, json=data)
372
374
 
373
- async def get_connections(self, categories: str = "*", connections: str = "*", types: str = "*") -> List[dict]:
375
+ async def get_connections(self, categories: str = "**", connections: str = "**", types: str = "*") -> List[dict]:
374
376
  uuids = await self.connection_query(categories, connections, types)
375
377
  return (await self.connection_info(uuids)) if uuids else []
376
378
 
@@ -0,0 +1,44 @@
1
+ Metadata-Version: 2.3
2
+ Name: xpipe_api
3
+ Version: 0.1.28
4
+ Summary: Client for the XPipe API
5
+ License: MIT
6
+ Author: Clint Olson
7
+ Author-email: coandco@gmail.com
8
+ Requires-Python: >=3.10,<4.0
9
+ Classifier: License :: OSI Approved :: MIT License
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3.10
12
+ Classifier: Programming Language :: Python :: 3.11
13
+ Classifier: Programming Language :: Python :: 3.12
14
+ Classifier: Programming Language :: Python :: 3.13
15
+ Requires-Dist: aiohttp-requests (>=0.2.4,<0.3.0)
16
+ Requires-Dist: packaging (>=24.1,<25.0)
17
+ Requires-Dist: requests (>=2.32.3,<3.0.0)
18
+ Project-URL: Repository, https://github.com/xpipe-io/xpipe-python-api
19
+ Description-Content-Type: text/markdown
20
+
21
+ # XPipe Python API
22
+
23
+ [![GitHub license](https://img.shields.io/github/license/xpipe-io/xpipe-python-api.svg)](https://github.com/xpipe-io/xpipe-python-api/blob/master/LICENSE)
24
+ [![PyPI version](https://img.shields.io/pypi/v/xpipe_api)](https://pypi.org/project/xpipe_api/)
25
+
26
+ Python client for the XPipe API. This library is a wrapper for the raw [HTTP API](https://github.com/xpipe-io/xpipe/blob/master/openapi.yaml) and intended to make working with it more convenient.
27
+
28
+ ```bash
29
+ python3 -m pip install xpipe_api
30
+ ```
31
+
32
+ You can find the documentation at https://docs.xpipe.io/guide/python-api.
33
+
34
+ ## Development
35
+
36
+ To run the test suite, you'll need to define the XPIPE_APIKEY env var. This will allow the two "log in with the ApiKey
37
+ rather than Local method" tests to work. Here's the recommended method for running the tests with poetry:
38
+
39
+ ```bash
40
+ cd /path/to/xpipe-python-api
41
+ poetry install
42
+ XPIPE_APIKEY=<api_key> poetry run pytest
43
+ ```
44
+
@@ -0,0 +1,7 @@
1
+ xpipe_api/__init__.py,sha256=XLv-a-mt7OcGS9OQbDBHKBsI4mO-4lgWDA13nZ0njFY,108
2
+ xpipe_api/clients.py,sha256=ZbNjpuOSsNtt_ge9XQYxNdYB_zQppBbJOUvg1IFg9Qo,19661
3
+ xpipe_api/exceptions.py,sha256=FdkNKLV1gOH8mOuNM9wH_q3hYNFEdMbQwAEZUX4yZQU,410
4
+ xpipe_api-0.1.28.dist-info/LICENSE,sha256=hWd_i4lSck0lBXcxe-2P4VCUyPAecKW-X1oOiXv21wE,1089
5
+ xpipe_api-0.1.28.dist-info/METADATA,sha256=sOkrtJfXrwEpfYmCW3nsbDI24hUqR8X5tSKH1ZWcKKU,1660
6
+ xpipe_api-0.1.28.dist-info/WHEEL,sha256=IYZQI976HJqqOpQU6PHkJ8fb3tMNBFjg-Cn-pwAbaFM,88
7
+ xpipe_api-0.1.28.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 1.9.0
2
+ Generator: poetry-core 2.0.1
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
@@ -1,246 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: xpipe_api
3
- Version: 0.1.27
4
- Summary: Client for the XPipe API
5
- Home-page: https://github.com/xpipe-io/xpipe-python-api
6
- License: MIT
7
- Author: Clint Olson
8
- Author-email: coandco@gmail.com
9
- Requires-Python: >=3.10,<4.0
10
- Classifier: License :: OSI Approved :: MIT License
11
- Classifier: Programming Language :: Python :: 3
12
- Classifier: Programming Language :: Python :: 3.10
13
- Classifier: Programming Language :: Python :: 3.11
14
- Classifier: Programming Language :: Python :: 3.12
15
- Requires-Dist: aiohttp-requests (>=0.2.4,<0.3.0)
16
- Requires-Dist: packaging (>=24.1,<25.0)
17
- Requires-Dist: requests (>=2.32.3,<3.0.0)
18
- Project-URL: Repository, https://github.com/xpipe-io/xpipe-python-api
19
- Description-Content-Type: text/markdown
20
-
21
- # XPipe Python API
22
-
23
- [![GitHub license](https://img.shields.io/github/license/xpipe-io/xpipe-python-api.svg)](https://github.com/xpipe-io/xpipe-python-api/blob/master/LICENSE)
24
- [![PyPI version](https://img.shields.io/pypi/v/xpipe_api)](https://pypi.org/project/xpipe_api/)
25
-
26
- Python client for the XPipe API. This library is a wrapper for the raw [HTTP API](https://github.com/xpipe-io/xpipe/blob/master/openapi.yaml) and intended to make working with it more convenient. You can find the raw API reference at http://localhost:21721 if your XPipe desktop application is running. XPipe contains a local webserver that includes the API docs as well.
27
-
28
- ## Installation
29
-
30
- ```
31
- python3 -m pip install xpipe_api
32
- ```
33
-
34
- ## Connecting to the XPipe application
35
-
36
- To start out, you need to enable the API access in the XPipe settings. You can find that under **Settings** -> **API**. For only a local API access, you don't need to worry about the API key in the settings menu.
37
-
38
- ```python
39
- from xpipe_api import Client
40
-
41
- # By default, Client() will read an access key from the file xpipe_auth on the local filesystem
42
- # and talk to the XPipe HTTP server on localhost.
43
- client = Client()
44
-
45
- # If you want to connect to a PTB build of XPipe, you have to configure the client with that information
46
- # as the PTB releases use a different port
47
- client = Client(ptb=True)
48
-
49
- # To connect to a remote instance with an API key, use
50
- client = Client(token="foo", base_url = "http://servername:21721")
51
- ```
52
-
53
- There's also an async version of the client that can be accessed as AsyncClient. All calls are run asynchronously with that client. This intro will only cover the sync client though.
54
-
55
- ```python
56
- import asyncio
57
- from xpipe_api import AsyncClient
58
-
59
- async def main():
60
- client = AsyncClient()
61
-
62
- # Do your stuff async
63
-
64
- if __name__ == "__main__":
65
- asyncio.run(main())
66
- ```
67
-
68
- ## Querying connections
69
-
70
- A connection reference is just a UUID string. You can query one or multiple connections stored in XPipe based on various filters.
71
-
72
- **API reference**: http://localhost:21721/#query-connections
73
-
74
- ```python
75
- from xpipe_api import Client
76
-
77
- client = Client()
78
-
79
- # connection_query accepts glob-based filters on the category, connection name, and connection type
80
- connections = client.connection_query(categories="Default/**")
81
-
82
- # Find only ssh config host connections in the "MyCategory" category that has the word "MyCompany" in its name
83
- # - Searching for strings is case-insensitive here
84
- # - This will not include subcategories of "MyCategory"
85
- # - You can find all the available connection type names by just querying all connections and taking a look add the individual type names of the connections.
86
- connections = client.connection_query(categories="MyCategory", types="sshConfigHost", connections="*MyCompany*")
87
-
88
- # Query a specific connection by name in a category
89
- # This will only return one element, so we can just access that
90
- connection = client.connection_query(categories="MyCategory", connections="MyConnectionName")[0]
91
-
92
- # Query the local machine connection
93
- connection = client.connection_query(connections="Local Machine")[0]
94
-
95
- # A connection reference is just a UUID string, so you can also specify it fixed
96
- # If you have the HTTP API setting enabled in XPipe, you can copy the API UUID of a connection in the context menu
97
- connection = "f0ec68aa-63f5-405c-b178-9a4454556d6b"
98
- ```
99
-
100
- ## Getting connection information
101
-
102
- Since each connection reference is just a UUID string, you have to retrieve information for it using another API call.
103
-
104
- **API Reference**: http://localhost:21721/#connection-information
105
-
106
- ```python
107
- from xpipe_api import Client
108
-
109
- client = Client()
110
-
111
- connections = client.connection_query(categories="Default/**")
112
-
113
- # Works in bulk, so it expects an array of connections
114
- infos = client.connection_info(connections)
115
- # Get the first info
116
- info = infos[0]
117
-
118
- # The connection UUID
119
- uuid = info["connection"]
120
- # This is an array containing all category hierarchy names
121
- category = info["category"]
122
- # This is an array containing all connection hierarchy names
123
- name = info["name"]
124
- # This is the connection type name that you can use in the query
125
- type = info["type"]
126
- # There is also some other data for internal state management, e.g. if a tunnel is running for example
127
- ```
128
-
129
- ## GUI actions
130
-
131
- You can perform some actions for the desktop application from the CLI as well.
132
-
133
- **API Reference**: http://localhost:21721/#open-connection-in-file-browser
134
-
135
- ```python
136
- from xpipe_api import Client
137
-
138
- client = Client()
139
-
140
- connection = "f0ec68aa-63f5-405c-b178-9a4454556d6b"
141
-
142
- # Opens the file browser in a specified starting directory for a connection
143
- client.connection_browse(connection, "/etc")
144
-
145
- # Opens a terminal session in a specified starting directory for a connection
146
- client.connection_terminal(connection, "/etc")
147
-
148
- # Toggles the session state for a connection. If this connection is a tunnel, then this operation will start or stop the tunnel
149
- client.connection_toggle(connection, True)
150
-
151
- # Refreshes a connection. This operation is the same as for validating a connection when creating it by attempting whether the connection is functioning.
152
- client.connection_refresh(connection)
153
- ```
154
-
155
- ## Shell operations
156
-
157
- You can open remote shell sessions to systems and run arbitrary commands in them.
158
-
159
- **API Reference**: http://localhost:21721/#start-shell-connection
160
-
161
- ```python
162
- from xpipe_api import Client
163
- import re
164
-
165
- client = Client()
166
-
167
- connection = "f0ec68aa-63f5-405c-b178-9a4454556d6b"
168
-
169
- # This will start a shell session for the connection
170
- # Note that this session is non-interactive, meaning that password prompts are not supported
171
- shell_info = client.shell_start(connection)
172
-
173
- # The shell dialect of the shell. For example cmd, powershell, bash, etc.
174
- dialect = shell_info["shellDialect"]
175
- # The operating system type of the system. For example, windows, linux, macos, bsd, solaris
176
- osType = shell_info["osType"]
177
- # The display name of the operating system. For example Windows 10 Home 22H2
178
- osName = shell_info["osName"]
179
-
180
- # Prints {'exitCode': 0, 'stdout': 'hello world', 'stderr': ''}
181
- print(client.shell_exec(connection, "echo hello world"))
182
-
183
- # Prints {'exitCode': 0, 'stdout': '<user>', 'stderr': ''}
184
- print(client.shell_exec(connection, "echo $USER"))
185
-
186
- # Prints {'exitCode': 127, 'stdout': 'invalid: command not found', 'stderr': ''}
187
- print(client.shell_exec(connection, "invalid"))
188
-
189
- # Extract ssh version from system
190
- version_format = re.compile(r'[0-9.]+')
191
- ret = client.shell_exec(connection, "ssh -V")
192
- ssh_version = version_format.findall(ret["stderr"])[0]
193
-
194
- # Clean up after ourselves by stopping the shell session
195
- client.shell_stop(connection)
196
- ```
197
-
198
- ## File system operations
199
-
200
- You can interact with the file system of any remote shell as well.
201
-
202
- **API reference**: http://localhost:21721/#store-a-raw-blob-to-be-used-later
203
-
204
- ```python
205
- from xpipe_api import Client
206
-
207
- client = Client()
208
-
209
- connection = "f0ec68aa-63f5-405c-b178-9a4454556d6b"
210
-
211
- # We need a shell for the file system
212
- client.shell_start(connection)
213
-
214
- # You are responsible for decoding files in the correct file encoding
215
- file_bytes = client.fs_read(connection, "~/.ssh/config")
216
- file_string = file_bytes.decode('utf-8')
217
-
218
- # Writing files can be done via blobs
219
- file_write_content = "test\nfile"
220
- blob_id = client.fs_blob(file_write_content)
221
- client.fs_write(connection, blob_id, "~/test_file.txt")
222
-
223
- # You can do the same with script files as well
224
- # This will create an executable script in the system's temp directory
225
- script_write_content = "echo hello\necho world"
226
- blob_script_id = client.fs_blob(file_write_content)
227
- script_path = client.fs_script(connection, blob_script_id)
228
-
229
- # You can then use this script for your commands
230
- # Prints {'exitCode': 0, 'stdout': 'hello\nworld', 'stderr': ''}
231
- print(client.shell_exec(connection, "\"" + script_path + "\""))
232
-
233
- # Clean up after ourselves by stopping the shell session
234
- client.shell_stop(connection)
235
- ```
236
-
237
- ## Development
238
-
239
- To run the test suite, you'll need to define the XPIPE_APIKEY env var. This will allow the two "log in with the ApiKey
240
- rather than Local method" tests to work. Here's the recommended method for running the tests with poetry:
241
-
242
- ```commandline
243
- cd /path/to/xpipe-python-api
244
- poetry install
245
- XPIPE_APIKEY=<api_key> poetry run pytest
246
- ```
@@ -1,7 +0,0 @@
1
- xpipe_api/__init__.py,sha256=XLv-a-mt7OcGS9OQbDBHKBsI4mO-4lgWDA13nZ0njFY,108
2
- xpipe_api/clients.py,sha256=N5CCrQJTIHAwTedPTpol21IQcVmECwVMSE_8XRSMW80,19563
3
- xpipe_api/exceptions.py,sha256=FdkNKLV1gOH8mOuNM9wH_q3hYNFEdMbQwAEZUX4yZQU,410
4
- xpipe_api-0.1.27.dist-info/LICENSE,sha256=hWd_i4lSck0lBXcxe-2P4VCUyPAecKW-X1oOiXv21wE,1089
5
- xpipe_api-0.1.27.dist-info/METADATA,sha256=FW1cTa8fBTcqjXBAbM_cxvXkNe98FERz6tRqx7bTmnI,8925
6
- xpipe_api-0.1.27.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
7
- xpipe_api-0.1.27.dist-info/RECORD,,