Skip to content

[pull] master from DataDog:master#570

Merged
pull[bot] merged 6 commits into
ConnectionMaster:masterfrom
DataDog:master
May 29, 2026
Merged

[pull] master from DataDog:master#570
pull[bot] merged 6 commits into
ConnectionMaster:masterfrom
DataDog:master

Conversation

@pull

@pull pull Bot commented May 29, 2026

Copy link
Copy Markdown

See Commits and Changes for more details.


Created by pull[bot] (v2.0.0-alpha.4)

Can you help keep this open source service alive? 💖 Please sponsor : )

albertvaka and others added 6 commits May 29, 2026 11:40
The backslashes here were not escaping anything, instead being treated as
literal backslashes that would show up in the logs.
…se (#23741)

* Add CronExpression and CronScheduler utilities to datadog_checks_base

CronExpression parses a standard 5-field UTC cron string and computes the
next/previous scheduled tick relative to any timestamp. CronScheduler wraps
an expression with a non-blocking 'has my tick elapsed?' state machine
designed to be polled once per AgentCheck.check() invocation, with an
optional startup_lookback for recovering a missed tick across check
restarts.

Supports *, n, n-m, n,m,k, */k, and n-m/k in each field, plus 7 as a
Sunday alias for day-of-week. Vixie OR semantics for day-of-month vs.
day-of-week when both are restricted.

* Add changelog entry for cron utility

* Fix N/step cron semantics, tighten error types, derive equality from parsed fields

- N/step in a single-integer base now extends to the field's high (Vixie
  semantics): "5/15 * * * *" fires {5, 20, 35, 50} instead of {5}.
- CronExpression raises TypeError for non-string input and ValueError for
  all malformed expressions, including parse-time rejection of DOM/month
  combos that can never fire ("0 0 31 2 *").
- Equality and hashing derive from the parsed fields, so "0 0 * * 7" and
  "0 0 * * 0" compare equal.
- _jump_month iterates self._months directly to match the other _jump_*
  helpers; the _roll_month helper is removed.
- CronScheduler.due_ticks returns list[float] matching the materialised
  behaviour; the typing.Iterator alias drops with it.
- Rename test helpers to their fully spelled form (utc_timestamp,
  iso_format, BASE_TIMESTAMP); drop em-dashes and motivational framing
  from comments and docstrings.

* Promote MAX_DAYS_PER_MONTH to module scope and tighten DOM/month guard

- Move the per-month max-day table from inside _reject_unsatisfiable_dom_month
  to a module-level MAX_DAYS_PER_MONTH constant, alongside the other range
  constants.
- Short-circuit _reject_unsatisfiable_dom_month when DOM is unrestricted as
  well: only the DOM-restricted + DOW-unrestricted case can be impossible at
  parse time.
- Add a NEXT_PREV_CASES row that crosses a month boundary backward while
  Vixie OR semantics are active ("0 0 31 1 3" anchored in Feb 2026), pinning
  the interaction between _jump_month and _day_matches.
- Drop the now-redundant list(...) wrappers around CronScheduler.due_ticks
  calls in the scheduler tests; due_ticks already returns list[float].

* Split _parse_field into single-purpose helpers and align backward jumps

- _parse_field now returns only the sorted values tuple; the is_restricted
  flag was discarded by three of five call sites. CronExpression.__init__
  computes _dom_restricted and _dow_restricted directly from the raw fields
  where the Vixie OR rule actually needs them.
- _parse_field delegates to four helpers, each with a single responsibility:
    _expand_chunk: one comma piece, with optional /step
    _split_step:   extracts and validates /step
    _parse_base:   dispatches between '*', 'n-m', and 'n'
    _parse_range:  parses an 'n-m' inclusive range
  Each helper raises with its own context so error messages still pinpoint
  the specific malformation.
- _jump_hour and _jump_minute backward paths now use self._minutes[-1]
  (and self._hours[-1]) instead of hardcoded 59/23 when crossing a
  boundary, so a sparse-minute schedule does not need an extra walk
  iteration to recover.

* Add edge-case tests adapted from croniter's test suite

Covers behavior surface our parser claims to support but had no dedicated
test:

- Duplicate and overlapping values in comma lists normalize to the same
  parsed form (e.g. "5,5,1-6 * * * *" equals "1-6 * * * *").
- Vixie OR with stepped DOM and a weekday ("0 16 */2 * 6"), pinning the
  interaction between */k expansion in DOM and DOW match in _day_matches.
- next_tick and previous_tick around stepped DOM ("5 0 */2 * *") from an
  even-numbered day where the anchor itself does not match.
- previous_tick crossing into the previous month with a simple DOM
  ("0 0 22 * *" anchored mid-March -> 22 February).
- Weekend DOW list ("0 0 * * 0,6") matching the most recent Sat/Sun in
  both directions.
- Comma list in the month field ("0 0 1 1,3,6,9,12 *") rolling forward
  and backward across allowed months.

* Reject cron expressions with whitespace inside fields

A field like "1, 1, 3,3" looks at a glance like one comma list, but the
spaces split it into multiple whitespace-separated fields, so the overall
expression no longer has five fields. The parser already rejects this
correctly via the field-count check; pinning the behaviour here covers
the common ways a user might accidentally introduce intra-field
whitespace (after a comma, before a comma, around a dash).

* Accept whitespace around commas in cron fields

A field like "1, 2, 3" is visually unambiguous: the writer means a
comma list. The previous parser was strict and rejected it as
multiple whitespace-separated fields. Normalise whitespace adjacent
to commas before splitting into fields, so "0 0 1 1, 2, 3 *" parses
the same as "0 0 1 1,2,3 *".

Dashes stay strict ("1- 3" is more likely a typo than a style
choice, so it is still rejected).

* Reject any whitespace inside a cron field

The previous commit accepted whitespace around commas but not around
dashes, which is inconsistent: every kind of intra-field whitespace
has only one plausible reading (the punctuation it sits next to), so
"unambiguous to a human" applies the same way to "1, 2" and "1- 3".
A single strict rule (no whitespace inside fields) gives the user
the same clear failure for every variant and matches standard cron,
croniter, and systemd timers.

* Slim MAX_DAYS_PER_MONTH to non-31 months and merge tick-table tests

- Drop the always-31 entries from MAX_DAYS_PER_MONTH and look them up via
  .get(month, 31) so the table communicates "31 is the rule, these are
  the exceptions." Add a short comment explaining why February uses 29.
- Collapse test_next_tick and test_previous_tick into a single
  test_bracketing_ticks with the cases inlined into the parametrize block.
  Removes the top-level NEXT_PREV_CASES constant and the underscore-prefixed
  unused arguments, while preserving the joint (prev, next) specification at
  each anchor. Failure messages now name the broken direction.

* Share a single parser between construction and is_valid

- Extract _parse() as the one grammar both __init__ and is_valid use, so
  is_valid validates without instantiating a CronExpression.
- Explain the scheduling sense of "due" in the due_ticks docstring.

* Drop is_valid; document walk budget and CronExpression exceptions

- Remove the is_valid predicate and update tests to validate through the
  constructor.
- Add a comment explaining WALK_ITERATION_BUDGET.
- Document the ValueError and TypeError CronExpression raises on bad input.
* [Release] Bumped datadog_checks_base version to 37.38.0

* [Release] Update metadata
* Revert "Aarakke/release checks base (#23877)"

This reverts commit 8abadad.

* Restore in-toto from master
* [Release] Bumped datadog_checks_base version to 37.39.0

* [Release] Update metadata
@pull pull Bot locked and limited conversation to collaborators May 29, 2026
@pull pull Bot added the ⤵️ pull label May 29, 2026
@pull pull Bot merged commit 8ea556c into ConnectionMaster:master May 29, 2026
1 check passed
@pull pull Bot temporarily deployed to release May 29, 2026 14:27 Inactive
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants