mirror of
https://github.com/xonsh/xonsh.git
synced 2025-03-04 00:14:41 +01:00
Add uname command, Update uptime comand (#3909)
* Add uname support * Changelog addition * Migration to platform module * Update uptime.py for the last version Merge the original uptime module to a single file Change the bootime() return be stay compatible with xonsh Add support for Haiku , suppose to close #3882 Add dependency from uptime to support to MacOS 10.10 by add _posix.c file. * Update uptime.py for the last version Merge the original uptime module to a single file Change the bootime() return be stay compatible with xonsh Add support for Haiku , suppose to close #3882 Add dependency from uptime to support to MacOS 10.10 by add _posix.c file. * typo fix * black reformat * remove usage of print * black is black * add original test for uptime convert original test via 2to3 black reformat tests * strange syntaxe fixe for flaske8 * black the incredible tool it stop a bug fixe just because it THE tool it want a return for make less readable code * flake8 the famous tool it permit to stop a big fixe without any information's about the trouble * workaround about xonsh CI don't respect docstring specs * RISC OS only comment thing * black is a good jock in a CI * black is a good jock in a CI * roll back uptime.py * look if we can make it work * fixe all i understand * add command in corutils alias * reformat uptime.py with black * fixe version * try with xonsh xp.LIBC lib * black in a CI is a stupid thing * stupid Windows and it \r * use os.linestep * use newline simple wrapper * use newline simple wrapper * use newline simple wrapper * use newline simple wrapper * try osx rollback method * fixe * fixe * a test on window via the CI because i haven't the OS * a test on window via the CI because i haven't the OS * a test on window via the CI because i haven't the OS * fix: black: format * refactor: update uname command now has auto-completions * docs: update news item and fix qa error * refactor: remove unused file * fix: qa imports * refactor: update getting boottime fallback to monotonic time on unix * fix: update haiku compatibility in uptime * refactor: add uptime to aliases * refactor: move xoreutils tests * fix: call aliases using xonsh Co-authored-by: Tuux <tuxa@rtnp.org> Co-authored-by: Noortheen Raja <jnoortheen@gmail.com>
This commit is contained in:
parent
70dd8bf24b
commit
343ea33998
11 changed files with 365 additions and 217 deletions
23
news/fixe_uptime.rst
Normal file
23
news/fixe_uptime.rst
Normal file
|
@ -0,0 +1,23 @@
|
|||
**Added:**
|
||||
|
||||
* added ``xonsh-uname`` command to ``xoreutils``
|
||||
|
||||
**Changed:**
|
||||
|
||||
* Update uptime lib by the last one from Pypi
|
||||
|
||||
**Deprecated:**
|
||||
|
||||
* <news item>
|
||||
|
||||
**Removed:**
|
||||
|
||||
* <news item>
|
||||
|
||||
**Fixed:**
|
||||
|
||||
* <news item>
|
||||
|
||||
**Security:**
|
||||
|
||||
* <news item>
|
4
setup.py
4
setup.py
|
@ -355,7 +355,9 @@ def main():
|
|||
"pytest11": ["xonsh = xonsh.pytest_plugin"],
|
||||
"console_scripts": [
|
||||
"xonsh = xonsh.main:main",
|
||||
"xonsh-cat = xonsh.xoreutils.cat:cat_main",
|
||||
"xonsh-cat = xonsh.xoreutils.cat:main",
|
||||
"xonsh-uname = xonsh.xoreutils.uname:main",
|
||||
"xonsh-uptime = xonsh.xoreutils.uptime:main",
|
||||
],
|
||||
}
|
||||
skw["cmdclass"]["develop"] = xdevelop
|
||||
|
|
|
@ -1,107 +1,10 @@
|
|||
import io
|
||||
import os
|
||||
import tempfile
|
||||
|
||||
import pytest
|
||||
|
||||
from xonsh.xoreutils import _which, uptime, cat
|
||||
from xonsh.tools import ON_WINDOWS
|
||||
from xonsh.platform import DEFAULT_ENCODING
|
||||
|
||||
|
||||
class TestWhich:
|
||||
# Tests for the _whichgen function which is the only thing we
|
||||
# use from the _which.py module.
|
||||
def setup(self):
|
||||
# Setup two folders with some test files.
|
||||
self.testdirs = [tempfile.TemporaryDirectory(), tempfile.TemporaryDirectory()]
|
||||
if ON_WINDOWS:
|
||||
self.testapps = ["whichtestapp1.exe", "whichtestapp2.wta"]
|
||||
self.exts = [".EXE"]
|
||||
else:
|
||||
self.testapps = ["whichtestapp1"]
|
||||
self.exts = None
|
||||
for app in self.testapps:
|
||||
for d in self.testdirs:
|
||||
path = os.path.join(d.name, app)
|
||||
with open(path, "wb") as f:
|
||||
f.write(b"")
|
||||
os.chmod(path, 0o755)
|
||||
|
||||
def teardown_module(self):
|
||||
for d in self.testdirs:
|
||||
d.cleanup()
|
||||
|
||||
def test_whichgen(self):
|
||||
testdir = self.testdirs[0].name
|
||||
arg = "whichtestapp1"
|
||||
matches = list(_which.whichgen(arg, path=[testdir], exts=self.exts))
|
||||
assert len(matches) == 1
|
||||
assert self._file_match(matches[0][0], os.path.join(testdir, arg))
|
||||
|
||||
def test_whichgen_failure(self):
|
||||
testdir = self.testdirs[0].name
|
||||
arg = "not_a_file"
|
||||
matches = list(_which.whichgen(arg, path=[testdir], exts=self.exts))
|
||||
assert len(matches) == 0
|
||||
|
||||
def test_whichgen_verbose(self):
|
||||
testdir = self.testdirs[0].name
|
||||
arg = "whichtestapp1"
|
||||
matches = list(
|
||||
_which.whichgen(arg, path=[testdir], exts=self.exts, verbose=True)
|
||||
)
|
||||
assert len(matches) == 1
|
||||
match, from_where = matches[0]
|
||||
assert self._file_match(match, os.path.join(testdir, arg))
|
||||
assert from_where == "from given path element 0"
|
||||
|
||||
def test_whichgen_multiple(self):
|
||||
testdir0 = self.testdirs[0].name
|
||||
testdir1 = self.testdirs[1].name
|
||||
arg = "whichtestapp1"
|
||||
matches = list(_which.whichgen(arg, path=[testdir0, testdir1], exts=self.exts))
|
||||
assert len(matches) == 2
|
||||
assert self._file_match(matches[0][0], os.path.join(testdir0, arg))
|
||||
assert self._file_match(matches[1][0], os.path.join(testdir1, arg))
|
||||
|
||||
if ON_WINDOWS:
|
||||
|
||||
def test_whichgen_ext_failure(self):
|
||||
testdir = self.testdirs[0].name
|
||||
arg = "whichtestapp2"
|
||||
matches = list(_which.whichgen(arg, path=[testdir], exts=self.exts))
|
||||
assert len(matches) == 0
|
||||
|
||||
def test_whichgen_ext_success(self):
|
||||
testdir = self.testdirs[0].name
|
||||
arg = "whichtestapp2"
|
||||
matches = list(_which.whichgen(arg, path=[testdir], exts=[".wta"]))
|
||||
assert len(matches) == 1
|
||||
assert self._file_match(matches[0][0], os.path.join(testdir, arg))
|
||||
|
||||
def _file_match(self, path1, path2):
|
||||
if ON_WINDOWS:
|
||||
path1 = os.path.normpath(os.path.normcase(path1))
|
||||
path2 = os.path.normpath(os.path.normcase(path2))
|
||||
path1 = os.path.splitext(path1)[0]
|
||||
path2 = os.path.splitext(path2)[0]
|
||||
return path1 == path2
|
||||
else:
|
||||
return os.path.samefile(path1, path2)
|
||||
|
||||
|
||||
def test_uptime():
|
||||
up = uptime.uptime()
|
||||
assert up is not None
|
||||
assert up > 0.0
|
||||
|
||||
|
||||
def test_boottime():
|
||||
bt = uptime.boottime()
|
||||
assert bt is not None
|
||||
assert bt > 0.0
|
||||
assert uptime._BOOTTIME is not None
|
||||
assert uptime._BOOTTIME > 0.0
|
||||
from xonsh.xoreutils import cat
|
||||
|
||||
|
||||
@pytest.fixture
|
15
tests/xoreutils/test_uname.py
Normal file
15
tests/xoreutils/test_uname.py
Normal file
|
@ -0,0 +1,15 @@
|
|||
import platform
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def uname(xession, load_xontrib):
|
||||
load_xontrib("coreutils")
|
||||
return xession.aliases["uname"]
|
||||
|
||||
|
||||
def test_uname_without_args(uname):
|
||||
out = uname(["-a"])
|
||||
|
||||
assert out.startswith(platform.uname().system)
|
21
tests/xoreutils/test_uptime.py
Normal file
21
tests/xoreutils/test_uptime.py
Normal file
|
@ -0,0 +1,21 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
import datetime
|
||||
import sys
|
||||
|
||||
sys.path.insert(0, ".")
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def uptime(xession, load_xontrib):
|
||||
load_xontrib("coreutils")
|
||||
return xession.aliases["uptime"]
|
||||
|
||||
|
||||
def test_uptime(uptime):
|
||||
out = uptime([])
|
||||
delta = datetime.timedelta(seconds=float(out))
|
||||
# make sure that it returns a positive time lapse
|
||||
assert delta > datetime.timedelta(microseconds=1)
|
87
tests/xoreutils/test_which.py
Normal file
87
tests/xoreutils/test_which.py
Normal file
|
@ -0,0 +1,87 @@
|
|||
import os
|
||||
import tempfile
|
||||
|
||||
from xonsh.tools import ON_WINDOWS
|
||||
from xonsh.xoreutils import _which
|
||||
|
||||
|
||||
class TestWhich:
|
||||
# Tests for the _whichgen function which is the only thing we
|
||||
# use from the _which.py module.
|
||||
def setup(self):
|
||||
# Setup two folders with some test files.
|
||||
self.testdirs = [tempfile.TemporaryDirectory(), tempfile.TemporaryDirectory()]
|
||||
if ON_WINDOWS:
|
||||
self.testapps = ["whichtestapp1.exe", "whichtestapp2.wta"]
|
||||
self.exts = [".EXE"]
|
||||
else:
|
||||
self.testapps = ["whichtestapp1"]
|
||||
self.exts = None
|
||||
for app in self.testapps:
|
||||
for d in self.testdirs:
|
||||
path = os.path.join(d.name, app)
|
||||
with open(path, "wb") as f:
|
||||
f.write(b"")
|
||||
os.chmod(path, 0o755)
|
||||
|
||||
def teardown_module(self):
|
||||
for d in self.testdirs:
|
||||
d.cleanup()
|
||||
|
||||
def test_whichgen(self):
|
||||
testdir = self.testdirs[0].name
|
||||
arg = "whichtestapp1"
|
||||
matches = list(_which.whichgen(arg, path=[testdir], exts=self.exts))
|
||||
assert len(matches) == 1
|
||||
assert self._file_match(matches[0][0], os.path.join(testdir, arg))
|
||||
|
||||
def test_whichgen_failure(self):
|
||||
testdir = self.testdirs[0].name
|
||||
arg = "not_a_file"
|
||||
matches = list(_which.whichgen(arg, path=[testdir], exts=self.exts))
|
||||
assert len(matches) == 0
|
||||
|
||||
def test_whichgen_verbose(self):
|
||||
testdir = self.testdirs[0].name
|
||||
arg = "whichtestapp1"
|
||||
matches = list(
|
||||
_which.whichgen(arg, path=[testdir], exts=self.exts, verbose=True)
|
||||
)
|
||||
assert len(matches) == 1
|
||||
match, from_where = matches[0]
|
||||
assert self._file_match(match, os.path.join(testdir, arg))
|
||||
assert from_where == "from given path element 0"
|
||||
|
||||
def test_whichgen_multiple(self):
|
||||
testdir0 = self.testdirs[0].name
|
||||
testdir1 = self.testdirs[1].name
|
||||
arg = "whichtestapp1"
|
||||
matches = list(_which.whichgen(arg, path=[testdir0, testdir1], exts=self.exts))
|
||||
assert len(matches) == 2
|
||||
assert self._file_match(matches[0][0], os.path.join(testdir0, arg))
|
||||
assert self._file_match(matches[1][0], os.path.join(testdir1, arg))
|
||||
|
||||
if ON_WINDOWS:
|
||||
|
||||
def test_whichgen_ext_failure(self):
|
||||
testdir = self.testdirs[0].name
|
||||
arg = "whichtestapp2"
|
||||
matches = list(_which.whichgen(arg, path=[testdir], exts=self.exts))
|
||||
assert len(matches) == 0
|
||||
|
||||
def test_whichgen_ext_success(self):
|
||||
testdir = self.testdirs[0].name
|
||||
arg = "whichtestapp2"
|
||||
matches = list(_which.whichgen(arg, path=[testdir], exts=[".wta"]))
|
||||
assert len(matches) == 1
|
||||
assert self._file_match(matches[0][0], os.path.join(testdir, arg))
|
||||
|
||||
def _file_match(self, path1, path2):
|
||||
if ON_WINDOWS:
|
||||
path1 = os.path.normpath(os.path.normcase(path1))
|
||||
path2 = os.path.normpath(os.path.normcase(path2))
|
||||
path1 = os.path.splitext(path1)[0]
|
||||
path2 = os.path.splitext(path2)[0]
|
||||
return path1 == path2
|
||||
else:
|
||||
return os.path.samefile(path1, path2)
|
|
@ -5,7 +5,7 @@ import time
|
|||
|
||||
import xonsh.procs.pipelines as xpp
|
||||
from xonsh.built_ins import XSH
|
||||
from xonsh.xoreutils.util import arg_handler
|
||||
from xonsh.xoreutils.util import arg_handler, run_alias
|
||||
|
||||
|
||||
def _cat_line(
|
||||
|
@ -156,14 +156,9 @@ Examples:
|
|||
# --version output version information and exit"""
|
||||
|
||||
|
||||
def cat_main(args=None):
|
||||
import sys
|
||||
from xonsh.main import setup
|
||||
|
||||
setup()
|
||||
args = sys.argv[1:] if args is None else args
|
||||
cat(args, sys.stdin, sys.stdout, sys.stderr)
|
||||
def main(args=None):
|
||||
run_alias("cat", args)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
cat_main()
|
||||
main()
|
||||
|
|
96
xonsh/xoreutils/uname.py
Normal file
96
xonsh/xoreutils/uname.py
Normal file
|
@ -0,0 +1,96 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Provides a cross-platform way to figure out the system uname.
|
||||
|
||||
This version of uname was written in Python for the xonsh project: http://xon.sh
|
||||
|
||||
Based on cat from GNU coreutils: http://www.gnu.org/software/coreutils/
|
||||
"""
|
||||
import platform
|
||||
import sys
|
||||
|
||||
from xonsh.cli_utils import ArgParserAlias
|
||||
|
||||
|
||||
def uname_fn(
|
||||
all=False,
|
||||
kernel_name=False,
|
||||
node_name=False,
|
||||
kernel_release=False,
|
||||
kernel_version=False,
|
||||
machine=False,
|
||||
processor=False,
|
||||
hardware_platform=False,
|
||||
operating_system=False,
|
||||
):
|
||||
"""This version of uname was written in Python for the xonsh project: https://xon.sh
|
||||
|
||||
Based on uname from GNU coreutils: http://www.gnu.org/software/coreutils/
|
||||
|
||||
|
||||
Parameters
|
||||
----------
|
||||
all : -a, --all
|
||||
print all information, in the following order, except omit -p and -i if unknown
|
||||
kernel_name : -s, --kernel-name
|
||||
print the kernel name
|
||||
node_name : -n, --nodename
|
||||
print the network node hostname
|
||||
kernel_release : -r, --kernel-release
|
||||
print the kernel release
|
||||
kernel_version : -v, --kernel-version
|
||||
print the kernel version
|
||||
machine : -m, --machine
|
||||
print the machine hardware name
|
||||
processor : -p, --processor
|
||||
print the processor type (non-portable)
|
||||
hardware_platform : -i, --hardware-platform
|
||||
print the hardware platform (non-portable)
|
||||
operating_system : -o, --operating-system
|
||||
print the operating system
|
||||
"""
|
||||
|
||||
info = platform.uname()
|
||||
|
||||
def gen_lines():
|
||||
if all or node_name:
|
||||
yield info.node
|
||||
|
||||
if all or kernel_release:
|
||||
yield info.release
|
||||
|
||||
if all or kernel_version:
|
||||
yield info.version
|
||||
|
||||
if all or machine:
|
||||
yield info.machine
|
||||
|
||||
if all or processor:
|
||||
yield info.processor or "unknown"
|
||||
|
||||
if all or hardware_platform:
|
||||
yield "unknown"
|
||||
|
||||
if all or operating_system:
|
||||
yield sys.platform
|
||||
|
||||
lines = list(gen_lines())
|
||||
if all or kernel_name or (not lines):
|
||||
lines.insert(0, info.system)
|
||||
line = " ".join(lines)
|
||||
|
||||
return line
|
||||
|
||||
|
||||
uname = ArgParserAlias(func=uname_fn, has_args=True, prog="uname")
|
||||
|
||||
|
||||
def main(args=None):
|
||||
from xonsh.xoreutils.util import run_alias
|
||||
|
||||
run_alias("uname", args)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
|
@ -10,23 +10,20 @@ to standard output.
|
|||
This file was forked from the uptime project: https://github.com/Cairnarvon/uptime
|
||||
Copyright (c) 2012, Koen Crolla, All rights reserved.
|
||||
"""
|
||||
import contextlib
|
||||
import ctypes
|
||||
import functools
|
||||
import os
|
||||
import struct
|
||||
import sys
|
||||
import time
|
||||
import ctypes
|
||||
import struct
|
||||
import typing as tp
|
||||
|
||||
import xonsh.platform as xp
|
||||
import xonsh.lazyimps as xlimps
|
||||
import xonsh.lazyasd as xl
|
||||
|
||||
_BOOTTIME: tp.Optional[float] = None
|
||||
import xonsh.platform as xp
|
||||
|
||||
|
||||
def _uptime_osx():
|
||||
def _boot_time_osx() -> "float|None":
|
||||
"""Returns the uptime on mac / darwin."""
|
||||
global _BOOTTIME
|
||||
bt = xlimps.macutils.sysctlbyname(b"kern.boottime", return_str=False)
|
||||
if len(bt) == 4:
|
||||
bt = struct.unpack_from("@hh", bt)
|
||||
|
@ -39,62 +36,50 @@ def _uptime_osx():
|
|||
bt = bt[0] + bt[1] * 1e-6
|
||||
if bt == 0.0:
|
||||
return None
|
||||
_BOOTTIME = bt
|
||||
return time.time() - bt
|
||||
return bt
|
||||
|
||||
|
||||
def _uptime_linux():
|
||||
"""Returns uptime in seconds or None, on Linux."""
|
||||
# With procfs
|
||||
try:
|
||||
with open("/proc/uptime") as f:
|
||||
up = float(f.readline().split()[0])
|
||||
return up
|
||||
except (OSError, ValueError):
|
||||
pass
|
||||
buf = ctypes.create_string_buffer(128) # 64 suffices on 32-bit, whatever.
|
||||
if xp.LIBC.sysinfo(buf) < 0:
|
||||
return None
|
||||
up = struct.unpack_from("@l", buf.raw)[0]
|
||||
if up < 0:
|
||||
up = None
|
||||
return up
|
||||
|
||||
|
||||
def _boottime_linux():
|
||||
def _boot_time_linux() -> "float|None":
|
||||
"""A way to figure out the boot time directly on Linux."""
|
||||
global _BOOTTIME
|
||||
# from the answer here -
|
||||
# https://stackoverflow.com/questions/42471475/fastest-way-to-get-system-uptime-in-python-in-linux
|
||||
bt_flag = getattr(time, "CLOCK_BOOTTIME", None)
|
||||
if bt_flag is not None:
|
||||
return time.clock_gettime(bt_flag)
|
||||
try:
|
||||
with open("/proc/stat") as f:
|
||||
for line in f:
|
||||
if line.startswith("btime"):
|
||||
_BOOTTIME = float(line.split()[1])
|
||||
return _BOOTTIME
|
||||
return float(line.split()[1])
|
||||
except (OSError, IndexError):
|
||||
return None
|
||||
|
||||
|
||||
def _uptime_amiga():
|
||||
def _boot_time_amiga() -> "float|None":
|
||||
"""Returns uptime in seconds or None, on AmigaOS."""
|
||||
global _BOOTTIME
|
||||
try:
|
||||
_BOOTTIME = os.stat("RAM:").st_ctime
|
||||
return time.time() - _BOOTTIME
|
||||
return os.stat("RAM:").st_ctime
|
||||
except (NameError, OSError):
|
||||
return None
|
||||
|
||||
|
||||
def _uptime_beos():
|
||||
def _boot_time_beos() -> "float|None":
|
||||
"""Returns uptime in seconds on None, on BeOS/Haiku."""
|
||||
if not hasattr(xp.LIBC, "system_time"):
|
||||
return None
|
||||
xp.LIBC.system_time.restype = ctypes.c_int64
|
||||
return xp.LIBC.system_time() / 1000000.0
|
||||
return time.time() - (xp.LIBC.system_time() / 1000000.0)
|
||||
|
||||
|
||||
def _uptime_bsd():
|
||||
def _boot_time_bsd() -> "float|None":
|
||||
"""Returns uptime in seconds or None, on BSD (including OS X)."""
|
||||
global _BOOTTIME
|
||||
# https://docs.python.org/3/library/time.html#time.CLOCK_UPTIME
|
||||
with contextlib.suppress(Exception):
|
||||
ut_flag = getattr(time, "CLOCK_UPTIME", None)
|
||||
if ut_flag is not None:
|
||||
ut = time.clock_gettime(ut_flag)
|
||||
return time.time() - ut
|
||||
|
||||
if not hasattr(xp.LIBC, "sysctlbyname"):
|
||||
# Not BSD.
|
||||
return None
|
||||
|
@ -111,24 +96,20 @@ def _uptime_bsd():
|
|||
# OS X disagrees what that second value is.
|
||||
if usec > 1000000:
|
||||
usec = 0.0
|
||||
_BOOTTIME = sec + usec / 1000000.0
|
||||
up = time.time() - _BOOTTIME
|
||||
if up < 0:
|
||||
up = None
|
||||
return up
|
||||
return sec + usec / 1000000.0
|
||||
|
||||
|
||||
def _uptime_minix():
|
||||
def _boot_time_minix():
|
||||
"""Returns uptime in seconds or None, on MINIX."""
|
||||
try:
|
||||
with open("/proc/uptime") as f:
|
||||
up = float(f.read())
|
||||
return up
|
||||
return time.time() - up
|
||||
except (OSError, ValueError):
|
||||
return None
|
||||
|
||||
|
||||
def _uptime_plan9():
|
||||
def _boot_time_plan9():
|
||||
"""Returns uptime in seconds or None, on Plan 9."""
|
||||
# Apparently Plan 9 only has Python 2.2, which I'm not prepared to
|
||||
# support. Maybe some Linuxes implement /dev/time, though, someone was
|
||||
|
@ -141,19 +122,19 @@ def _uptime_plan9():
|
|||
# -- cons(3)
|
||||
with open("/dev/time") as f:
|
||||
s, ns, ct, cf = f.read().split()
|
||||
return float(ct) / float(cf)
|
||||
return time.time() - (float(ct) / float(cf))
|
||||
except (OSError, ValueError):
|
||||
return None
|
||||
|
||||
|
||||
def _uptime_solaris():
|
||||
def _boot_time_solaris():
|
||||
"""Returns uptime in seconds or None, on Solaris."""
|
||||
global _BOOTTIME
|
||||
try:
|
||||
kstat = ctypes.CDLL("libkstat.so")
|
||||
except (AttributeError, OSError):
|
||||
return None
|
||||
|
||||
_BOOTTIME = None
|
||||
# kstat doesn't have uptime, but it does have boot time.
|
||||
# Unfortunately, getting at it isn't perfectly straightforward.
|
||||
# First, let's pretend to be kstat.h
|
||||
|
@ -202,83 +183,93 @@ def _uptime_solaris():
|
|||
_BOOTTIME = data.contents.value.time
|
||||
# Clean-up.
|
||||
kstat.kstat_close(kc)
|
||||
if _BOOTTIME is not None:
|
||||
return time.time() - _BOOTTIME
|
||||
return None
|
||||
return _BOOTTIME
|
||||
|
||||
|
||||
def _uptime_syllable():
|
||||
def _boot_time_syllable():
|
||||
"""Returns uptime in seconds or None, on Syllable."""
|
||||
global _BOOTTIME
|
||||
try:
|
||||
_BOOTTIME = os.stat("/dev/pty/mst/pty0").st_mtime
|
||||
return time.time() - _BOOTTIME
|
||||
return os.stat("/dev/pty/mst/pty0").st_mtime
|
||||
except (NameError, OSError):
|
||||
return None
|
||||
|
||||
|
||||
def _uptime_windows():
|
||||
def _boot_time_windows():
|
||||
"""
|
||||
Returns uptime in seconds or None, on Windows. Warning: may return
|
||||
incorrect answers after 49.7 days on versions older than Vista.
|
||||
"""
|
||||
uptime = None
|
||||
if hasattr(xp.LIBC, "GetTickCount64"):
|
||||
# Vista/Server 2008 or later.
|
||||
xp.LIBC.GetTickCount64.restype = ctypes.c_uint64
|
||||
return xp.LIBC.GetTickCount64() / 1000.0
|
||||
uptime = xp.LIBC.GetTickCount64() / 1000.0
|
||||
if hasattr(xp.LIBC, "GetTickCount"):
|
||||
# WinCE and Win2k or later; gives wrong answers after 49.7 days.
|
||||
xp.LIBC.GetTickCount.restype = ctypes.c_uint32
|
||||
return xp.LIBC.GetTickCount() / 1000.0
|
||||
uptime = xp.LIBC.GetTickCount() / 1000.0
|
||||
if uptime:
|
||||
return time.time() - uptime
|
||||
return None
|
||||
|
||||
|
||||
@xl.lazyobject
|
||||
def _UPTIME_FUNCS():
|
||||
return {
|
||||
"amiga": _uptime_amiga,
|
||||
"aros12": _uptime_amiga,
|
||||
"beos5": _uptime_beos,
|
||||
"cygwin": _uptime_linux,
|
||||
"darwin": _uptime_osx,
|
||||
"haiku1": _uptime_beos,
|
||||
"linux": _uptime_linux,
|
||||
"linux-armv71": _uptime_linux,
|
||||
"linux2": _uptime_linux,
|
||||
"minix3": _uptime_minix,
|
||||
"sunos5": _uptime_solaris,
|
||||
"syllable": _uptime_syllable,
|
||||
"win32": _uptime_windows,
|
||||
"wince": _uptime_windows,
|
||||
}
|
||||
def _boot_time_monotonic():
|
||||
# https://stackoverflow.com/a/68197354/5048394
|
||||
if hasattr(time, "CLOCK_MONOTONIC"):
|
||||
# this will work on unix systems
|
||||
monotime = time.clock_gettime(time.CLOCK_MONOTONIC)
|
||||
else:
|
||||
monotime = time.time()
|
||||
return time.time() - monotime
|
||||
|
||||
|
||||
def uptime():
|
||||
def _get_boot_time_func():
|
||||
plat = sys.platform
|
||||
if plat.startswith(("amiga", "aros12")):
|
||||
return _boot_time_amiga
|
||||
if plat.startswith(("beos5", "haiku1")):
|
||||
return _boot_time_beos()
|
||||
if plat.startswith(("cygwin", "linux")):
|
||||
# "cygwin", "linux","linux-armv71": "linux2"
|
||||
return _boot_time_linux
|
||||
if plat.startswith("minix3"):
|
||||
return _boot_time_minix
|
||||
if plat.startswith("darwin"):
|
||||
return _boot_time_osx
|
||||
if plat.startswith("sunos5"):
|
||||
return _boot_time_solaris
|
||||
if plat.startswith("syllable"):
|
||||
return _boot_time_syllable
|
||||
|
||||
# tried with all unix stuff
|
||||
if plat.startswith("win"):
|
||||
return _boot_time_windows
|
||||
|
||||
# fallback
|
||||
return _boot_time_monotonic
|
||||
|
||||
|
||||
def uptime(args):
|
||||
"""Returns uptime in seconds if even remotely possible, or None if not."""
|
||||
if _BOOTTIME is not None:
|
||||
return time.time() - _BOOTTIME
|
||||
up = _UPTIME_FUNCS.get(sys.platform, _uptime_bsd)()
|
||||
if up is None:
|
||||
up = (
|
||||
_uptime_bsd()
|
||||
or _uptime_plan9()
|
||||
or _uptime_linux()
|
||||
or _uptime_windows()
|
||||
or _uptime_solaris()
|
||||
or _uptime_beos()
|
||||
or _uptime_amiga()
|
||||
or _uptime_syllable()
|
||||
or _uptime_osx()
|
||||
)
|
||||
return up
|
||||
bt = boottime()
|
||||
return str(time.time() - bt)
|
||||
|
||||
|
||||
def boottime():
|
||||
@functools.lru_cache(None)
|
||||
def boottime() -> "float":
|
||||
"""Returns boot time if remotely possible, or None if not."""
|
||||
global _BOOTTIME
|
||||
if _BOOTTIME is None:
|
||||
up = uptime()
|
||||
if up is None:
|
||||
return None
|
||||
_BOOTTIME = time.time() - up
|
||||
return _BOOTTIME
|
||||
func = _get_boot_time_func()
|
||||
btime = func()
|
||||
if btime is None:
|
||||
return _boot_time_monotonic()
|
||||
return btime
|
||||
|
||||
|
||||
def main(args=None):
|
||||
from xonsh.xoreutils.util import run_alias
|
||||
|
||||
run_alias("uptime", args)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
|
@ -17,3 +17,17 @@ def arg_handler(args, out, short, key, val, long=None):
|
|||
out[k] = val
|
||||
else:
|
||||
out[key] = val
|
||||
|
||||
|
||||
def run_alias(name: str, args=None):
|
||||
import sys
|
||||
from xonsh.main import setup
|
||||
from xonsh.built_ins import subproc_uncaptured
|
||||
from xonsh.xontribs import xontribs_load
|
||||
|
||||
setup()
|
||||
|
||||
xontribs_load(["coreutils"])
|
||||
args = sys.argv[1:] if args is None else args
|
||||
|
||||
subproc_uncaptured([name] + args)
|
||||
|
|
|
@ -14,14 +14,13 @@ tools avoid the need for a full subprocess call. Additionally, these
|
|||
tools are cross-platform.
|
||||
"""
|
||||
from xonsh.built_ins import XSH
|
||||
from xonsh.platform import (
|
||||
ON_POSIX,
|
||||
)
|
||||
from xonsh.platform import ON_POSIX
|
||||
from xonsh.xoreutils.cat import cat
|
||||
from xonsh.xoreutils.echo import echo
|
||||
from xonsh.xoreutils.pwd import pwd
|
||||
from xonsh.xoreutils.tee import tee
|
||||
from xonsh.xoreutils.tty import tty
|
||||
from xonsh.xoreutils.uname import uname
|
||||
from xonsh.xoreutils.umask import umask
|
||||
from xonsh.xoreutils.uptime import uptime
|
||||
from xonsh.xoreutils.yes import yes
|
||||
|
@ -33,6 +32,8 @@ XSH.aliases["echo"] = echo
|
|||
XSH.aliases["pwd"] = pwd
|
||||
XSH.aliases["tee"] = tee
|
||||
XSH.aliases["tty"] = tty
|
||||
XSH.aliases["uname"] = uname
|
||||
XSH.aliases["uptime"] = uptime
|
||||
XSH.aliases["yes"] = yes
|
||||
XSH.aliases["umask"] = umask
|
||||
XSH.aliases["uptime"] = uptime
|
||||
|
|
Loading…
Add table
Reference in a new issue