{"id":255,"library":"iniconfig","title":"iniconfig","description":"iniconfig is a minimal, read-only INI-file parser maintained under the pytest-dev umbrella. It preserves section and key order, supports multi-line values, strips `#` comments from structure (not inline values in <2.3), raises `ParseError` with accurate line numbers, and rejects duplicate section names. Current stable version is 2.3.0, released 2024. Release cadence is irregular but healthy, driven by pytest ecosystem needs.","status":"active","version":"2.3.0","language":"python","source_language":"en","source_url":"https://github.com/pytest-dev/iniconfig","tags":["ini","config","configuration","parser","pytest","settings"],"install":[{"cmd":"pip install iniconfig","lang":"bash","label":"pip"}],"dependencies":[],"imports":[{"wrong":"import iniconfig","symbol":"IniConfig","correct":"from iniconfig import IniConfig"}],"quickstart":{"code":"import iniconfig\n\nINI_TEXT = \"\"\"\n[database]\nhost = localhost\nport = 5432\nnames = foo,bar\n\n[app]\ndebug = true\n\"\"\"\n\n# Parse from a string (no file needed)\nini = iniconfig.IniConfig(\"-\", data=INI_TEXT)\n\n# Direct access — raises KeyError if key/section missing\nhost = ini[\"database\"][\"host\"]          # 'localhost'\n\n# Safe access with default + optional converter\nport = ini.get(\"database\", \"port\", 5432, int)          # 5432 (int)\nnames = ini.get(\"database\", \"names\", [], lambda x: x.split(\",\"))  # ['foo', 'bar']\nmissing = ini.get(\"database\", \"user\", \"root\")           # 'root'\n\n# Membership check\nassert \"database\" in ini\nassert \"ghost\" not in ini\n\n# Iterate sections\nfor section in ini:\n    print(section.name, list(section.items()))\n\n# Catch parse errors\ntry:\n    bad = iniconfig.IniConfig(\"-\", data=\"[dup]\\n[dup]\\n\")\nexcept iniconfig.ParseError as exc:\n    print(f\"Parse failed: {exc}\")\n","lang":"python","description":"Parse an INI config from a string, access values, use .get() for safe access with a default and optional converter."},"warnings":[{"fix":"Use iniconfig==1.1.1 for Python < 3.10 environments, or upgrade the interpreter.","message":"v2.0.0 dropped Python 2 and older Python 3 (< 3.7) support and changed the packaging. The API surface stayed compatible, but pip will refuse to install 2.x on Python < 3.10 (requires_python >=3.10 as of 2.3.0).","severity":"breaking","affected_versions":"<2.0.0"},{"fix":"Ensure each section name appears exactly once in the INI source before parsing.","message":"Duplicate section names raise ParseError. Unlike stdlib configparser, iniconfig does NOT merge duplicates — the second occurrence is an error, not a silent override.","severity":"breaking","affected_versions":"all"},{"fix":"Use IniConfig.parse() (added in 2.3.0) which does strip inline comments, or strip manually: value.split('#')[0].strip().","message":"Inline comments (e.g. `key = value # comment`) are NOT stripped by IniConfig() — the raw string including `# comment` is returned as the value. This differed silently from the README example in versions 2.0–2.2.","severity":"gotcha","affected_versions":"1.x – 2.2.x"},{"fix":"Use ini.get(section, key, default) instead of direct bracket access for any optional key.","message":"ini['section']['key'] raises KeyError — not returning None — when the section or key is absent. There is no .get() short-circuit on the section-level dict.","severity":"gotcha","affected_versions":"all"},{"fix":"Use stdlib configparser or a different library (e.g. configupdater) if you need to write or round-trip INI files.","message":"iniconfig is READ-ONLY. There is no write-back, set(), or save() method. Attempts to assign to ini['section']['key'] will raise TypeError or silently do nothing depending on the internal namedtuple/mapping type.","severity":"gotcha","affected_versions":"all"},{"fix":"Replace `py.iniconfig` with `import iniconfig` and `iniconfig.IniConfig(...)`.","message":"The old py.iniconfig path (from the `py` / pylib package) was the predecessor of this standalone package. Any code doing `import py; py.iniconfig.IniConfig(...)` is using a long-deprecated shim.","severity":"deprecated","affected_versions":"py<2.0"},{"fix":"Always supply a non-None path: `IniConfig('-', data=my_string)`.","message":"IniConfig constructor requires a path as its first positional argument even when parsing from a string via the `data=` kwarg. Passing `None` raises TypeError; pass a placeholder string like '-' or '<string>' instead.","severity":"gotcha","affected_versions":"all"}],"env_vars":null,"search_vec":"'2.3':39 '2.3.0':55 '2024':57 'accur':43 'cadenc':59 'comment':32 'config':70 'configur':71 'current':51 'dev':18 'driven':64 'duplic':48 'ecosystem':67 'file':11 'healthi':63 'ini':10,69 'ini-fil':9 'iniconfig':1,2 'inlin':36 'irregular':61 'key':24 'line':29,44 'maintain':13 'minim':5 'multi':28 'multi-lin':27 'name':50 'need':68 'number':45 'order':25 'parseerror':41 'parser':12,72 'preserv':21 'pytest':17,66,73 'pytest-dev':16 'rais':40 'read':7 'read-on':6 'reject':47 'releas':56,58 'section':22,49 'set':74 'stabl':52 'strip':31 'structur':34 'support':26 'umbrella':19 'valu':30,37 'version':53","created_at":"2026-03-28T03:56:19.216646+00:00","updated_at":"2026-04-16T15:44:38.426013+00:00","problems":null,"ecosystem":"pypi","meta_description":null,"install_score":100,"quickstart_score":80,"quickstart_tag":"verified","pypi_latest":"2.3.0","cli_name":"","cli_version":null,"type":"library","homepage":null,"github":"https://github.com/pytest-dev/iniconfig","docs":null,"changelog":null,"pypi":"https://pypi.org/project/iniconfig/","npm":null,"openapi_spec":null,"status_page":null,"smithery":null,"categories":["serialization","testing"],"base_url":null,"auth_type":null,"provenance":{"verified_status":"passing","verified_at":"2026-06-30","last_verified":"2026-06-30","next_check":"2026-07-30","install_tag":"verified"}}