We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
'with_sequence' should not fail with 'count=0'
**Issue Type:** Bug Report

**Ansible Version:** 1.8.4

**Environment:** N/A

**Summary:**

The `with_sequence` statement should not fail when used with `count=0`. Instead, it should just skip the task.

**Steps To Reproduce:**

Here is a minimal playbook `bug.yml` to illustrate the issue:

``` yaml

---
- hosts: all
  gather_facts: False
  tasks:
    - name: "This task should be skipped because count=0 in the 'with_sequence' statement"
      command: echo "Hello world"
      with_sequence: count=0
```

It can be run with:

`ansible-playbook -c local -i localhost, bug.yml`

**Expected Results:**

The task should be skipped because `count=0`.

**Actual Results:**

The task fails with the error message "can't count backwards" (which is counterintuitive because `count` is zero, not negative).

```
TASK: [command echo "Hello world"] ******************************************** 
fatal: [localhost] => can't count backwards

FATAL: all hosts have already failed -- aborting
```


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `lib/ansible/runner/lookup_plugins/sequence.py`
Content:
```
1 # (c) 2013, Jayson Vantuyl <jayson@aggressive.ly>
2 #
3 # This file is part of Ansible
4 #
5 # Ansible is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation, either version 3 of the License, or
8 # (at your option) any later version.
9 #
10 # Ansible is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 # GNU General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with Ansible.  If not, see <http://www.gnu.org/licenses/>.
17 
18 from ansible.errors import AnsibleError
19 import ansible.utils as utils
20 from re import compile as re_compile, IGNORECASE
21 
22 # shortcut format
23 NUM = "(0?x?[0-9a-f]+)"
24 SHORTCUT = re_compile(
25     "^(" +        # Group 0
26     NUM +         # Group 1: Start
27     "-)?" +
28     NUM +         # Group 2: End
29     "(/" +        # Group 3
30     NUM +         # Group 4: Stride
31     ")?" +
32     "(:(.+))?$",  # Group 5, Group 6: Format String
33     IGNORECASE
34 )
35 
36 
37 class LookupModule(object):
38     """
39     sequence lookup module
40 
41     Used to generate some sequence of items. Takes arguments in two forms.
42 
43     The simple / shortcut form is:
44 
45       [start-]end[/stride][:format]
46 
47     As indicated by the brackets: start, stride, and format string are all
48     optional.  The format string is in the style of printf.  This can be used
49     to pad with zeros, format in hexadecimal, etc.  All of the numerical values
50     can be specified in octal (i.e. 0664) or hexadecimal (i.e. 0x3f8).
51     Negative numbers are not supported.
52 
53     Some examples:
54 
55       5 -> ["1","2","3","4","5"]
56       5-8 -> ["5", "6", "7", "8"]
57       2-10/2 -> ["2", "4", "6", "8", "10"]
58       4:host%02d -> ["host01","host02","host03","host04"]
59 
60     The standard Ansible key-value form is accepted as well.  For example:
61 
62       start=5 end=11 stride=2 format=0x%02x -> ["0x05","0x07","0x09","0x0a"]
63 
64     This format takes an alternate form of "end" called "count", which counts
65     some number from the starting value.  For example:
66 
67       count=5 -> ["1", "2", "3", "4", "5"]
68       start=0x0f00 count=4 format=%04x -> ["0f00", "0f01", "0f02", "0f03"]
69       start=0 count=5 stride=2 -> ["0", "2", "4", "6", "8"]
70       start=1 count=5 stride=2 -> ["1", "3", "5", "7", "9"]
71 
72     The count option is mostly useful for avoiding off-by-one errors and errors
73     calculating the number of entries in a sequence when a stride is specified.
74     """
75 
76     def __init__(self, basedir, **kwargs):
77         """absorb any keyword args"""
78         self.basedir = basedir
79 
80     def reset(self):
81         """set sensible defaults"""
82         self.start = 1
83         self.count = None
84         self.end = None
85         self.stride = 1
86         self.format = "%d"
87 
88     def parse_kv_args(self, args):
89         """parse key-value style arguments"""
90         for arg in ["start", "end", "count", "stride"]:
91             try:
92                 arg_raw = args.pop(arg, None)
93                 if arg_raw is None:
94                     continue
95                 arg_cooked = int(arg_raw, 0)
96                 setattr(self, arg, arg_cooked)
97             except ValueError:
98                 raise AnsibleError(
99                     "can't parse arg %s=%r as integer"
100                         % (arg, arg_raw)
101                 )
102             if 'format' in args:
103                 self.format = args.pop("format")
104         if args:
105             raise AnsibleError(
106                 "unrecognized arguments to with_sequence: %r"
107                 % args.keys()
108             )
109 
110     def parse_simple_args(self, term):
111         """parse the shortcut forms, return True/False"""
112         match = SHORTCUT.match(term)
113         if not match:
114             return False
115 
116         _, start, end, _, stride, _, format = match.groups()
117 
118         if start is not None:
119             try:
120                 start = int(start, 0)
121             except ValueError:
122                 raise AnsibleError("can't parse start=%s as integer" % start)
123         if end is not None:
124             try:
125                 end = int(end, 0)
126             except ValueError:
127                 raise AnsibleError("can't parse end=%s as integer" % end)
128         if stride is not None:
129             try:
130                 stride = int(stride, 0)
131             except ValueError:
132                 raise AnsibleError("can't parse stride=%s as integer" % stride)
133 
134         if start is not None:
135             self.start = start
136         if end is not None:
137             self.end = end
138         if stride is not None:
139             self.stride = stride
140         if format is not None:
141             self.format = format
142 
143     def sanity_check(self):
144         if self.count is None and self.end is None:
145             raise AnsibleError(
146                 "must specify count or end in with_sequence"
147             )
148         elif self.count is not None and self.end is not None:
149             raise AnsibleError(
150                 "can't specify both count and end in with_sequence"
151             )
152         elif self.count is not None:
153             # convert count to end
154             self.end = self.start + self.count * self.stride - 1
155             del self.count
156         if self.end < self.start:
157             raise AnsibleError("can't count backwards")
158         if self.format.count('%') != 1:
159             raise AnsibleError("bad formatting string: %s" % self.format)
160 
161     def generate_sequence(self):
162         numbers = xrange(self.start, self.end + 1, self.stride)
163 
164         for i in numbers:
165             try:
166                 formatted = self.format % i
167                 yield formatted
168             except (ValueError, TypeError):
169                 raise AnsibleError(
170                     "problem formatting %r with %r" % self.format
171                 )
172 
173     def run(self, terms, inject=None, **kwargs):
174         results = []
175 
176         terms = utils.listify_lookup_plugin_terms(terms, self.basedir, inject)
177 
178         if isinstance(terms, basestring):
179             terms = [ terms ]
180 
181         for term in terms:
182             try:
183                 self.reset()  # clear out things for this iteration
184 
185                 try:
186                     if not self.parse_simple_args(term):
187                         self.parse_kv_args(utils.parse_kv(term))
188                 except Exception:
189                     raise AnsibleError(
190                         "unknown error parsing with_sequence arguments: %r"
191                         % term
192                     )
193 
194                 self.sanity_check()
195 
196                 results.extend(self.generate_sequence())
197             except AnsibleError:
198                 raise
199             except Exception:
200                 raise AnsibleError(
201                     "unknown error generating sequence"
202                 )
203 
204         return results
205
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/lib/ansible/runner/lookup_plugins/sequence.py b/lib/ansible/runner/lookup_plugins/sequence.py
--- a/lib/ansible/runner/lookup_plugins/sequence.py
+++ b/lib/ansible/runner/lookup_plugins/sequence.py
@@ -151,15 +151,26 @@
             )
         elif self.count is not None:
             # convert count to end
-            self.end = self.start + self.count * self.stride - 1
+            if self.count != 0:
+                self.end = self.start + self.count * self.stride - 1
+            else:
+                self.start = 0
+                self.end = 0
+                self.stride = 0
             del self.count
-        if self.end < self.start:
-            raise AnsibleError("can't count backwards")
+        if self.stride > 0 and self.end < self.start:
+            raise AnsibleError("to count backwards make stride negative")
+        if self.stride < 0 and self.end > self.start:
+            raise AnsibleError("to count forward don't make stride negative")
         if self.format.count('%') != 1:
             raise AnsibleError("bad formatting string: %s" % self.format)
 
     def generate_sequence(self):
-        numbers = xrange(self.start, self.end + 1, self.stride)
+        if self.stride > 0:
+            adjust = 1
+        else:
+            adjust = -1
+        numbers = xrange(self.start, self.end + adjust, self.stride)
 
         for i in numbers:
             try:
@@ -193,12 +204,13 @@
 
                 self.sanity_check()
 
-                results.extend(self.generate_sequence())
+                if self.start != self.end:
+                    results.extend(self.generate_sequence())
             except AnsibleError:
                 raise
-            except Exception:
+            except Exception, e:
                 raise AnsibleError(
-                    "unknown error generating sequence"
+                    "unknown error generating sequence: %s" % str(e)
                 )
 
         return results

{"golden_diff": "diff --git a/lib/ansible/runner/lookup_plugins/sequence.py b/lib/ansible/runner/lookup_plugins/sequence.py\n--- a/lib/ansible/runner/lookup_plugins/sequence.py\n+++ b/lib/ansible/runner/lookup_plugins/sequence.py\n@@ -151,15 +151,26 @@\n             )\n         elif self.count is not None:\n             # convert count to end\n-            self.end = self.start + self.count * self.stride - 1\n+            if self.count != 0:\n+                self.end = self.start + self.count * self.stride - 1\n+            else:\n+                self.start = 0\n+                self.end = 0\n+                self.stride = 0\n             del self.count\n-        if self.end < self.start:\n-            raise AnsibleError(\"can't count backwards\")\n+        if self.stride > 0 and self.end < self.start:\n+            raise AnsibleError(\"to count backwards make stride negative\")\n+        if self.stride < 0 and self.end > self.start:\n+            raise AnsibleError(\"to count forward don't make stride negative\")\n         if self.format.count('%') != 1:\n             raise AnsibleError(\"bad formatting string: %s\" % self.format)\n \n     def generate_sequence(self):\n-        numbers = xrange(self.start, self.end + 1, self.stride)\n+        if self.stride > 0:\n+            adjust = 1\n+        else:\n+            adjust = -1\n+        numbers = xrange(self.start, self.end + adjust, self.stride)\n \n         for i in numbers:\n             try:\n@@ -193,12 +204,13 @@\n \n                 self.sanity_check()\n \n-                results.extend(self.generate_sequence())\n+                if self.start != self.end:\n+                    results.extend(self.generate_sequence())\n             except AnsibleError:\n                 raise\n-            except Exception:\n+            except Exception, e:\n                 raise AnsibleError(\n-                    \"unknown error generating sequence\"\n+                    \"unknown error generating sequence: %s\" % str(e)\n                 )\n \n         return results\n", "issue": "'with_sequence' should not fail with 'count=0'\n**Issue Type:** Bug Report\n\n**Ansible Version:** 1.8.4\n\n**Environment:** N/A\n\n**Summary:**\n\nThe `with_sequence` statement should not fail when used with `count=0`. Instead, it should just skip the task.\n\n**Steps To Reproduce:**\n\nHere is a minimal playbook `bug.yml` to illustrate the issue:\n\n``` yaml\n\n---\n- hosts: all\n  gather_facts: False\n  tasks:\n    - name: \"This task should be skipped because count=0 in the 'with_sequence' statement\"\n      command: echo \"Hello world\"\n      with_sequence: count=0\n```\n\nIt can be run with:\n\n`ansible-playbook -c local -i localhost, bug.yml`\n\n**Expected Results:**\n\nThe task should be skipped because `count=0`.\n\n**Actual Results:**\n\nThe task fails with the error message \"can't count backwards\" (which is counterintuitive because `count` is zero, not negative).\n\n```\nTASK: [command echo \"Hello world\"] ******************************************** \nfatal: [localhost] => can't count backwards\n\nFATAL: all hosts have already failed -- aborting\n```\n\n", "before_files": [{"content": "# (c) 2013, Jayson Vantuyl <jayson@aggressive.ly>\n#\n# This file is part of Ansible\n#\n# Ansible is free software: you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n#\n# Ansible is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with Ansible.  If not, see <http://www.gnu.org/licenses/>.\n\nfrom ansible.errors import AnsibleError\nimport ansible.utils as utils\nfrom re import compile as re_compile, IGNORECASE\n\n# shortcut format\nNUM = \"(0?x?[0-9a-f]+)\"\nSHORTCUT = re_compile(\n    \"^(\" +        # Group 0\n    NUM +         # Group 1: Start\n    \"-)?\" +\n    NUM +         # Group 2: End\n    \"(/\" +        # Group 3\n    NUM +         # Group 4: Stride\n    \")?\" +\n    \"(:(.+))?$\",  # Group 5, Group 6: Format String\n    IGNORECASE\n)\n\n\nclass LookupModule(object):\n    \"\"\"\n    sequence lookup module\n\n    Used to generate some sequence of items. Takes arguments in two forms.\n\n    The simple / shortcut form is:\n\n      [start-]end[/stride][:format]\n\n    As indicated by the brackets: start, stride, and format string are all\n    optional.  The format string is in the style of printf.  This can be used\n    to pad with zeros, format in hexadecimal, etc.  All of the numerical values\n    can be specified in octal (i.e. 0664) or hexadecimal (i.e. 0x3f8).\n    Negative numbers are not supported.\n\n    Some examples:\n\n      5 -> [\"1\",\"2\",\"3\",\"4\",\"5\"]\n      5-8 -> [\"5\", \"6\", \"7\", \"8\"]\n      2-10/2 -> [\"2\", \"4\", \"6\", \"8\", \"10\"]\n      4:host%02d -> [\"host01\",\"host02\",\"host03\",\"host04\"]\n\n    The standard Ansible key-value form is accepted as well.  For example:\n\n      start=5 end=11 stride=2 format=0x%02x -> [\"0x05\",\"0x07\",\"0x09\",\"0x0a\"]\n\n    This format takes an alternate form of \"end\" called \"count\", which counts\n    some number from the starting value.  For example:\n\n      count=5 -> [\"1\", \"2\", \"3\", \"4\", \"5\"]\n      start=0x0f00 count=4 format=%04x -> [\"0f00\", \"0f01\", \"0f02\", \"0f03\"]\n      start=0 count=5 stride=2 -> [\"0\", \"2\", \"4\", \"6\", \"8\"]\n      start=1 count=5 stride=2 -> [\"1\", \"3\", \"5\", \"7\", \"9\"]\n\n    The count option is mostly useful for avoiding off-by-one errors and errors\n    calculating the number of entries in a sequence when a stride is specified.\n    \"\"\"\n\n    def __init__(self, basedir, **kwargs):\n        \"\"\"absorb any keyword args\"\"\"\n        self.basedir = basedir\n\n    def reset(self):\n        \"\"\"set sensible defaults\"\"\"\n        self.start = 1\n        self.count = None\n        self.end = None\n        self.stride = 1\n        self.format = \"%d\"\n\n    def parse_kv_args(self, args):\n        \"\"\"parse key-value style arguments\"\"\"\n        for arg in [\"start\", \"end\", \"count\", \"stride\"]:\n            try:\n                arg_raw = args.pop(arg, None)\n                if arg_raw is None:\n                    continue\n                arg_cooked = int(arg_raw, 0)\n                setattr(self, arg, arg_cooked)\n            except ValueError:\n                raise AnsibleError(\n                    \"can't parse arg %s=%r as integer\"\n                        % (arg, arg_raw)\n                )\n            if 'format' in args:\n                self.format = args.pop(\"format\")\n        if args:\n            raise AnsibleError(\n                \"unrecognized arguments to with_sequence: %r\"\n                % args.keys()\n            )\n\n    def parse_simple_args(self, term):\n        \"\"\"parse the shortcut forms, return True/False\"\"\"\n        match = SHORTCUT.match(term)\n        if not match:\n            return False\n\n        _, start, end, _, stride, _, format = match.groups()\n\n        if start is not None:\n            try:\n                start = int(start, 0)\n            except ValueError:\n                raise AnsibleError(\"can't parse start=%s as integer\" % start)\n        if end is not None:\n            try:\n                end = int(end, 0)\n            except ValueError:\n                raise AnsibleError(\"can't parse end=%s as integer\" % end)\n        if stride is not None:\n            try:\n                stride = int(stride, 0)\n            except ValueError:\n                raise AnsibleError(\"can't parse stride=%s as integer\" % stride)\n\n        if start is not None:\n            self.start = start\n        if end is not None:\n            self.end = end\n        if stride is not None:\n            self.stride = stride\n        if format is not None:\n            self.format = format\n\n    def sanity_check(self):\n        if self.count is None and self.end is None:\n            raise AnsibleError(\n                \"must specify count or end in with_sequence\"\n            )\n        elif self.count is not None and self.end is not None:\n            raise AnsibleError(\n                \"can't specify both count and end in with_sequence\"\n            )\n        elif self.count is not None:\n            # convert count to end\n            self.end = self.start + self.count * self.stride - 1\n            del self.count\n        if self.end < self.start:\n            raise AnsibleError(\"can't count backwards\")\n        if self.format.count('%') != 1:\n            raise AnsibleError(\"bad formatting string: %s\" % self.format)\n\n    def generate_sequence(self):\n        numbers = xrange(self.start, self.end + 1, self.stride)\n\n        for i in numbers:\n            try:\n                formatted = self.format % i\n                yield formatted\n            except (ValueError, TypeError):\n                raise AnsibleError(\n                    \"problem formatting %r with %r\" % self.format\n                )\n\n    def run(self, terms, inject=None, **kwargs):\n        results = []\n\n        terms = utils.listify_lookup_plugin_terms(terms, self.basedir, inject)\n\n        if isinstance(terms, basestring):\n            terms = [ terms ]\n\n        for term in terms:\n            try:\n                self.reset()  # clear out things for this iteration\n\n                try:\n                    if not self.parse_simple_args(term):\n                        self.parse_kv_args(utils.parse_kv(term))\n                except Exception:\n                    raise AnsibleError(\n                        \"unknown error parsing with_sequence arguments: %r\"\n                        % term\n                    )\n\n                self.sanity_check()\n\n                results.extend(self.generate_sequence())\n            except AnsibleError:\n                raise\n            except Exception:\n                raise AnsibleError(\n                    \"unknown error generating sequence\"\n                )\n\n        return results\n", "path": "lib/ansible/runner/lookup_plugins/sequence.py"}], "after_files": [{"content": "# (c) 2013, Jayson Vantuyl <jayson@aggressive.ly>\n#\n# This file is part of Ansible\n#\n# Ansible is free software: you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n#\n# Ansible is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with Ansible.  If not, see <http://www.gnu.org/licenses/>.\n\nfrom ansible.errors import AnsibleError\nimport ansible.utils as utils\nfrom re import compile as re_compile, IGNORECASE\n\n# shortcut format\nNUM = \"(0?x?[0-9a-f]+)\"\nSHORTCUT = re_compile(\n    \"^(\" +        # Group 0\n    NUM +         # Group 1: Start\n    \"-)?\" +\n    NUM +         # Group 2: End\n    \"(/\" +        # Group 3\n    NUM +         # Group 4: Stride\n    \")?\" +\n    \"(:(.+))?$\",  # Group 5, Group 6: Format String\n    IGNORECASE\n)\n\n\nclass LookupModule(object):\n    \"\"\"\n    sequence lookup module\n\n    Used to generate some sequence of items. Takes arguments in two forms.\n\n    The simple / shortcut form is:\n\n      [start-]end[/stride][:format]\n\n    As indicated by the brackets: start, stride, and format string are all\n    optional.  The format string is in the style of printf.  This can be used\n    to pad with zeros, format in hexadecimal, etc.  All of the numerical values\n    can be specified in octal (i.e. 0664) or hexadecimal (i.e. 0x3f8).\n    Negative numbers are not supported.\n\n    Some examples:\n\n      5 -> [\"1\",\"2\",\"3\",\"4\",\"5\"]\n      5-8 -> [\"5\", \"6\", \"7\", \"8\"]\n      2-10/2 -> [\"2\", \"4\", \"6\", \"8\", \"10\"]\n      4:host%02d -> [\"host01\",\"host02\",\"host03\",\"host04\"]\n\n    The standard Ansible key-value form is accepted as well.  For example:\n\n      start=5 end=11 stride=2 format=0x%02x -> [\"0x05\",\"0x07\",\"0x09\",\"0x0a\"]\n\n    This format takes an alternate form of \"end\" called \"count\", which counts\n    some number from the starting value.  For example:\n\n      count=5 -> [\"1\", \"2\", \"3\", \"4\", \"5\"]\n      start=0x0f00 count=4 format=%04x -> [\"0f00\", \"0f01\", \"0f02\", \"0f03\"]\n      start=0 count=5 stride=2 -> [\"0\", \"2\", \"4\", \"6\", \"8\"]\n      start=1 count=5 stride=2 -> [\"1\", \"3\", \"5\", \"7\", \"9\"]\n\n    The count option is mostly useful for avoiding off-by-one errors and errors\n    calculating the number of entries in a sequence when a stride is specified.\n    \"\"\"\n\n    def __init__(self, basedir, **kwargs):\n        \"\"\"absorb any keyword args\"\"\"\n        self.basedir = basedir\n\n    def reset(self):\n        \"\"\"set sensible defaults\"\"\"\n        self.start = 1\n        self.count = None\n        self.end = None\n        self.stride = 1\n        self.format = \"%d\"\n\n    def parse_kv_args(self, args):\n        \"\"\"parse key-value style arguments\"\"\"\n        for arg in [\"start\", \"end\", \"count\", \"stride\"]:\n            try:\n                arg_raw = args.pop(arg, None)\n                if arg_raw is None:\n                    continue\n                arg_cooked = int(arg_raw, 0)\n                setattr(self, arg, arg_cooked)\n            except ValueError:\n                raise AnsibleError(\n                    \"can't parse arg %s=%r as integer\"\n                        % (arg, arg_raw)\n                )\n            if 'format' in args:\n                self.format = args.pop(\"format\")\n        if args:\n            raise AnsibleError(\n                \"unrecognized arguments to with_sequence: %r\"\n                % args.keys()\n            )\n\n    def parse_simple_args(self, term):\n        \"\"\"parse the shortcut forms, return True/False\"\"\"\n        match = SHORTCUT.match(term)\n        if not match:\n            return False\n\n        _, start, end, _, stride, _, format = match.groups()\n\n        if start is not None:\n            try:\n                start = int(start, 0)\n            except ValueError:\n                raise AnsibleError(\"can't parse start=%s as integer\" % start)\n        if end is not None:\n            try:\n                end = int(end, 0)\n            except ValueError:\n                raise AnsibleError(\"can't parse end=%s as integer\" % end)\n        if stride is not None:\n            try:\n                stride = int(stride, 0)\n            except ValueError:\n                raise AnsibleError(\"can't parse stride=%s as integer\" % stride)\n\n        if start is not None:\n            self.start = start\n        if end is not None:\n            self.end = end\n        if stride is not None:\n            self.stride = stride\n        if format is not None:\n            self.format = format\n\n    def sanity_check(self):\n        if self.count is None and self.end is None:\n            raise AnsibleError(\n                \"must specify count or end in with_sequence\"\n            )\n        elif self.count is not None and self.end is not None:\n            raise AnsibleError(\n                \"can't specify both count and end in with_sequence\"\n            )\n        elif self.count is not None:\n            # convert count to end\n            if self.count != 0:\n                self.end = self.start + self.count * self.stride - 1\n            else:\n                self.start = 0\n                self.end = 0\n                self.stride = 0\n            del self.count\n        if self.stride > 0 and self.end < self.start:\n            raise AnsibleError(\"to count backwards make stride negative\")\n        if self.stride < 0 and self.end > self.start:\n            raise AnsibleError(\"to count forward don't make stride negative\")\n        if self.format.count('%') != 1:\n            raise AnsibleError(\"bad formatting string: %s\" % self.format)\n\n    def generate_sequence(self):\n        if self.stride > 0:\n            adjust = 1\n        else:\n            adjust = -1\n        numbers = xrange(self.start, self.end + adjust, self.stride)\n\n        for i in numbers:\n            try:\n                formatted = self.format % i\n                yield formatted\n            except (ValueError, TypeError):\n                raise AnsibleError(\n                    \"problem formatting %r with %r\" % self.format\n                )\n\n    def run(self, terms, inject=None, **kwargs):\n        results = []\n\n        terms = utils.listify_lookup_plugin_terms(terms, self.basedir, inject)\n\n        if isinstance(terms, basestring):\n            terms = [ terms ]\n\n        for term in terms:\n            try:\n                self.reset()  # clear out things for this iteration\n\n                try:\n                    if not self.parse_simple_args(term):\n                        self.parse_kv_args(utils.parse_kv(term))\n                except Exception:\n                    raise AnsibleError(\n                        \"unknown error parsing with_sequence arguments: %r\"\n                        % term\n                    )\n\n                self.sanity_check()\n\n                if self.start != self.end:\n                    results.extend(self.generate_sequence())\n            except AnsibleError:\n                raise\n            except Exception, e:\n                raise AnsibleError(\n                    \"unknown error generating sequence: %s\" % str(e)\n                )\n\n        return results\n", "path": "lib/ansible/runner/lookup_plugins/sequence.py"}]}