everything-sdk 1.0.0__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.
everything/__init__.py
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"""
|
|
2
|
+
everything — Python wrapper for the Everything SDK v3.
|
|
3
|
+
|
|
4
|
+
Provides :class:`EverythingClient`, :class:`SearchResult`,
|
|
5
|
+
:class:`PropertyID`, :class:`FileAttribute`, :class:`EverythingError`,
|
|
6
|
+
and the :func:`format_size` utility.
|
|
7
|
+
|
|
8
|
+
Quick start::
|
|
9
|
+
|
|
10
|
+
from everything import EverythingClient, format_size
|
|
11
|
+
|
|
12
|
+
with EverythingClient() as client:
|
|
13
|
+
client.connect()
|
|
14
|
+
results, total = client.search("*.txt")
|
|
15
|
+
for r in results:
|
|
16
|
+
print(f"{r.full_path}: {format_size(r.size)}")
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
from .client import EverythingClient, EverythingError, PropertyID, FileAttribute, SearchResult, format_size
|
|
20
|
+
|
|
21
|
+
__version__ = "1.0.0"
|
|
22
|
+
__all__ = [
|
|
23
|
+
"EverythingClient",
|
|
24
|
+
"EverythingError",
|
|
25
|
+
"PropertyID",
|
|
26
|
+
"FileAttribute",
|
|
27
|
+
"SearchResult",
|
|
28
|
+
"format_size",
|
|
29
|
+
]
|
everything/client.py
ADDED
|
@@ -0,0 +1,757 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Everything SDK v3 Python Wrapper
|
|
3
|
+
|
|
4
|
+
This module provides a Pythonic interface to the Everything desktop search
|
|
5
|
+
engine (https://www.voidtools.com/) via its native v3 DLL API. It uses
|
|
6
|
+
``ctypes`` to call the C exports directly, so no compilation or additional
|
|
7
|
+
C-extension build step is required.
|
|
8
|
+
|
|
9
|
+
Typical usage::
|
|
10
|
+
|
|
11
|
+
from everything import EverythingClient, format_size
|
|
12
|
+
|
|
13
|
+
with EverythingClient() as client:
|
|
14
|
+
client.connect()
|
|
15
|
+
results, total = client.search("*.txt", match_path=True)
|
|
16
|
+
for r in results:
|
|
17
|
+
print(f"{r.full_path}: {format_size(r.size)}")
|
|
18
|
+
|
|
19
|
+
Note:
|
|
20
|
+
Everything must be running on the host machine before a connection
|
|
21
|
+
can be established. Download it from https://www.voidtools.com/.
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
import ctypes
|
|
25
|
+
import ctypes.wintypes as wintypes
|
|
26
|
+
import os
|
|
27
|
+
import sys
|
|
28
|
+
from datetime import datetime
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class PropertyID:
|
|
32
|
+
"""Integer identifiers for the result properties exposed by the
|
|
33
|
+
Everything SDK. Used with ``Everything3_AddSearchPropertyRequest`` and
|
|
34
|
+
``Everything3_GetResultProperty*`` calls.
|
|
35
|
+
|
|
36
|
+
See the SDK header ``Everything3.h`` for the canonical definitions.
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
NAME = 0
|
|
40
|
+
PATH = 1
|
|
41
|
+
SIZE = 2
|
|
42
|
+
EXTENSION = 3
|
|
43
|
+
TYPE = 4
|
|
44
|
+
DATE_MODIFIED = 5
|
|
45
|
+
DATE_CREATED = 6
|
|
46
|
+
DATE_ACCESSED = 7
|
|
47
|
+
ATTRIBUTES = 8
|
|
48
|
+
DATE_RECENTLY_CHANGED = 9
|
|
49
|
+
RUN_COUNT = 10
|
|
50
|
+
DATE_RUN = 11
|
|
51
|
+
FILE_LIST_NAME = 12
|
|
52
|
+
WIDTH = 13
|
|
53
|
+
HEIGHT = 14
|
|
54
|
+
DIMENSIONS = 15
|
|
55
|
+
ASPECT_RATIO = 16
|
|
56
|
+
BIT_DEPTH = 17
|
|
57
|
+
LENGTH = 18
|
|
58
|
+
AUDIO_SAMPLE_RATE = 19
|
|
59
|
+
AUDIO_CHANNELS = 20
|
|
60
|
+
AUDIO_BITS_PER_SAMPLE = 21
|
|
61
|
+
AUDIO_BIT_RATE = 22
|
|
62
|
+
AUDIO_FORMAT = 23
|
|
63
|
+
FILE_SIGNATURE = 24
|
|
64
|
+
TITLE = 25
|
|
65
|
+
ARTIST = 26
|
|
66
|
+
ALBUM = 27
|
|
67
|
+
YEAR = 28
|
|
68
|
+
COMMENT = 29
|
|
69
|
+
TRACK = 30
|
|
70
|
+
GENRE = 31
|
|
71
|
+
FRAME_RATE = 32
|
|
72
|
+
VIDEO_BIT_RATE = 33
|
|
73
|
+
VIDEO_FORMAT = 34
|
|
74
|
+
RATING = 35
|
|
75
|
+
TAGS = 36
|
|
76
|
+
MD5 = 37
|
|
77
|
+
SHA1 = 38
|
|
78
|
+
SHA256 = 39
|
|
79
|
+
CRC32 = 40
|
|
80
|
+
SIZE_ON_DISK = 41
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
class FileAttribute:
|
|
84
|
+
"""Windows file-attribute bit flags (mirrors ``FILE_ATTRIBUTE_*``)."""
|
|
85
|
+
|
|
86
|
+
READONLY = 0x01
|
|
87
|
+
HIDDEN = 0x02
|
|
88
|
+
SYSTEM = 0x04
|
|
89
|
+
DIRECTORY = 0x10
|
|
90
|
+
ARCHIVE = 0x20
|
|
91
|
+
COMPRESSED = 0x40
|
|
92
|
+
NORMAL = 0x80
|
|
93
|
+
TEMPORARY = 0x100
|
|
94
|
+
OFFLINE = 0x200
|
|
95
|
+
INTEGRITY_STREAM = 0x1000
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
class EverythingError(Exception):
|
|
99
|
+
"""Raised when an Everything SDK call reports a failure.
|
|
100
|
+
|
|
101
|
+
Attributes:
|
|
102
|
+
error_code: The 32-bit error code returned by
|
|
103
|
+
``Everything3_GetLastError``.
|
|
104
|
+
"""
|
|
105
|
+
|
|
106
|
+
ERROR_IPC_PIPE_NOT_FOUND = 0xE0000002
|
|
107
|
+
|
|
108
|
+
def __init__(self, error_code):
|
|
109
|
+
self.error_code = error_code
|
|
110
|
+
if error_code == self.ERROR_IPC_PIPE_NOT_FOUND:
|
|
111
|
+
message = "Everything is not running or IPC pipe not found"
|
|
112
|
+
else:
|
|
113
|
+
message = f"Everything SDK error, code: 0x{error_code:X}"
|
|
114
|
+
super().__init__(message)
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
class SearchResult:
|
|
118
|
+
"""Immutable container holding the properties of a single Everything
|
|
119
|
+
search result.
|
|
120
|
+
|
|
121
|
+
All FILETIME timestamps are stored as raw 64-bit integers. Convenience
|
|
122
|
+
properties (``modified_time``, ``created_time``, ``accessed_time``)
|
|
123
|
+
convert them to :class:`datetime.datetime` objects on the fly.
|
|
124
|
+
"""
|
|
125
|
+
|
|
126
|
+
def __init__(self, name, parent_path, full_path, size, is_folder,
|
|
127
|
+
date_modified, date_created, date_accessed, attributes,
|
|
128
|
+
extension=""):
|
|
129
|
+
self.name = name
|
|
130
|
+
self.parent_path = parent_path
|
|
131
|
+
self.full_path = full_path
|
|
132
|
+
self.size = size
|
|
133
|
+
self.is_folder = is_folder
|
|
134
|
+
self.date_modified = date_modified
|
|
135
|
+
self.date_created = date_created
|
|
136
|
+
self.date_accessed = date_accessed
|
|
137
|
+
self.attributes = attributes
|
|
138
|
+
self.extension = extension
|
|
139
|
+
|
|
140
|
+
@property
|
|
141
|
+
def type_str(self):
|
|
142
|
+
"""Return ``"Folder"`` or ``"File"``."""
|
|
143
|
+
return "Folder" if self.is_folder else "File"
|
|
144
|
+
|
|
145
|
+
@property
|
|
146
|
+
def modified_time(self):
|
|
147
|
+
"""Convert the FILETIME timestamp to a :class:`datetime`, or
|
|
148
|
+
``None`` if the value is zero (not available)."""
|
|
149
|
+
if self.date_modified == 0:
|
|
150
|
+
return None
|
|
151
|
+
return datetime.fromtimestamp(
|
|
152
|
+
self.date_modified / 10_000_000 - 11644473600
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
@property
|
|
156
|
+
def created_time(self):
|
|
157
|
+
"""Convert the FILETIME timestamp to a :class:`datetime`, or
|
|
158
|
+
``None`` if the value is zero (not available)."""
|
|
159
|
+
if self.date_created == 0:
|
|
160
|
+
return None
|
|
161
|
+
return datetime.fromtimestamp(
|
|
162
|
+
self.date_created / 10_000_000 - 11644473600
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
@property
|
|
166
|
+
def accessed_time(self):
|
|
167
|
+
"""Convert the FILETIME timestamp to a :class:`datetime`, or
|
|
168
|
+
``None`` if the value is zero (not available)."""
|
|
169
|
+
if self.date_accessed == 0:
|
|
170
|
+
return None
|
|
171
|
+
return datetime.fromtimestamp(
|
|
172
|
+
self.date_accessed / 10_000_000 - 11644473600
|
|
173
|
+
)
|
|
174
|
+
|
|
175
|
+
@property
|
|
176
|
+
def attr_str(self):
|
|
177
|
+
"""Human-readable attribute string, e.g. ``"DA"`` for a normal
|
|
178
|
+
directory with the archive bit set."""
|
|
179
|
+
attr_map = {
|
|
180
|
+
0x01: "R", 0x02: "H", 0x04: "S", 0x10: "D",
|
|
181
|
+
0x20: "A", 0x40: "C", 0x80: "N", 0x100: "T",
|
|
182
|
+
0x200: "O", 0x1000: "I",
|
|
183
|
+
}
|
|
184
|
+
result = []
|
|
185
|
+
for bit, char in attr_map.items():
|
|
186
|
+
if self.attributes & bit:
|
|
187
|
+
result.append(char)
|
|
188
|
+
return "".join(result) if result else "-"
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
class EverythingClient:
|
|
192
|
+
"""High-level wrapper around the Everything v3 DLL.
|
|
193
|
+
|
|
194
|
+
Args:
|
|
195
|
+
dll_path: Optional path to ``Everything3_x64.dll``. When *None*
|
|
196
|
+
(the default), the constructor searches for the DLL in several
|
|
197
|
+
well-known locations — see :meth:`_find_dll` for details.
|
|
198
|
+
|
|
199
|
+
Example::
|
|
200
|
+
|
|
201
|
+
with EverythingClient() as client:
|
|
202
|
+
client.connect()
|
|
203
|
+
results, total = client.search("*.pdf")
|
|
204
|
+
"""
|
|
205
|
+
|
|
206
|
+
def __init__(self, dll_path=None):
|
|
207
|
+
if dll_path is None:
|
|
208
|
+
dll_path = self._find_dll()
|
|
209
|
+
|
|
210
|
+
if not os.path.exists(dll_path):
|
|
211
|
+
raise FileNotFoundError(
|
|
212
|
+
f"Everything3 DLL not found: {dll_path}"
|
|
213
|
+
)
|
|
214
|
+
|
|
215
|
+
self._dll = ctypes.WinDLL(dll_path)
|
|
216
|
+
self._client = None
|
|
217
|
+
self._setup_function_signatures()
|
|
218
|
+
|
|
219
|
+
# ------------------------------------------------------------------
|
|
220
|
+
# DLL discovery
|
|
221
|
+
# ------------------------------------------------------------------
|
|
222
|
+
|
|
223
|
+
@staticmethod
|
|
224
|
+
def _find_dll():
|
|
225
|
+
"""Locate ``Everything3_x64.dll`` using a multi-strategy search.
|
|
226
|
+
|
|
227
|
+
Strategies (checked in order):
|
|
228
|
+
|
|
229
|
+
1. ``EVERYTHING_SDK_DIR`` environment variable — looks for
|
|
230
|
+
``<dir>/dll/Everything3_x64.dll`` or ``<dir>/Everything3_x64.dll``.
|
|
231
|
+
2. ``PATH`` environment variable — scans every directory for
|
|
232
|
+
``Everything3_x64.dll``.
|
|
233
|
+
3. Relative to this module — looks in sibling ``Everything-SDK``
|
|
234
|
+
directories that are commonly found in developer setups.
|
|
235
|
+
4. Common installation directories — checks ``Program Files`` and
|
|
236
|
+
``Program Files (x86)`` under an ``Everything`` sub-folder.
|
|
237
|
+
|
|
238
|
+
Returns:
|
|
239
|
+
Absolute path to the DLL.
|
|
240
|
+
|
|
241
|
+
Raises:
|
|
242
|
+
FileNotFoundError: If none of the strategies found the DLL.
|
|
243
|
+
"""
|
|
244
|
+
# Strategy 1: Check EVERYTHING_SDK_DIR environment variable
|
|
245
|
+
sdk_dir = os.environ.get("EVERYTHING_SDK_DIR")
|
|
246
|
+
if sdk_dir:
|
|
247
|
+
dll_path = os.path.join(sdk_dir, "dll", "Everything3_x64.dll")
|
|
248
|
+
if os.path.exists(dll_path):
|
|
249
|
+
return dll_path
|
|
250
|
+
dll_path = os.path.join(sdk_dir, "Everything3_x64.dll")
|
|
251
|
+
if os.path.exists(dll_path):
|
|
252
|
+
return dll_path
|
|
253
|
+
|
|
254
|
+
# Strategy 2: Check PATH environment variable
|
|
255
|
+
path_env = os.environ.get("PATH", "")
|
|
256
|
+
for path_dir in path_env.split(os.pathsep):
|
|
257
|
+
dll_path = os.path.join(path_dir, "Everything3_x64.dll")
|
|
258
|
+
if os.path.exists(dll_path):
|
|
259
|
+
return dll_path
|
|
260
|
+
|
|
261
|
+
# Strategy 3: Search relative to the SDK module location
|
|
262
|
+
module_dir = os.path.dirname(os.path.abspath(__file__))
|
|
263
|
+
for search_dir in [
|
|
264
|
+
os.path.join(module_dir, "..", "..", "Everything-SDK"),
|
|
265
|
+
os.path.join(module_dir, "..", "..", "..", "Everything-SDK"),
|
|
266
|
+
]:
|
|
267
|
+
search_dir = os.path.normpath(search_dir)
|
|
268
|
+
if os.path.exists(search_dir):
|
|
269
|
+
for dll_subdir in ["dll", "SDK/DLL/x64", ""]:
|
|
270
|
+
dll_path = os.path.join(
|
|
271
|
+
search_dir, dll_subdir, "Everything3_x64.dll"
|
|
272
|
+
)
|
|
273
|
+
if os.path.exists(dll_path):
|
|
274
|
+
return dll_path
|
|
275
|
+
|
|
276
|
+
# Strategy 4: Common installation locations
|
|
277
|
+
common_paths = [
|
|
278
|
+
os.path.join(
|
|
279
|
+
os.environ.get("ProgramFiles", "C:\\Program Files"),
|
|
280
|
+
"Everything", "Everything3_x64.dll",
|
|
281
|
+
),
|
|
282
|
+
os.path.join(
|
|
283
|
+
os.environ.get("ProgramFiles(x86)",
|
|
284
|
+
"C:\\Program Files (x86)"),
|
|
285
|
+
"Everything", "Everything3_x64.dll",
|
|
286
|
+
),
|
|
287
|
+
]
|
|
288
|
+
for dll_path in common_paths:
|
|
289
|
+
if os.path.exists(dll_path):
|
|
290
|
+
return dll_path
|
|
291
|
+
|
|
292
|
+
raise FileNotFoundError(
|
|
293
|
+
"Cannot find Everything3_x64.dll. Tried:\n"
|
|
294
|
+
" 1. EVERYTHING_SDK_DIR environment variable, or\n"
|
|
295
|
+
" 2. PATH environment variable, or\n"
|
|
296
|
+
" 3. Passing dll_path directly to EverythingClient()"
|
|
297
|
+
)
|
|
298
|
+
|
|
299
|
+
# ------------------------------------------------------------------
|
|
300
|
+
# DLL function signature setup
|
|
301
|
+
# ------------------------------------------------------------------
|
|
302
|
+
|
|
303
|
+
def _setup_function_signatures(self):
|
|
304
|
+
"""Declare ``restype`` / ``argtypes`` for every DLL export we use.
|
|
305
|
+
|
|
306
|
+
This avoids ctypes calling-convention mis-detection and improves
|
|
307
|
+
both safety and error messages when argument types are wrong.
|
|
308
|
+
"""
|
|
309
|
+
dll = self._dll
|
|
310
|
+
|
|
311
|
+
# Client lifecycle
|
|
312
|
+
dll.Everything3_ConnectW.restype = ctypes.c_void_p
|
|
313
|
+
dll.Everything3_ConnectW.argtypes = [ctypes.c_wchar_p]
|
|
314
|
+
|
|
315
|
+
dll.Everything3_DestroyClient.restype = wintypes.BOOL
|
|
316
|
+
dll.Everything3_DestroyClient.argtypes = [ctypes.c_void_p]
|
|
317
|
+
|
|
318
|
+
dll.Everything3_GetLastError.restype = wintypes.DWORD
|
|
319
|
+
dll.Everything3_GetLastError.argtypes = []
|
|
320
|
+
|
|
321
|
+
# Version information
|
|
322
|
+
dll.Everything3_GetMajorVersion.restype = wintypes.DWORD
|
|
323
|
+
dll.Everything3_GetMajorVersion.argtypes = [ctypes.c_void_p]
|
|
324
|
+
|
|
325
|
+
dll.Everything3_GetMinorVersion.restype = wintypes.DWORD
|
|
326
|
+
dll.Everything3_GetMinorVersion.argtypes = [ctypes.c_void_p]
|
|
327
|
+
|
|
328
|
+
dll.Everything3_GetRevision.restype = wintypes.DWORD
|
|
329
|
+
dll.Everything3_GetRevision.argtypes = [ctypes.c_void_p]
|
|
330
|
+
|
|
331
|
+
dll.Everything3_GetBuildNumber.restype = wintypes.DWORD
|
|
332
|
+
dll.Everything3_GetBuildNumber.argtypes = [ctypes.c_void_p]
|
|
333
|
+
|
|
334
|
+
# Database status
|
|
335
|
+
dll.Everything3_IsDBLoaded.restype = wintypes.BOOL
|
|
336
|
+
dll.Everything3_IsDBLoaded.argtypes = [ctypes.c_void_p]
|
|
337
|
+
|
|
338
|
+
dll.Everything3_GetTargetMachine.restype = wintypes.DWORD
|
|
339
|
+
dll.Everything3_GetTargetMachine.argtypes = [ctypes.c_void_p]
|
|
340
|
+
|
|
341
|
+
# Search state management
|
|
342
|
+
dll.Everything3_CreateSearchState.restype = ctypes.c_void_p
|
|
343
|
+
dll.Everything3_CreateSearchState.argtypes = []
|
|
344
|
+
|
|
345
|
+
dll.Everything3_DestroySearchState.restype = wintypes.BOOL
|
|
346
|
+
dll.Everything3_DestroySearchState.argtypes = [ctypes.c_void_p]
|
|
347
|
+
|
|
348
|
+
# Search options
|
|
349
|
+
dll.Everything3_SetSearchTextW.restype = wintypes.BOOL
|
|
350
|
+
dll.Everything3_SetSearchTextW.argtypes = [
|
|
351
|
+
ctypes.c_void_p, ctypes.c_wchar_p,
|
|
352
|
+
]
|
|
353
|
+
|
|
354
|
+
dll.Everything3_SetSearchMatchPath.restype = wintypes.BOOL
|
|
355
|
+
dll.Everything3_SetSearchMatchPath.argtypes = [
|
|
356
|
+
ctypes.c_void_p, wintypes.BOOL,
|
|
357
|
+
]
|
|
358
|
+
|
|
359
|
+
dll.Everything3_SetSearchMatchCase.restype = wintypes.BOOL
|
|
360
|
+
dll.Everything3_SetSearchMatchCase.argtypes = [
|
|
361
|
+
ctypes.c_void_p, wintypes.BOOL,
|
|
362
|
+
]
|
|
363
|
+
|
|
364
|
+
dll.Everything3_SetSearchMatchWholeWords.restype = wintypes.BOOL
|
|
365
|
+
dll.Everything3_SetSearchMatchWholeWords.argtypes = [
|
|
366
|
+
ctypes.c_void_p, wintypes.BOOL,
|
|
367
|
+
]
|
|
368
|
+
|
|
369
|
+
dll.Everything3_SetSearchRegex.restype = wintypes.BOOL
|
|
370
|
+
dll.Everything3_SetSearchRegex.argtypes = [
|
|
371
|
+
ctypes.c_void_p, wintypes.BOOL,
|
|
372
|
+
]
|
|
373
|
+
|
|
374
|
+
# Viewport (pagination) control
|
|
375
|
+
dll.Everything3_SetSearchViewportCount.restype = wintypes.BOOL
|
|
376
|
+
dll.Everything3_SetSearchViewportCount.argtypes = [
|
|
377
|
+
ctypes.c_void_p, ctypes.c_size_t,
|
|
378
|
+
]
|
|
379
|
+
|
|
380
|
+
dll.Everything3_SetSearchViewportOffset.restype = wintypes.BOOL
|
|
381
|
+
dll.Everything3_SetSearchViewportOffset.argtypes = [
|
|
382
|
+
ctypes.c_void_p, ctypes.c_size_t,
|
|
383
|
+
]
|
|
384
|
+
|
|
385
|
+
# Property request / sort
|
|
386
|
+
dll.Everything3_AddSearchPropertyRequest.restype = wintypes.BOOL
|
|
387
|
+
dll.Everything3_AddSearchPropertyRequest.argtypes = [
|
|
388
|
+
ctypes.c_void_p, wintypes.DWORD,
|
|
389
|
+
]
|
|
390
|
+
|
|
391
|
+
dll.Everything3_AddSearchSort.restype = wintypes.BOOL
|
|
392
|
+
dll.Everything3_AddSearchSort.argtypes = [
|
|
393
|
+
ctypes.c_void_p, wintypes.DWORD, wintypes.BOOL,
|
|
394
|
+
]
|
|
395
|
+
|
|
396
|
+
dll.Everything3_ClearSearchSorts.restype = wintypes.BOOL
|
|
397
|
+
dll.Everything3_ClearSearchSorts.argtypes = [ctypes.c_void_p]
|
|
398
|
+
|
|
399
|
+
# Execution & result list
|
|
400
|
+
dll.Everything3_Search.restype = ctypes.c_void_p
|
|
401
|
+
dll.Everything3_Search.argtypes = [
|
|
402
|
+
ctypes.c_void_p, ctypes.c_void_p,
|
|
403
|
+
]
|
|
404
|
+
|
|
405
|
+
dll.Everything3_DestroyResultList.restype = wintypes.BOOL
|
|
406
|
+
dll.Everything3_DestroyResultList.argtypes = [ctypes.c_void_p]
|
|
407
|
+
|
|
408
|
+
dll.Everything3_GetResultListCount.restype = ctypes.c_size_t
|
|
409
|
+
dll.Everything3_GetResultListCount.argtypes = [ctypes.c_void_p]
|
|
410
|
+
|
|
411
|
+
dll.Everything3_GetResultListViewportCount.restype = ctypes.c_size_t
|
|
412
|
+
dll.Everything3_GetResultListViewportCount.argtypes = [
|
|
413
|
+
ctypes.c_void_p,
|
|
414
|
+
]
|
|
415
|
+
|
|
416
|
+
# Result property accessors
|
|
417
|
+
dll.Everything3_GetResultPropertyUINT64.restype = ctypes.c_uint64
|
|
418
|
+
dll.Everything3_GetResultPropertyUINT64.argtypes = [
|
|
419
|
+
ctypes.c_void_p, ctypes.c_size_t, wintypes.DWORD,
|
|
420
|
+
]
|
|
421
|
+
|
|
422
|
+
dll.Everything3_GetResultPropertyDWORD.restype = wintypes.DWORD
|
|
423
|
+
dll.Everything3_GetResultPropertyDWORD.argtypes = [
|
|
424
|
+
ctypes.c_void_p, ctypes.c_size_t, wintypes.DWORD,
|
|
425
|
+
]
|
|
426
|
+
|
|
427
|
+
dll.Everything3_GetResultPropertyTextW.restype = ctypes.c_size_t
|
|
428
|
+
dll.Everything3_GetResultPropertyTextW.argtypes = [
|
|
429
|
+
ctypes.c_void_p, ctypes.c_size_t, wintypes.DWORD,
|
|
430
|
+
ctypes.c_wchar_p, ctypes.c_size_t,
|
|
431
|
+
]
|
|
432
|
+
|
|
433
|
+
dll.Everything3_IsFolderResult.restype = wintypes.BOOL
|
|
434
|
+
dll.Everything3_IsFolderResult.argtypes = [
|
|
435
|
+
ctypes.c_void_p, ctypes.c_size_t,
|
|
436
|
+
]
|
|
437
|
+
|
|
438
|
+
dll.Everything3_GetResultFullPathNameW.restype = ctypes.c_size_t
|
|
439
|
+
dll.Everything3_GetResultFullPathNameW.argtypes = [
|
|
440
|
+
ctypes.c_void_p, ctypes.c_size_t, ctypes.c_wchar_p,
|
|
441
|
+
ctypes.c_size_t,
|
|
442
|
+
]
|
|
443
|
+
|
|
444
|
+
# Folder size query
|
|
445
|
+
dll.Everything3_GetFolderSizeFromFilenameW.restype = ctypes.c_uint64
|
|
446
|
+
dll.Everything3_GetFolderSizeFromFilenameW.argtypes = [
|
|
447
|
+
ctypes.c_void_p, ctypes.c_wchar_p,
|
|
448
|
+
]
|
|
449
|
+
|
|
450
|
+
# ------------------------------------------------------------------
|
|
451
|
+
# Public connection API
|
|
452
|
+
# ------------------------------------------------------------------
|
|
453
|
+
|
|
454
|
+
def connect(self, version="1.5.0.1409a"):
|
|
455
|
+
"""Connect to a running Everything instance.
|
|
456
|
+
|
|
457
|
+
Args:
|
|
458
|
+
version: API version string to request (e.g. ``"1.5.0.1409a"``).
|
|
459
|
+
|
|
460
|
+
Returns:
|
|
461
|
+
*self*, to allow chaining with the constructor.
|
|
462
|
+
|
|
463
|
+
Raises:
|
|
464
|
+
EverythingError: If the connection attempt fails.
|
|
465
|
+
"""
|
|
466
|
+
self._client = self._dll.Everything3_ConnectW(version)
|
|
467
|
+
if not self._client:
|
|
468
|
+
error = self._dll.Everything3_GetLastError()
|
|
469
|
+
raise EverythingError(error)
|
|
470
|
+
return self
|
|
471
|
+
|
|
472
|
+
def disconnect(self):
|
|
473
|
+
"""Gracefully disconnect and release the client handle."""
|
|
474
|
+
if self._client:
|
|
475
|
+
self._dll.Everything3_DestroyClient(self._client)
|
|
476
|
+
self._client = None
|
|
477
|
+
|
|
478
|
+
# Context-manager support
|
|
479
|
+
|
|
480
|
+
def __enter__(self):
|
|
481
|
+
return self
|
|
482
|
+
|
|
483
|
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
484
|
+
self.disconnect()
|
|
485
|
+
|
|
486
|
+
# ------------------------------------------------------------------
|
|
487
|
+
# Informational properties
|
|
488
|
+
# ------------------------------------------------------------------
|
|
489
|
+
|
|
490
|
+
@property
|
|
491
|
+
def version(self):
|
|
492
|
+
"""Short version string, e.g. ``"1.5"``."""
|
|
493
|
+
if not self._client:
|
|
494
|
+
raise RuntimeError("Not connected to Everything")
|
|
495
|
+
major = self._dll.Everything3_GetMajorVersion(self._client)
|
|
496
|
+
minor = self._dll.Everything3_GetMinorVersion(self._client)
|
|
497
|
+
return f"{major}.{minor}"
|
|
498
|
+
|
|
499
|
+
@property
|
|
500
|
+
def full_version(self):
|
|
501
|
+
"""Full version string including revision and build, e.g.
|
|
502
|
+
``"1.5.0.1234"``."""
|
|
503
|
+
if not self._client:
|
|
504
|
+
raise RuntimeError("Not connected to Everything")
|
|
505
|
+
major = self._dll.Everything3_GetMajorVersion(self._client)
|
|
506
|
+
minor = self._dll.Everything3_GetMinorVersion(self._client)
|
|
507
|
+
revision = self._dll.Everything3_GetRevision(self._client)
|
|
508
|
+
build = self._dll.Everything3_GetBuildNumber(self._client)
|
|
509
|
+
return f"{major}.{minor}.{revision}.{build}"
|
|
510
|
+
|
|
511
|
+
def is_db_loaded(self):
|
|
512
|
+
"""Return ``True`` if the Everything database has finished
|
|
513
|
+
loading."""
|
|
514
|
+
if not self._client:
|
|
515
|
+
raise RuntimeError("Not connected to Everything")
|
|
516
|
+
return bool(self._dll.Everything3_IsDBLoaded(self._client))
|
|
517
|
+
|
|
518
|
+
def get_target_machine(self):
|
|
519
|
+
"""Return the target machine architecture code (0 = x86, 1 =
|
|
520
|
+
x64)."""
|
|
521
|
+
if not self._client:
|
|
522
|
+
raise RuntimeError("Not connected to Everything")
|
|
523
|
+
return self._dll.Everything3_GetTargetMachine(self._client)
|
|
524
|
+
|
|
525
|
+
# ------------------------------------------------------------------
|
|
526
|
+
# Search
|
|
527
|
+
# ------------------------------------------------------------------
|
|
528
|
+
|
|
529
|
+
def search(self, search_text, match_path=False, match_case=False,
|
|
530
|
+
match_whole_word=False, regex=False, properties=None,
|
|
531
|
+
sort=None, max_results=None, offset=None):
|
|
532
|
+
"""Execute an Everything search query.
|
|
533
|
+
|
|
534
|
+
Args:
|
|
535
|
+
search_text: Everything query string (e.g. ``"*.txt"``,
|
|
536
|
+
``parent:"C:\\\\Users"``).
|
|
537
|
+
match_path: Match against full file paths as well as names.
|
|
538
|
+
match_case: Perform a case-sensitive match.
|
|
539
|
+
match_whole_word: Only match whole words.
|
|
540
|
+
regex: Treat *search_text* as a regular expression.
|
|
541
|
+
properties: List of :class:`PropertyID` values to request.
|
|
542
|
+
Defaults to NAME, PATH, SIZE, DATE_CREATED, DATE_MODIFIED,
|
|
543
|
+
ATTRIBUTES, and EXTENSION.
|
|
544
|
+
sort: List of ``(PropertyID, ascending)`` tuples for
|
|
545
|
+
server-side result ordering.
|
|
546
|
+
max_results: Maximum number of results to return (viewport
|
|
547
|
+
count).
|
|
548
|
+
offset: Result offset for pagination.
|
|
549
|
+
|
|
550
|
+
Returns:
|
|
551
|
+
A tuple ``(results, total_count)`` where *results* is a list
|
|
552
|
+
of :class:`SearchResult` instances.
|
|
553
|
+
|
|
554
|
+
Raises:
|
|
555
|
+
RuntimeError: If the client is not connected.
|
|
556
|
+
EverythingError: If the DLL reports an error during the search.
|
|
557
|
+
"""
|
|
558
|
+
if not self._client:
|
|
559
|
+
raise RuntimeError("Not connected to Everything")
|
|
560
|
+
|
|
561
|
+
if properties is None:
|
|
562
|
+
properties = [
|
|
563
|
+
PropertyID.NAME, PropertyID.PATH, PropertyID.SIZE,
|
|
564
|
+
PropertyID.DATE_CREATED, PropertyID.DATE_MODIFIED,
|
|
565
|
+
PropertyID.ATTRIBUTES, PropertyID.EXTENSION,
|
|
566
|
+
]
|
|
567
|
+
|
|
568
|
+
search_state = self._dll.Everything3_CreateSearchState()
|
|
569
|
+
if not search_state:
|
|
570
|
+
raise RuntimeError("Failed to create search state")
|
|
571
|
+
|
|
572
|
+
try:
|
|
573
|
+
# Configure search options
|
|
574
|
+
self._dll.Everything3_SetSearchTextW(search_state, search_text)
|
|
575
|
+
self._dll.Everything3_SetSearchMatchPath(
|
|
576
|
+
search_state, match_path
|
|
577
|
+
)
|
|
578
|
+
self._dll.Everything3_SetSearchMatchCase(
|
|
579
|
+
search_state, match_case
|
|
580
|
+
)
|
|
581
|
+
self._dll.Everything3_SetSearchMatchWholeWords(
|
|
582
|
+
search_state, match_whole_word
|
|
583
|
+
)
|
|
584
|
+
self._dll.Everything3_SetSearchRegex(search_state, regex)
|
|
585
|
+
|
|
586
|
+
# Pagination
|
|
587
|
+
if max_results is not None:
|
|
588
|
+
self._dll.Everything3_SetSearchViewportCount(
|
|
589
|
+
search_state, max_results
|
|
590
|
+
)
|
|
591
|
+
if offset is not None:
|
|
592
|
+
self._dll.Everything3_SetSearchViewportOffset(
|
|
593
|
+
search_state, offset
|
|
594
|
+
)
|
|
595
|
+
|
|
596
|
+
# Request specific properties
|
|
597
|
+
for prop_id in properties:
|
|
598
|
+
self._dll.Everything3_AddSearchPropertyRequest(
|
|
599
|
+
search_state, prop_id
|
|
600
|
+
)
|
|
601
|
+
|
|
602
|
+
# Server-side sorting
|
|
603
|
+
if sort:
|
|
604
|
+
self._dll.Everything3_ClearSearchSorts(search_state)
|
|
605
|
+
for prop_id, ascending in sort:
|
|
606
|
+
self._dll.Everything3_AddSearchSort(
|
|
607
|
+
search_state, prop_id, ascending
|
|
608
|
+
)
|
|
609
|
+
|
|
610
|
+
# Execute
|
|
611
|
+
result_list = self._dll.Everything3_Search(
|
|
612
|
+
self._client, search_state
|
|
613
|
+
)
|
|
614
|
+
if not result_list:
|
|
615
|
+
error = self._dll.Everything3_GetLastError()
|
|
616
|
+
raise EverythingError(error)
|
|
617
|
+
|
|
618
|
+
try:
|
|
619
|
+
return self._parse_results(result_list, max_results)
|
|
620
|
+
finally:
|
|
621
|
+
self._dll.Everything3_DestroyResultList(result_list)
|
|
622
|
+
finally:
|
|
623
|
+
self._dll.Everything3_DestroySearchState(search_state)
|
|
624
|
+
|
|
625
|
+
# ------------------------------------------------------------------
|
|
626
|
+
# Internal result parsing
|
|
627
|
+
# ------------------------------------------------------------------
|
|
628
|
+
|
|
629
|
+
def _parse_results(self, result_list, max_results=None):
|
|
630
|
+
"""Convert a raw DLL result list into Python :class:`SearchResult`
|
|
631
|
+
objects.
|
|
632
|
+
|
|
633
|
+
Args:
|
|
634
|
+
result_list: Opaque pointer returned by ``Everything3_Search``.
|
|
635
|
+
max_results: Optional cap on how many results to extract.
|
|
636
|
+
|
|
637
|
+
Returns:
|
|
638
|
+
A tuple ``(results, total_count)``.
|
|
639
|
+
"""
|
|
640
|
+
num_results = self._dll.Everything3_GetResultListViewportCount(
|
|
641
|
+
result_list
|
|
642
|
+
)
|
|
643
|
+
total_results = self._dll.Everything3_GetResultListCount(
|
|
644
|
+
result_list
|
|
645
|
+
)
|
|
646
|
+
|
|
647
|
+
if max_results is not None:
|
|
648
|
+
num_results = min(num_results, max_results)
|
|
649
|
+
|
|
650
|
+
# Pre-allocate reusable buffers to avoid per-iteration allocations
|
|
651
|
+
name_buf = ctypes.create_unicode_buffer(260)
|
|
652
|
+
path_buf = ctypes.create_unicode_buffer(1024)
|
|
653
|
+
ext_buf = ctypes.create_unicode_buffer(64)
|
|
654
|
+
|
|
655
|
+
results = []
|
|
656
|
+
for i in range(num_results):
|
|
657
|
+
is_folder = bool(
|
|
658
|
+
self._dll.Everything3_IsFolderResult(result_list, i)
|
|
659
|
+
)
|
|
660
|
+
|
|
661
|
+
# File name
|
|
662
|
+
self._dll.Everything3_GetResultPropertyTextW(
|
|
663
|
+
result_list, i, PropertyID.NAME, name_buf, 260
|
|
664
|
+
)
|
|
665
|
+
file_name = name_buf.value
|
|
666
|
+
|
|
667
|
+
# Parent directory path
|
|
668
|
+
self._dll.Everything3_GetResultPropertyTextW(
|
|
669
|
+
result_list, i, PropertyID.PATH, path_buf, 1024
|
|
670
|
+
)
|
|
671
|
+
parent_path = path_buf.value
|
|
672
|
+
|
|
673
|
+
if parent_path and not parent_path.endswith("\\"):
|
|
674
|
+
parent_path += "\\"
|
|
675
|
+
full_path = os.path.join(parent_path, file_name)
|
|
676
|
+
|
|
677
|
+
# Numeric properties
|
|
678
|
+
size_val = self._dll.Everything3_GetResultPropertyUINT64(
|
|
679
|
+
result_list, i, PropertyID.SIZE
|
|
680
|
+
)
|
|
681
|
+
date_modified = self._dll.Everything3_GetResultPropertyUINT64(
|
|
682
|
+
result_list, i, PropertyID.DATE_MODIFIED
|
|
683
|
+
)
|
|
684
|
+
date_created = self._dll.Everything3_GetResultPropertyUINT64(
|
|
685
|
+
result_list, i, PropertyID.DATE_CREATED
|
|
686
|
+
)
|
|
687
|
+
date_accessed = self._dll.Everything3_GetResultPropertyUINT64(
|
|
688
|
+
result_list, i, PropertyID.DATE_ACCESSED
|
|
689
|
+
)
|
|
690
|
+
attrs_val = self._dll.Everything3_GetResultPropertyDWORD(
|
|
691
|
+
result_list, i, PropertyID.ATTRIBUTES
|
|
692
|
+
)
|
|
693
|
+
|
|
694
|
+
# Extension (files only — folders return an empty string)
|
|
695
|
+
extension = ""
|
|
696
|
+
if not is_folder:
|
|
697
|
+
self._dll.Everything3_GetResultPropertyTextW(
|
|
698
|
+
result_list, i, PropertyID.EXTENSION, ext_buf, 64
|
|
699
|
+
)
|
|
700
|
+
extension = ext_buf.value
|
|
701
|
+
|
|
702
|
+
results.append(SearchResult(
|
|
703
|
+
name=file_name,
|
|
704
|
+
parent_path=parent_path,
|
|
705
|
+
full_path=full_path,
|
|
706
|
+
size=size_val,
|
|
707
|
+
is_folder=is_folder,
|
|
708
|
+
date_modified=date_modified,
|
|
709
|
+
date_created=date_created,
|
|
710
|
+
date_accessed=date_accessed,
|
|
711
|
+
attributes=attrs_val,
|
|
712
|
+
extension=extension,
|
|
713
|
+
))
|
|
714
|
+
|
|
715
|
+
return results, total_results
|
|
716
|
+
|
|
717
|
+
# ------------------------------------------------------------------
|
|
718
|
+
# Folder size helper
|
|
719
|
+
# ------------------------------------------------------------------
|
|
720
|
+
|
|
721
|
+
def get_folder_size(self, folder_path):
|
|
722
|
+
"""Retrieve the on-disk size of a folder by querying Everything.
|
|
723
|
+
|
|
724
|
+
Args:
|
|
725
|
+
folder_path: Absolute path to the folder.
|
|
726
|
+
|
|
727
|
+
Returns:
|
|
728
|
+
Size in bytes.
|
|
729
|
+
"""
|
|
730
|
+
if not self._client:
|
|
731
|
+
raise RuntimeError("Not connected to Everything")
|
|
732
|
+
return self._dll.Everything3_GetFolderSizeFromFilenameW(
|
|
733
|
+
self._client, folder_path
|
|
734
|
+
)
|
|
735
|
+
|
|
736
|
+
|
|
737
|
+
# ------------------------------------------------------------------
|
|
738
|
+
# Standalone utility
|
|
739
|
+
# ------------------------------------------------------------------
|
|
740
|
+
|
|
741
|
+
def format_size(size_bytes):
|
|
742
|
+
"""Format a byte count into a human-readable string.
|
|
743
|
+
|
|
744
|
+
Examples::
|
|
745
|
+
|
|
746
|
+
>>> format_size(1024)
|
|
747
|
+
'1.00 KB'
|
|
748
|
+
>>> format_size(1073741824)
|
|
749
|
+
'1.00 GB'
|
|
750
|
+
"""
|
|
751
|
+
if size_bytes == 0:
|
|
752
|
+
return "0 B"
|
|
753
|
+
for unit in ("B", "KB", "MB", "GB", "TB"):
|
|
754
|
+
if size_bytes < 1024.0:
|
|
755
|
+
return f"{size_bytes:.2f} {unit}"
|
|
756
|
+
size_bytes /= 1024.0
|
|
757
|
+
return f"{size_bytes:.2f} PB"
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: everything-sdk
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Python wrapper for the Windows Everything SDK (v3)
|
|
5
|
+
Home-page:
|
|
6
|
+
Author: kinsurfong
|
|
7
|
+
License: MIT
|
|
8
|
+
Project-URL: Homepage, https://github.com/firesurfing/everything-sdk-python
|
|
9
|
+
Project-URL: Documentation, https://github.com/firesurfing/everything-sdk-python#readme
|
|
10
|
+
Project-URL: Issues, https://github.com/firesurfing/everything-sdk-python/issues
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
14
|
+
Classifier: Development Status :: 4 - Beta
|
|
15
|
+
Classifier: Intended Audience :: Developers
|
|
16
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
17
|
+
Requires-Python: >=3.7
|
|
18
|
+
Description-Content-Type: text/markdown
|
|
19
|
+
License-File: LICENSE
|
|
20
|
+
Dynamic: license-file
|
|
21
|
+
Dynamic: requires-python
|
|
22
|
+
|
|
23
|
+
# Everything SDK Python
|
|
24
|
+
|
|
25
|
+
Python wrapper for the Windows Everything SDK (v3). Provides a clean, Pythonic interface to search files and folders using the [Everything](https://www.voidtools.com/) search engine.
|
|
26
|
+
|
|
27
|
+
[中文文档](README_CN.md)
|
|
28
|
+
|
|
29
|
+
## Requirements
|
|
30
|
+
|
|
31
|
+
- Windows OS
|
|
32
|
+
- Python 3.7+
|
|
33
|
+
- [Everything](https://www.voidtools.com/) application running (v1.5.0.1409a recommended)
|
|
34
|
+
- Everything SDK v3 DLL (`Everything3_x64.dll`)
|
|
35
|
+
|
|
36
|
+
### Getting the SDK
|
|
37
|
+
|
|
38
|
+
Download SDK v3 from the Everything official forum: [SDK Download](https://www.voidtools.com/forum/viewtopic.php?t=15853&sid=b9bf71c12ae48b33567ab9f8dafdaccc)
|
|
39
|
+
|
|
40
|
+
Recommended version: **Everything SDK v3** (bundled with Everything 1.5.0.1409a)
|
|
41
|
+
|
|
42
|
+
### Getting Everything 1.5
|
|
43
|
+
|
|
44
|
+
Download Everything 1.5 from the official site: [Everything 1.5 Download](https://www.voidtools.com/everything-1.5/)
|
|
45
|
+
|
|
46
|
+
> Note: This library requires the Everything application to be running.
|
|
47
|
+
|
|
48
|
+
## Installation
|
|
49
|
+
|
|
50
|
+
### From source
|
|
51
|
+
|
|
52
|
+
Download or clone the project repository, then:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
cd everything-sdk-python
|
|
56
|
+
pip install -e .
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Direct usage
|
|
60
|
+
|
|
61
|
+
Copy the `src/everything` folder to your project and import directly.
|
|
62
|
+
|
|
63
|
+
## Quick Start
|
|
64
|
+
|
|
65
|
+
```python
|
|
66
|
+
from everything import EverythingClient, PropertyID, format_size
|
|
67
|
+
|
|
68
|
+
with EverythingClient() as client:
|
|
69
|
+
client.connect("1.5")
|
|
70
|
+
print(f"Everything version: {client.version}")
|
|
71
|
+
|
|
72
|
+
# Search files in a directory
|
|
73
|
+
results, total = client.search('parent:"D:\\\\test"', match_path=True)
|
|
74
|
+
print(f"Found {len(results)} results (total: {total})")
|
|
75
|
+
|
|
76
|
+
for r in results:
|
|
77
|
+
if r.is_folder:
|
|
78
|
+
size = client.get_folder_size(r.full_path)
|
|
79
|
+
else:
|
|
80
|
+
size = r.size
|
|
81
|
+
print(f"{r.name}: {format_size(size)}")
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## API Reference
|
|
85
|
+
|
|
86
|
+
### EverythingClient
|
|
87
|
+
|
|
88
|
+
#### `__init__(dll_path=None)`
|
|
89
|
+
|
|
90
|
+
Initialize the client. DLL discovery order:
|
|
91
|
+
|
|
92
|
+
1. If `dll_path` is specified, use it directly
|
|
93
|
+
2. Check `EVERYTHING_SDK_DIR` environment variable, use `<SDK_DIR>/dll/Everything3_x64.dll`
|
|
94
|
+
3. Search all directories in `PATH` environment variable for `Everything3_x64.dll`
|
|
95
|
+
|
|
96
|
+
#### `connect(version="1.5a")`
|
|
97
|
+
|
|
98
|
+
Connect to the Everything application. Raises `EverythingError` if connection fails.
|
|
99
|
+
|
|
100
|
+
#### `disconnect()`
|
|
101
|
+
|
|
102
|
+
Disconnect from Everything.
|
|
103
|
+
|
|
104
|
+
#### Context Manager
|
|
105
|
+
|
|
106
|
+
Supports `with` statement for automatic connection management:
|
|
107
|
+
|
|
108
|
+
```python
|
|
109
|
+
with EverythingClient() as client:
|
|
110
|
+
client.connect("1.5a")
|
|
111
|
+
# ... use client
|
|
112
|
+
# automatically disconnected
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
#### `version` (property)
|
|
116
|
+
|
|
117
|
+
Returns the Everything version string, e.g., `"1.5"`.
|
|
118
|
+
|
|
119
|
+
#### `full_version` (property)
|
|
120
|
+
|
|
121
|
+
Returns the full version string including major, minor, revision and build number, e.g., `"1.5.0.1234"`.
|
|
122
|
+
|
|
123
|
+
#### `is_db_loaded()`
|
|
124
|
+
|
|
125
|
+
Check if the Everything database has finished loading.
|
|
126
|
+
|
|
127
|
+
#### `get_target_machine()`
|
|
128
|
+
|
|
129
|
+
Get the target machine architecture (x86 or x64).
|
|
130
|
+
|
|
131
|
+
#### `search(search_text, match_path=False, match_case=False, match_whole_word=False, regex=False, properties=None, sort=None, max_results=None, offset=None)`
|
|
132
|
+
|
|
133
|
+
Execute a search.
|
|
134
|
+
|
|
135
|
+
- `search_text`: Everything search query (e.g., `parent:"D:\\test"`, `*.txt`, etc.)
|
|
136
|
+
- `match_path`: Whether to match against full paths
|
|
137
|
+
- `match_case`: Whether to match case
|
|
138
|
+
- `match_whole_word`: Whether to match whole words
|
|
139
|
+
- `regex`: Whether to use regular expressions
|
|
140
|
+
- `properties`: List of `PropertyID` values to retrieve. Defaults to NAME, PATH, SIZE, DATE_CREATED, DATE_MODIFIED, ATTRIBUTES, EXTENSION.
|
|
141
|
+
- `sort`: List of `(PropertyID, ascending)` tuples for server-side sorting.
|
|
142
|
+
- `max_results`: Maximum number of results to return.
|
|
143
|
+
- `offset`: Result offset for pagination.
|
|
144
|
+
|
|
145
|
+
Returns: `(results_list, total_count)` tuple.
|
|
146
|
+
|
|
147
|
+
#### `get_folder_size(folder_path)`
|
|
148
|
+
|
|
149
|
+
Get the actual size of a folder by querying Everything. Returns size in bytes.
|
|
150
|
+
|
|
151
|
+
### SearchResult
|
|
152
|
+
|
|
153
|
+
Represents a single search result with the following attributes:
|
|
154
|
+
|
|
155
|
+
- `name`: File/folder name
|
|
156
|
+
- `parent_path`: Parent directory path
|
|
157
|
+
- `full_path`: Full file/folder path
|
|
158
|
+
- `size`: Size in bytes (for files; folders may show 0 - use `get_folder_size` instead)
|
|
159
|
+
- `is_folder`: Boolean indicating if it's a folder
|
|
160
|
+
- `date_modified`: FILETIME timestamp
|
|
161
|
+
- `date_created`: FILETIME timestamp
|
|
162
|
+
- `date_accessed`: FILETIME timestamp
|
|
163
|
+
- `attributes`: File attribute bitmask
|
|
164
|
+
- `extension`: File extension (without dot)
|
|
165
|
+
|
|
166
|
+
Properties:
|
|
167
|
+
- `type_str`: `"File"` or `"Folder"`
|
|
168
|
+
- `modified_time`: Python `datetime` object
|
|
169
|
+
- `created_time`: Python `datetime` object
|
|
170
|
+
- `accessed_time`: Python `datetime` object
|
|
171
|
+
- `attr_str`: Human-readable attribute string (e.g., `"DA"`)
|
|
172
|
+
|
|
173
|
+
### PropertyID
|
|
174
|
+
|
|
175
|
+
Constants for all available property IDs:
|
|
176
|
+
|
|
177
|
+
```python
|
|
178
|
+
PropertyID.NAME # 0
|
|
179
|
+
PropertyID.PATH # 1
|
|
180
|
+
PropertyID.SIZE # 2
|
|
181
|
+
PropertyID.EXTENSION # 3
|
|
182
|
+
PropertyID.TYPE # 4
|
|
183
|
+
PropertyID.DATE_MODIFIED # 5
|
|
184
|
+
PropertyID.DATE_CREATED # 6
|
|
185
|
+
PropertyID.DATE_ACCESSED # 7
|
|
186
|
+
PropertyID.ATTRIBUTES # 8
|
|
187
|
+
# ... and more
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
### format_size(size_bytes)
|
|
191
|
+
|
|
192
|
+
Format bytes into human-readable string:
|
|
193
|
+
|
|
194
|
+
```python
|
|
195
|
+
format_size(1024) # "1.00 KB"
|
|
196
|
+
format_size(1048576) # "1.00 MB"
|
|
197
|
+
format_size(1073741824) # "1.00 GB"
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### EverythingError
|
|
201
|
+
|
|
202
|
+
Exception raised on SDK errors. Includes `error_code` attribute.
|
|
203
|
+
|
|
204
|
+
## Advanced Usage
|
|
205
|
+
|
|
206
|
+
### Custom Properties
|
|
207
|
+
|
|
208
|
+
```python
|
|
209
|
+
results, total = client.search(
|
|
210
|
+
search_text='*.txt',
|
|
211
|
+
properties=[
|
|
212
|
+
PropertyID.NAME,
|
|
213
|
+
PropertyID.PATH,
|
|
214
|
+
PropertyID.SIZE,
|
|
215
|
+
PropertyID.DATE_MODIFIED,
|
|
216
|
+
]
|
|
217
|
+
)
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
### Sorting
|
|
221
|
+
|
|
222
|
+
```python
|
|
223
|
+
# Sort by size ascending, then by name descending
|
|
224
|
+
sort = [
|
|
225
|
+
(PropertyID.SIZE, True),
|
|
226
|
+
(PropertyID.NAME, False),
|
|
227
|
+
]
|
|
228
|
+
results, total = client.search(
|
|
229
|
+
search_text='parent:"D:\\\\test"',
|
|
230
|
+
match_path=True,
|
|
231
|
+
sort=sort,
|
|
232
|
+
)
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
### Limit Results
|
|
236
|
+
|
|
237
|
+
```python
|
|
238
|
+
results, total = client.search(
|
|
239
|
+
search_text='*.pdf',
|
|
240
|
+
max_results=10,
|
|
241
|
+
)
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
## License
|
|
245
|
+
|
|
246
|
+
MIT
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
everything/__init__.py,sha256=mU7OsdiV6n2myLUeh18y6MfjweUZ3wGU9E5CvdbrZQk,775
|
|
2
|
+
everything/client.py,sha256=9MloqOEngGt4SDzY2mtr4xOZ0h8aaB1bZv6uMicHtzw,26725
|
|
3
|
+
everything_sdk-1.0.0.dist-info/licenses/LICENSE,sha256=cgElLKZ4JL3Oa5WJVzhOxzQhSBbUIpxIf12LSo2DuEc,1068
|
|
4
|
+
everything_sdk-1.0.0.dist-info/METADATA,sha256=2qZwxnEbFgOhbWZn-imIHzIZMpBKw7CfEPpC5It_vyU,6857
|
|
5
|
+
everything_sdk-1.0.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
|
|
6
|
+
everything_sdk-1.0.0.dist-info/top_level.txt,sha256=64FxbamBy6gWEhZE4npTYLGiS_tFEc_7PBr6gaxnzaA,11
|
|
7
|
+
everything_sdk-1.0.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 firesurfing
|
|
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 @@
|
|
|
1
|
+
everything
|