Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 34 additions & 10 deletions .github/workflows/cicd.yml
Original file line number Diff line number Diff line change
@@ -1,26 +1,50 @@
name: croniter
on: [workflow_dispatch, push, pull_request]
jobs:
build:
build-py2:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: ["2.7"]
steps:
- uses: actions/checkout@v4
- name: install dependencies && test on py27
run: |
set -ex
sudo apt update && sudo apt install -y python2.7
# install py 2 with eg: apt install python2.7
mkdir venv2 && curl -sSL "https://github.com/pypa/get-virtualenv/blob/20.27.0/public/2.7/virtualenv.pyz?raw=true" > venv2/venv && python2.7 venv2/venv venv2
venv2/bin/python2 -m pip install -r ./requirements/test.txt
venv2/bin/tox --direct -e "py${pyver//\.}-{std,coverage}"

build-py3:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
- name: install dependencies && test on py3
run: |
set -ex
python -m pip install --upgrade --use-pep517 pip
pip install --use-pep517 -r requirements/test.txt
pip install --use-pep517 -r requirements/test.txt tox-direct
pyver=$(python --version 2>&1 | awk '{print substr($2, 0, 4)}' | awk '{ sub(/[ \t]+$/, ""); print }')
tox --direct -e "py${pyver//\.}-{std,coverage}"

build-32bits:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Test with pytest
run: |
pyver=$(python --version 2>&1 | awk '{print substr($2, 0, 4)}' | awk '{ sub(/[ \t]+$/, ""); print }');
case $pyver in
2.7) tox -e "py${pyver//\.}-{std,coverage}";;
*) tox -e "py${pyver//\.}-std";;
esac
export COMPOSE_FILE="docker-compose.yml:docker-compose-32bits.yml"
docker compose build
docker compose run --rm --entrypoint tox app --direct -e py312-std

46 changes: 46 additions & 0 deletions .github/workflows/dockerimages.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
env:
DOCKER_BUILDKIT: "1"
COMPOSE_DOCKER_CLI_BUILD: "1"
BUILDKIT_PROGRESS: "plain"
NO_SQUASH: ""
RELEASABLE_REPOS: "^kiorky/"
RELEASABLE_BRANCHES: "^(refs/heads/)?(master|main|32b)$"
jobs:
build-32bits:
runs-on: ubuntu-24.04
strategy:
max-parallel: 5
fail-fast: false
matrix:
FLAVOR: [32bits, latest]
steps:
- name: Set vars
run: |-
if ( echo "$GITHUB_REF" | egrep -q "${RELEASABLE_BRANCHES}" ) \
&& ( echo "$GITHUB_REPOSITORY" | egrep -q "${RELEASABLE_REPOS}" )
then releasable=true;else releasable=false;fi
echo "releasable=$releasable" >> $GITHUB_OUTPUT
id: v
- name: Login to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKER_HUB_USERNAME }}
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
- uses: actions/checkout@v3
- name: Build & test
run: |
set -ex
export COMPOSE_FILE="docker-compose.yml:docker-compose-build.yml"
if ( "${{matrix.FLAVOR}}" | grep -q 32 );then
export COMPOSE_FILE="${COMPOSE_FILE}:docker-compose-32bits.yml:docker-compose-build-32bits.yml"
fi
docker compose build
docker compose run --rm --entrypoint tox app --direct -e py312-std
- name: Release
run: |
if [ "x${{steps.v.outputs.releasable}}" = "xtrue" ];then
set -ex && docker push kiorky/croniter:${{matrix.FLAVOR}}
fi
on:
workflow_dispatch:
schedule: [{cron: '1 0 1,3,5,15,17,19 * *'}]
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/.tox
.env
/dist
\.*.cfg
*.egg-info
Expand Down
4 changes: 2 additions & 2 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ Changelog
3.0.4 (unreleased)
------------------

- Nothing changed yet.

- Fix overflow on 32bits systems (#87) [kiorky]
- Fix python2 testing (related to #93) [kiorky]

3.0.3 (2024-07-26)
------------------
Expand Down
46 changes: 39 additions & 7 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,12 +1,44 @@
ARG RSYNC=corpusops/rsync
ARG PY_VER=3.12.1
FROM python:${PY_VER}
ARG BASE=${BASE:-python:${PY_VER}}
FROM $BASE AS base
ENV CFLAGS="-I/usr/include/python3.12/"
FROM base AS final
WORKDIR /app
ADD *.rst LICENSE MANIFEST.in *.txt *.cfg *.py *.ini ./
RUN <<EOF
set -ex
apt update
apt install -y python3 python3-dev libpython3-dev cargo
if ! ( python --version );then
ln -s /usr/bin/python3 /usr/bin/python
fi
if ! ( pip --version );then
wget https://bootstrap.pypa.io/get-pip.py
chmod +x get-pip.py
./get-pip.py --break-system-packages
fi
mkdir src/ && touch src/__init__.py
EOF
ADD *.rst LICENSE MANIFEST.in *.txt *.cfg *.py *.ini ./
ADD requirements/ ./requirements/
RUN mkdir src/ && touch src/__init__.py
RUN pip install -r req*/base.txt
RUN pip install -r req*/release.txt
RUN pip install -r req*/test.txt
ADD *.rst LICENSE MANIFEST.in *.txt *.sh *.cfg *.py *.ini ./
RUN <<EOF
pip install --no-cache-dir --break-system-packages -r req*/base.txt
pip install --no-cache-dir --break-system-packages -r req*/test.txt
pip install --no-cache-dir --break-system-packages -r req*/release.txt
EOF
RUN <<EOF
apt remove -y python3-dev libpython3-dev cargo
apt autoremove -y
rm -rf /var/lib/apt/lists/*
EOF

# SQUASH Stage
FROM $RSYNC AS squashed-rsync
FROM base AS squashed-ancestor
ARG ROOTFS="/BASE_ROOTFS_TO_COPY_THAT_WONT_COLLIDE_1234567890"
ARG PATH="${ROOTFS}_rsync/bin:$PATH"
RUN --mount=type=bind,from=final,target=$ROOTFS --mount=type=bind,from=squashed-rsync,target=${ROOTFS}_rsync \
rsync -Aaz --delete ${ROOTFS}/ / --exclude=/proc --exclude=/sys --exclude=/etc/resolv.conf --exclude=/etc/hosts --exclude=$ROOTFS* --exclude=dev/shm --exclude=dev/pts --exclude=dev/mqueue
ADD *.rst LICENSE MANIFEST.in *.txt *.cfg *.py *.ini *sh ./
ADD src/ src/
ENTRYPOINT /app/docker-entry.sh
14 changes: 14 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,20 @@ Develop this package
py.test src


Testing under py2
==================

Install prerequisisites ::

# install py 2 with eg: apt install python2.7
mkdir venv2 && curl -sSL "https://github.com/pypa/get-virtualenv/blob/20.27.0/public/2.7/virtualenv.pyz?raw=true" > venv2/venv && python2 venv2/venv venv2
venv2/bin/python2 -m pip install -r ./requirements/test.txt

Run tests::

./venv2/bin/tox --direct -e py27-std


Make a new release
====================
We use zest.fullreleaser, a great release infrastructure.
Expand Down
4 changes: 4 additions & 0 deletions docker-compose-32bits.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
version: "3.8"
services:
app:
image: "${CRONITER_IMAGE:-corpusops/croniter:32bits}"
6 changes: 6 additions & 0 deletions docker-compose-build-32bits.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
version: "3.8"
services:
app:
build:
args:
BASE: "corpusops/debian-32:trixie"
4 changes: 4 additions & 0 deletions docker-compose-build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
version: "3.8"
services:
app:
build: {context: .}
4 changes: 3 additions & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
version: "3.8"
services:
app:
build: {context: .}
image: "${CRONITER_IMAGE:-corpusops/croniter:latest}"
volumes:
- ./src:/app/src
- ./setup.cfg:/app/setup.cfg
- ./tox.ini:/app/tox.ini
- ./setup.py:/app/setup.py
- ./docker-entry.sh:/app/docker-entry.sh
3 changes: 0 additions & 3 deletions requirements/base.txt

This file was deleted.

1 change: 1 addition & 0 deletions requirements/lint.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
flake8
1 change: 0 additions & 1 deletion requirements/release.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
-r base.txt
zest.releaser[recommended]>=6.7
8 changes: 2 additions & 6 deletions requirements/test.txt
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
-r base.txt
pytz
pytest>=3.0.3
tox>=2.4.1
coverage>=4.2
mock>=2.0.0 # For Python 2
coveralls
flake8
tzlocal
setuptools
pytz # Tests require pytz on all versions
10 changes: 4 additions & 6 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,6 @@ def read(*rnames):
os.path.join('.', *rnames), encoding="utf-8"
).read()

install_requires = [
a.strip()
for a in read('requirements/base.txt').splitlines()
if a.strip() and not a.startswith(('#', '-'))
]

long_description = "\n\n".join(
[
Expand All @@ -35,7 +30,10 @@ def read(*rnames):
author_email='[email protected], [email protected]',
url='http://github.com/kiorky/croniter',
keywords='datetime, iterator, cron',
install_requires=install_requires,
install_requires=[
"python_dateutil",
"pytz>2021.1;python_version<'3.9'",
],
license="MIT License",
python_requires='>=2.6, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*',
classifiers=[
Expand Down
1 change: 1 addition & 0 deletions src/croniter/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from __future__ import absolute_import
from .croniter import (
croniter,
OVERFLOW32B_MODE,
datetime_to_timestamp,
croniter_range,
CroniterBadTypeRangeError, # noqa
Expand Down
70 changes: 65 additions & 5 deletions src/croniter/croniter.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,11 @@
import traceback as _traceback
import copy
import math
import platform
import re
import sys
import struct

import inspect
from time import time
import datetime
Expand All @@ -17,16 +20,68 @@
import binascii
import random

# as pytz is optional in thirdparty libs but we need it for good support under
# python2, just test that it's well installed
import pytz # noqa

try:
# py3 recent
UTC_DT = datetime.timezone.utc
except AttributeError:
# as pytz is optional in thirdparty libs but we need it for good support under
# python2, just test that it's well installed
import pytz # noqa
UTC_DT = pytz.utc


def is_32bit():
"""
Detect if Python is running in 32-bit mode.
Compatible with Python 2.6 and later versions.
Returns True if running on 32-bit Python, False for 64-bit.
"""
# Method 1: Check pointer size
bits = struct.calcsize("P") * 8

# Method 2: Check platform architecture string
try:
architecture = platform.architecture()[0]
except RuntimeError:
architecture = None

# Method 3: Check maxsize (sys.maxint in Python 2)
try:
# Python 2
is_small_maxsize = sys.maxint <= 2**32
except AttributeError:
# Python 3
is_small_maxsize = sys.maxsize <= 2**32

# Evaluate all available methods
is_32 = False

if bits == 32:
is_32 = True
elif architecture and '32' in architecture:
is_32 = True
elif is_small_maxsize:
is_32 = True

return is_32


try:
# https://github.com/python/cpython/issues/101069 detection
if is_32bit():
datetime.datetime.fromtimestamp(3999999999)
OVERFLOW32B_MODE = False
except OverflowError:
OVERFLOW32B_MODE = True

try:
from collections import OrderedDict
except ImportError:
OrderedDict = dict # py26 degraded mode, expanders order will not be immutable


EPOCH = datetime.datetime.fromtimestamp(0)
M_ALPHAS = {'jan': 1, 'feb': 2, 'mar': 3, 'apr': 4, 'may': 5, 'jun': 6,
'jul': 7, 'aug': 8, 'sep': 9, 'oct': 10, 'nov': 11, 'dec': 12}
DOW_ALPHAS = {'sun': 0, 'mon': 1, 'tue': 2, 'wed': 3, 'thu': 4, 'fri': 5, 'sat': 6}
Expand Down Expand Up @@ -274,7 +329,12 @@ def _timestamp_to_datetime(self, timestamp):
"""
Converts a UNIX timestamp `timestamp` into a `datetime` object.
"""
result = datetime.datetime.fromtimestamp(timestamp, tz=tzutc()).replace(tzinfo=None)
if OVERFLOW32B_MODE:
# degraded mode to workaround Y2038
# see https://github.com/python/cpython/issues/101069
result = EPOCH + datetime.timedelta(seconds=timestamp)
else:
result = datetime.datetime.fromtimestamp(timestamp, tz=tzutc()).replace(tzinfo=None)
if self.tzinfo:
result = result.replace(tzinfo=tzutc()).astimezone(self.tzinfo)

Expand Down Expand Up @@ -956,7 +1016,7 @@ def expand(cls, expr_format, hash_id=None, second_at_beginning=False, from_times

@classmethod
def _get_low_from_current_date_number(cls, i, step, from_timestamp):
dt = datetime.datetime.fromtimestamp(from_timestamp, tz=datetime.timezone.utc)
dt = datetime.datetime.fromtimestamp(from_timestamp, tz=UTC_DT)
if i == MINUTE_FIELD:
return dt.minute % step
if i == HOUR_FIELD:
Expand Down
Loading
Loading