diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index 544b516..cc06a01 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -6,11 +6,16 @@ on: jobs: tests: - name: ${{ matrix.python }} - runs-on: ubuntu-latest + name: ${{ matrix.os }} - python${{ matrix.python }} - ${{ matrix.tz }} + runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: + os: + - ubuntu-22.04 + - macos-14 + - macos-13 + - macos-12 python: - '3.12' - '3.11' @@ -21,15 +26,18 @@ jobs: - 'utc' - 'cest' steps: - - uses: actions/checkout@v2 - - uses: actions/setup-python@v2 + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 with: python-version: ${{ matrix.python }} - - uses: actions/cache@v1 + - uses: actions/cache@v4 with: path: ~/.cache/pip key: pip|${{ hashFiles('setup.py') }}|${{ hashFiles('setup.cfg') }} - run: pip install tox - - run: git submodule update --init + - run: git submodule update --init --force + - run: env FAKETIME_COMPILE_CFLAGS="-UFAKE_STAT -UFAKE_UTIME -UFAKE_SLEEP" make -C libfaketime/vendor/libfaketime + if: runner.os == 'Linux' - run: make -C libfaketime/vendor/libfaketime - - run: tox -e ${{ matrix.python }}-${{ matrix.tz }} + if: runner.os == 'macOS' + - run: tox -e ${{ matrix.python }}-${{ matrix.tz }} --recreate diff --git a/.gitmodules b/.gitmodules index 51214e3..f0ed0ea 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,8 +1,4 @@ [submodule "vendor/libfaketime"] path = libfaketime/vendor/libfaketime - url = https://github.com/simon-weber/libfaketime.git + url = https://github.com/wolfcw/libfaketime.git branch = python-libfaketime -[submodule "vendor/libfaketime-pre_sierra"] - path = libfaketime/vendor/libfaketime-pre_sierra - url = https://github.com/simon-weber/libfaketime.git - branch = python-libfaketime-pre_sierra diff --git a/MANIFEST.in b/MANIFEST.in index e8e8bb2..c7dbb74 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -5,8 +5,3 @@ include libfaketime/vendor/libfaketime/src/Makefile include libfaketime/vendor/libfaketime/src/Makefile.OSX include libfaketime/vendor/libfaketime/COPYING recursive-include libfaketime/vendor/libfaketime/src *.c *.h *.map -include libfaketime/vendor/libfaketime-pre_sierra/Makefile -include libfaketime/vendor/libfaketime-pre_sierra/src/Makefile -include libfaketime/vendor/libfaketime-pre_sierra/src/Makefile.OSX -include libfaketime/vendor/libfaketime-pre_sierra/COPYING -recursive-include libfaketime/vendor/libfaketime-pre_sierra/src *.c *.h *.map diff --git a/README.md b/README.md index 2bbc636..53c87fc 100644 --- a/README.md +++ b/README.md @@ -147,6 +147,7 @@ In some cases - especially when your tests start other processes - re-execing ca $ python-libfaketime export LD_PRELOAD="/home/foo//vendor/libfaketime/src/libfaketime.so.1" export DONT_FAKE_MONOTONIC="1" +export FAKETIME_NO_CACHE="1" export FAKETIME_DID_REEXEC=true ``` @@ -163,7 +164,11 @@ Contributing and testing Contributions are welcome! You should compile libfaketime before running tests: ```bash -make -C libfaketime/vendor/libfaketime +git submodule init --update +# For Linux: +env FAKETIME_COMPILE_CFLAGS="-UFAKE_STAT -UFAKE_UTIME -UFAKE_SLEEP" make -C libfaketime/vendor/libfaketime +# For macOS +env make -C libfaketime/vendor/libfaketime ``` Then you can install requirements with ``pip install -r requirements.txt`` and use ``pytest`` and ``tox`` to run the tests. diff --git a/libfaketime/__init__.py b/libfaketime/__init__.py index b82bb72..e59bdfb 100644 --- a/libfaketime/__init__.py +++ b/libfaketime/__init__.py @@ -6,7 +6,6 @@ import functools import inspect import os -import platform import sys import threading import time @@ -21,24 +20,17 @@ basestring = (str, bytes) -SIERRA_VERSION_TUPLE = (10, 12) # When using reexec_if_needed, remove_vars=True and a test loader that purges sys.modules # (like nose), it can be tough to run reexec_if_needed only once. # This env var is set by reexec to ensure we don't reload more than once. _DID_REEXEC_VAR = 'FAKETIME_DID_REEXEC' - +_FAKETIME_FMT = '%Y-%m-%d %T.%f' def _get_lib_path(): vendor_dir = 'libfaketime' - if sys.platform == "darwin": - version_tuple = tuple(int(x) for x in platform.mac_ver()[0].split('.')) - pre_sierra = version_tuple < SIERRA_VERSION_TUPLE - if pre_sierra: - vendor_dir = 'libfaketime-pre_sierra' - return os.path.join( os.path.dirname(__file__), os.path.join('vendor', vendor_dir, 'src')) @@ -71,10 +63,12 @@ def _setup_ld_preload(soname): _other_additions = { 'linux': { 'DONT_FAKE_MONOTONIC': '1', + 'FAKETIME_NO_CACHE': '1', }, 'darwi': { 'DONT_FAKE_MONOTONIC': '1', 'DYLD_FORCE_FLAT_NAMESPACE': '1', + 'FAKETIME_NO_CACHE': '1', }, } @@ -168,7 +162,7 @@ def _should_patch_uuid(self): return None def _format_datetime(self, _datetime): - return _datetime.strftime('%Y-%m-%d %T %f') + return _datetime.strftime(_FAKETIME_FMT) def tick(self, delta=datetime.timedelta(seconds=1)): self.time_to_freeze += delta @@ -179,11 +173,13 @@ def __enter__(self): begin_callback(self) self._prev_spec = os.environ.get('FAKETIME') self._prev_tz = os.environ.get('TZ') + self._prev_fmt = os.environ.get('FAKETIME_FMT') os.environ['TZ'] = self.timezone_str time.tzset() os.environ['FAKETIME'] = self._format_datetime(self.time_to_freeze) + os.environ['FAKETIME_FMT'] = _FAKETIME_FMT func_name = self._should_patch_uuid() if func_name: @@ -208,7 +204,13 @@ def __exit__(self, *exc): os.environ['FAKETIME'] = self._prev_spec else: del os.environ['FAKETIME'] - end_callback(self) + + if self._prev_fmt is not None: + os.environ['FAKETIME_FMT'] = self._prev_spec + else: + del os.environ['FAKETIME_FMT'] + + end_callback(self) return False diff --git a/libfaketime/vendor/libfaketime b/libfaketime/vendor/libfaketime index d9d2bd7..d475b92 160000 --- a/libfaketime/vendor/libfaketime +++ b/libfaketime/vendor/libfaketime @@ -1 +1 @@ -Subproject commit d9d2bd76f00f95e9409e4a53d0469aef0e988a0b +Subproject commit d475b925943ad404c6c728ac868dc73949e7281c diff --git a/libfaketime/vendor/libfaketime-pre_sierra b/libfaketime/vendor/libfaketime-pre_sierra deleted file mode 160000 index 83c997b..0000000 --- a/libfaketime/vendor/libfaketime-pre_sierra +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 83c997b9c11b437ec5791387045c0364626649df diff --git a/setup.py b/setup.py index 4f28d7a..6add73e 100644 --- a/setup.py +++ b/setup.py @@ -1,8 +1,6 @@ #!/usr/bin/env python -# -*- coding: utf-8 -*- import os -import platform import re from setuptools import setup, find_packages from setuptools.command.install import install @@ -10,10 +8,6 @@ import sys -# libfaketime broke compatibility with osx before sierra. -# We keep a separate submodule for each and choose between them dynamically. -SIERRA_VERSION_TUPLE = (10, 12) - # This hack is from http://stackoverflow.com/a/7071358/1231454; # the version is kept in a seperate file and gets parsed - this # way, setup.py doesn't have to import the package. @@ -35,13 +29,6 @@ elif sys.platform == "darwin": libname = 'libfaketime.1.dylib' - version_tuple = tuple(int(x) for x in platform.mac_ver()[0].split('.')) - pre_sierra = version_tuple < SIERRA_VERSION_TUPLE - if pre_sierra: - _vendor_path = 'libfaketime/vendor/libfaketime-pre_sierra' - - print("OSX version is %s-sierra: %r" % ('pre' if pre_sierra else 'post', version_tuple)) - else: raise RuntimeError("libfaketime does not support platform %s" % sys.platform) @@ -51,7 +38,10 @@ class CustomInstall(install): def run(self): self.my_outputs = [] - subprocess.check_call(['make', '-C', _vendor_path]) + if sys.platform in ("linux", "linux2"): + subprocess.check_call(['env', 'FAKETIME_COMPILE_CFLAGS=-UFAKE_STAT -UFAKE_UTIME -UFAKE_SLEEP', 'make', '-C', _vendor_path]) + elif sys.platform == "darwin": + subprocess.check_call(['make', '-C', _vendor_path]) dest = os.path.join(self.install_purelib, os.path.dirname(faketime_lib)) try: