login page
This commit is contained in:
93
Lib/site-packages/pipenv/vendor/shellingham/posix/__init__.py
vendored
Normal file
93
Lib/site-packages/pipenv/vendor/shellingham/posix/__init__.py
vendored
Normal file
@@ -0,0 +1,93 @@
|
||||
import os
|
||||
import re
|
||||
|
||||
from .._core import SHELL_NAMES, ShellDetectionFailure
|
||||
from . import proc, ps
|
||||
|
||||
|
||||
def _get_process_mapping():
|
||||
"""Select a way to obtain process information from the system.
|
||||
|
||||
* `/proc` is used if supported.
|
||||
* The system `ps` utility is used as a fallback option.
|
||||
"""
|
||||
for impl in (proc, ps):
|
||||
try:
|
||||
mapping = impl.get_process_mapping()
|
||||
except EnvironmentError:
|
||||
continue
|
||||
return mapping
|
||||
raise ShellDetectionFailure('compatible proc fs or ps utility is required')
|
||||
|
||||
|
||||
def _iter_process_args(mapping, pid, max_depth):
|
||||
"""Iterator to traverse up the tree, yielding each process's argument list.
|
||||
"""
|
||||
for _ in range(max_depth):
|
||||
try:
|
||||
proc = mapping[pid]
|
||||
except KeyError: # We've reached the root process. Give up.
|
||||
break
|
||||
if proc.args: # Persumably the process should always have a name?
|
||||
yield proc.args
|
||||
pid = proc.ppid # Go up one level.
|
||||
|
||||
|
||||
def _get_login_shell(proc_cmd):
|
||||
"""Form shell information from the SHELL environment variable if possible.
|
||||
"""
|
||||
login_shell = os.environ.get('SHELL', '')
|
||||
if login_shell:
|
||||
proc_cmd = login_shell
|
||||
else:
|
||||
proc_cmd = proc_cmd[1:]
|
||||
return (os.path.basename(proc_cmd).lower(), proc_cmd)
|
||||
|
||||
|
||||
_INTERPRETER_SHELL_NAMES = [
|
||||
(re.compile(r'^python(\d+(\.\d+)?)?$'), {'xonsh'}),
|
||||
]
|
||||
|
||||
|
||||
def _get_interpreter_shell(proc_name, proc_args):
|
||||
"""Get shell invoked via an interpreter.
|
||||
|
||||
Some shells are implemented on, and invoked with an interpreter, e.g. xonsh
|
||||
is commonly executed with an executable Python script. This detects what
|
||||
script the interpreter is actually running, and check whether that looks
|
||||
like a shell.
|
||||
|
||||
See sarugaku/shellingham#26 for rational.
|
||||
"""
|
||||
for pattern, shell_names in _INTERPRETER_SHELL_NAMES:
|
||||
if not pattern.match(proc_name):
|
||||
continue
|
||||
for arg in proc_args:
|
||||
name = os.path.basename(arg).lower()
|
||||
if os.path.isfile(arg) and name in shell_names:
|
||||
return (name, arg)
|
||||
return None
|
||||
|
||||
|
||||
def _get_shell(cmd, *args):
|
||||
if cmd.startswith('-'): # Login shell! Let's use this.
|
||||
return _get_login_shell(cmd)
|
||||
name = os.path.basename(cmd).lower()
|
||||
if name in SHELL_NAMES: # Command looks like a shell.
|
||||
return (name, cmd)
|
||||
shell = _get_interpreter_shell(name, args)
|
||||
if shell:
|
||||
return shell
|
||||
return None
|
||||
|
||||
|
||||
def get_shell(pid=None, max_depth=6):
|
||||
"""Get the shell that the supplied pid or os.getpid() is running in.
|
||||
"""
|
||||
pid = str(pid or os.getpid())
|
||||
mapping = _get_process_mapping()
|
||||
for proc_args in _iter_process_args(mapping, pid, max_depth):
|
||||
shell = _get_shell(*proc_args)
|
||||
if shell:
|
||||
return shell
|
||||
return None
|
||||
BIN
Lib/site-packages/pipenv/vendor/shellingham/posix/__pycache__/__init__.cpython-38.pyc
vendored
Normal file
BIN
Lib/site-packages/pipenv/vendor/shellingham/posix/__pycache__/__init__.cpython-38.pyc
vendored
Normal file
Binary file not shown.
BIN
Lib/site-packages/pipenv/vendor/shellingham/posix/__pycache__/_core.cpython-38.pyc
vendored
Normal file
BIN
Lib/site-packages/pipenv/vendor/shellingham/posix/__pycache__/_core.cpython-38.pyc
vendored
Normal file
Binary file not shown.
BIN
Lib/site-packages/pipenv/vendor/shellingham/posix/__pycache__/_proc.cpython-38.pyc
vendored
Normal file
BIN
Lib/site-packages/pipenv/vendor/shellingham/posix/__pycache__/_proc.cpython-38.pyc
vendored
Normal file
Binary file not shown.
BIN
Lib/site-packages/pipenv/vendor/shellingham/posix/__pycache__/_ps.cpython-38.pyc
vendored
Normal file
BIN
Lib/site-packages/pipenv/vendor/shellingham/posix/__pycache__/_ps.cpython-38.pyc
vendored
Normal file
Binary file not shown.
BIN
Lib/site-packages/pipenv/vendor/shellingham/posix/__pycache__/proc.cpython-38.pyc
vendored
Normal file
BIN
Lib/site-packages/pipenv/vendor/shellingham/posix/__pycache__/proc.cpython-38.pyc
vendored
Normal file
Binary file not shown.
BIN
Lib/site-packages/pipenv/vendor/shellingham/posix/__pycache__/ps.cpython-38.pyc
vendored
Normal file
BIN
Lib/site-packages/pipenv/vendor/shellingham/posix/__pycache__/ps.cpython-38.pyc
vendored
Normal file
Binary file not shown.
3
Lib/site-packages/pipenv/vendor/shellingham/posix/_core.py
vendored
Normal file
3
Lib/site-packages/pipenv/vendor/shellingham/posix/_core.py
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
import collections
|
||||
|
||||
Process = collections.namedtuple('Process', 'args pid ppid')
|
||||
35
Lib/site-packages/pipenv/vendor/shellingham/posix/_proc.py
vendored
Normal file
35
Lib/site-packages/pipenv/vendor/shellingham/posix/_proc.py
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
import os
|
||||
import re
|
||||
|
||||
from ._default import Process
|
||||
|
||||
|
||||
STAT_PPID = 3
|
||||
STAT_TTY = 6
|
||||
|
||||
|
||||
def get_process_mapping():
|
||||
"""Try to look up the process tree via the /proc interface.
|
||||
"""
|
||||
with open('/proc/{0}/stat'.format(os.getpid())) as f:
|
||||
self_tty = f.read().split()[STAT_TTY]
|
||||
processes = {}
|
||||
for pid in os.listdir('/proc'):
|
||||
if not pid.isdigit():
|
||||
continue
|
||||
try:
|
||||
stat = '/proc/{0}/stat'.format(pid)
|
||||
cmdline = '/proc/{0}/cmdline'.format(pid)
|
||||
with open(stat) as fstat, open(cmdline) as fcmdline:
|
||||
stat = re.findall(r'\(.+\)|\S+', fstat.read())
|
||||
cmd = fcmdline.read().split('\x00')[:-1]
|
||||
ppid = stat[STAT_PPID]
|
||||
tty = stat[STAT_TTY]
|
||||
if tty == self_tty:
|
||||
processes[pid] = Process(
|
||||
args=tuple(cmd), pid=pid, ppid=ppid,
|
||||
)
|
||||
except IOError:
|
||||
# Process has disappeared - just ignore it.
|
||||
continue
|
||||
return processes
|
||||
27
Lib/site-packages/pipenv/vendor/shellingham/posix/_ps.py
vendored
Normal file
27
Lib/site-packages/pipenv/vendor/shellingham/posix/_ps.py
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
import collections
|
||||
import shlex
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
|
||||
Process = collections.namedtuple('Process', 'args pid ppid')
|
||||
|
||||
|
||||
def get_process_mapping():
|
||||
"""Try to look up the process tree via the output of `ps`.
|
||||
"""
|
||||
output = subprocess.check_output([
|
||||
'ps', '-ww', '-o', 'pid=', '-o', 'ppid=', '-o', 'args=',
|
||||
])
|
||||
if not isinstance(output, str):
|
||||
output = output.decode(sys.stdout.encoding)
|
||||
processes = {}
|
||||
for line in output.split('\n'):
|
||||
try:
|
||||
pid, ppid, args = line.strip().split(None, 2)
|
||||
except ValueError:
|
||||
continue
|
||||
processes[pid] = Process(
|
||||
args=tuple(shlex.split(args)), pid=pid, ppid=ppid,
|
||||
)
|
||||
return processes
|
||||
72
Lib/site-packages/pipenv/vendor/shellingham/posix/proc.py
vendored
Normal file
72
Lib/site-packages/pipenv/vendor/shellingham/posix/proc.py
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
import io
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
from ._core import Process
|
||||
|
||||
|
||||
STAT_PPID = 3
|
||||
STAT_TTY = 6
|
||||
|
||||
STAT_PATTERN = re.compile(r'\(.+\)|\S+')
|
||||
|
||||
|
||||
def detect_proc():
|
||||
"""Detect /proc filesystem style.
|
||||
|
||||
This checks the /proc/{pid} directory for possible formats. Returns one of
|
||||
the followings as str:
|
||||
|
||||
* `stat`: Linux-style, i.e. ``/proc/{pid}/stat``.
|
||||
* `status`: BSD-style, i.e. ``/proc/{pid}/status``.
|
||||
"""
|
||||
pid = os.getpid()
|
||||
for name in ('stat', 'status'):
|
||||
if os.path.exists(os.path.join('/proc', str(pid), name)):
|
||||
return name
|
||||
raise ProcFormatError('unsupported proc format')
|
||||
|
||||
|
||||
def _get_stat(pid, name):
|
||||
path = os.path.join('/proc', str(pid), name)
|
||||
with io.open(path, encoding='ascii', errors='replace') as f:
|
||||
# We only care about TTY and PPID -- all numbers.
|
||||
parts = STAT_PATTERN.findall(f.read())
|
||||
return parts[STAT_TTY], parts[STAT_PPID]
|
||||
|
||||
|
||||
def _get_cmdline(pid):
|
||||
path = os.path.join('/proc', str(pid), 'cmdline')
|
||||
encoding = sys.getfilesystemencoding() or 'utf-8'
|
||||
with io.open(path, encoding=encoding, errors='replace') as f:
|
||||
# XXX: Command line arguments can be arbitrary byte sequences, not
|
||||
# necessarily decodable. For Shellingham's purpose, however, we don't
|
||||
# care. (pypa/pipenv#2820)
|
||||
# cmdline appends an extra NULL at the end, hence the [:-1].
|
||||
return tuple(f.read().split('\0')[:-1])
|
||||
|
||||
|
||||
class ProcFormatError(EnvironmentError):
|
||||
pass
|
||||
|
||||
|
||||
def get_process_mapping():
|
||||
"""Try to look up the process tree via the /proc interface.
|
||||
"""
|
||||
stat_name = detect_proc()
|
||||
self_tty = _get_stat(os.getpid(), stat_name)[0]
|
||||
processes = {}
|
||||
for pid in os.listdir('/proc'):
|
||||
if not pid.isdigit():
|
||||
continue
|
||||
try:
|
||||
tty, ppid = _get_stat(pid, stat_name)
|
||||
if tty != self_tty:
|
||||
continue
|
||||
args = _get_cmdline(pid)
|
||||
processes[pid] = Process(args=args, pid=pid, ppid=ppid)
|
||||
except IOError:
|
||||
# Process has disappeared - just ignore it.
|
||||
continue
|
||||
return processes
|
||||
45
Lib/site-packages/pipenv/vendor/shellingham/posix/ps.py
vendored
Normal file
45
Lib/site-packages/pipenv/vendor/shellingham/posix/ps.py
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
import errno
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
from ._core import Process
|
||||
|
||||
|
||||
class PsNotAvailable(EnvironmentError):
|
||||
pass
|
||||
|
||||
|
||||
def get_process_mapping():
|
||||
"""Try to look up the process tree via the output of `ps`.
|
||||
"""
|
||||
try:
|
||||
output = subprocess.check_output([
|
||||
'ps', '-ww', '-o', 'pid=', '-o', 'ppid=', '-o', 'args=',
|
||||
])
|
||||
except OSError as e: # Python 2-compatible FileNotFoundError.
|
||||
if e.errno != errno.ENOENT:
|
||||
raise
|
||||
raise PsNotAvailable('ps not found')
|
||||
except subprocess.CalledProcessError as e:
|
||||
# `ps` can return 1 if the process list is completely empty.
|
||||
# (sarugaku/shellingham#15)
|
||||
if not e.output.strip():
|
||||
return {}
|
||||
raise
|
||||
if not isinstance(output, str):
|
||||
encoding = sys.getfilesystemencoding() or sys.getdefaultencoding()
|
||||
output = output.decode(encoding)
|
||||
processes = {}
|
||||
for line in output.split('\n'):
|
||||
try:
|
||||
pid, ppid, args = line.strip().split(None, 2)
|
||||
# XXX: This is not right, but we are really out of options.
|
||||
# ps does not offer a sane way to decode the argument display,
|
||||
# and this is "Good Enough" for obtaining shell names. Hopefully
|
||||
# people don't name their shell with a space, or have something
|
||||
# like "/usr/bin/xonsh is uber". (sarugaku/shellingham#14)
|
||||
args = tuple(a.strip() for a in args.split(' '))
|
||||
except ValueError:
|
||||
continue
|
||||
processes[pid] = Process(args=args, pid=pid, ppid=ppid)
|
||||
return processes
|
||||
Reference in New Issue
Block a user