We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Push to PyPi failing
```
error in cirq setup command: 'extras_require' must be a dictionary whose values are strings or lists of strings containing valid project/version requirement specifiers.
```

See https://github.com/quantumlib/Cirq/runs/2851981344


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `setup.py`
Content:
```
1 # Copyright 2018 The Cirq Developers
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 #     https://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14 
15 import io
16 import os
17 from setuptools import setup
18 
19 # This reads the __version__ variable from cirq/_version.py
20 __version__ = ''
21 
22 from dev_tools import modules
23 from dev_tools.requirements import explode
24 
25 exec(open('cirq-core/cirq/_version.py').read())
26 
27 name = 'cirq'
28 
29 description = (
30     'A framework for creating, editing, and invoking '
31     'Noisy Intermediate Scale Quantum (NISQ) circuits.'
32 )
33 
34 # README file as long_description.
35 long_description = io.open('README.rst', encoding='utf-8').read()
36 
37 # If CIRQ_PRE_RELEASE_VERSION is set then we update the version to this value.
38 # It is assumed that it ends with one of `.devN`, `.aN`, `.bN`, `.rcN` and hence
39 # it will be a pre-release version on PyPi. See
40 # https://packaging.python.org/guides/distributing-packages-using-setuptools/#pre-release-versioning
41 # for more details.
42 if 'CIRQ_PRE_RELEASE_VERSION' in os.environ:
43     __version__ = os.environ['CIRQ_PRE_RELEASE_VERSION']
44     long_description = (
45         "**This is a development version of Cirq and may be "
46         "unstable.**\n\n**For the latest stable release of Cirq "
47         "see**\n`here <https://pypi.org/project/cirq>`__.\n\n" + long_description
48     )
49 
50 # Sanity check
51 assert __version__, 'Version string cannot be empty'
52 
53 # This is a pure metapackage that installs all our packages
54 requirements = [f'{p.name}=={p.version}' for p in modules.list_modules()]
55 
56 dev_requirements = explode('dev_tools/requirements/deps/dev-tools.txt')
57 dev_requirements = [r.strip() for r in dev_requirements]
58 
59 setup(
60     name=name,
61     version=__version__,
62     url='http://github.com/quantumlib/cirq',
63     author='The Cirq Developers',
64     author_email='cirq-dev@googlegroups.com',
65     python_requires=('>=3.6.0'),
66     install_requires=requirements,
67     extras_require={
68         'dev_env': dev_requirements,
69     },
70     license='Apache 2',
71     description=description,
72     long_description=long_description,
73 )
74
```

Path: `dev_tools/modules.py`
Content:
```
1 # Copyright 2021 The Cirq Developers
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 #     https://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14 
15 
16 """Utility tool for cirq modules.
17 
18 It can be used as a python library for python scripts as well as a CLI tool for
19 bash scripts and interactive use.
20 
21 Features:
22 
23 listing modules:
24  - Python: see list_modules
25  - CLI: python3 dev_tools/modules.py list
26 
27 optional arguments:
28   -h, --help            show this help message and exit
29   --mode {folder,package-path}
30                         'folder' to list root folder for module, 'package-path' for top level
31                         python package path
32   --include-parent      whether to include the parent package or not
33 """
34 
35 import argparse
36 import dataclasses
37 import os
38 import sys
39 from pathlib import Path
40 from typing import List, Dict, Any
41 
42 _FOLDER = 'folder'
43 _PACKAGE_PATH = 'package-path'
44 
45 
46 @dataclasses.dataclass
47 class Module:
48     root: Path
49     raw_setup: Dict[str, Any]
50 
51     name: str = dataclasses.field(init=False)
52     version: str = dataclasses.field(init=False)
53     top_level_packages: List[str] = dataclasses.field(init=False)
54     top_level_package_paths: List[Path] = dataclasses.field(init=False)
55 
56     def __post_init__(self) -> None:
57         self.name = self.raw_setup['name']
58         if 'packages' in self.raw_setup:
59             self.top_level_packages = [p for p in self.raw_setup['packages'] if '.' not in p]
60         else:
61             self.top_level_packages = []
62         self.top_level_package_paths = [self.root / p for p in self.top_level_packages]
63         self.version = self.raw_setup['version']
64 
65 
66 def list_modules(
67     search_dir: Path = Path(__file__).parents[1], include_parent: bool = False
68 ) -> List[Module]:
69     """Returns a list of python modules based defined by setup.py files.
70 
71     Args:
72         include_parent: if true, a setup.py is expected in `search_dir`, and the corresponding
73         module will be included.
74         search_dir: the search directory for modules, by default the repo root.
75     Returns:
76           a list of `Module`s that were found, where each module `m` is initialized with `m.root`
77            relative to `search_dir`, `m.raw_setup` contains the dictionary equivalent to the
78            keyword args passed to the `setuptools.setup` method in setup.py
79     """
80 
81     relative_folders = sorted(
82         f.relative_to(search_dir)
83         for f in search_dir.glob("*")
84         if f.is_dir() and (f / "setup.py").is_file()
85     )
86     if include_parent:
87         parent_setup_py = search_dir / "setup.py"
88         assert parent_setup_py.exists(), (
89             f"include_parent=True, but {parent_setup_py} " f"does not exist."
90         )
91         relative_folders.append(Path("."))
92 
93     result = [
94         Module(root=folder, raw_setup=_parse_module(search_dir / folder))
95         for folder in relative_folders
96     ]
97 
98     return result
99 
100 
101 def _parse_module(folder: Path) -> Dict[str, Any]:
102     setup_args = {}
103     import setuptools
104 
105     orig_setup = setuptools.setup
106     cwd = os.getcwd()
107 
108     def setup(**kwargs):
109         setup_args.update(kwargs)
110 
111     try:
112         setuptools.setup = setup
113         os.chdir(str(folder))
114         setup_py = open("setup.py").read()
115         exec(setup_py, globals(), {})
116         assert setup_args, f"Invalid setup.py - setup() was not called in {folder}/setup.py!"
117         return setup_args
118     except BaseException:
119         print(f"Failed to run {folder}/setup.py:")
120         raise
121     finally:
122         setuptools.setup = orig_setup
123         os.chdir(cwd)
124 
125 
126 def _print_list_modules(mode: str, include_parent: bool = False):
127     """Prints certain properties of cirq modules on separate lines.
128 
129     Module root folder and top level package paths are supported. The search dir is the current
130     directory.
131 
132     Args:
133         mode: 'folder' lists the root folder for each module, 'package-path' lists the path to
134          the top level package(s).
135         include_cirq: when true the cirq metapackage is included in the list
136     Returns:
137           a list of strings
138     """
139     for m in list_modules(Path("."), include_parent):
140         if mode == _FOLDER:
141             print(m.root, end=" ")
142         elif mode == _PACKAGE_PATH:
143             for p in m.top_level_package_paths:
144                 print(p, end=" ")
145 
146 
147 def main(argv: List[str]):
148     args = parse(argv)
149     # args.func is where we store the function to be called for a given subparser
150     # e.g. it is list_modules for the `list` subcommand
151     f = args.func
152     # however the func is not going to be needed for the function itself, so
153     # we remove it here
154     del args.func
155     f(**vars(args))
156 
157 
158 def parse(args):
159     parser = argparse.ArgumentParser('A utility for modules.')
160     subparsers = parser.add_subparsers(
161         title='subcommands', description='valid subcommands', help='additional help'
162     )
163     _add_list_modules_cmd(subparsers)
164     return parser.parse_args(args)
165 
166 
167 def _add_list_modules_cmd(subparsers):
168     list_modules_cmd = subparsers.add_parser("list", help="lists all the modules")
169     list_modules_cmd.add_argument(
170         "--mode",
171         default=_FOLDER,
172         choices=[_FOLDER, _PACKAGE_PATH],
173         type=str,
174         help="'folder' to list root folder for module,\n"
175         "'package-path' for top level python package path",
176     )
177     list_modules_cmd.add_argument(
178         "--include-parent",
179         help="whether to include the parent package or not",
180         default=False,
181         action="store_true",
182     )
183     list_modules_cmd.set_defaults(func=_print_list_modules)
184 
185 
186 if __name__ == '__main__':
187     main(sys.argv[1:])  # coverage: ignore
188
```
--- 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/dev_tools/modules.py b/dev_tools/modules.py
--- a/dev_tools/modules.py
+++ b/dev_tools/modules.py
@@ -27,8 +27,10 @@
 optional arguments:
   -h, --help            show this help message and exit
   --mode {folder,package-path}
-                        'folder' to list root folder for module, 'package-path' for top level
-                        python package path
+                        'folder' to list root folder for module (e.g. cirq-google),
+                        'package-path' for top level python package path
+                            (e.g. cirq-google/cirq_google),
+                        'package' for top level python package (e.g cirq_google),
   --include-parent      whether to include the parent package or not
 """
 
@@ -41,6 +43,7 @@
 
 _FOLDER = 'folder'
 _PACKAGE_PATH = 'package-path'
+_PACKAGE = 'package'
 
 
 @dataclasses.dataclass
@@ -142,6 +145,9 @@
         elif mode == _PACKAGE_PATH:
             for p in m.top_level_package_paths:
                 print(p, end=" ")
+        elif mode == _PACKAGE:
+            for package in m.top_level_packages:
+                print(package, end=" ")
 
 
 def main(argv: List[str]):
@@ -169,10 +175,11 @@
     list_modules_cmd.add_argument(
         "--mode",
         default=_FOLDER,
-        choices=[_FOLDER, _PACKAGE_PATH],
+        choices=[_FOLDER, _PACKAGE_PATH, _PACKAGE],
         type=str,
-        help="'folder' to list root folder for module,\n"
-        "'package-path' for top level python package path",
+        help="'folder' to list root folder for module (e.g. cirq-google),\n"
+        "'package-path' for top level python package path (e.g. cirq-google/cirq_google),\n"
+        "'package' for top level python package (e.g cirq_google),\n",
     )
     list_modules_cmd.add_argument(
         "--include-parent",
diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -62,7 +62,7 @@
     url='http://github.com/quantumlib/cirq',
     author='The Cirq Developers',
     author_email='cirq-dev@googlegroups.com',
-    python_requires=('>=3.6.0'),
+    python_requires='>=3.6.0',
     install_requires=requirements,
     extras_require={
         'dev_env': dev_requirements,

{"golden_diff": "diff --git a/dev_tools/modules.py b/dev_tools/modules.py\n--- a/dev_tools/modules.py\n+++ b/dev_tools/modules.py\n@@ -27,8 +27,10 @@\n optional arguments:\n   -h, --help            show this help message and exit\n   --mode {folder,package-path}\n-                        'folder' to list root folder for module, 'package-path' for top level\n-                        python package path\n+                        'folder' to list root folder for module (e.g. cirq-google),\n+                        'package-path' for top level python package path\n+                            (e.g. cirq-google/cirq_google),\n+                        'package' for top level python package (e.g cirq_google),\n   --include-parent      whether to include the parent package or not\n \"\"\"\n \n@@ -41,6 +43,7 @@\n \n _FOLDER = 'folder'\n _PACKAGE_PATH = 'package-path'\n+_PACKAGE = 'package'\n \n \n @dataclasses.dataclass\n@@ -142,6 +145,9 @@\n         elif mode == _PACKAGE_PATH:\n             for p in m.top_level_package_paths:\n                 print(p, end=\" \")\n+        elif mode == _PACKAGE:\n+            for package in m.top_level_packages:\n+                print(package, end=\" \")\n \n \n def main(argv: List[str]):\n@@ -169,10 +175,11 @@\n     list_modules_cmd.add_argument(\n         \"--mode\",\n         default=_FOLDER,\n-        choices=[_FOLDER, _PACKAGE_PATH],\n+        choices=[_FOLDER, _PACKAGE_PATH, _PACKAGE],\n         type=str,\n-        help=\"'folder' to list root folder for module,\\n\"\n-        \"'package-path' for top level python package path\",\n+        help=\"'folder' to list root folder for module (e.g. cirq-google),\\n\"\n+        \"'package-path' for top level python package path (e.g. cirq-google/cirq_google),\\n\"\n+        \"'package' for top level python package (e.g cirq_google),\\n\",\n     )\n     list_modules_cmd.add_argument(\n         \"--include-parent\",\ndiff --git a/setup.py b/setup.py\n--- a/setup.py\n+++ b/setup.py\n@@ -62,7 +62,7 @@\n     url='http://github.com/quantumlib/cirq',\n     author='The Cirq Developers',\n     author_email='cirq-dev@googlegroups.com',\n-    python_requires=('>=3.6.0'),\n+    python_requires='>=3.6.0',\n     install_requires=requirements,\n     extras_require={\n         'dev_env': dev_requirements,\n", "issue": "Push to PyPi failing\n```\r\nerror in cirq setup command: 'extras_require' must be a dictionary whose values are strings or lists of strings containing valid project/version requirement specifiers.\r\n```\r\n\r\nSee https://github.com/quantumlib/Cirq/runs/2851981344\r\n\n", "before_files": [{"content": "# Copyright 2018 The Cirq Developers\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nimport io\nimport os\nfrom setuptools import setup\n\n# This reads the __version__ variable from cirq/_version.py\n__version__ = ''\n\nfrom dev_tools import modules\nfrom dev_tools.requirements import explode\n\nexec(open('cirq-core/cirq/_version.py').read())\n\nname = 'cirq'\n\ndescription = (\n    'A framework for creating, editing, and invoking '\n    'Noisy Intermediate Scale Quantum (NISQ) circuits.'\n)\n\n# README file as long_description.\nlong_description = io.open('README.rst', encoding='utf-8').read()\n\n# If CIRQ_PRE_RELEASE_VERSION is set then we update the version to this value.\n# It is assumed that it ends with one of `.devN`, `.aN`, `.bN`, `.rcN` and hence\n# it will be a pre-release version on PyPi. See\n# https://packaging.python.org/guides/distributing-packages-using-setuptools/#pre-release-versioning\n# for more details.\nif 'CIRQ_PRE_RELEASE_VERSION' in os.environ:\n    __version__ = os.environ['CIRQ_PRE_RELEASE_VERSION']\n    long_description = (\n        \"**This is a development version of Cirq and may be \"\n        \"unstable.**\\n\\n**For the latest stable release of Cirq \"\n        \"see**\\n`here <https://pypi.org/project/cirq>`__.\\n\\n\" + long_description\n    )\n\n# Sanity check\nassert __version__, 'Version string cannot be empty'\n\n# This is a pure metapackage that installs all our packages\nrequirements = [f'{p.name}=={p.version}' for p in modules.list_modules()]\n\ndev_requirements = explode('dev_tools/requirements/deps/dev-tools.txt')\ndev_requirements = [r.strip() for r in dev_requirements]\n\nsetup(\n    name=name,\n    version=__version__,\n    url='http://github.com/quantumlib/cirq',\n    author='The Cirq Developers',\n    author_email='cirq-dev@googlegroups.com',\n    python_requires=('>=3.6.0'),\n    install_requires=requirements,\n    extras_require={\n        'dev_env': dev_requirements,\n    },\n    license='Apache 2',\n    description=description,\n    long_description=long_description,\n)\n", "path": "setup.py"}, {"content": "# Copyright 2021 The Cirq Developers\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\n\n\"\"\"Utility tool for cirq modules.\n\nIt can be used as a python library for python scripts as well as a CLI tool for\nbash scripts and interactive use.\n\nFeatures:\n\nlisting modules:\n - Python: see list_modules\n - CLI: python3 dev_tools/modules.py list\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --mode {folder,package-path}\n                        'folder' to list root folder for module, 'package-path' for top level\n                        python package path\n  --include-parent      whether to include the parent package or not\n\"\"\"\n\nimport argparse\nimport dataclasses\nimport os\nimport sys\nfrom pathlib import Path\nfrom typing import List, Dict, Any\n\n_FOLDER = 'folder'\n_PACKAGE_PATH = 'package-path'\n\n\n@dataclasses.dataclass\nclass Module:\n    root: Path\n    raw_setup: Dict[str, Any]\n\n    name: str = dataclasses.field(init=False)\n    version: str = dataclasses.field(init=False)\n    top_level_packages: List[str] = dataclasses.field(init=False)\n    top_level_package_paths: List[Path] = dataclasses.field(init=False)\n\n    def __post_init__(self) -> None:\n        self.name = self.raw_setup['name']\n        if 'packages' in self.raw_setup:\n            self.top_level_packages = [p for p in self.raw_setup['packages'] if '.' not in p]\n        else:\n            self.top_level_packages = []\n        self.top_level_package_paths = [self.root / p for p in self.top_level_packages]\n        self.version = self.raw_setup['version']\n\n\ndef list_modules(\n    search_dir: Path = Path(__file__).parents[1], include_parent: bool = False\n) -> List[Module]:\n    \"\"\"Returns a list of python modules based defined by setup.py files.\n\n    Args:\n        include_parent: if true, a setup.py is expected in `search_dir`, and the corresponding\n        module will be included.\n        search_dir: the search directory for modules, by default the repo root.\n    Returns:\n          a list of `Module`s that were found, where each module `m` is initialized with `m.root`\n           relative to `search_dir`, `m.raw_setup` contains the dictionary equivalent to the\n           keyword args passed to the `setuptools.setup` method in setup.py\n    \"\"\"\n\n    relative_folders = sorted(\n        f.relative_to(search_dir)\n        for f in search_dir.glob(\"*\")\n        if f.is_dir() and (f / \"setup.py\").is_file()\n    )\n    if include_parent:\n        parent_setup_py = search_dir / \"setup.py\"\n        assert parent_setup_py.exists(), (\n            f\"include_parent=True, but {parent_setup_py} \" f\"does not exist.\"\n        )\n        relative_folders.append(Path(\".\"))\n\n    result = [\n        Module(root=folder, raw_setup=_parse_module(search_dir / folder))\n        for folder in relative_folders\n    ]\n\n    return result\n\n\ndef _parse_module(folder: Path) -> Dict[str, Any]:\n    setup_args = {}\n    import setuptools\n\n    orig_setup = setuptools.setup\n    cwd = os.getcwd()\n\n    def setup(**kwargs):\n        setup_args.update(kwargs)\n\n    try:\n        setuptools.setup = setup\n        os.chdir(str(folder))\n        setup_py = open(\"setup.py\").read()\n        exec(setup_py, globals(), {})\n        assert setup_args, f\"Invalid setup.py - setup() was not called in {folder}/setup.py!\"\n        return setup_args\n    except BaseException:\n        print(f\"Failed to run {folder}/setup.py:\")\n        raise\n    finally:\n        setuptools.setup = orig_setup\n        os.chdir(cwd)\n\n\ndef _print_list_modules(mode: str, include_parent: bool = False):\n    \"\"\"Prints certain properties of cirq modules on separate lines.\n\n    Module root folder and top level package paths are supported. The search dir is the current\n    directory.\n\n    Args:\n        mode: 'folder' lists the root folder for each module, 'package-path' lists the path to\n         the top level package(s).\n        include_cirq: when true the cirq metapackage is included in the list\n    Returns:\n          a list of strings\n    \"\"\"\n    for m in list_modules(Path(\".\"), include_parent):\n        if mode == _FOLDER:\n            print(m.root, end=\" \")\n        elif mode == _PACKAGE_PATH:\n            for p in m.top_level_package_paths:\n                print(p, end=\" \")\n\n\ndef main(argv: List[str]):\n    args = parse(argv)\n    # args.func is where we store the function to be called for a given subparser\n    # e.g. it is list_modules for the `list` subcommand\n    f = args.func\n    # however the func is not going to be needed for the function itself, so\n    # we remove it here\n    del args.func\n    f(**vars(args))\n\n\ndef parse(args):\n    parser = argparse.ArgumentParser('A utility for modules.')\n    subparsers = parser.add_subparsers(\n        title='subcommands', description='valid subcommands', help='additional help'\n    )\n    _add_list_modules_cmd(subparsers)\n    return parser.parse_args(args)\n\n\ndef _add_list_modules_cmd(subparsers):\n    list_modules_cmd = subparsers.add_parser(\"list\", help=\"lists all the modules\")\n    list_modules_cmd.add_argument(\n        \"--mode\",\n        default=_FOLDER,\n        choices=[_FOLDER, _PACKAGE_PATH],\n        type=str,\n        help=\"'folder' to list root folder for module,\\n\"\n        \"'package-path' for top level python package path\",\n    )\n    list_modules_cmd.add_argument(\n        \"--include-parent\",\n        help=\"whether to include the parent package or not\",\n        default=False,\n        action=\"store_true\",\n    )\n    list_modules_cmd.set_defaults(func=_print_list_modules)\n\n\nif __name__ == '__main__':\n    main(sys.argv[1:])  # coverage: ignore\n", "path": "dev_tools/modules.py"}], "after_files": [{"content": "# Copyright 2018 The Cirq Developers\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nimport io\nimport os\nfrom setuptools import setup\n\n# This reads the __version__ variable from cirq/_version.py\n__version__ = ''\n\nfrom dev_tools import modules\nfrom dev_tools.requirements import explode\n\nexec(open('cirq-core/cirq/_version.py').read())\n\nname = 'cirq'\n\ndescription = (\n    'A framework for creating, editing, and invoking '\n    'Noisy Intermediate Scale Quantum (NISQ) circuits.'\n)\n\n# README file as long_description.\nlong_description = io.open('README.rst', encoding='utf-8').read()\n\n# If CIRQ_PRE_RELEASE_VERSION is set then we update the version to this value.\n# It is assumed that it ends with one of `.devN`, `.aN`, `.bN`, `.rcN` and hence\n# it will be a pre-release version on PyPi. See\n# https://packaging.python.org/guides/distributing-packages-using-setuptools/#pre-release-versioning\n# for more details.\nif 'CIRQ_PRE_RELEASE_VERSION' in os.environ:\n    __version__ = os.environ['CIRQ_PRE_RELEASE_VERSION']\n    long_description = (\n        \"**This is a development version of Cirq and may be \"\n        \"unstable.**\\n\\n**For the latest stable release of Cirq \"\n        \"see**\\n`here <https://pypi.org/project/cirq>`__.\\n\\n\" + long_description\n    )\n\n# Sanity check\nassert __version__, 'Version string cannot be empty'\n\n# This is a pure metapackage that installs all our packages\nrequirements = [f'{p.name}=={p.version}' for p in modules.list_modules()]\n\ndev_requirements = explode('dev_tools/requirements/deps/dev-tools.txt')\ndev_requirements = [r.strip() for r in dev_requirements]\n\nsetup(\n    name=name,\n    version=__version__,\n    url='http://github.com/quantumlib/cirq',\n    author='The Cirq Developers',\n    author_email='cirq-dev@googlegroups.com',\n    python_requires='>=3.6.0',\n    install_requires=requirements,\n    extras_require={\n        'dev_env': dev_requirements,\n    },\n    license='Apache 2',\n    description=description,\n    long_description=long_description,\n)\n", "path": "setup.py"}, {"content": "# Copyright 2021 The Cirq Developers\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\n\n\"\"\"Utility tool for cirq modules.\n\nIt can be used as a python library for python scripts as well as a CLI tool for\nbash scripts and interactive use.\n\nFeatures:\n\nlisting modules:\n - Python: see list_modules\n - CLI: python3 dev_tools/modules.py list\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --mode {folder,package-path}\n                        'folder' to list root folder for module (e.g. cirq-google),\n                        'package-path' for top level python package path\n                            (e.g. cirq-google/cirq_google),\n                        'package' for top level python package (e.g cirq_google),\n  --include-parent      whether to include the parent package or not\n\"\"\"\n\nimport argparse\nimport dataclasses\nimport os\nimport sys\nfrom pathlib import Path\nfrom typing import List, Dict, Any\n\n_FOLDER = 'folder'\n_PACKAGE_PATH = 'package-path'\n_PACKAGE = 'package'\n\n\n@dataclasses.dataclass\nclass Module:\n    root: Path\n    raw_setup: Dict[str, Any]\n\n    name: str = dataclasses.field(init=False)\n    version: str = dataclasses.field(init=False)\n    top_level_packages: List[str] = dataclasses.field(init=False)\n    top_level_package_paths: List[Path] = dataclasses.field(init=False)\n\n    def __post_init__(self) -> None:\n        self.name = self.raw_setup['name']\n        if 'packages' in self.raw_setup:\n            self.top_level_packages = [p for p in self.raw_setup['packages'] if '.' not in p]\n        else:\n            self.top_level_packages = []\n        self.top_level_package_paths = [self.root / p for p in self.top_level_packages]\n        self.version = self.raw_setup['version']\n\n\ndef list_modules(\n    search_dir: Path = Path(__file__).parents[1], include_parent: bool = False\n) -> List[Module]:\n    \"\"\"Returns a list of python modules based defined by setup.py files.\n\n    Args:\n        include_parent: if true, a setup.py is expected in `search_dir`, and the corresponding\n        module will be included.\n        search_dir: the search directory for modules, by default the repo root.\n    Returns:\n          a list of `Module`s that were found, where each module `m` is initialized with `m.root`\n           relative to `search_dir`, `m.raw_setup` contains the dictionary equivalent to the\n           keyword args passed to the `setuptools.setup` method in setup.py\n    \"\"\"\n\n    relative_folders = sorted(\n        f.relative_to(search_dir)\n        for f in search_dir.glob(\"*\")\n        if f.is_dir() and (f / \"setup.py\").is_file()\n    )\n    if include_parent:\n        parent_setup_py = search_dir / \"setup.py\"\n        assert parent_setup_py.exists(), (\n            f\"include_parent=True, but {parent_setup_py} \" f\"does not exist.\"\n        )\n        relative_folders.append(Path(\".\"))\n\n    result = [\n        Module(root=folder, raw_setup=_parse_module(search_dir / folder))\n        for folder in relative_folders\n    ]\n\n    return result\n\n\ndef _parse_module(folder: Path) -> Dict[str, Any]:\n    setup_args = {}\n    import setuptools\n\n    orig_setup = setuptools.setup\n    cwd = os.getcwd()\n\n    def setup(**kwargs):\n        setup_args.update(kwargs)\n\n    try:\n        setuptools.setup = setup\n        os.chdir(str(folder))\n        setup_py = open(\"setup.py\").read()\n        exec(setup_py, globals(), {})\n        assert setup_args, f\"Invalid setup.py - setup() was not called in {folder}/setup.py!\"\n        return setup_args\n    except BaseException:\n        print(f\"Failed to run {folder}/setup.py:\")\n        raise\n    finally:\n        setuptools.setup = orig_setup\n        os.chdir(cwd)\n\n\ndef _print_list_modules(mode: str, include_parent: bool = False):\n    \"\"\"Prints certain properties of cirq modules on separate lines.\n\n    Module root folder and top level package paths are supported. The search dir is the current\n    directory.\n\n    Args:\n        mode: 'folder' lists the root folder for each module, 'package-path' lists the path to\n         the top level package(s).\n        include_cirq: when true the cirq metapackage is included in the list\n    Returns:\n          a list of strings\n    \"\"\"\n    for m in list_modules(Path(\".\"), include_parent):\n        if mode == _FOLDER:\n            print(m.root, end=\" \")\n        elif mode == _PACKAGE_PATH:\n            for p in m.top_level_package_paths:\n                print(p, end=\" \")\n        elif mode == _PACKAGE:\n            for package in m.top_level_packages:\n                print(package, end=\" \")\n\n\ndef main(argv: List[str]):\n    args = parse(argv)\n    # args.func is where we store the function to be called for a given subparser\n    # e.g. it is list_modules for the `list` subcommand\n    f = args.func\n    # however the func is not going to be needed for the function itself, so\n    # we remove it here\n    del args.func\n    f(**vars(args))\n\n\ndef parse(args):\n    parser = argparse.ArgumentParser('A utility for modules.')\n    subparsers = parser.add_subparsers(\n        title='subcommands', description='valid subcommands', help='additional help'\n    )\n    _add_list_modules_cmd(subparsers)\n    return parser.parse_args(args)\n\n\ndef _add_list_modules_cmd(subparsers):\n    list_modules_cmd = subparsers.add_parser(\"list\", help=\"lists all the modules\")\n    list_modules_cmd.add_argument(\n        \"--mode\",\n        default=_FOLDER,\n        choices=[_FOLDER, _PACKAGE_PATH, _PACKAGE],\n        type=str,\n        help=\"'folder' to list root folder for module (e.g. cirq-google),\\n\"\n        \"'package-path' for top level python package path (e.g. cirq-google/cirq_google),\\n\"\n        \"'package' for top level python package (e.g cirq_google),\\n\",\n    )\n    list_modules_cmd.add_argument(\n        \"--include-parent\",\n        help=\"whether to include the parent package or not\",\n        default=False,\n        action=\"store_true\",\n    )\n    list_modules_cmd.set_defaults(func=_print_list_modules)\n\n\nif __name__ == '__main__':\n    main(sys.argv[1:])  # coverage: ignore\n", "path": "dev_tools/modules.py"}]}