From 44ba87515fdfb993dbd4574e85ed9a64be950e57 Mon Sep 17 00:00:00 2001 From: mrosca Date: Tue, 8 Apr 2025 23:01:10 +1000 Subject: [PATCH 1/5] Fix http_date function to correctly handle UTC time --- README.md | 23 +++++++++++++---------- tests/test_utils.py | 16 ++++++++++++++++ xcover/utils.py | 8 +++----- 3 files changed, 32 insertions(+), 15 deletions(-) create mode 100644 tests/test_utils.py diff --git a/README.md b/README.md index 6b0336d..d4b8b8e 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ # · xcover-python · + [![Supported Versions](https://img.shields.io/pypi/pyversions/xcover-python.svg)](https://pypi.org/project/xcover-python) [![codecov](https://codecov.io/gh/CoverGenius/xcover-python/branch/master/graph/badge.svg?token=KINNTVZV07)](https://codecov.io/gh/CoverGenius/xcover-python) @@ -16,7 +17,7 @@ or - poertry install xcover-python + poetry install xcover-python ## Features @@ -50,15 +51,17 @@ Alternatively, it is possible to use env variables. The full list of configuration options: -* `XC_BASE_URL` (`XCoverConfig.base_url`): XCover base URL (e.g. `https://api.xcover.com/api/v2/`). -* `XC_PARTNER_CODE` (`XCoverConfig.partner_code`): Partner code (e.g. `LLODT`). -* `XC_HTTP_TIMEOUT` (`XCoverConfig.http_timeout`): HTTP timeout in seconds. Default value is `10`. -* `XC_AUTH_API_KEY` (`XCoverConfig.auth_api_key`): API key to use. -* `XC_AUTH_API_SECRET` (`XCoverConfig.auth_api_secret`): API secret to use. -* `XC_AUTH_ALGORITHM` (`XCoverConfig.auth_algorithm`): HMAC encoding algorithm to use. Default is `hmac-sha512`. -* `XC_AUTH_HEADERS` (`XCoverConfig.auth_headers`): Headers to sign. Default is `(request-target) date`. -* `XC_RETRY_TOTAL` (`XCoverConfig.retry_total`): Total number of retries. Default is `5`. -* `XC_RETRY_BACKOFF_FACTOR` (`XCoverConfig.retry_backoff_factor`): Backoff factor for retries timeout. Default is `2`. +| Environment Variable | Config Property | Description | Default Value | +|---------------------|-----------------|-------------|---------------| +| `XC_BASE_URL` | `XCoverConfig.base_url` | XCover base URL (e.g. `https://api.xcover.com/api/v2/`) | - | +| `XC_PARTNER_CODE` | `XCoverConfig.partner_code` | Partner code (e.g. `LLODT`) | - | +| `XC_HTTP_TIMEOUT` | `XCoverConfig.http_timeout` | HTTP timeout in seconds | `10` | +| `XC_AUTH_API_KEY` | `XCoverConfig.auth_api_key` | API key to use | - | +| `XC_AUTH_API_SECRET` | `XCoverConfig.auth_api_secret` | API secret to use | - | +| `XC_AUTH_ALGORITHM` | `XCoverConfig.auth_algorithm` | HMAC encoding algorithm to use | `hmac-sha512` | +| `XC_AUTH_HEADERS` | `XCoverConfig.auth_headers` | Headers to sign | `(request-target) date` | +| `XC_RETRY_TOTAL` | `XCoverConfig.retry_total` | Total number of retries | `5` | +| `XC_RETRY_BACKOFF_FACTOR` | `XCoverConfig.retry_backoff_factor` | Backoff factor for retries timeout | `2` | ## Usage example diff --git a/tests/test_utils.py b/tests/test_utils.py new file mode 100644 index 0000000..1be7c39 --- /dev/null +++ b/tests/test_utils.py @@ -0,0 +1,16 @@ +from datetime import datetime, timezone +from unittest import mock +from xcover.utils import http_date + + +def test_http_date(): + fixed_dt = datetime(2025, 4, 8, 12, 0, 0, tzinfo=timezone.utc) + + with mock.patch("xcover.utils.datetime") as mock_datetime: + mock_datetime.now.return_value = fixed_dt + mock_datetime.timezone = timezone + + date_header = http_date() + + mock_datetime.now.assert_called_once_with(timezone.utc) + assert date_header == "Tue, 08 Apr 2025 12:00:00 GMT" diff --git a/xcover/utils.py b/xcover/utils.py index cb8741a..be99096 100644 --- a/xcover/utils.py +++ b/xcover/utils.py @@ -1,8 +1,6 @@ -from datetime import datetime -from time import mktime -from wsgiref.handlers import format_date_time +from datetime import datetime, timezone def http_date(): - now = datetime.utcnow() - return format_date_time(mktime(now.timetuple())) + now = datetime.now(timezone.utc) + return now.strftime("%a, %d %b %Y %H:%M:%S GMT") # RFC 7231 format From 122ef39666f60ceb232a23f0e57de4cb5ea4b234 Mon Sep 17 00:00:00 2001 From: mrosca Date: Tue, 8 Apr 2025 23:18:52 +1000 Subject: [PATCH 2/5] Fix isort formatting in test_utils.py --- tests/test_utils.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_utils.py b/tests/test_utils.py index 1be7c39..a19e83c 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -1,5 +1,6 @@ from datetime import datetime, timezone from unittest import mock + from xcover.utils import http_date From ae480202b0fda33acffd6ebee3682b11ca0b0ec0 Mon Sep 17 00:00:00 2001 From: mrosca Date: Tue, 8 Apr 2025 23:30:20 +1000 Subject: [PATCH 3/5] Update GitHub Actions to latest versions --- .github/workflows/ci.yaml | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index c6e6625..9dbd4d3 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -18,8 +18,8 @@ jobs: python: [ "3.8", "3.9", "3.10", "3.11" ] requests: [ "2.26", "2.27", "2.28", "2.29" ] steps: - - uses: actions/checkout@v2 - - uses: actions/setup-python@v2 + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 with: python-version: ${{ matrix.python }} architecture: x64 @@ -30,7 +30,7 @@ jobs: - run: poetry add requests@~${{ matrix.requests }} - run: cp .github-ci.env .env - run: poetry run pytest - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v4 with: name: coverage-report path: ./coverage.xml @@ -38,8 +38,8 @@ jobs: pre-commit: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - uses: actions/setup-python@v4 + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 with: python-version: "3.10" - uses: pre-commit/action@v3.0.0 @@ -50,15 +50,15 @@ jobs: needs: pytest runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - uses: actions/setup-python@v2 + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 with: python-version: 3.9 architecture: x64 - run: pip install --upgrade pip - run: pip install poetry - run: poetry build - - uses: pypa/gh-action-pypi-publish@master + - uses: pypa/gh-action-pypi-publish@release/v1 with: password: ${{ secrets.pypi_password }} @@ -67,8 +67,10 @@ jobs: - pytest runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - uses: actions/download-artifact@v2 + - uses: actions/checkout@v4 + - uses: actions/download-artifact@v4 with: name: coverage-report - - uses: codecov/codecov-action@v1 + - uses: codecov/codecov-action@v4 + with: + token: ${{ secrets.CODECOV_TOKEN }} From 65fca1d8eb817443922edca964d098f50ba21fc3 Mon Sep 17 00:00:00 2001 From: mrosca Date: Tue, 8 Apr 2025 23:33:51 +1000 Subject: [PATCH 4/5] Update GitHub Actions to use ubuntu-latest and checkout@v4 --- .github/workflows/semgrep.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/semgrep.yml b/.github/workflows/semgrep.yml index 08e15a6..61ba4fb 100644 --- a/.github/workflows/semgrep.yml +++ b/.github/workflows/semgrep.yml @@ -12,11 +12,11 @@ name: Semgrep jobs: semgrep: name: Scan - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest env: SEMGREP_APP_TOKEN: ${{ secrets.SEMGREP_APP_TOKEN }} container: image: returntocorp/semgrep steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - run: semgrep ci From 9e05ba2708bfb7e8f155af988a94c2c39f77a75a Mon Sep 17 00:00:00 2001 From: mrosca Date: Tue, 8 Apr 2025 23:39:00 +1000 Subject: [PATCH 5/5] ci: resolve CI artefact conflicts and udpate GH Actions --- .github/workflows/ci.yaml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 9dbd4d3..952c188 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -32,8 +32,9 @@ jobs: - run: poetry run pytest - uses: actions/upload-artifact@v4 with: - name: coverage-report + name: coverage-report-python-${{ matrix.python }}-requests-${{ matrix.requests }} path: ./coverage.xml + overwrite: true pre-commit: runs-on: ubuntu-latest @@ -70,7 +71,9 @@ jobs: - uses: actions/checkout@v4 - uses: actions/download-artifact@v4 with: - name: coverage-report + pattern: coverage-report-* + path: coverage-reports - uses: codecov/codecov-action@v4 with: token: ${{ secrets.CODECOV_TOKEN }} + directory: coverage-reports