hgext/fsmonitor/pywatchman/__init__.py
author Matt Harbison <matt_harbison@yahoo.com>
Sun, 23 Sep 2018 00:47:04 -0400
changeset 39826 c31ce080eb75
parent 33769 dd35abc409ee
child 41968 57264906a996
permissions -rw-r--r--
py3: convert arguments, cwd and env to native strings when spawning subprocess This keeps Windows happy.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
28432
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
     1
# Copyright 2014-present Facebook, Inc.
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
     2
# All rights reserved.
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
     3
#
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
     4
# Redistribution and use in source and binary forms, with or without
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
     5
# modification, are permitted provided that the following conditions are met:
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
     6
#
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
     7
#  * Redistributions of source code must retain the above copyright notice,
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
     8
#    this list of conditions and the following disclaimer.
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
     9
#
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    10
#  * Redistributions in binary form must reproduce the above copyright notice,
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    11
#    this list of conditions and the following disclaimer in the documentation
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    12
#    and/or other materials provided with the distribution.
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    13
#
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    14
#  * Neither the name Facebook nor the names of its contributors may be used to
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    15
#    endorse or promote products derived from this software without specific
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    16
#    prior written permission.
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    17
#
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    18
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    19
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    20
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    21
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    22
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    23
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    24
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    25
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    26
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    27
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    28
30656
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
    29
from __future__ import absolute_import
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
    30
from __future__ import division
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
    31
from __future__ import print_function
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
    32
# no unicode literals
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
    33
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
    34
import inspect
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
    35
import math
28432
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    36
import os
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    37
import socket
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    38
import subprocess
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    39
import time
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    40
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    41
# Sometimes it's really hard to get Python extensions to compile,
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    42
# so fall back to a pure Python implementation.
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    43
try:
30656
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
    44
    from . import bser
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
    45
    # Demandimport causes modules to be loaded lazily. Force the load now
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
    46
    # so that we can fall back on pybser if bser doesn't exist
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
    47
    bser.pdu_info
28432
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    48
except ImportError:
30656
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
    49
    from . import pybser as bser
28432
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    50
39826
c31ce080eb75 py3: convert arguments, cwd and env to native strings when spawning subprocess
Matt Harbison <matt_harbison@yahoo.com>
parents: 33769
diff changeset
    51
from mercurial.utils import (
c31ce080eb75 py3: convert arguments, cwd and env to native strings when spawning subprocess
Matt Harbison <matt_harbison@yahoo.com>
parents: 33769
diff changeset
    52
    procutil,
c31ce080eb75 py3: convert arguments, cwd and env to native strings when spawning subprocess
Matt Harbison <matt_harbison@yahoo.com>
parents: 33769
diff changeset
    53
)
c31ce080eb75 py3: convert arguments, cwd and env to native strings when spawning subprocess
Matt Harbison <matt_harbison@yahoo.com>
parents: 33769
diff changeset
    54
c31ce080eb75 py3: convert arguments, cwd and env to native strings when spawning subprocess
Matt Harbison <matt_harbison@yahoo.com>
parents: 33769
diff changeset
    55
from mercurial import (
c31ce080eb75 py3: convert arguments, cwd and env to native strings when spawning subprocess
Matt Harbison <matt_harbison@yahoo.com>
parents: 33769
diff changeset
    56
    pycompat,
c31ce080eb75 py3: convert arguments, cwd and env to native strings when spawning subprocess
Matt Harbison <matt_harbison@yahoo.com>
parents: 33769
diff changeset
    57
)
c31ce080eb75 py3: convert arguments, cwd and env to native strings when spawning subprocess
Matt Harbison <matt_harbison@yahoo.com>
parents: 33769
diff changeset
    58
30656
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
    59
from . import (
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
    60
    capabilities,
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
    61
    compat,
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
    62
    encoding,
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
    63
    load,
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
    64
)
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
    65
28432
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    66
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    67
if os.name == 'nt':
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    68
    import ctypes
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    69
    import ctypes.wintypes
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    70
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    71
    wintypes = ctypes.wintypes
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    72
    GENERIC_READ = 0x80000000
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    73
    GENERIC_WRITE = 0x40000000
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    74
    FILE_FLAG_OVERLAPPED = 0x40000000
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    75
    OPEN_EXISTING = 3
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    76
    INVALID_HANDLE_VALUE = -1
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    77
    FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    78
    FORMAT_MESSAGE_ALLOCATE_BUFFER = 0x00000100
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    79
    FORMAT_MESSAGE_IGNORE_INSERTS = 0x00000200
30656
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
    80
    WAIT_FAILED = 0xFFFFFFFF
28432
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    81
    WAIT_TIMEOUT = 0x00000102
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    82
    WAIT_OBJECT_0 = 0x00000000
30656
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
    83
    WAIT_IO_COMPLETION = 0x000000C0
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
    84
    INFINITE = 0xFFFFFFFF
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
    85
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
    86
    # Overlapped I/O operation is in progress. (997)
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
    87
    ERROR_IO_PENDING = 0x000003E5
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
    88
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
    89
    # The pointer size follows the architecture
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
    90
    # We use WPARAM since this type is already conditionally defined
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
    91
    ULONG_PTR = ctypes.wintypes.WPARAM
28432
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    92
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    93
    class OVERLAPPED(ctypes.Structure):
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    94
        _fields_ = [
30656
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
    95
            ("Internal", ULONG_PTR), ("InternalHigh", ULONG_PTR),
28432
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    96
            ("Offset", wintypes.DWORD), ("OffsetHigh", wintypes.DWORD),
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    97
            ("hEvent", wintypes.HANDLE)
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    98
        ]
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
    99
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   100
        def __init__(self):
30656
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   101
            self.Internal = 0
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   102
            self.InternalHigh = 0
28432
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   103
            self.Offset = 0
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   104
            self.OffsetHigh = 0
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   105
            self.hEvent = 0
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   106
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   107
    LPDWORD = ctypes.POINTER(wintypes.DWORD)
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   108
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   109
    CreateFile = ctypes.windll.kernel32.CreateFileA
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   110
    CreateFile.argtypes = [wintypes.LPSTR, wintypes.DWORD, wintypes.DWORD,
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   111
                           wintypes.LPVOID, wintypes.DWORD, wintypes.DWORD,
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   112
                           wintypes.HANDLE]
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   113
    CreateFile.restype = wintypes.HANDLE
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   114
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   115
    CloseHandle = ctypes.windll.kernel32.CloseHandle
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   116
    CloseHandle.argtypes = [wintypes.HANDLE]
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   117
    CloseHandle.restype = wintypes.BOOL
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   118
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   119
    ReadFile = ctypes.windll.kernel32.ReadFile
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   120
    ReadFile.argtypes = [wintypes.HANDLE, wintypes.LPVOID, wintypes.DWORD,
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   121
                         LPDWORD, ctypes.POINTER(OVERLAPPED)]
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   122
    ReadFile.restype = wintypes.BOOL
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   123
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   124
    WriteFile = ctypes.windll.kernel32.WriteFile
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   125
    WriteFile.argtypes = [wintypes.HANDLE, wintypes.LPVOID, wintypes.DWORD,
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   126
                          LPDWORD, ctypes.POINTER(OVERLAPPED)]
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   127
    WriteFile.restype = wintypes.BOOL
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   128
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   129
    GetLastError = ctypes.windll.kernel32.GetLastError
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   130
    GetLastError.argtypes = []
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   131
    GetLastError.restype = wintypes.DWORD
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   132
30656
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   133
    SetLastError = ctypes.windll.kernel32.SetLastError
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   134
    SetLastError.argtypes = [wintypes.DWORD]
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   135
    SetLastError.restype = None
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   136
28432
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   137
    FormatMessage = ctypes.windll.kernel32.FormatMessageA
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   138
    FormatMessage.argtypes = [wintypes.DWORD, wintypes.LPVOID, wintypes.DWORD,
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   139
                              wintypes.DWORD, ctypes.POINTER(wintypes.LPSTR),
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   140
                              wintypes.DWORD, wintypes.LPVOID]
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   141
    FormatMessage.restype = wintypes.DWORD
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   142
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   143
    LocalFree = ctypes.windll.kernel32.LocalFree
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   144
30656
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   145
    GetOverlappedResult = ctypes.windll.kernel32.GetOverlappedResult
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   146
    GetOverlappedResult.argtypes = [wintypes.HANDLE,
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   147
                                    ctypes.POINTER(OVERLAPPED), LPDWORD,
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   148
                                    wintypes.BOOL]
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   149
    GetOverlappedResult.restype = wintypes.BOOL
28432
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   150
30656
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   151
    GetOverlappedResultEx = getattr(ctypes.windll.kernel32,
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   152
                                    'GetOverlappedResultEx', None)
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   153
    if GetOverlappedResultEx is not None:
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   154
        GetOverlappedResultEx.argtypes = [wintypes.HANDLE,
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   155
                                          ctypes.POINTER(OVERLAPPED), LPDWORD,
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   156
                                          wintypes.DWORD, wintypes.BOOL]
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   157
        GetOverlappedResultEx.restype = wintypes.BOOL
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   158
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   159
    WaitForSingleObjectEx = ctypes.windll.kernel32.WaitForSingleObjectEx
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   160
    WaitForSingleObjectEx.argtypes = [wintypes.HANDLE, wintypes.DWORD, wintypes.BOOL]
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   161
    WaitForSingleObjectEx.restype = wintypes.DWORD
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   162
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   163
    CreateEvent = ctypes.windll.kernel32.CreateEventA
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   164
    CreateEvent.argtypes = [LPDWORD, wintypes.BOOL, wintypes.BOOL,
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   165
                            wintypes.LPSTR]
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   166
    CreateEvent.restype = wintypes.HANDLE
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   167
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   168
    # Windows Vista is the minimum supported client for CancelIoEx.
28432
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   169
    CancelIoEx = ctypes.windll.kernel32.CancelIoEx
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   170
    CancelIoEx.argtypes = [wintypes.HANDLE, ctypes.POINTER(OVERLAPPED)]
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   171
    CancelIoEx.restype = wintypes.BOOL
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   172
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   173
# 2 bytes marker, 1 byte int size, 8 bytes int64 value
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   174
sniff_len = 13
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   175
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   176
# This is a helper for debugging the client.
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   177
_debugging = False
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   178
if _debugging:
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   179
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   180
    def log(fmt, *args):
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   181
        print('[%s] %s' %
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   182
              (time.strftime("%a, %d %b %Y %H:%M:%S", time.gmtime()),
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   183
               fmt % args[:]))
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   184
else:
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   185
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   186
    def log(fmt, *args):
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   187
        pass
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   188
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   189
30656
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   190
def _win32_strerror(err):
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   191
    """ expand a win32 error code into a human readable message """
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   192
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   193
    # FormatMessage will allocate memory and assign it here
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   194
    buf = ctypes.c_char_p()
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   195
    FormatMessage(
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   196
        FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   197
        | FORMAT_MESSAGE_IGNORE_INSERTS, None, err, 0, buf, 0, None)
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   198
    try:
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   199
        return buf.value
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   200
    finally:
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   201
        LocalFree(buf)
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   202
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   203
28432
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   204
class WatchmanError(Exception):
30656
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   205
    def __init__(self, msg=None, cmd=None):
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   206
        self.msg = msg
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   207
        self.cmd = cmd
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   208
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   209
    def setCommand(self, cmd):
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   210
        self.cmd = cmd
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   211
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   212
    def __str__(self):
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   213
        if self.cmd:
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   214
            return '%s, while executing %s' % (self.msg, self.cmd)
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   215
        return self.msg
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   216
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   217
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   218
class WatchmanEnvironmentError(WatchmanError):
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   219
    def __init__(self, msg, errno, errmsg, cmd=None):
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   220
        super(WatchmanEnvironmentError, self).__init__(
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   221
            '{0}: errno={1} errmsg={2}'.format(msg, errno, errmsg),
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   222
            cmd)
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   223
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   224
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   225
class SocketConnectError(WatchmanError):
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   226
    def __init__(self, sockpath, exc):
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   227
        super(SocketConnectError, self).__init__(
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   228
            'unable to connect to %s: %s' % (sockpath, exc))
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   229
        self.sockpath = sockpath
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   230
        self.exc = exc
28432
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   231
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   232
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   233
class SocketTimeout(WatchmanError):
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   234
    """A specialized exception raised for socket timeouts during communication to/from watchman.
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   235
       This makes it easier to implement non-blocking loops as callers can easily distinguish
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   236
       between a routine timeout and an actual error condition.
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   237
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   238
       Note that catching WatchmanError will also catch this as it is a super-class, so backwards
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   239
       compatibility in exception handling is preserved.
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   240
    """
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   241
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   242
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   243
class CommandError(WatchmanError):
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   244
    """error returned by watchman
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   245
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   246
    self.msg is the message returned by watchman.
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   247
    """
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   248
    def __init__(self, msg, cmd=None):
30656
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   249
        super(CommandError, self).__init__(
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   250
            'watchman command error: %s' % (msg, ),
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   251
            cmd,
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   252
        )
28432
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   253
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   254
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   255
class Transport(object):
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   256
    """ communication transport to the watchman server """
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   257
    buf = None
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   258
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   259
    def close(self):
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   260
        """ tear it down """
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   261
        raise NotImplementedError()
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   262
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   263
    def readBytes(self, size):
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   264
        """ read size bytes """
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   265
        raise NotImplementedError()
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   266
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   267
    def write(self, buf):
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   268
        """ write some data """
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   269
        raise NotImplementedError()
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   270
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   271
    def setTimeout(self, value):
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   272
        pass
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   273
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   274
    def readLine(self):
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   275
        """ read a line
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   276
        Maintains its own buffer, callers of the transport should not mix
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   277
        calls to readBytes and readLine.
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   278
        """
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   279
        if self.buf is None:
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   280
            self.buf = []
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   281
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   282
        # Buffer may already have a line if we've received unilateral
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   283
        # response(s) from the server
30656
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   284
        if len(self.buf) == 1 and b"\n" in self.buf[0]:
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   285
            (line, b) = self.buf[0].split(b"\n", 1)
28432
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   286
            self.buf = [b]
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   287
            return line
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   288
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   289
        while True:
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   290
            b = self.readBytes(4096)
30656
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   291
            if b"\n" in b:
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   292
                result = b''.join(self.buf)
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   293
                (line, b) = b.split(b"\n", 1)
28432
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   294
                self.buf = [b]
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   295
                return result + line
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   296
            self.buf.append(b)
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   297
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   298
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   299
class Codec(object):
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   300
    """ communication encoding for the watchman server """
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   301
    transport = None
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   302
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   303
    def __init__(self, transport):
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   304
        self.transport = transport
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   305
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   306
    def receive(self):
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   307
        raise NotImplementedError()
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   308
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   309
    def send(self, *args):
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   310
        raise NotImplementedError()
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   311
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   312
    def setTimeout(self, value):
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   313
        self.transport.setTimeout(value)
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   314
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   315
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   316
class UnixSocketTransport(Transport):
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   317
    """ local unix domain socket transport """
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   318
    sock = None
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   319
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   320
    def __init__(self, sockpath, timeout):
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   321
        self.sockpath = sockpath
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   322
        self.timeout = timeout
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   323
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   324
        sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   325
        try:
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   326
            sock.settimeout(self.timeout)
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   327
            sock.connect(self.sockpath)
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   328
            self.sock = sock
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   329
        except socket.error as e:
30656
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   330
            sock.close()
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   331
            raise SocketConnectError(self.sockpath, e)
28432
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   332
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   333
    def close(self):
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   334
        self.sock.close()
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   335
        self.sock = None
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   336
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   337
    def setTimeout(self, value):
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   338
        self.timeout = value
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   339
        self.sock.settimeout(self.timeout)
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   340
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   341
    def readBytes(self, size):
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   342
        try:
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   343
            buf = [self.sock.recv(size)]
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   344
            if not buf[0]:
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   345
                raise WatchmanError('empty watchman response')
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   346
            return buf[0]
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   347
        except socket.timeout:
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   348
            raise SocketTimeout('timed out waiting for response')
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   349
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   350
    def write(self, data):
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   351
        try:
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   352
            self.sock.sendall(data)
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   353
        except socket.timeout:
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   354
            raise SocketTimeout('timed out sending query command')
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   355
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   356
30656
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   357
def _get_overlapped_result_ex_impl(pipe, olap, nbytes, millis, alertable):
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   358
    """ Windows 7 and earlier does not support GetOverlappedResultEx. The
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   359
    alternative is to use GetOverlappedResult and wait for read or write
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   360
    operation to complete. This is done be using CreateEvent and
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   361
    WaitForSingleObjectEx. CreateEvent, WaitForSingleObjectEx
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   362
    and GetOverlappedResult are all part of Windows API since WindowsXP.
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   363
    This is the exact same implementation that can be found in the watchman
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   364
    source code (see get_overlapped_result_ex_impl in stream_win.c). This
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   365
    way, maintenance should be simplified.
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   366
    """
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   367
    log('Preparing to wait for maximum %dms', millis )
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   368
    if millis != 0:
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   369
        waitReturnCode = WaitForSingleObjectEx(olap.hEvent, millis, alertable)
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   370
        if waitReturnCode == WAIT_OBJECT_0:
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   371
            # Event is signaled, overlapped IO operation result should be available.
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   372
            pass
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   373
        elif waitReturnCode == WAIT_IO_COMPLETION:
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   374
            # WaitForSingleObjectEx returnes because the system added an I/O completion
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   375
            # routine or an asynchronous procedure call (APC) to the thread queue.
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   376
            SetLastError(WAIT_IO_COMPLETION)
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   377
            pass
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   378
        elif waitReturnCode == WAIT_TIMEOUT:
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   379
            # We reached the maximum allowed wait time, the IO operation failed
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   380
            # to complete in timely fashion.
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   381
            SetLastError(WAIT_TIMEOUT)
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   382
            return False
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   383
        elif waitReturnCode == WAIT_FAILED:
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   384
            # something went wrong calling WaitForSingleObjectEx
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   385
            err = GetLastError()
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   386
            log('WaitForSingleObjectEx failed: %s', _win32_strerror(err))
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   387
            return False
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   388
        else:
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   389
            # unexpected situation deserving investigation.
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   390
            err = GetLastError()
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   391
            log('Unexpected error: %s', _win32_strerror(err))
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   392
            return False
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   393
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   394
    return GetOverlappedResult(pipe, olap, nbytes, False)
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   395
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   396
28432
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   397
class WindowsNamedPipeTransport(Transport):
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   398
    """ connect to a named pipe """
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   399
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   400
    def __init__(self, sockpath, timeout):
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   401
        self.sockpath = sockpath
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   402
        self.timeout = int(math.ceil(timeout * 1000))
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   403
        self._iobuf = None
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   404
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   405
        self.pipe = CreateFile(sockpath, GENERIC_READ | GENERIC_WRITE, 0, None,
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   406
                               OPEN_EXISTING, FILE_FLAG_OVERLAPPED, None)
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   407
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   408
        if self.pipe == INVALID_HANDLE_VALUE:
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   409
            self.pipe = None
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   410
            self._raise_win_err('failed to open pipe %s' % sockpath,
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   411
                                GetLastError())
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   412
30656
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   413
        # event for the overlapped I/O operations
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   414
        self._waitable = CreateEvent(None, True, False, None)
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   415
        if self._waitable is None:
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   416
            self._raise_win_err('CreateEvent failed', GetLastError())
28432
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   417
30656
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   418
        self._get_overlapped_result_ex = GetOverlappedResultEx
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   419
        if (os.getenv('WATCHMAN_WIN7_COMPAT') == '1' or
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   420
            self._get_overlapped_result_ex is None):
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   421
            self._get_overlapped_result_ex = _get_overlapped_result_ex_impl
28432
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   422
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   423
    def _raise_win_err(self, msg, err):
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   424
        raise IOError('%s win32 error code: %d %s' %
30656
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   425
                      (msg, err, _win32_strerror(err)))
28432
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   426
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   427
    def close(self):
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   428
        if self.pipe:
30656
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   429
            log('Closing pipe')
28432
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   430
            CloseHandle(self.pipe)
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   431
        self.pipe = None
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   432
30656
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   433
        if self._waitable is not None:
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   434
            # We release the handle for the event
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   435
            CloseHandle(self._waitable)
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   436
        self._waitable = None
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   437
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   438
    def setTimeout(self, value):
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   439
        # convert to milliseconds
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   440
        self.timeout = int(value * 1000)
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   441
28432
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   442
    def readBytes(self, size):
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   443
        """ A read can block for an unbounded amount of time, even if the
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   444
            kernel reports that the pipe handle is signalled, so we need to
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   445
            always perform our reads asynchronously
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   446
        """
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   447
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   448
        # try to satisfy the read from any buffered data
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   449
        if self._iobuf:
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   450
            if size >= len(self._iobuf):
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   451
                res = self._iobuf
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   452
                self.buf = None
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   453
                return res
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   454
            res = self._iobuf[:size]
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   455
            self._iobuf = self._iobuf[size:]
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   456
            return res
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   457
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   458
        # We need to initiate a read
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   459
        buf = ctypes.create_string_buffer(size)
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   460
        olap = OVERLAPPED()
30656
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   461
        olap.hEvent = self._waitable
28432
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   462
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   463
        log('made read buff of size %d', size)
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   464
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   465
        # ReadFile docs warn against sending in the nread parameter for async
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   466
        # operations, so we always collect it via GetOverlappedResultEx
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   467
        immediate = ReadFile(self.pipe, buf, size, None, olap)
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   468
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   469
        if not immediate:
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   470
            err = GetLastError()
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   471
            if err != ERROR_IO_PENDING:
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   472
                self._raise_win_err('failed to read %d bytes' % size,
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   473
                                    GetLastError())
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   474
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   475
        nread = wintypes.DWORD()
30656
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   476
        if not self._get_overlapped_result_ex(self.pipe, olap, nread,
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   477
                                              0 if immediate else self.timeout,
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   478
                                              True):
28432
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   479
            err = GetLastError()
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   480
            CancelIoEx(self.pipe, olap)
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   481
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   482
            if err == WAIT_TIMEOUT:
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   483
                log('GetOverlappedResultEx timedout')
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   484
                raise SocketTimeout('timed out after waiting %dms for read' %
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   485
                                    self.timeout)
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   486
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   487
            log('GetOverlappedResultEx reports error %d', err)
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   488
            self._raise_win_err('error while waiting for read', err)
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   489
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   490
        nread = nread.value
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   491
        if nread == 0:
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   492
            # Docs say that named pipes return 0 byte when the other end did
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   493
            # a zero byte write.  Since we don't ever do that, the only
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   494
            # other way this shows up is if the client has gotten in a weird
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   495
            # state, so let's bail out
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   496
            CancelIoEx(self.pipe, olap)
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   497
            raise IOError('Async read yielded 0 bytes; unpossible!')
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   498
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   499
        # Holds precisely the bytes that we read from the prior request
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   500
        buf = buf[:nread]
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   501
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   502
        returned_size = min(nread, size)
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   503
        if returned_size == nread:
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   504
            return buf
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   505
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   506
        # keep any left-overs around for a later read to consume
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   507
        self._iobuf = buf[returned_size:]
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   508
        return buf[:returned_size]
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   509
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   510
    def write(self, data):
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   511
        olap = OVERLAPPED()
30656
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   512
        olap.hEvent = self._waitable
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   513
28432
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   514
        immediate = WriteFile(self.pipe, ctypes.c_char_p(data), len(data),
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   515
                              None, olap)
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   516
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   517
        if not immediate:
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   518
            err = GetLastError()
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   519
            if err != ERROR_IO_PENDING:
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   520
                self._raise_win_err('failed to write %d bytes' % len(data),
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   521
                                    GetLastError())
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   522
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   523
        # Obtain results, waiting if needed
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   524
        nwrote = wintypes.DWORD()
30656
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   525
        if self._get_overlapped_result_ex(self.pipe, olap, nwrote,
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   526
                                          0 if immediate else self.timeout,
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   527
                                          True):
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   528
            log('made write of %d bytes', nwrote.value)
28432
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   529
            return nwrote.value
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   530
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   531
        err = GetLastError()
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   532
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   533
        # It's potentially unsafe to allow the write to continue after
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   534
        # we unwind, so let's make a best effort to avoid that happening
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   535
        CancelIoEx(self.pipe, olap)
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   536
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   537
        if err == WAIT_TIMEOUT:
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   538
            raise SocketTimeout('timed out after waiting %dms for write' %
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   539
                                self.timeout)
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   540
        self._raise_win_err('error while waiting for write of %d bytes' %
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   541
                            len(data), err)
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   542
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   543
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   544
class CLIProcessTransport(Transport):
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   545
    """ open a pipe to the cli to talk to the service
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   546
    This intended to be used only in the test harness!
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   547
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   548
    The CLI is an oddball because we only support JSON input
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   549
    and cannot send multiple commands through the same instance,
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   550
    so we spawn a new process for each command.
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   551
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   552
    We disable server spawning for this implementation, again, because
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   553
    it is intended to be used only in our test harness.  You really
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   554
    should not need to use the CLI transport for anything real.
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   555
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   556
    While the CLI can output in BSER, our Transport interface doesn't
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   557
    support telling this instance that it should do so.  That effectively
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   558
    limits this implementation to JSON input and output only at this time.
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   559
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   560
    It is the responsibility of the caller to set the send and
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   561
    receive codecs appropriately.
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   562
    """
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   563
    proc = None
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   564
    closed = True
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   565
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   566
    def __init__(self, sockpath, timeout):
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   567
        self.sockpath = sockpath
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   568
        self.timeout = timeout
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   569
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   570
    def close(self):
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   571
        if self.proc:
30656
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   572
            if self.proc.pid is not None:
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   573
                self.proc.kill()
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   574
            self.proc.stdin.close()
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   575
            self.proc.stdout.close()
28432
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   576
            self.proc = None
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   577
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   578
    def _connect(self):
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   579
        if self.proc:
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   580
            return self.proc
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   581
        args = [
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   582
            'watchman',
30656
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   583
            '--sockname={0}'.format(self.sockpath),
28432
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   584
            '--logfile=/BOGUS',
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   585
            '--statefile=/BOGUS',
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   586
            '--no-spawn',
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   587
            '--no-local',
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   588
            '--no-pretty',
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   589
            '-j',
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   590
        ]
39826
c31ce080eb75 py3: convert arguments, cwd and env to native strings when spawning subprocess
Matt Harbison <matt_harbison@yahoo.com>
parents: 33769
diff changeset
   591
        self.proc = subprocess.Popen(pycompat.rapply(procutil.tonativestr,
c31ce080eb75 py3: convert arguments, cwd and env to native strings when spawning subprocess
Matt Harbison <matt_harbison@yahoo.com>
parents: 33769
diff changeset
   592
                                                     args),
28432
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   593
                                     stdin=subprocess.PIPE,
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   594
                                     stdout=subprocess.PIPE)
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   595
        return self.proc
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   596
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   597
    def readBytes(self, size):
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   598
        self._connect()
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   599
        res = self.proc.stdout.read(size)
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   600
        if res == '':
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   601
            raise WatchmanError('EOF on CLI process transport')
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   602
        return res
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   603
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   604
    def write(self, data):
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   605
        if self.closed:
30656
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   606
            self.close()
28432
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   607
            self.closed = False
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   608
        self._connect()
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   609
        res = self.proc.stdin.write(data)
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   610
        self.proc.stdin.close()
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   611
        self.closed = True
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   612
        return res
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   613
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   614
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   615
class BserCodec(Codec):
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   616
    """ use the BSER encoding.  This is the default, preferred codec """
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   617
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   618
    def _loads(self, response):
30656
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   619
        return bser.loads(response) # Defaults to BSER v1
28432
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   620
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   621
    def receive(self):
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   622
        buf = [self.transport.readBytes(sniff_len)]
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   623
        if not buf[0]:
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   624
            raise WatchmanError('empty watchman response')
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   625
30656
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   626
        _1, _2, elen = bser.pdu_info(buf[0])
28432
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   627
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   628
        rlen = len(buf[0])
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   629
        while elen > rlen:
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   630
            buf.append(self.transport.readBytes(elen - rlen))
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   631
            rlen += len(buf[-1])
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   632
30656
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   633
        response = b''.join(buf)
28432
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   634
        try:
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   635
            res = self._loads(response)
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   636
            return res
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   637
        except ValueError as e:
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   638
            raise WatchmanError('watchman response decode error: %s' % e)
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   639
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   640
    def send(self, *args):
30656
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   641
        cmd = bser.dumps(*args) # Defaults to BSER v1
28432
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   642
        self.transport.write(cmd)
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   643
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   644
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   645
class ImmutableBserCodec(BserCodec):
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   646
    """ use the BSER encoding, decoding values using the newer
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   647
        immutable object support """
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   648
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   649
    def _loads(self, response):
30656
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   650
        return bser.loads(response, False) # Defaults to BSER v1
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   651
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   652
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   653
class Bser2WithFallbackCodec(BserCodec):
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   654
    """ use BSER v2 encoding """
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   655
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   656
    def __init__(self, transport):
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   657
        super(Bser2WithFallbackCodec, self).__init__(transport)
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   658
        # Once the server advertises support for bser-v2 we should switch this
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   659
        # to 'required' on Python 3.
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   660
        self.send(["version", {"optional": ["bser-v2"]}])
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   661
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   662
        capabilities = self.receive()
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   663
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   664
        if 'error' in capabilities:
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   665
          raise Exception('Unsupported BSER version')
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   666
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   667
        if capabilities['capabilities']['bser-v2']:
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   668
            self.bser_version = 2
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   669
            self.bser_capabilities = 0
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   670
        else:
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   671
            self.bser_version = 1
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   672
            self.bser_capabilities = 0
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   673
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   674
    def _loads(self, response):
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   675
        return bser.loads(response)
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   676
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   677
    def receive(self):
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   678
        buf = [self.transport.readBytes(sniff_len)]
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   679
        if not buf[0]:
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   680
            raise WatchmanError('empty watchman response')
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   681
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   682
        recv_bser_version, recv_bser_capabilities, elen = bser.pdu_info(buf[0])
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   683
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   684
        if hasattr(self, 'bser_version'):
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   685
          # Readjust BSER version and capabilities if necessary
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   686
          self.bser_version = max(self.bser_version, recv_bser_version)
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   687
          self.capabilities = self.bser_capabilities & recv_bser_capabilities
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   688
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   689
        rlen = len(buf[0])
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   690
        while elen > rlen:
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   691
            buf.append(self.transport.readBytes(elen - rlen))
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   692
            rlen += len(buf[-1])
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   693
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   694
        response = b''.join(buf)
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   695
        try:
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   696
            res = self._loads(response)
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   697
            return res
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   698
        except ValueError as e:
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   699
            raise WatchmanError('watchman response decode error: %s' % e)
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   700
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   701
    def send(self, *args):
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   702
        if hasattr(self, 'bser_version'):
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   703
            cmd = bser.dumps(*args, version=self.bser_version,
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   704
                capabilities=self.bser_capabilities)
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   705
        else:
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   706
            cmd = bser.dumps(*args)
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   707
        self.transport.write(cmd)
28432
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   708
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   709
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   710
class JsonCodec(Codec):
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   711
    """ Use json codec.  This is here primarily for testing purposes """
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   712
    json = None
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   713
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   714
    def __init__(self, transport):
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   715
        super(JsonCodec, self).__init__(transport)
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   716
        # optional dep on json, only if JsonCodec is used
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   717
        import json
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   718
        self.json = json
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   719
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   720
    def receive(self):
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   721
        line = self.transport.readLine()
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   722
        try:
30656
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   723
            # In Python 3, json.loads is a transformation from Unicode string to
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   724
            # objects possibly containing Unicode strings. We typically expect
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   725
            # the JSON blob to be ASCII-only with non-ASCII characters escaped,
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   726
            # but it's possible we might get non-ASCII bytes that are valid
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   727
            # UTF-8.
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   728
            if compat.PYTHON3:
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   729
                line = line.decode('utf-8')
28432
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   730
            return self.json.loads(line)
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   731
        except Exception as e:
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   732
            print(e, line)
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   733
            raise
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   734
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   735
    def send(self, *args):
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   736
        cmd = self.json.dumps(*args)
30656
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   737
        # In Python 3, json.dumps is a transformation from objects possibly
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   738
        # containing Unicode strings to Unicode string. Even with (the default)
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   739
        # ensure_ascii=True, dumps returns a Unicode string.
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   740
        if compat.PYTHON3:
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   741
            cmd = cmd.encode('ascii')
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   742
        self.transport.write(cmd + b"\n")
28432
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   743
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   744
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   745
class client(object):
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   746
    """ Handles the communication with the watchman service """
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   747
    sockpath = None
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   748
    transport = None
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   749
    sendCodec = None
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   750
    recvCodec = None
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   751
    sendConn = None
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   752
    recvConn = None
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   753
    subs = {}  # Keyed by subscription name
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   754
    sub_by_root = {}  # Keyed by root, then by subscription name
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   755
    logs = []  # When log level is raised
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   756
    unilateral = ['log', 'subscription']
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   757
    tport = None
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   758
    useImmutableBser = None
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   759
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   760
    def __init__(self,
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   761
                 sockpath=None,
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   762
                 timeout=1.0,
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   763
                 transport=None,
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   764
                 sendEncoding=None,
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   765
                 recvEncoding=None,
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   766
                 useImmutableBser=False):
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   767
        self.sockpath = sockpath
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   768
        self.timeout = timeout
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   769
        self.useImmutableBser = useImmutableBser
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   770
30656
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   771
        if inspect.isclass(transport) and issubclass(transport, Transport):
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   772
            self.transport = transport
28432
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   773
        else:
30656
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   774
            transport = transport or os.getenv('WATCHMAN_TRANSPORT') or 'local'
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   775
            if transport == 'local' and os.name == 'nt':
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   776
                self.transport = WindowsNamedPipeTransport
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   777
            elif transport == 'local':
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   778
                self.transport = UnixSocketTransport
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   779
            elif transport == 'cli':
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   780
                self.transport = CLIProcessTransport
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   781
                if sendEncoding is None:
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   782
                    sendEncoding = 'json'
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   783
                if recvEncoding is None:
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   784
                    recvEncoding = sendEncoding
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   785
            else:
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   786
                raise WatchmanError('invalid transport %s' % transport)
28432
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   787
30656
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   788
        sendEncoding = str(sendEncoding or os.getenv('WATCHMAN_ENCODING') or
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   789
                           'bser')
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   790
        recvEncoding = str(recvEncoding or os.getenv('WATCHMAN_ENCODING') or
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   791
                           'bser')
28432
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   792
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   793
        self.recvCodec = self._parseEncoding(recvEncoding)
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   794
        self.sendCodec = self._parseEncoding(sendEncoding)
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   795
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   796
    def _parseEncoding(self, enc):
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   797
        if enc == 'bser':
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   798
            if self.useImmutableBser:
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   799
                return ImmutableBserCodec
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   800
            return BserCodec
30656
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   801
        elif enc == 'experimental-bser-v2':
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   802
          return Bser2WithFallbackCodec
28432
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   803
        elif enc == 'json':
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   804
            return JsonCodec
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   805
        else:
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   806
            raise WatchmanError('invalid encoding %s' % enc)
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   807
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   808
    def _hasprop(self, result, name):
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   809
        if self.useImmutableBser:
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   810
            return hasattr(result, name)
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   811
        return name in result
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   812
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   813
    def _resolvesockname(self):
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   814
        # if invoked via a trigger, watchman will set this env var; we
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   815
        # should use it unless explicitly set otherwise
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   816
        path = os.getenv('WATCHMAN_SOCK')
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   817
        if path:
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   818
            return path
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   819
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   820
        cmd = ['watchman', '--output-encoding=bser', 'get-sockname']
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   821
        try:
30656
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   822
            args = dict(stdout=subprocess.PIPE,
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   823
                        stderr=subprocess.PIPE,
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   824
                        close_fds=os.name != 'nt')
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   825
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   826
            if os.name == 'nt':
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   827
                # if invoked via an application with graphical user interface,
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   828
                # this call will cause a brief command window pop-up.
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   829
                # Using the flag STARTF_USESHOWWINDOW to avoid this behavior.
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   830
                startupinfo = subprocess.STARTUPINFO()
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   831
                startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   832
                args['startupinfo'] = startupinfo
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   833
39826
c31ce080eb75 py3: convert arguments, cwd and env to native strings when spawning subprocess
Matt Harbison <matt_harbison@yahoo.com>
parents: 33769
diff changeset
   834
            p = subprocess.Popen(pycompat.rapply(procutil.tonativestr, cmd),
c31ce080eb75 py3: convert arguments, cwd and env to native strings when spawning subprocess
Matt Harbison <matt_harbison@yahoo.com>
parents: 33769
diff changeset
   835
                                 **args)
30656
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   836
28432
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   837
        except OSError as e:
33769
dd35abc409ee fsmonitor: correct an error message
Jun Wu <quark@fb.com>
parents: 30656
diff changeset
   838
            raise WatchmanError('"watchman" executable not in PATH (%s)' % e)
28432
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   839
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   840
        stdout, stderr = p.communicate()
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   841
        exitcode = p.poll()
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   842
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   843
        if exitcode:
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   844
            raise WatchmanError("watchman exited with code %d" % exitcode)
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   845
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   846
        result = bser.loads(stdout)
30656
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   847
        if b'error' in result:
28432
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   848
            raise WatchmanError('get-sockname error: %s' % result['error'])
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   849
30656
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   850
        return result[b'sockname']
28432
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   851
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   852
    def _connect(self):
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   853
        """ establish transport connection """
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   854
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   855
        if self.recvConn:
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   856
            return
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   857
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   858
        if self.sockpath is None:
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   859
            self.sockpath = self._resolvesockname()
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   860
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   861
        self.tport = self.transport(self.sockpath, self.timeout)
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   862
        self.sendConn = self.sendCodec(self.tport)
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   863
        self.recvConn = self.recvCodec(self.tport)
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   864
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   865
    def __del__(self):
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   866
        self.close()
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   867
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   868
    def close(self):
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   869
        if self.tport:
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   870
            self.tport.close()
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   871
            self.tport = None
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   872
            self.recvConn = None
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   873
            self.sendConn = None
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   874
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   875
    def receive(self):
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   876
        """ receive the next PDU from the watchman service
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   877
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   878
        If the client has activated subscriptions or logs then
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   879
        this PDU may be a unilateral PDU sent by the service to
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   880
        inform the client of a log event or subscription change.
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   881
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   882
        It may also simply be the response portion of a request
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   883
        initiated by query.
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   884
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   885
        There are clients in production that subscribe and call
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   886
        this in a loop to retrieve all subscription responses,
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   887
        so care should be taken when making changes here.
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   888
        """
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   889
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   890
        self._connect()
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   891
        result = self.recvConn.receive()
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   892
        if self._hasprop(result, 'error'):
30656
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   893
            error = result['error']
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   894
            if compat.PYTHON3 and isinstance(self.recvConn, BserCodec):
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   895
                error = result['error'].decode('utf-8', 'surrogateescape')
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   896
            raise CommandError(error)
28432
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   897
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   898
        if self._hasprop(result, 'log'):
30656
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   899
            log = result['log']
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   900
            if compat.PYTHON3 and isinstance(self.recvConn, BserCodec):
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   901
                log = log.decode('utf-8', 'surrogateescape')
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   902
            self.logs.append(log)
28432
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   903
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   904
        if self._hasprop(result, 'subscription'):
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   905
            sub = result['subscription']
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   906
            if not (sub in self.subs):
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   907
                self.subs[sub] = []
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   908
            self.subs[sub].append(result)
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   909
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   910
            # also accumulate in {root,sub} keyed store
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   911
            root = os.path.normcase(result['root'])
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   912
            if not root in self.sub_by_root:
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   913
                self.sub_by_root[root] = {}
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   914
            if not sub in self.sub_by_root[root]:
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   915
                self.sub_by_root[root][sub] = []
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   916
            self.sub_by_root[root][sub].append(result)
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   917
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   918
        return result
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   919
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   920
    def isUnilateralResponse(self, res):
30656
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   921
        if 'unilateral' in res and res['unilateral']:
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   922
            return True
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   923
        # Fall back to checking for known unilateral responses
28432
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   924
        for k in self.unilateral:
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   925
            if k in res:
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   926
                return True
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   927
        return False
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   928
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   929
    def getLog(self, remove=True):
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   930
        """ Retrieve buffered log data
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   931
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   932
        If remove is true the data will be removed from the buffer.
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   933
        Otherwise it will be left in the buffer
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   934
        """
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   935
        res = self.logs
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   936
        if remove:
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   937
            self.logs = []
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   938
        return res
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   939
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   940
    def getSubscription(self, name, remove=True, root=None):
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   941
        """ Retrieve the data associated with a named subscription
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   942
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   943
        If remove is True (the default), the subscription data is removed
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   944
        from the buffer.  Otherwise the data is returned but left in
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   945
        the buffer.
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   946
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   947
        Returns None if there is no data associated with `name`
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   948
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   949
        If root is not None, then only return the subscription
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   950
        data that matches both root and name.  When used in this way,
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   951
        remove processing impacts both the unscoped and scoped stores
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   952
        for the subscription data.
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   953
        """
30656
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   954
        if compat.PYTHON3 and issubclass(self.recvCodec, BserCodec):
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   955
            # People may pass in Unicode strings here -- but currently BSER only
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   956
            # returns bytestrings. Deal with that.
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   957
            if isinstance(root, str):
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   958
                root = encoding.encode_local(root)
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   959
            if isinstance(name, str):
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
   960
                name = name.encode('utf-8')
28432
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   961
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   962
        if root is not None:
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   963
            if not root in self.sub_by_root:
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   964
                return None
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   965
            if not name in self.sub_by_root[root]:
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   966
                return None
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   967
            sub = self.sub_by_root[root][name]
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   968
            if remove:
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   969
                del self.sub_by_root[root][name]
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   970
                # don't let this grow unbounded
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   971
                if name in self.subs:
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   972
                    del self.subs[name]
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   973
            return sub
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   974
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   975
        if not (name in self.subs):
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   976
            return None
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   977
        sub = self.subs[name]
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   978
        if remove:
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   979
            del self.subs[name]
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   980
        return sub
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   981
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   982
    def query(self, *args):
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   983
        """ Send a query to the watchman service and return the response
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   984
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   985
        This call will block until the response is returned.
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   986
        If any unilateral responses are sent by the service in between
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   987
        the request-response they will be buffered up in the client object
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   988
        and NOT returned via this method.
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   989
        """
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   990
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   991
        log('calling client.query')
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   992
        self._connect()
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   993
        try:
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   994
            self.sendConn.send(args)
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   995
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   996
            res = self.receive()
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   997
            while self.isUnilateralResponse(res):
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   998
                res = self.receive()
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
   999
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
  1000
            return res
30656
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
  1001
        except EnvironmentError as ee:
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
  1002
            # When we can depend on Python 3, we can use PEP 3134
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
  1003
            # exception chaining here.
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
  1004
            raise WatchmanEnvironmentError(
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
  1005
                'I/O error communicating with watchman daemon',
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
  1006
                ee.errno,
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
  1007
                ee.strerror,
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
  1008
                args)
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
  1009
        except WatchmanError as ex:
28432
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
  1010
            ex.setCommand(args)
30656
16f4b341288d fsmonitor: refresh pywatchman to upstream
Zack Hricz <zphricz@fb.com>
parents: 28432
diff changeset
  1011
            raise
28432
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
  1012
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
  1013
    def capabilityCheck(self, optional=None, required=None):
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
  1014
        """ Perform a server capability check """
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
  1015
        res = self.query('version', {
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
  1016
            'optional': optional or [],
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
  1017
            'required': required or []
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
  1018
        })
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
  1019
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
  1020
        if not self._hasprop(res, 'capabilities'):
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
  1021
            # Server doesn't support capabilities, so we need to
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
  1022
            # synthesize the results based on the version
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
  1023
            capabilities.synthesize(res, optional)
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
  1024
            if 'error' in res:
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
  1025
                raise CommandError(res['error'])
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
  1026
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
  1027
        return res
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
  1028
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
  1029
    def setTimeout(self, value):
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
  1030
        self.recvConn.setTimeout(value)
2377c4ac4eec fsmonitor: dependencies for new experimental extension
Martijn Pieters <mjpieters@fb.com>
parents:
diff changeset
  1031
        self.sendConn.setTimeout(value)