diff --git a/devbin/make-executable-zip.sh b/devbin/make-executable-zip.sh index a145ca9..342a20c 100755 --- a/devbin/make-executable-zip.sh +++ b/devbin/make-executable-zip.sh @@ -30,8 +30,8 @@ echo 'import px.px; px.px.main()' >"$WORKDIR/__main__.py" cp -a "$ROOTDIR/px" "$WORKDIR/" # Dependencies, must match list in requirements.txt -cp -a "$ENVDIR"/lib/python*/site-packages/dateutil "$WORKDIR/" -cp -a "$ENVDIR"/lib/python*/site-packages/six.py "$WORKDIR/" +# +# NOTE: This section intentionally left blank # Tidy up a bit find "$WORKDIR" -name '*.pyc' -delete diff --git a/px/px_loginhistory.py b/px/px_loginhistory.py index 1fe5379..5a19a6f 100644 --- a/px/px_loginhistory.py +++ b/px/px_loginhistory.py @@ -2,7 +2,6 @@ import datetime import re -import dateutil.tz from . import px_exec_util @@ -10,6 +9,8 @@ LOG = logging.getLogger(__name__) +TIMEZONE = datetime.datetime.now(datetime.timezone.utc).astimezone().tzinfo + # last regexp parts LAST_USERNAME = "([^ ]+)" LAST_DEVICE = "([^ ]+)" @@ -72,7 +73,7 @@ def get_users_at( """ if now is None: - now = datetime.datetime.now(dateutil.tz.tzlocal()) + now = datetime.datetime.now(datetime.timezone.utc).astimezone() if last_output is None: last_output = call_last() @@ -158,7 +159,7 @@ def _to_timestamp(string, now): try: timestamp = datetime.datetime( - now.year, month, day, hour, minute, tzinfo=dateutil.tz.tzlocal() + now.year, month, day, hour, minute, tzinfo=TIMEZONE ) if timestamp <= now: return timestamp @@ -169,9 +170,7 @@ def _to_timestamp(string, now): else: raise - return datetime.datetime( - now.year - 1, month, day, hour, minute, tzinfo=dateutil.tz.tzlocal() - ) + return datetime.datetime(now.year - 1, month, day, hour, minute, tzinfo=TIMEZONE) def _to_timedelta(string: str) -> datetime.timedelta: diff --git a/px/px_process.py b/px/px_process.py index 8d8bf69..06b9213 100644 --- a/px/px_process.py +++ b/px/px_process.py @@ -7,7 +7,6 @@ import pwd import errno import subprocess -import dateutil.tz from . import px_commandline from . import px_exec_util @@ -38,7 +37,7 @@ CPUTIME_LINUX_DAYS = re.compile("^([0-9]+)-([0-9][0-9]):([0-9][0-9]):([0-9][0-9])$") -TIMEZONE = dateutil.tz.tzlocal() +TIMEZONE = datetime.datetime.now(datetime.timezone.utc).astimezone().tzinfo uid_to_username_cache: Dict[int, str] = {} @@ -356,9 +355,9 @@ def create_kernel_process(now: datetime.datetime) -> PxProcess: process_builder.ppid = None # FIXME: This should be the system boot timestamp, not the epoch - process_builder.start_time_string = datetime.datetime.utcfromtimestamp(0).strftime( - "%c" - ) + process_builder.start_time_string = datetime.datetime.fromtimestamp( + 0, datetime.timezone.utc + ).strftime("%c") process_builder.rss_kb = 0 process_builder.username = "root" diff --git a/requirements.txt b/requirements.txt index 9516d45..1e6774e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -5,11 +5,5 @@ # NOTE: If you change something here, you must update make-executable-zip.sh as # well, search for "requirements.txt"! -# NOTE: We don't use six ourselves, but python-dateutil does. Do remove once -# we're on a Python-3-only python-dateutil! -six - -# 2.6.1 is what we started out using, older is probably fine -# as well but I don't know *how* old. If anybody wants older, -# let me know and we'll see. /johan.walles@gmail.com 2019mar11 -python-dateutil >= 2.6.1 +# NOTE: This file intentionally left blank because we don't have any third-party +# runtime dependencies. \ No newline at end of file diff --git a/tests/px_loginhistory_test.py b/tests/px_loginhistory_test.py index 4e18533..e415e48 100644 --- a/tests/px_loginhistory_test.py +++ b/tests/px_loginhistory_test.py @@ -1,14 +1,12 @@ import datetime import pytest -import dateutil.tz from px import px_loginhistory from typing import Set -# These warnings conflict with how pytest fixtures work: -# https://docs.pytest.org/en/6.2.x/fixture.html +TIMEZONE = datetime.datetime.now(datetime.timezone.utc).astimezone().tzinfo @pytest.fixture @@ -33,85 +31,81 @@ def get_users_at( def test_get_users_at_range(check_output): # Test user logged in between two timestamps - now = datetime.datetime(2016, 4, 3, 12, 8, tzinfo=dateutil.tz.tzlocal()) + now = datetime.datetime(2016, 4, 3, 12, 8, tzinfo=TIMEZONE) lastline = "johan ttys000 Thu Mar 31 14:39 - 11:08 (20:29)" # Before assert not get_users_at( lastline, now, - datetime.datetime(2016, 3, 31, 14, 38, tzinfo=dateutil.tz.tzlocal()), + datetime.datetime(2016, 3, 31, 14, 38, tzinfo=TIMEZONE), ) # During assert {"johan"} == get_users_at( lastline, now, - datetime.datetime(2016, 3, 31, 14, 39, tzinfo=dateutil.tz.tzlocal()), + datetime.datetime(2016, 3, 31, 14, 39, tzinfo=TIMEZONE), ) assert {"johan"} == get_users_at( lastline, now, - datetime.datetime(2016, 3, 31, 17, 46, tzinfo=dateutil.tz.tzlocal()), + datetime.datetime(2016, 3, 31, 17, 46, tzinfo=TIMEZONE), ) assert {"johan"} == get_users_at( lastline, now, - datetime.datetime(2016, 4, 1, 11, 8, tzinfo=dateutil.tz.tzlocal()), + datetime.datetime(2016, 4, 1, 11, 8, tzinfo=TIMEZONE), ) # After assert not get_users_at( lastline, now, - datetime.datetime(2016, 4, 1, 11, 9, tzinfo=dateutil.tz.tzlocal()), + datetime.datetime(2016, 4, 1, 11, 9, tzinfo=TIMEZONE), ) def test_get_users_at_still_logged_in(check_output): - now = datetime.datetime(2016, 4, 3, 12, 8, tzinfo=dateutil.tz.tzlocal()) + now = datetime.datetime(2016, 4, 3, 12, 8, tzinfo=TIMEZONE) lastline = "johan ttys000 Sun Apr 3 11:54 still logged in" # Before assert not get_users_at( lastline, now, - datetime.datetime(2016, 4, 3, 11, 53, tzinfo=dateutil.tz.tzlocal()), + datetime.datetime(2016, 4, 3, 11, 53, tzinfo=TIMEZONE), ) # During assert {"johan"} == get_users_at( lastline, now, - datetime.datetime(2016, 4, 3, 11, 54, tzinfo=dateutil.tz.tzlocal()), - ) - assert {"johan"} == get_users_at( - lastline, now, datetime.datetime.now(dateutil.tz.tzlocal()) + datetime.datetime(2016, 4, 3, 11, 54, tzinfo=TIMEZONE), ) + assert {"johan"} == get_users_at(lastline, now, datetime.datetime.now(TIMEZONE)) def test_get_users_at_remote(check_output): - now = datetime.datetime(2016, 4, 3, 12, 8, tzinfo=dateutil.tz.tzlocal()) + now = datetime.datetime(2016, 4, 3, 12, 8, tzinfo=TIMEZONE) lastline = ( "root pts/1 10.1.6.120 Tue Jan 28 05:59 still logged in" ) assert {"root from 10.1.6.120"} == get_users_at( - lastline, now, datetime.datetime.now(dateutil.tz.tzlocal()) + lastline, now, datetime.datetime.now(TIMEZONE) ) def test_get_users_at_local_osx(check_output): - now = datetime.datetime(2016, 4, 3, 12, 8, tzinfo=dateutil.tz.tzlocal()) + now = datetime.datetime(2016, 4, 3, 12, 8, tzinfo=TIMEZONE) lastline = "johan ttys000 Sun Apr 3 11:54 still logged in" - assert {"johan"} == get_users_at( - lastline, now, datetime.datetime.now(dateutil.tz.tzlocal()) - ) + assert {"johan"} == get_users_at(lastline, now, datetime.datetime.now(TIMEZONE)) def test_get_users_at_local_linux(check_output): - now = datetime.datetime(2016, 4, 3, 12, 8, tzinfo=dateutil.tz.tzlocal()) + now = datetime.datetime(2016, 4, 3, 12, 8, tzinfo=TIMEZONE) lastline = ( "johan pts/2 :0 Wed Mar 9 13:25 - 13:38 (00:12)" ) @@ -119,43 +113,43 @@ def test_get_users_at_local_linux(check_output): assert {"johan from :0"} == get_users_at( lastline, now, - datetime.datetime(2016, 3, 9, 13, 26, tzinfo=dateutil.tz.tzlocal()), + datetime.datetime(2016, 3, 9, 13, 26, tzinfo=TIMEZONE), ) def test_get_users_at_until_crash(check_output): - now = datetime.datetime(2016, 4, 3, 12, 8, tzinfo=dateutil.tz.tzlocal()) + now = datetime.datetime(2016, 4, 3, 12, 8, tzinfo=TIMEZONE) lastline = "johan ttys001 Thu Nov 26 19:55 - crash (27+07:11)" # Before assert not get_users_at( lastline, now, - datetime.datetime(2015, 11, 26, 19, 54, tzinfo=dateutil.tz.tzlocal()), + datetime.datetime(2015, 11, 26, 19, 54, tzinfo=TIMEZONE), ) # During assert {"johan"} == get_users_at( lastline, now, - datetime.datetime(2015, 11, 26, 19, 55, tzinfo=dateutil.tz.tzlocal()), + datetime.datetime(2015, 11, 26, 19, 55, tzinfo=TIMEZONE), ) assert {"johan"} == get_users_at( lastline, now, - datetime.datetime(2015, 12, 10, 19, 53, tzinfo=dateutil.tz.tzlocal()), + datetime.datetime(2015, 12, 10, 19, 53, tzinfo=TIMEZONE), ) # A bit after assert not get_users_at( lastline, now, - datetime.datetime(2015, 12, 26, 19, 55, tzinfo=dateutil.tz.tzlocal()), + datetime.datetime(2015, 12, 26, 19, 55, tzinfo=TIMEZONE), ) def test_get_users_at_until_shutdown_osx(check_output): - now = datetime.datetime(2016, 4, 3, 12, 8, tzinfo=dateutil.tz.tzlocal()) + now = datetime.datetime(2016, 4, 3, 12, 8, tzinfo=TIMEZONE) lastline = ( "_mbsetupuser console Mon Jan 18 20:31 - shutdown (34+01:29)" ) @@ -164,31 +158,31 @@ def test_get_users_at_until_shutdown_osx(check_output): assert not get_users_at( lastline, now, - datetime.datetime(2016, 1, 18, 20, 30, tzinfo=dateutil.tz.tzlocal()), + datetime.datetime(2016, 1, 18, 20, 30, tzinfo=TIMEZONE), ) # During assert {"_mbsetupuser"} == get_users_at( lastline, now, - datetime.datetime(2016, 1, 18, 20, 31, tzinfo=dateutil.tz.tzlocal()), + datetime.datetime(2016, 1, 18, 20, 31, tzinfo=TIMEZONE), ) assert {"_mbsetupuser"} == get_users_at( lastline, now, - datetime.datetime(2016, 2, 18, 20, 30, tzinfo=dateutil.tz.tzlocal()), + datetime.datetime(2016, 2, 18, 20, 30, tzinfo=TIMEZONE), ) # A bit after assert not get_users_at( lastline, now, - datetime.datetime(2016, 2, 28, 20, 30, tzinfo=dateutil.tz.tzlocal()), + datetime.datetime(2016, 2, 28, 20, 30, tzinfo=TIMEZONE), ) def test_get_users_at_until_shutdown_linux(check_output): - now = datetime.datetime(2016, 4, 3, 12, 8, tzinfo=dateutil.tz.tzlocal()) + now = datetime.datetime(2016, 4, 3, 12, 8, tzinfo=TIMEZONE) lastline = ( "johan :0 :0 Sat Mar 26 22:04 - down (00:08)" ) @@ -197,32 +191,32 @@ def test_get_users_at_until_shutdown_linux(check_output): assert not get_users_at( lastline, now, - datetime.datetime(2016, 3, 26, 22, 3, tzinfo=dateutil.tz.tzlocal()), + datetime.datetime(2016, 3, 26, 22, 3, tzinfo=TIMEZONE), ) # During assert {"johan from :0"} == get_users_at( lastline, now, - datetime.datetime(2016, 3, 26, 22, 4, tzinfo=dateutil.tz.tzlocal()), + datetime.datetime(2016, 3, 26, 22, 4, tzinfo=TIMEZONE), ) assert {"johan from :0"} == get_users_at( lastline, now, - datetime.datetime(2016, 3, 26, 22, 9, tzinfo=dateutil.tz.tzlocal()), + datetime.datetime(2016, 3, 26, 22, 9, tzinfo=TIMEZONE), ) # A bit after assert not get_users_at( lastline, now, - datetime.datetime(2016, 3, 26, 22, 15, tzinfo=dateutil.tz.tzlocal()), + datetime.datetime(2016, 3, 26, 22, 15, tzinfo=TIMEZONE), ) def test_get_users_at_multiple(check_output): # Test multiple users logged in between two timestamps - now = datetime.datetime(2016, 4, 3, 12, 8, tzinfo=dateutil.tz.tzlocal()) + now = datetime.datetime(2016, 4, 3, 12, 8, tzinfo=TIMEZONE) lastline = "\n".join( [ "johan1 ttys000 Thu Mar 31 14:39 - 11:08 (20:29)", @@ -234,36 +228,36 @@ def test_get_users_at_multiple(check_output): assert not get_users_at( lastline, now, - datetime.datetime(2016, 3, 31, 14, 38, tzinfo=dateutil.tz.tzlocal()), + datetime.datetime(2016, 3, 31, 14, 38, tzinfo=TIMEZONE), ) # During assert {"johan1", "johan2"} == get_users_at( lastline, now, - datetime.datetime(2016, 3, 31, 14, 39, tzinfo=dateutil.tz.tzlocal()), + datetime.datetime(2016, 3, 31, 14, 39, tzinfo=TIMEZONE), ) assert {"johan1", "johan2"} == get_users_at( lastline, now, - datetime.datetime(2016, 3, 31, 17, 46, tzinfo=dateutil.tz.tzlocal()), + datetime.datetime(2016, 3, 31, 17, 46, tzinfo=TIMEZONE), ) assert {"johan1", "johan2"} == get_users_at( lastline, now, - datetime.datetime(2016, 4, 1, 11, 8, tzinfo=dateutil.tz.tzlocal()), + datetime.datetime(2016, 4, 1, 11, 8, tzinfo=TIMEZONE), ) # After assert not get_users_at( lastline, now, - datetime.datetime(2016, 4, 1, 11, 9, tzinfo=dateutil.tz.tzlocal()), + datetime.datetime(2016, 4, 1, 11, 9, tzinfo=TIMEZONE), ) def test_get_users_at_pseudousers_osx(check_output): - now = datetime.datetime(2016, 4, 3, 12, 8, tzinfo=dateutil.tz.tzlocal()) + now = datetime.datetime(2016, 4, 3, 12, 8, tzinfo=TIMEZONE) # Note trailing space in test string, we get that from last on OS X 10.11.3 lastline = "reboot ~ Fri Oct 23 06:50 " @@ -271,7 +265,7 @@ def test_get_users_at_pseudousers_osx(check_output): assert not get_users_at( lastline, now, - datetime.datetime(2015, 10, 23, 6, 50, tzinfo=dateutil.tz.tzlocal()), + datetime.datetime(2015, 10, 23, 6, 50, tzinfo=TIMEZONE), ) # Note trailing space in test string, we get that from last on OS X 10.11.3 @@ -280,12 +274,12 @@ def test_get_users_at_pseudousers_osx(check_output): assert not get_users_at( lastline, now, - datetime.datetime(2015, 10, 23, 6, 49, tzinfo=dateutil.tz.tzlocal()), + datetime.datetime(2015, 10, 23, 6, 49, tzinfo=TIMEZONE), ) def test_get_users_at_pseudousers_linux(check_output): - now = datetime.datetime(2016, 4, 3, 12, 8, tzinfo=dateutil.tz.tzlocal()) + now = datetime.datetime(2016, 4, 3, 12, 8, tzinfo=TIMEZONE) lastline = ( "reboot system boot 4.2.0-30-generic Thu Mar 3 11:19 - 13:38 (6+02:18)" @@ -294,7 +288,7 @@ def test_get_users_at_pseudousers_linux(check_output): assert not get_users_at( lastline, now, - datetime.datetime(2016, 3, 3, 11, 19, tzinfo=dateutil.tz.tzlocal()), + datetime.datetime(2016, 3, 3, 11, 19, tzinfo=TIMEZONE), ) @@ -304,7 +298,7 @@ def test_get_users_at_gone_no_logout(check_output): That's the only place I've seen it. """ - now = datetime.datetime(2016, 4, 7, 12, 8, tzinfo=dateutil.tz.tzlocal()) + now = datetime.datetime(2016, 4, 7, 12, 8, tzinfo=TIMEZONE) lastline = ( "johan pts/3 :0 Mon Apr 4 23:10 gone - no logout" ) @@ -313,22 +307,22 @@ def test_get_users_at_gone_no_logout(check_output): assert not get_users_at( lastline, now, - datetime.datetime(2016, 4, 4, 23, 9, tzinfo=dateutil.tz.tzlocal()), + datetime.datetime(2016, 4, 4, 23, 9, tzinfo=TIMEZONE), ) # During assert {"johan from :0"} == get_users_at( lastline, now, - datetime.datetime(2016, 4, 4, 23, 10, tzinfo=dateutil.tz.tzlocal()), + datetime.datetime(2016, 4, 4, 23, 10, tzinfo=TIMEZONE), ) assert {"johan from :0"} == get_users_at( - lastline, now, datetime.datetime.now(dateutil.tz.tzlocal()) + lastline, now, datetime.datetime.now(TIMEZONE) ) def test_get_users_at_trailing_noise(check_output): - now = datetime.datetime(2016, 4, 7, 12, 8, tzinfo=dateutil.tz.tzlocal()) + now = datetime.datetime(2016, 4, 7, 12, 8, tzinfo=TIMEZONE) assert not get_users_at("", now, now) # Note trailing space in test string, we get that from last on OS X 10.11.3 @@ -338,7 +332,7 @@ def test_get_users_at_trailing_noise(check_output): def test_get_users_at_unexpected_last_output(caplog): UNEXPECTED = "glasskiosk" - now = datetime.datetime(2016, 4, 7, 12, 8, tzinfo=dateutil.tz.tzlocal()) + now = datetime.datetime(2016, 4, 7, 12, 8, tzinfo=TIMEZONE) assert not get_users_at(UNEXPECTED, now, now) assert UNEXPECTED in caplog.text @@ -346,20 +340,20 @@ def test_get_users_at_unexpected_last_output(caplog): def test_get_users_at_just_run_it(check_output): # Just tyre kick it live wherever we happen to be. This shouldn't crash. - px_loginhistory.get_users_at(datetime.datetime.now(dateutil.tz.tzlocal())) + px_loginhistory.get_users_at(datetime.datetime.now(TIMEZONE)) def test_to_timestamp(check_output): - now = datetime.datetime(2016, 4, 3, 12, 8, tzinfo=dateutil.tz.tzlocal()) - expected = datetime.datetime(2016, 3, 5, 11, 19, tzinfo=dateutil.tz.tzlocal()) + now = datetime.datetime(2016, 4, 3, 12, 8, tzinfo=TIMEZONE) + expected = datetime.datetime(2016, 3, 5, 11, 19, tzinfo=TIMEZONE) assert px_loginhistory._to_timestamp("Thu Mar 5 11:19", now) == expected - now = datetime.datetime(2016, 4, 3, 12, 8, tzinfo=dateutil.tz.tzlocal()) - expected = datetime.datetime(2016, 2, 29, 13, 19, tzinfo=dateutil.tz.tzlocal()) + now = datetime.datetime(2016, 4, 3, 12, 8, tzinfo=TIMEZONE) + expected = datetime.datetime(2016, 2, 29, 13, 19, tzinfo=TIMEZONE) assert px_loginhistory._to_timestamp("Mon Feb 29 13:19", now) == expected - now = datetime.datetime(2017, 1, 3, 12, 8, tzinfo=dateutil.tz.tzlocal()) - expected = datetime.datetime(2016, 2, 29, 13, 19, tzinfo=dateutil.tz.tzlocal()) + now = datetime.datetime(2017, 1, 3, 12, 8, tzinfo=TIMEZONE) + expected = datetime.datetime(2016, 2, 29, 13, 19, tzinfo=TIMEZONE) assert px_loginhistory._to_timestamp("Mon Feb 29 13:19", now) == expected @@ -379,8 +373,8 @@ def test_realworld_debian(check_output): """ Regression test for https://github.com/walles/px/issues/48 """ - now = datetime.datetime(2016, 12, 6, 9, 21, tzinfo=dateutil.tz.tzlocal()) - testtime = datetime.datetime(2016, 10, 24, 15, 34, tzinfo=dateutil.tz.tzlocal()) + now = datetime.datetime(2016, 12, 6, 9, 21, tzinfo=TIMEZONE) + testtime = datetime.datetime(2016, 10, 24, 15, 34, tzinfo=TIMEZONE) lastline = ( "norbert pts/3 mosh [29846] Wed Oct 24 15:33 - 15:34 (00:01)" ) diff --git a/tests/px_tree_test.py b/tests/px_tree_test.py index 8fabe2e..d6f75cd 100644 --- a/tests/px_tree_test.py +++ b/tests/px_tree_test.py @@ -6,11 +6,10 @@ from typing import List import datetime -import dateutil.tz def resolve(processes: List[px_process.PxProcess]) -> List[px_process.PxProcess]: - now = datetime.datetime.now().replace(tzinfo=dateutil.tz.tzlocal()) + now = datetime.datetime.now(datetime.timezone.utc).astimezone() process_dict = {p.pid: p for p in processes} px_process.resolve_links(process_dict, now) diff --git a/tests/testutils.py b/tests/testutils.py index 9744c18..1614daa 100644 --- a/tests/testutils.py +++ b/tests/testutils.py @@ -7,7 +7,6 @@ from px import px_process from px import px_ipc_map -import dateutil.tz import dateutil.parser from typing import MutableMapping @@ -16,7 +15,8 @@ # An example time string that can be produced by ps TIMESTRING = "Mon Mar 7 09:33:11 2016" -TIME = dateutil.parser.parse(TIMESTRING).replace(tzinfo=dateutil.tz.tzlocal()) +TIMEZONE = datetime.datetime.now(datetime.timezone.utc).astimezone().tzinfo +TIME = dateutil.parser.parse(TIMESTRING).replace(tzinfo=TIMEZONE) def load(sample_file_name: str) -> str: @@ -31,7 +31,7 @@ def spaces(at_least=1, at_most=3): def local_now(): - return datetime.datetime.now().replace(tzinfo=dateutil.tz.tzlocal()) + return datetime.datetime.now().replace(tzinfo=TIMEZONE) def create_process( diff --git a/tox.ini b/tox.ini index e0e848c..db3fcd4 100644 --- a/tox.ini +++ b/tox.ini @@ -8,6 +8,7 @@ minversion = 3.8.0 mypy_version = 1.2.0 ruff_version = 0.1.3 pytest_version = 7.1.3 +setuptools_version = 68.2.2 envlist= version.py @@ -26,6 +27,8 @@ basepython = python3 allowlist_externals = /bin/bash [testenv:version.py] +deps = + setuptools == {[tox]setuptools_version} commands = # This creates px/version.py /bin/bash -c './setup.py check' @@ -79,6 +82,7 @@ depends = version.py ruff-format deps = pytest == {[tox]pytest_version} pytest-avoidance == 0.3.0 + python-dateutil >= 2.6.1 -r requirements.txt commands = pytest --durations=10 --color=yes tests @@ -113,7 +117,7 @@ allowlist_externals = /bin/bash /bin/rm deps = - setuptools == 44.1.1 + setuptools == {[tox]setuptools_version} wheel == 0.35.1 commands = # clean up build/ and dist/ folders