@@ -65,6 +65,41 @@ when building markers dynamically from separate conditions.
6565
6666.. versionadded :: 26.1
6767
68+ You can combine existing :class: `Marker ` instances with ``& `` and ``| `` instead of
69+ parsing one long marker string. The string form preserves PEP 508 ``and `` / ``or ``
70+ precedence. :meth: `Marker.as_ast ` returns an immutable tree of
71+ :class: `MarkerCompare `, :class: `MarkerAnd `, and :class: `MarkerOr ` nodes (see
72+ :class: `MarkerNode `).
73+
74+ .. doctest ::
75+
76+ >>> from packaging.markers import Marker, MarkerCompare, MarkerAnd, MarkerOr
77+ >>> py_at_least_310 = Marker(' python_version >= "3.10"' )
78+ >>> posix = Marker(' os_name == "posix"' )
79+ >>> py_at_least_310 & posix
80+ <Marker('python_version >= "3.10" and os_name == "posix"')>
81+ >>> windows = Marker(' sys_platform == "win32"' )
82+ >>> macos = Marker(' sys_platform == "darwin"' )
83+ >>> windows | macos
84+ <Marker('sys_platform == "win32" or sys_platform == "darwin"')>
85+ >>> expr = Marker(
86+ ... " python_version > '3.12' or (python_version == '3.12' and os_name == 'unix')"
87+ ... )
88+ >>> node = expr.as_ast()
89+ >>> isinstance (node, MarkerOr)
90+ True
91+ >>> len (node.operands)
92+ 2
93+ >>> isinstance (node.operands[0 ], MarkerCompare)
94+ True
95+ >>> (node.operands[0 ].left, node.operands[0 ].op, node.operands[0 ].right)
96+ ('python_version', '>', '3.12')
97+ >>> isinstance (node.operands[1 ], MarkerAnd)
98+ True
99+ >>> [type (p).__name__ for p in node.operands[1 ].operands]
100+ ['MarkerCompare', 'MarkerCompare']
101+
102+ .. versionadded :: 26.1
68103
69104Reference
70105---------
@@ -73,3 +108,6 @@ Reference
73108 :members:
74109 :special-members: __and__, __or__
75110 :exclude-members: __init__
111+
112+ .. autodata :: MarkerCompareOp
113+ :no-value:
0 commit comments