0
# PyWatchman
1
2
Python client library for Facebook's Watchman file watching service. Provides a simple interface to connect to and query Watchman to discover file system changes efficiently.
3
4
## Package Information
5
6
- **Package Name**: pywatchman
7
- **Language**: Python
8
- **Installation**: `pip install pywatchman`
9
10
## Core Imports
11
12
```python
13
import pywatchman
14
```
15
16
For binary serialization:
17
18
```python
19
from pywatchman import bser
20
```
21
22
## Basic Usage
23
24
```python
25
import pywatchman
26
27
# Create a client connection
28
client = pywatchman.client()
29
30
# Query Watchman for socket name
31
result = client.query('get-sockname')
32
print(result['sockname'])
33
34
# Watch a directory for changes
35
watch_result = client.query('watch', '/path/to/directory')
36
37
# Query for file changes
38
files = client.query('query', '/path/to/directory', {
39
'expression': ['allof', ['type', 'f'], ['suffix', 'py']],
40
'fields': ['name', 'size', 'mtime_ms']
41
})
42
43
# Handle errors
44
try:
45
result = client.query('invalid-command')
46
except pywatchman.Unavailable as e:
47
print(f"Watchman unavailable: {e}")
48
```
49
50
## Capabilities
51
52
### Client Connection
53
54
Connect to and communicate with the Watchman service via Unix domain socket.
55
56
```python { .api }
57
class client:
58
def __init__(self, sockpath=None, timeout=1.0):
59
"""
60
Create a new Watchman client.
61
62
Args:
63
sockpath (str, optional): Path to Watchman socket. If None, auto-discovered.
64
timeout (float): Connection timeout in seconds. Default: 1.0
65
"""
66
```
67
68
### Query Execution
69
70
Send commands to Watchman and receive structured responses.
71
72
```python { .api }
73
def query(self, *args):
74
"""
75
Send query to Watchman service and return result.
76
77
Args:
78
*args: Variable arguments representing the Watchman command and parameters
79
80
Returns:
81
dict: Structured response from Watchman
82
83
Raises:
84
Unavailable: When Watchman service is unavailable or command fails
85
"""
86
```
87
88
Common query patterns:
89
90
```python
91
# Get socket name
92
client.query('get-sockname')
93
94
# Watch a directory
95
client.query('watch', '/path/to/directory')
96
97
# Query files with expression
98
client.query('query', '/path/to/directory', {
99
'expression': ['allof', ['type', 'f'], ['suffix', 'py']],
100
'fields': ['name', 'size', 'mtime_ms', 'exists']
101
})
102
103
# Get version info
104
client.query('version')
105
106
# Shutdown watchman
107
client.query('shutdown-server')
108
```
109
110
### Binary Serialization
111
112
High-performance binary serialization for Watchman protocol communication.
113
114
```python { .api }
115
def dumps(obj):
116
"""
117
Serialize Python object to BSER (Binary Serialization) format.
118
119
Args:
120
obj: Python object to serialize (dict, list, str, int, float, bool, None)
121
122
Returns:
123
bytes: Binary data in BSER format
124
125
Supported types:
126
- dict, list, tuple (converted to list)
127
- str, unicode (encoded as UTF-8)
128
- int, float, bool, None
129
"""
130
131
def loads(data):
132
"""
133
Deserialize BSER binary data to Python object.
134
135
Args:
136
data (bytes): Binary data in BSER format
137
138
Returns:
139
Python object (dict, list, str, int, float, bool, None)
140
141
Raises:
142
ValueError: On invalid BSER data
143
"""
144
145
def pdu_len(data):
146
"""
147
Extract PDU (Protocol Data Unit) length from BSER header.
148
149
Args:
150
data (bytes): Binary data containing BSER PDU header (minimum 13 bytes)
151
152
Returns:
153
int: Length of complete PDU for reading from socket
154
"""
155
```
156
157
Example binary serialization usage:
158
159
```python
160
from pywatchman import bser
161
162
# Serialize data
163
query_data = {'expression': ['type', 'f'], 'fields': ['name']}
164
serialized = bser.dumps(query_data)
165
166
# Deserialize response
167
response_data = bser.loads(serialized)
168
169
# Get PDU length for socket reading
170
pdu_length = bser.pdu_len(serialized[:13])
171
```
172
173
### Error Handling
174
175
Handle connection failures and service unavailability.
176
177
```python { .api }
178
class Unavailable(Exception):
179
"""
180
Exception raised when Watchman service is unavailable.
181
182
Raised in cases of:
183
- Connection failures to Watchman socket
184
- Watchman executable not found in PATH
185
- Socket communication timeouts
186
- Watchman command errors
187
- Invalid response data
188
"""
189
```
190
191
Error handling patterns:
192
193
```python
194
try:
195
client = pywatchman.client()
196
result = client.query('watch', '/nonexistent/path')
197
except pywatchman.Unavailable as e:
198
if 'executable not in PATH' in str(e):
199
print("Watchman is not installed")
200
elif 'unable to connect' in str(e):
201
print("Watchman service is not running")
202
elif 'timed out' in str(e):
203
print("Connection timed out")
204
else:
205
print(f"Watchman error: {e}")
206
```
207
208
## Types
209
210
```python { .api }
211
# Response structure for typical Watchman queries
212
QueryResponse = dict[str, Any] # Contains 'files', 'clock', 'is_fresh_instance', etc.
213
214
# File information structure
215
FileInfo = dict[str, Any] # Contains 'name', 'size', 'mtime_ms', 'exists', etc.
216
217
# Watch response structure
218
WatchResponse = dict[str, Any] # Contains 'watch', 'watcher', etc.
219
220
# Version response structure
221
VersionResponse = dict[str, Any] # Contains 'version', 'buildinfo', etc.
222
```
223
224
## Constants
225
226
```python { .api }
227
sniff_len = 13 # PDU header length for protocol detection
228
```
229
230
## External Dependencies
231
232
- **System Requirements**: Watchman service must be installed and running
233
- **Python Standard Library**: os, errno, socket, subprocess
234
- **Native Extension**: Compiled C extension (bser.c) for binary serialization