{"record":{"id":"3674cd2afd08c867","repo":"Textualize/rich","slug":"slices-with-step-1-are-not-supported","errorCode":null,"errorMessage":"slices with step!=1 are not supported","messagePattern":"slices with step!=1 are not supported","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"warning","filePath":"rich/text.py","lineNumber":222,"sourceCode":"                    _Span(0, 1, style)\n                    for start, end, style in self._spans\n                    if end > offset >= start\n                ],\n                end=\"\",\n            )\n            return text\n\n        if isinstance(slice, int):\n            return get_text_at(slice)\n        else:\n            start, stop, step = slice.indices(len(self.plain))\n            if step == 1:\n                lines = self.divide([start, stop])\n                return lines[1]\n            else:\n                # This would be a bit of work to implement efficiently\n                # For now, its not required\n                raise TypeError(\"slices with step!=1 are not supported\")\n\n    @property\n    def cell_len(self) -> int:\n        \"\"\"Get the number of cells required to render this text.\"\"\"\n        return cell_len(self.plain)\n\n    @property\n    def markup(self) -> str:\n        \"\"\"Get console markup to render this Text.\n\n        Returns:\n            str: A string potentially creating markup tags.\n        \"\"\"\n        from .markup import escape\n\n        output: List[str] = []\n\n        plain = self.plain","sourceCodeStart":204,"sourceCodeEnd":240,"githubUrl":"https://github.com/Textualize/rich/blob/9d8f9a372cc5916fd4781fec207ced7ddac2f08f/rich/text.py#L204-L240","documentation":"Text.__getitem__ supports int indexing and slicing, but only slices with step == 1 (it uses divide() to keep style spans aligned with the cut). Slices with step != 1 (e.g. t[::2], t[::-1]) would require non-contiguous span handling, which rich deliberately did not implement, so it raises TypeError('slices with step!=1 are not supported').","triggerScenarios":"text[::2], text[1:10:2], text[::-1] on a Text instance — including negative step (reversal) which always has step != 1. Slices like t[2:8] or t[:5] work fine; slice.indices() is used so any step other than 1, positive or negative, trips it.","commonSituations":"Porting plain-str slicing code (s[::-1] for reversal, s[::2] for every-other-char) to Text; truncation/abbreviation helpers generalized from strings; list-comprehension style tricks applied to styled text.","solutions":["Operate on the plain string and rebuild: Text(text.plain[::2]) — accepting that styles are lost.","For step != 1 with styles preserved, build manually: Text('').join(text.plain[i] and text[i] ... ) — or concatenate per-character slices text[i:i+1] in a loop.","Restructure to use contiguous sub-slices only (step 1), e.g. reverse via ''.join(reversed(...)) on .plain if styling is unimportant."],"exampleFix":"# before\nout = text[::-1]  # TypeError: slices with step!=1\n\n# after\nout = Text(text.plain[::-1])  # styles dropped, works","handlingStrategy":"fallback","validationCode":"def safe_slice(text, start=None, stop=None, step=1):\n    if step == 1:\n        return text[start:stop]\n    return Text(text.plain[start:stop:step])  # styles lost","typeGuard":"def is_contiguous_slice(s: slice) -> bool:\n    return s.step is None or s.step == 1","tryCatchPattern":"try:\n    part = text[::2]\nexcept TypeError:\n    part = Text(text.plain[::2])","preventionTips":["Keep step=1 when slicing Text; use .plain for exotic slicing and rebuild.","Port str-slicing utilities consciously: reversal/striding are unsupported on Text by design."],"tags":["rich","text","slicing","typeerror","unsupported-operation"],"backgroundTag":null,"analyzedSha":"9d8f9a372cc5916fd4781fec207ced7ddac2f08f","analyzedAt":"2026-08-15T03:30:11.781Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}