{"id":2665,"library":"portion","title":"Portion Library for Python Intervals","description":"The portion library (current version 2.6.1) provides a robust data structure and operations for intervals in Python. It supports various types of intervals (closed, open, finite, semi-infinite) with any comparable objects, including interval sets (disjunctions of atomic intervals). The library offers automatic simplification, comparison, transformation, intersection, union, complement, difference, containment, and discrete iteration, along with a dict-like structure (`IntervalDict`) to map intervals to data. It is actively maintained with regular releases.","status":"active","version":"2.6.1","language":"en","source_language":"en","source_url":"https://github.com/AlexandreDecan/portion","tags":["interval","data-structure","time-series","ranges","discrete-math"],"install":[{"cmd":"pip install portion","lang":"bash","label":"Install stable version"}],"dependencies":[],"imports":[{"symbol":"Interval","correct":"import portion as P\ninterval = P.Interval([1, 5])"},{"note":"Importing all symbols with `*` is discouraged for clarity and potential name collisions. Prefer `import portion as P`.","wrong":"from portion import *\ninterval = open(1, 5)","symbol":"open, closed, openclosed, closedopen, singleton, empty, inf","correct":"import portion as P\nopen_interval = P.open(1, 5)\nclosed_interval = P.closed(1, 5)\nempty_interval = P.empty()\npositive_infinity = P.inf"},{"symbol":"IntervalDict","correct":"import portion as P\ndata_dict = P.IntervalDict()"}],"quickstart":{"code":"import portion as P\n\n# Create intervals\ni1 = P.closed(1, 5) # [1,5]\ni2 = P.open(3, 7)   # (3,7)\ni3 = P.singleton(10) # [10,10]\ni_inf = P.openclosed(-P.inf, 0) # (-inf,0]\n\nprint(f\"Interval 1: {i1}\")\nprint(f\"Interval 2: {i2}\")\n\n# Perform operations\nunion = i1 | i2       # Union\nintersection = i1 & i2  # Intersection\ndifference = i1 - i2  # Difference\ncomplement = ~i1      # Complement (relative to the full domain)\n\nprint(f\"Union: {union}\")\nprint(f\"Intersection: {intersection}\")\nprint(f\"Difference: {difference}\")\nprint(f\"Complement of [1,5]: {complement}\")\n\n# Check properties\nprint(f\"Is i1 in i2? {i2.contains(i1)}\") # False\nprint(f\"Does i1 overlap i2? {i1.overlaps(i2)}\") # True\nprint(f\"Is empty interval empty? {P.empty().empty}\") # True\n\n# Using IntervalDict\nid = P.IntervalDict()\nid[P.closed(0, 10)] = 'Phase 1'\nid[P.open(10, 20)] = 'Phase 2'\nid[P.singleton(25)] = 'Event'\n\nprint(f\"\\nIntervalDict: {id}\")\nprint(f\"Value at 5: {id[5]}\") # 'Phase 1'\nprint(f\"Value at 15: {id[15]}\") # 'Phase 2'\nprint(f\"Value at 25: {id[25]}\") # 'Event'\n\n# Get items as (interval, value) pairs\nprint(f\"Items: {list(id.items())}\")","lang":"python","description":"This quickstart demonstrates how to create various types of intervals, perform common set operations (union, intersection, difference, complement), check interval properties (containment, overlap, emptiness), and utilize the `IntervalDict` for mapping data to intervals."},"warnings":[{"fix":"Update logic that relies on `list(P.empty())` to expect an empty list, and adjust comparisons involving `P.empty()` to explicitly check for emptiness or use set operations where appropriate.","message":"In version 2.3.0, the representation and comparison of the empty interval changed. `list(P.empty())` now correctly returns `[]` (an empty list) instead of `[P.empty()]`. Additionally, the empty interval is no longer considered less than, greater than, less than or equal to, or greater than or equal to any other interval for consistency.","severity":"breaking","affected_versions":">=2.3.0"},{"fix":"Review the `CHANGELOG.md` for a comprehensive list of API changes. Update method calls and attribute accesses to align with the new API, ensuring all parameters are passed as keyword arguments where required.","message":"Version 2.0.0 introduced significant breaking changes, including the renaming of the library from `python-intervals` to `portion`. Many optional parameters became keyword-only arguments. Key methods like `is_empty()`, `is_atomic()`, and `to_atomic()` were removed in favor of attributes (`.empty`, `.atomic`) or other methods (`.enclosure`), and `AtomicInterval` was removed from the public API.","severity":"breaking","affected_versions":">=2.0.0"},{"fix":"Convert scalar values to singleton intervals (e.g., `P.singleton(value)`) before performing comparisons with intervals to ensure well-defined behavior.","message":"Direct comparison between an interval and a scalar value (e.g., `interval <= value` or `value >= interval`) is deprecated since version 2.3.0 as it is ill-defined. This applies when the scalar is on the left side of a comparison operator.","severity":"deprecated","affected_versions":">=2.3.0"},{"fix":"Ensure your project is running on Python 3.9 or a newer compatible version to use the latest features and receive official support.","message":"Official support for older Python versions has been progressively dropped: Python 3.8 support was dropped in 2.6.1, 3.7 in 2.5.0, and 3.6 in 2.3.1. The `portion` library now officially requires Python 3.9 or newer.","severity":"gotcha","affected_versions":">=2.3.1 (for 3.6), >=2.5.0 (for 3.7), >=2.6.1 (for 3.8)"},{"fix":"If using `create_api`, upgrade to a version past 2.4.2 where these import issues have been addressed, or consider using the direct `portion` API.","message":"The experimental `create_api` function experienced import errors in versions 2.4.1 and 2.4.2, particularly when used outside a REPL environment or with Python 3.10+.","severity":"gotcha","affected_versions":"2.4.1, 2.4.2"}],"env_vars":null,"last_verified":"2026-04-10T00:00:00.000Z","next_check":"2026-07-09T00:00:00.000Z"}