diff options
Diffstat (limited to 'venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_vendor/lockfile')
6 files changed, 920 insertions, 0 deletions
diff --git a/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_vendor/lockfile/__init__.py b/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_vendor/lockfile/__init__.py new file mode 100644 index 0000000..228e051 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_vendor/lockfile/__init__.py | |||
| @@ -0,0 +1,347 @@ | |||
| 1 | # -*- coding: utf-8 -*- | ||
| 2 | |||
| 3 | """ | ||
| 4 | lockfile.py - Platform-independent advisory file locks. | ||
| 5 | |||
| 6 | Requires Python 2.5 unless you apply 2.4.diff | ||
| 7 | Locking is done on a per-thread basis instead of a per-process basis. | ||
| 8 | |||
| 9 | Usage: | ||
| 10 | |||
| 11 | >>> lock = LockFile('somefile') | ||
| 12 | >>> try: | ||
| 13 | ... lock.acquire() | ||
| 14 | ... except AlreadyLocked: | ||
| 15 | ... print 'somefile', 'is locked already.' | ||
| 16 | ... except LockFailed: | ||
| 17 | ... print 'somefile', 'can\\'t be locked.' | ||
| 18 | ... else: | ||
| 19 | ... print 'got lock' | ||
| 20 | got lock | ||
| 21 | >>> print lock.is_locked() | ||
| 22 | True | ||
| 23 | >>> lock.release() | ||
| 24 | |||
| 25 | >>> lock = LockFile('somefile') | ||
| 26 | >>> print lock.is_locked() | ||
| 27 | False | ||
| 28 | >>> with lock: | ||
| 29 | ... print lock.is_locked() | ||
| 30 | True | ||
| 31 | >>> print lock.is_locked() | ||
| 32 | False | ||
| 33 | |||
| 34 | >>> lock = LockFile('somefile') | ||
| 35 | >>> # It is okay to lock twice from the same thread... | ||
| 36 | >>> with lock: | ||
| 37 | ... lock.acquire() | ||
| 38 | ... | ||
| 39 | >>> # Though no counter is kept, so you can't unlock multiple times... | ||
| 40 | >>> print lock.is_locked() | ||
| 41 | False | ||
| 42 | |||
| 43 | Exceptions: | ||
| 44 | |||
| 45 | Error - base class for other exceptions | ||
| 46 | LockError - base class for all locking exceptions | ||
| 47 | AlreadyLocked - Another thread or process already holds the lock | ||
| 48 | LockFailed - Lock failed for some other reason | ||
| 49 | UnlockError - base class for all unlocking exceptions | ||
| 50 | AlreadyUnlocked - File was not locked. | ||
| 51 | NotMyLock - File was locked but not by the current thread/process | ||
| 52 | """ | ||
| 53 | |||
| 54 | from __future__ import absolute_import | ||
| 55 | |||
| 56 | import functools | ||
| 57 | import os | ||
| 58 | import socket | ||
| 59 | import threading | ||
| 60 | import warnings | ||
| 61 | |||
| 62 | # Work with PEP8 and non-PEP8 versions of threading module. | ||
| 63 | if not hasattr(threading, "current_thread"): | ||
| 64 | threading.current_thread = threading.currentThread | ||
| 65 | if not hasattr(threading.Thread, "get_name"): | ||
| 66 | threading.Thread.get_name = threading.Thread.getName | ||
| 67 | |||
| 68 | __all__ = ['Error', 'LockError', 'LockTimeout', 'AlreadyLocked', | ||
| 69 | 'LockFailed', 'UnlockError', 'NotLocked', 'NotMyLock', | ||
| 70 | 'LinkFileLock', 'MkdirFileLock', 'SQLiteFileLock', | ||
| 71 | 'LockBase', 'locked'] | ||
| 72 | |||
| 73 | |||
| 74 | class Error(Exception): | ||
| 75 | """ | ||
| 76 | Base class for other exceptions. | ||
| 77 | |||
| 78 | >>> try: | ||
| 79 | ... raise Error | ||
| 80 | ... except Exception: | ||
| 81 | ... pass | ||
| 82 | """ | ||
| 83 | pass | ||
| 84 | |||
| 85 | |||
| 86 | class LockError(Error): | ||
| 87 | """ | ||
| 88 | Base class for error arising from attempts to acquire the lock. | ||
| 89 | |||
| 90 | >>> try: | ||
| 91 | ... raise LockError | ||
| 92 | ... except Error: | ||
| 93 | ... pass | ||
| 94 | """ | ||
| 95 | pass | ||
| 96 | |||
| 97 | |||
| 98 | class LockTimeout(LockError): | ||
| 99 | """Raised when lock creation fails within a user-defined period of time. | ||
| 100 | |||
| 101 | >>> try: | ||
| 102 | ... raise LockTimeout | ||
| 103 | ... except LockError: | ||
| 104 | ... pass | ||
| 105 | """ | ||
| 106 | pass | ||
| 107 | |||
| 108 | |||
| 109 | class AlreadyLocked(LockError): | ||
| 110 | """Some other thread/process is locking the file. | ||
| 111 | |||
| 112 | >>> try: | ||
| 113 | ... raise AlreadyLocked | ||
| 114 | ... except LockError: | ||
| 115 | ... pass | ||
| 116 | """ | ||
| 117 | pass | ||
| 118 | |||
| 119 | |||
| 120 | class LockFailed(LockError): | ||
| 121 | """Lock file creation failed for some other reason. | ||
| 122 | |||
| 123 | >>> try: | ||
| 124 | ... raise LockFailed | ||
| 125 | ... except LockError: | ||
| 126 | ... pass | ||
| 127 | """ | ||
| 128 | pass | ||
| 129 | |||
| 130 | |||
| 131 | class UnlockError(Error): | ||
| 132 | """ | ||
| 133 | Base class for errors arising from attempts to release the lock. | ||
| 134 | |||
| 135 | >>> try: | ||
| 136 | ... raise UnlockError | ||
| 137 | ... except Error: | ||
| 138 | ... pass | ||
| 139 | """ | ||
| 140 | pass | ||
| 141 | |||
| 142 | |||
| 143 | class NotLocked(UnlockError): | ||
| 144 | """Raised when an attempt is made to unlock an unlocked file. | ||
| 145 | |||
| 146 | >>> try: | ||
| 147 | ... raise NotLocked | ||
| 148 | ... except UnlockError: | ||
| 149 | ... pass | ||
| 150 | """ | ||
| 151 | pass | ||
| 152 | |||
| 153 | |||
| 154 | class NotMyLock(UnlockError): | ||
| 155 | """Raised when an attempt is made to unlock a file someone else locked. | ||
| 156 | |||
| 157 | >>> try: | ||
| 158 | ... raise NotMyLock | ||
| 159 | ... except UnlockError: | ||
| 160 | ... pass | ||
| 161 | """ | ||
| 162 | pass | ||
| 163 | |||
| 164 | |||
| 165 | class _SharedBase(object): | ||
| 166 | def __init__(self, path): | ||
| 167 | self.path = path | ||
| 168 | |||
| 169 | def acquire(self, timeout=None): | ||
| 170 | """ | ||
| 171 | Acquire the lock. | ||
| 172 | |||
| 173 | * If timeout is omitted (or None), wait forever trying to lock the | ||
| 174 | file. | ||
| 175 | |||
| 176 | * If timeout > 0, try to acquire the lock for that many seconds. If | ||
| 177 | the lock period expires and the file is still locked, raise | ||
| 178 | LockTimeout. | ||
| 179 | |||
| 180 | * If timeout <= 0, raise AlreadyLocked immediately if the file is | ||
| 181 | already locked. | ||
| 182 | """ | ||
| 183 | raise NotImplemented("implement in subclass") | ||
| 184 | |||
| 185 | def release(self): | ||
| 186 | """ | ||
| 187 | Release the lock. | ||
| 188 | |||
| 189 | If the file is not locked, raise NotLocked. | ||
| 190 | """ | ||
| 191 | raise NotImplemented("implement in subclass") | ||
| 192 | |||
| 193 | def __enter__(self): | ||
| 194 | """ | ||
| 195 | Context manager support. | ||
| 196 | """ | ||
| 197 | self.acquire() | ||
| 198 | return self | ||
| 199 | |||
| 200 | def __exit__(self, *_exc): | ||
| 201 | """ | ||
| 202 | Context manager support. | ||
| 203 | """ | ||
| 204 | self.release() | ||
| 205 | |||
| 206 | def __repr__(self): | ||
| 207 | return "<%s: %r>" % (self.__class__.__name__, self.path) | ||
| 208 | |||
| 209 | |||
| 210 | class LockBase(_SharedBase): | ||
| 211 | """Base class for platform-specific lock classes.""" | ||
| 212 | def __init__(self, path, threaded=True, timeout=None): | ||
| 213 | """ | ||
| 214 | >>> lock = LockBase('somefile') | ||
| 215 | >>> lock = LockBase('somefile', threaded=False) | ||
| 216 | """ | ||
| 217 | super(LockBase, self).__init__(path) | ||
| 218 | self.lock_file = os.path.abspath(path) + ".lock" | ||
| 219 | self.hostname = socket.gethostname() | ||
| 220 | self.pid = os.getpid() | ||
| 221 | if threaded: | ||
| 222 | t = threading.current_thread() | ||
| 223 | # Thread objects in Python 2.4 and earlier do not have ident | ||
| 224 | # attrs. Worm around that. | ||
| 225 | ident = getattr(t, "ident", hash(t)) | ||
| 226 | self.tname = "-%x" % (ident & 0xffffffff) | ||
| 227 | else: | ||
| 228 | self.tname = "" | ||
| 229 | dirname = os.path.dirname(self.lock_file) | ||
| 230 | |||
| 231 | # unique name is mostly about the current process, but must | ||
| 232 | # also contain the path -- otherwise, two adjacent locked | ||
| 233 | # files conflict (one file gets locked, creating lock-file and | ||
| 234 | # unique file, the other one gets locked, creating lock-file | ||
| 235 | # and overwriting the already existing lock-file, then one | ||
| 236 | # gets unlocked, deleting both lock-file and unique file, | ||
| 237 | # finally the last lock errors out upon releasing. | ||
| 238 | self.unique_name = os.path.join(dirname, | ||
| 239 | "%s%s.%s%s" % (self.hostname, | ||
| 240 | self.tname, | ||
| 241 | self.pid, | ||
| 242 | hash(self.path))) | ||
| 243 | self.timeout = timeout | ||
| 244 | |||
| 245 | def is_locked(self): | ||
| 246 | """ | ||
| 247 | Tell whether or not the file is locked. | ||
| 248 | """ | ||
| 249 | raise NotImplemented("implement in subclass") | ||
| 250 | |||
| 251 | def i_am_locking(self): | ||
| 252 | """ | ||
| 253 | Return True if this object is locking the file. | ||
| 254 | """ | ||
| 255 | raise NotImplemented("implement in subclass") | ||
| 256 | |||
| 257 | def break_lock(self): | ||
| 258 | """ | ||
| 259 | Remove a lock. Useful if a locking thread failed to unlock. | ||
| 260 | """ | ||
| 261 | raise NotImplemented("implement in subclass") | ||
| 262 | |||
| 263 | def __repr__(self): | ||
| 264 | return "<%s: %r -- %r>" % (self.__class__.__name__, self.unique_name, | ||
| 265 | self.path) | ||
| 266 | |||
| 267 | |||
| 268 | def _fl_helper(cls, mod, *args, **kwds): | ||
| 269 | warnings.warn("Import from %s module instead of lockfile package" % mod, | ||
| 270 | DeprecationWarning, stacklevel=2) | ||
| 271 | # This is a bit funky, but it's only for awhile. The way the unit tests | ||
| 272 | # are constructed this function winds up as an unbound method, so it | ||
| 273 | # actually takes three args, not two. We want to toss out self. | ||
| 274 | if not isinstance(args[0], str): | ||
| 275 | # We are testing, avoid the first arg | ||
| 276 | args = args[1:] | ||
| 277 | if len(args) == 1 and not kwds: | ||
| 278 | kwds["threaded"] = True | ||
| 279 | return cls(*args, **kwds) | ||
| 280 | |||
| 281 | |||
| 282 | def LinkFileLock(*args, **kwds): | ||
| 283 | """Factory function provided for backwards compatibility. | ||
| 284 | |||
| 285 | Do not use in new code. Instead, import LinkLockFile from the | ||
| 286 | lockfile.linklockfile module. | ||
| 287 | """ | ||
| 288 | from . import linklockfile | ||
| 289 | return _fl_helper(linklockfile.LinkLockFile, "lockfile.linklockfile", | ||
| 290 | *args, **kwds) | ||
| 291 | |||
| 292 | |||
| 293 | def MkdirFileLock(*args, **kwds): | ||
| 294 | """Factory function provided for backwards compatibility. | ||
| 295 | |||
| 296 | Do not use in new code. Instead, import MkdirLockFile from the | ||
| 297 | lockfile.mkdirlockfile module. | ||
| 298 | """ | ||
| 299 | from . import mkdirlockfile | ||
| 300 | return _fl_helper(mkdirlockfile.MkdirLockFile, "lockfile.mkdirlockfile", | ||
| 301 | *args, **kwds) | ||
| 302 | |||
| 303 | |||
| 304 | def SQLiteFileLock(*args, **kwds): | ||
| 305 | """Factory function provided for backwards compatibility. | ||
| 306 | |||
| 307 | Do not use in new code. Instead, import SQLiteLockFile from the | ||
| 308 | lockfile.mkdirlockfile module. | ||
| 309 | """ | ||
| 310 | from . import sqlitelockfile | ||
| 311 | return _fl_helper(sqlitelockfile.SQLiteLockFile, "lockfile.sqlitelockfile", | ||
| 312 | *args, **kwds) | ||
| 313 | |||
| 314 | |||
| 315 | def locked(path, timeout=None): | ||
| 316 | """Decorator which enables locks for decorated function. | ||
| 317 | |||
| 318 | Arguments: | ||
| 319 | - path: path for lockfile. | ||
| 320 | - timeout (optional): Timeout for acquiring lock. | ||
| 321 | |||
| 322 | Usage: | ||
| 323 | @locked('/var/run/myname', timeout=0) | ||
| 324 | def myname(...): | ||
| 325 | ... | ||
| 326 | """ | ||
| 327 | def decor(func): | ||
| 328 | @functools.wraps(func) | ||
| 329 | def wrapper(*args, **kwargs): | ||
| 330 | lock = FileLock(path, timeout=timeout) | ||
| 331 | lock.acquire() | ||
| 332 | try: | ||
| 333 | return func(*args, **kwargs) | ||
| 334 | finally: | ||
| 335 | lock.release() | ||
| 336 | return wrapper | ||
| 337 | return decor | ||
| 338 | |||
| 339 | |||
| 340 | if hasattr(os, "link"): | ||
| 341 | from . import linklockfile as _llf | ||
| 342 | LockFile = _llf.LinkLockFile | ||
| 343 | else: | ||
| 344 | from . import mkdirlockfile as _mlf | ||
| 345 | LockFile = _mlf.MkdirLockFile | ||
| 346 | |||
| 347 | FileLock = LockFile | ||
diff --git a/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_vendor/lockfile/linklockfile.py b/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_vendor/lockfile/linklockfile.py new file mode 100644 index 0000000..11af0f3 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_vendor/lockfile/linklockfile.py | |||
| @@ -0,0 +1,73 @@ | |||
| 1 | from __future__ import absolute_import | ||
| 2 | |||
| 3 | import time | ||
| 4 | import os | ||
| 5 | |||
| 6 | from . import (LockBase, LockFailed, NotLocked, NotMyLock, LockTimeout, | ||
| 7 | AlreadyLocked) | ||
| 8 | |||
| 9 | |||
| 10 | class LinkLockFile(LockBase): | ||
| 11 | """Lock access to a file using atomic property of link(2). | ||
| 12 | |||
| 13 | >>> lock = LinkLockFile('somefile') | ||
| 14 | >>> lock = LinkLockFile('somefile', threaded=False) | ||
| 15 | """ | ||
| 16 | |||
| 17 | def acquire(self, timeout=None): | ||
| 18 | try: | ||
| 19 | open(self.unique_name, "wb").close() | ||
| 20 | except IOError: | ||
| 21 | raise LockFailed("failed to create %s" % self.unique_name) | ||
| 22 | |||
| 23 | timeout = timeout if timeout is not None else self.timeout | ||
| 24 | end_time = time.time() | ||
| 25 | if timeout is not None and timeout > 0: | ||
| 26 | end_time += timeout | ||
| 27 | |||
| 28 | while True: | ||
| 29 | # Try and create a hard link to it. | ||
| 30 | try: | ||
| 31 | os.link(self.unique_name, self.lock_file) | ||
| 32 | except OSError: | ||
| 33 | # Link creation failed. Maybe we've double-locked? | ||
| 34 | nlinks = os.stat(self.unique_name).st_nlink | ||
| 35 | if nlinks == 2: | ||
| 36 | # The original link plus the one I created == 2. We're | ||
| 37 | # good to go. | ||
| 38 | return | ||
| 39 | else: | ||
| 40 | # Otherwise the lock creation failed. | ||
| 41 | if timeout is not None and time.time() > end_time: | ||
| 42 | os.unlink(self.unique_name) | ||
| 43 | if timeout > 0: | ||
| 44 | raise LockTimeout("Timeout waiting to acquire" | ||
| 45 | " lock for %s" % | ||
| 46 | self.path) | ||
| 47 | else: | ||
| 48 | raise AlreadyLocked("%s is already locked" % | ||
| 49 | self.path) | ||
| 50 | time.sleep(timeout is not None and timeout / 10 or 0.1) | ||
| 51 | else: | ||
| 52 | # Link creation succeeded. We're good to go. | ||
| 53 | return | ||
| 54 | |||
| 55 | def release(self): | ||
| 56 | if not self.is_locked(): | ||
| 57 | raise NotLocked("%s is not locked" % self.path) | ||
| 58 | elif not os.path.exists(self.unique_name): | ||
| 59 | raise NotMyLock("%s is locked, but not by me" % self.path) | ||
| 60 | os.unlink(self.unique_name) | ||
| 61 | os.unlink(self.lock_file) | ||
| 62 | |||
| 63 | def is_locked(self): | ||
| 64 | return os.path.exists(self.lock_file) | ||
| 65 | |||
| 66 | def i_am_locking(self): | ||
| 67 | return (self.is_locked() and | ||
| 68 | os.path.exists(self.unique_name) and | ||
| 69 | os.stat(self.unique_name).st_nlink == 2) | ||
| 70 | |||
| 71 | def break_lock(self): | ||
| 72 | if os.path.exists(self.lock_file): | ||
| 73 | os.unlink(self.lock_file) | ||
diff --git a/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_vendor/lockfile/mkdirlockfile.py b/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_vendor/lockfile/mkdirlockfile.py new file mode 100644 index 0000000..bd5a51e --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_vendor/lockfile/mkdirlockfile.py | |||
| @@ -0,0 +1,84 @@ | |||
| 1 | from __future__ import absolute_import, division | ||
| 2 | |||
| 3 | import time | ||
| 4 | import os | ||
| 5 | import sys | ||
| 6 | import errno | ||
| 7 | |||
| 8 | from . import (LockBase, LockFailed, NotLocked, NotMyLock, LockTimeout, | ||
| 9 | AlreadyLocked) | ||
| 10 | |||
| 11 | |||
| 12 | class MkdirLockFile(LockBase): | ||
| 13 | """Lock file by creating a directory.""" | ||
| 14 | def __init__(self, path, threaded=True, timeout=None): | ||
| 15 | """ | ||
| 16 | >>> lock = MkdirLockFile('somefile') | ||
| 17 | >>> lock = MkdirLockFile('somefile', threaded=False) | ||
| 18 | """ | ||
| 19 | LockBase.__init__(self, path, threaded, timeout) | ||
| 20 | # Lock file itself is a directory. Place the unique file name into | ||
| 21 | # it. | ||
| 22 | self.unique_name = os.path.join(self.lock_file, | ||
| 23 | "%s.%s%s" % (self.hostname, | ||
| 24 | self.tname, | ||
| 25 | self.pid)) | ||
| 26 | |||
| 27 | def acquire(self, timeout=None): | ||
| 28 | timeout = timeout if timeout is not None else self.timeout | ||
| 29 | end_time = time.time() | ||
| 30 | if timeout is not None and timeout > 0: | ||
| 31 | end_time += timeout | ||
| 32 | |||
| 33 | if timeout is None: | ||
| 34 | wait = 0.1 | ||
| 35 | else: | ||
| 36 | wait = max(0, timeout / 10) | ||
| 37 | |||
| 38 | while True: | ||
| 39 | try: | ||
| 40 | os.mkdir(self.lock_file) | ||
| 41 | except OSError: | ||
| 42 | err = sys.exc_info()[1] | ||
| 43 | if err.errno == errno.EEXIST: | ||
| 44 | # Already locked. | ||
| 45 | if os.path.exists(self.unique_name): | ||
| 46 | # Already locked by me. | ||
| 47 | return | ||
| 48 | if timeout is not None and time.time() > end_time: | ||
| 49 | if timeout > 0: | ||
| 50 | raise LockTimeout("Timeout waiting to acquire" | ||
| 51 | " lock for %s" % | ||
| 52 | self.path) | ||
| 53 | else: | ||
| 54 | # Someone else has the lock. | ||
| 55 | raise AlreadyLocked("%s is already locked" % | ||
| 56 | self.path) | ||
| 57 | time.sleep(wait) | ||
| 58 | else: | ||
| 59 | # Couldn't create the lock for some other reason | ||
| 60 | raise LockFailed("failed to create %s" % self.lock_file) | ||
| 61 | else: | ||
| 62 | open(self.unique_name, "wb").close() | ||
| 63 | return | ||
| 64 | |||
| 65 | def release(self): | ||
| 66 | if not self.is_locked(): | ||
| 67 | raise NotLocked("%s is not locked" % self.path) | ||
| 68 | elif not os.path.exists(self.unique_name): | ||
| 69 | raise NotMyLock("%s is locked, but not by me" % self.path) | ||
| 70 | os.unlink(self.unique_name) | ||
| 71 | os.rmdir(self.lock_file) | ||
| 72 | |||
| 73 | def is_locked(self): | ||
| 74 | return os.path.exists(self.lock_file) | ||
| 75 | |||
| 76 | def i_am_locking(self): | ||
| 77 | return (self.is_locked() and | ||
| 78 | os.path.exists(self.unique_name)) | ||
| 79 | |||
| 80 | def break_lock(self): | ||
| 81 | if os.path.exists(self.lock_file): | ||
| 82 | for name in os.listdir(self.lock_file): | ||
| 83 | os.unlink(os.path.join(self.lock_file, name)) | ||
| 84 | os.rmdir(self.lock_file) | ||
diff --git a/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_vendor/lockfile/pidlockfile.py b/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_vendor/lockfile/pidlockfile.py new file mode 100644 index 0000000..d776de5 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_vendor/lockfile/pidlockfile.py | |||
| @@ -0,0 +1,190 @@ | |||
| 1 | # -*- coding: utf-8 -*- | ||
| 2 | |||
| 3 | # pidlockfile.py | ||
| 4 | # | ||
| 5 | # Copyright © 2008–2009 Ben Finney <ben+python@benfinney.id.au> | ||
| 6 | # | ||
| 7 | # This is free software: you may copy, modify, and/or distribute this work | ||
| 8 | # under the terms of the Python Software Foundation License, version 2 or | ||
| 9 | # later as published by the Python Software Foundation. | ||
| 10 | # No warranty expressed or implied. See the file LICENSE.PSF-2 for details. | ||
| 11 | |||
| 12 | """ Lockfile behaviour implemented via Unix PID files. | ||
| 13 | """ | ||
| 14 | |||
| 15 | from __future__ import absolute_import | ||
| 16 | |||
| 17 | import errno | ||
| 18 | import os | ||
| 19 | import time | ||
| 20 | |||
| 21 | from . import (LockBase, AlreadyLocked, LockFailed, NotLocked, NotMyLock, | ||
| 22 | LockTimeout) | ||
| 23 | |||
| 24 | |||
| 25 | class PIDLockFile(LockBase): | ||
| 26 | """ Lockfile implemented as a Unix PID file. | ||
| 27 | |||
| 28 | The lock file is a normal file named by the attribute `path`. | ||
| 29 | A lock's PID file contains a single line of text, containing | ||
| 30 | the process ID (PID) of the process that acquired the lock. | ||
| 31 | |||
| 32 | >>> lock = PIDLockFile('somefile') | ||
| 33 | >>> lock = PIDLockFile('somefile') | ||
| 34 | """ | ||
| 35 | |||
| 36 | def __init__(self, path, threaded=False, timeout=None): | ||
| 37 | # pid lockfiles don't support threaded operation, so always force | ||
| 38 | # False as the threaded arg. | ||
| 39 | LockBase.__init__(self, path, False, timeout) | ||
| 40 | self.unique_name = self.path | ||
| 41 | |||
| 42 | def read_pid(self): | ||
| 43 | """ Get the PID from the lock file. | ||
| 44 | """ | ||
| 45 | return read_pid_from_pidfile(self.path) | ||
| 46 | |||
| 47 | def is_locked(self): | ||
| 48 | """ Test if the lock is currently held. | ||
| 49 | |||
| 50 | The lock is held if the PID file for this lock exists. | ||
| 51 | |||
| 52 | """ | ||
| 53 | return os.path.exists(self.path) | ||
| 54 | |||
| 55 | def i_am_locking(self): | ||
| 56 | """ Test if the lock is held by the current process. | ||
| 57 | |||
| 58 | Returns ``True`` if the current process ID matches the | ||
| 59 | number stored in the PID file. | ||
| 60 | """ | ||
| 61 | return self.is_locked() and os.getpid() == self.read_pid() | ||
| 62 | |||
| 63 | def acquire(self, timeout=None): | ||
| 64 | """ Acquire the lock. | ||
| 65 | |||
| 66 | Creates the PID file for this lock, or raises an error if | ||
| 67 | the lock could not be acquired. | ||
| 68 | """ | ||
| 69 | |||
| 70 | timeout = timeout if timeout is not None else self.timeout | ||
| 71 | end_time = time.time() | ||
| 72 | if timeout is not None and timeout > 0: | ||
| 73 | end_time += timeout | ||
| 74 | |||
| 75 | while True: | ||
| 76 | try: | ||
| 77 | write_pid_to_pidfile(self.path) | ||
| 78 | except OSError as exc: | ||
| 79 | if exc.errno == errno.EEXIST: | ||
| 80 | # The lock creation failed. Maybe sleep a bit. | ||
| 81 | if time.time() > end_time: | ||
| 82 | if timeout is not None and timeout > 0: | ||
| 83 | raise LockTimeout("Timeout waiting to acquire" | ||
| 84 | " lock for %s" % | ||
| 85 | self.path) | ||
| 86 | else: | ||
| 87 | raise AlreadyLocked("%s is already locked" % | ||
| 88 | self.path) | ||
| 89 | time.sleep(timeout is not None and timeout / 10 or 0.1) | ||
| 90 | else: | ||
| 91 | raise LockFailed("failed to create %s" % self.path) | ||
| 92 | else: | ||
| 93 | return | ||
| 94 | |||
| 95 | def release(self): | ||
| 96 | """ Release the lock. | ||
| 97 | |||
| 98 | Removes the PID file to release the lock, or raises an | ||
| 99 | error if the current process does not hold the lock. | ||
| 100 | |||
| 101 | """ | ||
| 102 | if not self.is_locked(): | ||
| 103 | raise NotLocked("%s is not locked" % self.path) | ||
| 104 | if not self.i_am_locking(): | ||
| 105 | raise NotMyLock("%s is locked, but not by me" % self.path) | ||
| 106 | remove_existing_pidfile(self.path) | ||
| 107 | |||
| 108 | def break_lock(self): | ||
| 109 | """ Break an existing lock. | ||
| 110 | |||
| 111 | Removes the PID file if it already exists, otherwise does | ||
| 112 | nothing. | ||
| 113 | |||
| 114 | """ | ||
| 115 | remove_existing_pidfile(self.path) | ||
| 116 | |||
| 117 | |||
| 118 | def read_pid_from_pidfile(pidfile_path): | ||
| 119 | """ Read the PID recorded in the named PID file. | ||
| 120 | |||
| 121 | Read and return the numeric PID recorded as text in the named | ||
| 122 | PID file. If the PID file cannot be read, or if the content is | ||
| 123 | not a valid PID, return ``None``. | ||
| 124 | |||
| 125 | """ | ||
| 126 | pid = None | ||
| 127 | try: | ||
| 128 | pidfile = open(pidfile_path, 'r') | ||
| 129 | except IOError: | ||
| 130 | pass | ||
| 131 | else: | ||
| 132 | # According to the FHS 2.3 section on PID files in /var/run: | ||
| 133 | # | ||
| 134 | # The file must consist of the process identifier in | ||
| 135 | # ASCII-encoded decimal, followed by a newline character. | ||
| 136 | # | ||
| 137 | # Programs that read PID files should be somewhat flexible | ||
| 138 | # in what they accept; i.e., they should ignore extra | ||
| 139 | # whitespace, leading zeroes, absence of the trailing | ||
| 140 | # newline, or additional lines in the PID file. | ||
| 141 | |||
| 142 | line = pidfile.readline().strip() | ||
| 143 | try: | ||
| 144 | pid = int(line) | ||
| 145 | except ValueError: | ||
| 146 | pass | ||
| 147 | pidfile.close() | ||
| 148 | |||
| 149 | return pid | ||
| 150 | |||
| 151 | |||
| 152 | def write_pid_to_pidfile(pidfile_path): | ||
| 153 | """ Write the PID in the named PID file. | ||
| 154 | |||
| 155 | Get the numeric process ID (“PID”) of the current process | ||
| 156 | and write it to the named file as a line of text. | ||
| 157 | |||
| 158 | """ | ||
| 159 | open_flags = (os.O_CREAT | os.O_EXCL | os.O_WRONLY) | ||
| 160 | open_mode = 0o644 | ||
| 161 | pidfile_fd = os.open(pidfile_path, open_flags, open_mode) | ||
| 162 | pidfile = os.fdopen(pidfile_fd, 'w') | ||
| 163 | |||
| 164 | # According to the FHS 2.3 section on PID files in /var/run: | ||
| 165 | # | ||
| 166 | # The file must consist of the process identifier in | ||
| 167 | # ASCII-encoded decimal, followed by a newline character. For | ||
| 168 | # example, if crond was process number 25, /var/run/crond.pid | ||
| 169 | # would contain three characters: two, five, and newline. | ||
| 170 | |||
| 171 | pid = os.getpid() | ||
| 172 | pidfile.write("%s\n" % pid) | ||
| 173 | pidfile.close() | ||
| 174 | |||
| 175 | |||
| 176 | def remove_existing_pidfile(pidfile_path): | ||
| 177 | """ Remove the named PID file if it exists. | ||
| 178 | |||
| 179 | Removing a PID file that doesn't already exist puts us in the | ||
| 180 | desired state, so we ignore the condition if the file does not | ||
| 181 | exist. | ||
| 182 | |||
| 183 | """ | ||
| 184 | try: | ||
| 185 | os.remove(pidfile_path) | ||
| 186 | except OSError as exc: | ||
| 187 | if exc.errno == errno.ENOENT: | ||
| 188 | pass | ||
| 189 | else: | ||
| 190 | raise | ||
diff --git a/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_vendor/lockfile/sqlitelockfile.py b/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_vendor/lockfile/sqlitelockfile.py new file mode 100644 index 0000000..278dff4 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_vendor/lockfile/sqlitelockfile.py | |||
| @@ -0,0 +1,156 @@ | |||
| 1 | from __future__ import absolute_import, division | ||
| 2 | |||
| 3 | import time | ||
| 4 | import os | ||
| 5 | |||
| 6 | try: | ||
| 7 | unicode | ||
| 8 | except NameError: | ||
| 9 | unicode = str | ||
| 10 | |||
| 11 | from . import LockBase, NotLocked, NotMyLock, LockTimeout, AlreadyLocked | ||
| 12 | |||
| 13 | |||
| 14 | class SQLiteLockFile(LockBase): | ||
| 15 | "Demonstrate SQL-based locking." | ||
| 16 | |||
| 17 | testdb = None | ||
| 18 | |||
| 19 | def __init__(self, path, threaded=True, timeout=None): | ||
| 20 | """ | ||
| 21 | >>> lock = SQLiteLockFile('somefile') | ||
| 22 | >>> lock = SQLiteLockFile('somefile', threaded=False) | ||
| 23 | """ | ||
| 24 | LockBase.__init__(self, path, threaded, timeout) | ||
| 25 | self.lock_file = unicode(self.lock_file) | ||
| 26 | self.unique_name = unicode(self.unique_name) | ||
| 27 | |||
| 28 | if SQLiteLockFile.testdb is None: | ||
| 29 | import tempfile | ||
| 30 | _fd, testdb = tempfile.mkstemp() | ||
| 31 | os.close(_fd) | ||
| 32 | os.unlink(testdb) | ||
| 33 | del _fd, tempfile | ||
| 34 | SQLiteLockFile.testdb = testdb | ||
| 35 | |||
| 36 | import sqlite3 | ||
| 37 | self.connection = sqlite3.connect(SQLiteLockFile.testdb) | ||
| 38 | |||
| 39 | c = self.connection.cursor() | ||
| 40 | try: | ||
| 41 | c.execute("create table locks" | ||
| 42 | "(" | ||
| 43 | " lock_file varchar(32)," | ||
| 44 | " unique_name varchar(32)" | ||
| 45 | ")") | ||
| 46 | except sqlite3.OperationalError: | ||
| 47 | pass | ||
| 48 | else: | ||
| 49 | self.connection.commit() | ||
| 50 | import atexit | ||
| 51 | atexit.register(os.unlink, SQLiteLockFile.testdb) | ||
| 52 | |||
| 53 | def acquire(self, timeout=None): | ||
| 54 | timeout = timeout if timeout is not None else self.timeout | ||
| 55 | end_time = time.time() | ||
| 56 | if timeout is not None and timeout > 0: | ||
| 57 | end_time += timeout | ||
| 58 | |||
| 59 | if timeout is None: | ||
| 60 | wait = 0.1 | ||
| 61 | elif timeout <= 0: | ||
| 62 | wait = 0 | ||
| 63 | else: | ||
| 64 | wait = timeout / 10 | ||
| 65 | |||
| 66 | cursor = self.connection.cursor() | ||
| 67 | |||
| 68 | while True: | ||
| 69 | if not self.is_locked(): | ||
| 70 | # Not locked. Try to lock it. | ||
| 71 | cursor.execute("insert into locks" | ||
| 72 | " (lock_file, unique_name)" | ||
| 73 | " values" | ||
| 74 | " (?, ?)", | ||
| 75 | (self.lock_file, self.unique_name)) | ||
| 76 | self.connection.commit() | ||
| 77 | |||
| 78 | # Check to see if we are the only lock holder. | ||
| 79 | cursor.execute("select * from locks" | ||
| 80 | " where unique_name = ?", | ||
| 81 | (self.unique_name,)) | ||
| 82 | rows = cursor.fetchall() | ||
| 83 | if len(rows) > 1: | ||
| 84 | # Nope. Someone else got there. Remove our lock. | ||
| 85 | cursor.execute("delete from locks" | ||
| 86 | " where unique_name = ?", | ||
| 87 | (self.unique_name,)) | ||
| 88 | self.connection.commit() | ||
| 89 | else: | ||
| 90 | # Yup. We're done, so go home. | ||
| 91 | return | ||
| 92 | else: | ||
| 93 | # Check to see if we are the only lock holder. | ||
| 94 | cursor.execute("select * from locks" | ||
| 95 | " where unique_name = ?", | ||
| 96 | (self.unique_name,)) | ||
| 97 | rows = cursor.fetchall() | ||
| 98 | if len(rows) == 1: | ||
| 99 | # We're the locker, so go home. | ||
| 100 | return | ||
| 101 | |||
| 102 | # Maybe we should wait a bit longer. | ||
| 103 | if timeout is not None and time.time() > end_time: | ||
| 104 | if timeout > 0: | ||
| 105 | # No more waiting. | ||
| 106 | raise LockTimeout("Timeout waiting to acquire" | ||
| 107 | " lock for %s" % | ||
| 108 | self.path) | ||
| 109 | else: | ||
| 110 | # Someone else has the lock and we are impatient.. | ||
| 111 | raise AlreadyLocked("%s is already locked" % self.path) | ||
| 112 | |||
| 113 | # Well, okay. We'll give it a bit longer. | ||
| 114 | time.sleep(wait) | ||
| 115 | |||
| 116 | def release(self): | ||
| 117 | if not self.is_locked(): | ||
| 118 | raise NotLocked("%s is not locked" % self.path) | ||
| 119 | if not self.i_am_locking(): | ||
| 120 | raise NotMyLock("%s is locked, but not by me (by %s)" % | ||
| 121 | (self.unique_name, self._who_is_locking())) | ||
| 122 | cursor = self.connection.cursor() | ||
| 123 | cursor.execute("delete from locks" | ||
| 124 | " where unique_name = ?", | ||
| 125 | (self.unique_name,)) | ||
| 126 | self.connection.commit() | ||
| 127 | |||
| 128 | def _who_is_locking(self): | ||
| 129 | cursor = self.connection.cursor() | ||
| 130 | cursor.execute("select unique_name from locks" | ||
| 131 | " where lock_file = ?", | ||
| 132 | (self.lock_file,)) | ||
| 133 | return cursor.fetchone()[0] | ||
| 134 | |||
| 135 | def is_locked(self): | ||
| 136 | cursor = self.connection.cursor() | ||
| 137 | cursor.execute("select * from locks" | ||
| 138 | " where lock_file = ?", | ||
| 139 | (self.lock_file,)) | ||
| 140 | rows = cursor.fetchall() | ||
| 141 | return not not rows | ||
| 142 | |||
| 143 | def i_am_locking(self): | ||
| 144 | cursor = self.connection.cursor() | ||
| 145 | cursor.execute("select * from locks" | ||
| 146 | " where lock_file = ?" | ||
| 147 | " and unique_name = ?", | ||
| 148 | (self.lock_file, self.unique_name)) | ||
| 149 | return not not cursor.fetchall() | ||
| 150 | |||
| 151 | def break_lock(self): | ||
| 152 | cursor = self.connection.cursor() | ||
| 153 | cursor.execute("delete from locks" | ||
| 154 | " where lock_file = ?", | ||
| 155 | (self.lock_file,)) | ||
| 156 | self.connection.commit() | ||
diff --git a/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_vendor/lockfile/symlinklockfile.py b/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_vendor/lockfile/symlinklockfile.py new file mode 100644 index 0000000..93ff2b5 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_vendor/lockfile/symlinklockfile.py | |||
| @@ -0,0 +1,70 @@ | |||
| 1 | from __future__ import absolute_import | ||
| 2 | |||
| 3 | import os | ||
| 4 | import time | ||
| 5 | |||
| 6 | from . import (LockBase, NotLocked, NotMyLock, LockTimeout, | ||
| 7 | AlreadyLocked) | ||
| 8 | |||
| 9 | |||
| 10 | class SymlinkLockFile(LockBase): | ||
| 11 | """Lock access to a file using symlink(2).""" | ||
| 12 | |||
| 13 | def __init__(self, path, threaded=True, timeout=None): | ||
| 14 | # super(SymlinkLockFile).__init(...) | ||
| 15 | LockBase.__init__(self, path, threaded, timeout) | ||
| 16 | # split it back! | ||
| 17 | self.unique_name = os.path.split(self.unique_name)[1] | ||
| 18 | |||
| 19 | def acquire(self, timeout=None): | ||
| 20 | # Hopefully unnecessary for symlink. | ||
| 21 | # try: | ||
| 22 | # open(self.unique_name, "wb").close() | ||
| 23 | # except IOError: | ||
| 24 | # raise LockFailed("failed to create %s" % self.unique_name) | ||
| 25 | timeout = timeout if timeout is not None else self.timeout | ||
| 26 | end_time = time.time() | ||
| 27 | if timeout is not None and timeout > 0: | ||
| 28 | end_time += timeout | ||
| 29 | |||
| 30 | while True: | ||
| 31 | # Try and create a symbolic link to it. | ||
| 32 | try: | ||
| 33 | os.symlink(self.unique_name, self.lock_file) | ||
| 34 | except OSError: | ||
| 35 | # Link creation failed. Maybe we've double-locked? | ||
| 36 | if self.i_am_locking(): | ||
| 37 | # Linked to out unique name. Proceed. | ||
| 38 | return | ||
| 39 | else: | ||
| 40 | # Otherwise the lock creation failed. | ||
| 41 | if timeout is not None and time.time() > end_time: | ||
| 42 | if timeout > 0: | ||
| 43 | raise LockTimeout("Timeout waiting to acquire" | ||
| 44 | " lock for %s" % | ||
| 45 | self.path) | ||
| 46 | else: | ||
| 47 | raise AlreadyLocked("%s is already locked" % | ||
| 48 | self.path) | ||
| 49 | time.sleep(timeout / 10 if timeout is not None else 0.1) | ||
| 50 | else: | ||
| 51 | # Link creation succeeded. We're good to go. | ||
| 52 | return | ||
| 53 | |||
| 54 | def release(self): | ||
| 55 | if not self.is_locked(): | ||
| 56 | raise NotLocked("%s is not locked" % self.path) | ||
| 57 | elif not self.i_am_locking(): | ||
| 58 | raise NotMyLock("%s is locked, but not by me" % self.path) | ||
| 59 | os.unlink(self.lock_file) | ||
| 60 | |||
| 61 | def is_locked(self): | ||
| 62 | return os.path.islink(self.lock_file) | ||
| 63 | |||
| 64 | def i_am_locking(self): | ||
| 65 | return (os.path.islink(self.lock_file) | ||
| 66 | and os.readlink(self.lock_file) == self.unique_name) | ||
| 67 | |||
| 68 | def break_lock(self): | ||
| 69 | if os.path.islink(self.lock_file): # exists && link | ||
| 70 | os.unlink(self.lock_file) | ||
