We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Remove the delete-collection command 
This command was introduced to fix a very specific use-case a long time ago where we had created a collection with an invalid ID. It could thus not be deleted via the HTTP API. 

I think we can remove it.

(from #1953)

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `kinto/scripts.py`
Content:
```
1 import logging
2 
3 import transaction as current_transaction
4 from pyramid.settings import asbool
5 
6 from kinto.core.storage import exceptions as storage_exceptions
7 from kinto.plugins.quotas import scripts as quotas
8 
9 
10 logger = logging.getLogger(__name__)
11 
12 
13 def delete_collection(env, bucket_id, collection_id):
14     registry = env["registry"]
15     settings = registry.settings
16     readonly_mode = asbool(settings.get("readonly", False))
17 
18     if readonly_mode:
19         message = "Cannot delete the collection while in readonly mode."
20         logger.error(message)
21         return 31
22 
23     bucket = f"/buckets/{bucket_id}"
24     collection = f"/buckets/{bucket_id}/collections/{collection_id}"
25 
26     try:
27         registry.storage.get(resource_name="bucket", parent_id="", object_id=bucket_id)
28     except storage_exceptions.ObjectNotFoundError:
29         logger.error(f"Bucket '{bucket}' does not exist.")
30         return 32
31 
32     try:
33         registry.storage.get(resource_name="collection", parent_id=bucket, object_id=collection_id)
34     except storage_exceptions.ObjectNotFoundError:
35         logger.error(f"Collection '{collection}' does not exist.")
36         return 33
37 
38     deleted = registry.storage.delete_all(
39         resource_name="record", parent_id=collection, with_deleted=False
40     )
41     if len(deleted) == 0:
42         logger.info(f"No records found for '{collection}'.")
43     else:
44         logger.info(f"{len(deleted)} record(s) were deleted.")
45 
46     registry.storage.delete(
47         resource_name="collection", parent_id=bucket, object_id=collection_id, with_deleted=False
48     )
49     logger.info(f"'{collection}' collection object was deleted.")
50 
51     obj = "/buckets/{bucket_id}/collections/{collection_id}/records/{object_id}"
52     registry.permission.delete_object_permissions(
53         collection,
54         *[
55             obj.format(bucket_id=bucket_id, collection_id=collection_id, object_id=r["id"])
56             for r in deleted
57         ],
58     )
59     logger.info("Related permissions were deleted.")
60 
61     current_transaction.commit()
62 
63     return 0
64 
65 
66 def rebuild_quotas(env, dry_run=False):
67     """Administrative command to rebuild quota usage information.
68 
69     This command recomputes the amount of space used by all
70     collections and all buckets and updates the quota objects in the
71     storage backend to their correct values. This can be useful when
72     cleaning up after a bug like e.g.
73     https://github.com/Kinto/kinto/issues/1226.
74     """
75     registry = env["registry"]
76     settings = registry.settings
77     readonly_mode = asbool(settings.get("readonly", False))
78 
79     # FIXME: readonly_mode is not meant to be a "maintenance mode" but
80     # rather used with a database user that has read-only permissions.
81     # If we ever introduce a maintenance mode, we should maybe enforce
82     # it here.
83     if readonly_mode:
84         message = "Cannot rebuild quotas while in readonly mode."
85         logger.error(message)
86         return 41
87 
88     if "kinto.plugins.quotas" not in settings["includes"]:
89         message = "Cannot rebuild quotas when quotas plugin is not installed."
90         logger.error(message)
91         return 42
92 
93     quotas.rebuild_quotas(registry.storage, dry_run=dry_run)
94     current_transaction.commit()
95     return 0
96
```

Path: `kinto/__main__.py`
Content:
```
1 import argparse
2 import os
3 import subprocess
4 import sys
5 import logging
6 import logging.config
7 
8 from kinto.core import scripts as core_scripts
9 from kinto import scripts as kinto_scripts
10 from kinto.plugins.accounts import scripts as accounts_scripts
11 from pyramid.scripts import pserve
12 from pyramid.paster import bootstrap
13 from kinto import __version__
14 from kinto.config import init
15 
16 DEFAULT_CONFIG_FILE = os.getenv("KINTO_INI", "config/kinto.ini")
17 DEFAULT_PORT = 8888
18 DEFAULT_LOG_LEVEL = logging.INFO
19 DEFAULT_LOG_FORMAT = "%(levelname)-5.5s  %(message)s"
20 
21 
22 def main(args=None):
23     """The main routine."""
24     if args is None:
25         args = sys.argv[1:]
26 
27     parser = argparse.ArgumentParser(description="Kinto Command-Line " "Interface")
28     commands = (
29         "init",
30         "start",
31         "migrate",
32         "delete-collection",
33         "version",
34         "rebuild-quotas",
35         "create-user",
36     )
37     subparsers = parser.add_subparsers(
38         title="subcommands",
39         description="Main Kinto CLI commands",
40         dest="subcommand",
41         help="Choose and run with --help",
42     )
43     subparsers.required = True
44 
45     for command in commands:
46         subparser = subparsers.add_parser(command)
47         subparser.set_defaults(which=command)
48 
49         subparser.add_argument(
50             "--ini",
51             help="Application configuration file",
52             dest="ini_file",
53             required=False,
54             default=DEFAULT_CONFIG_FILE,
55         )
56 
57         subparser.add_argument(
58             "-q",
59             "--quiet",
60             action="store_const",
61             const=logging.CRITICAL,
62             dest="verbosity",
63             help="Show only critical errors.",
64         )
65 
66         subparser.add_argument(
67             "-v",
68             "--debug",
69             action="store_const",
70             const=logging.DEBUG,
71             dest="verbosity",
72             help="Show all messages, including debug messages.",
73         )
74 
75         if command == "init":
76             subparser.add_argument(
77                 "--backend",
78                 help="{memory,redis,postgresql}",
79                 dest="backend",
80                 required=False,
81                 default=None,
82             )
83             subparser.add_argument(
84                 "--cache-backend",
85                 help="{memory,redis,postgresql,memcached}",
86                 dest="cache-backend",
87                 required=False,
88                 default=None,
89             )
90             subparser.add_argument(
91                 "--host",
92                 help="Host to listen() on.",
93                 dest="host",
94                 required=False,
95                 default="127.0.0.1",
96             )
97         elif command == "migrate":
98             subparser.add_argument(
99                 "--dry-run",
100                 action="store_true",
101                 help="Simulate the migration operations " "and show information",
102                 dest="dry_run",
103                 required=False,
104                 default=False,
105             )
106         elif command == "delete-collection":
107             subparser.add_argument(
108                 "--bucket", help="The bucket where the collection " "belongs to.", required=True
109             )
110             subparser.add_argument("--collection", help="The collection to remove.", required=True)
111 
112         elif command == "rebuild-quotas":
113             subparser.add_argument(
114                 "--dry-run",
115                 action="store_true",
116                 help="Simulate the rebuild operation " "and show information",
117                 dest="dry_run",
118                 required=False,
119                 default=False,
120             )
121 
122         elif command == "start":
123             subparser.add_argument(
124                 "--reload",
125                 action="store_true",
126                 help="Restart when code or config changes",
127                 required=False,
128                 default=False,
129             )
130             subparser.add_argument(
131                 "--port",
132                 type=int,
133                 help="Listening port number",
134                 required=False,
135                 default=DEFAULT_PORT,
136             )
137 
138         elif command == "create-user":
139             subparser.add_argument(
140                 "-u", "--username", help="Superuser username", required=False, default=None
141             )
142             subparser.add_argument(
143                 "-p", "--password", help="Superuser password", required=False, default=None
144             )
145 
146     # Parse command-line arguments
147     parsed_args = vars(parser.parse_args(args))
148 
149     config_file = parsed_args["ini_file"]
150     which_command = parsed_args["which"]
151 
152     # Initialize logging from
153     level = parsed_args.get("verbosity") or DEFAULT_LOG_LEVEL
154     logging.basicConfig(level=level, format=DEFAULT_LOG_FORMAT)
155 
156     if which_command == "init":
157         if os.path.exists(config_file):
158             print(f"{config_file} already exists.", file=sys.stderr)
159             return 1
160 
161         backend = parsed_args["backend"]
162         cache_backend = parsed_args["cache-backend"]
163         if not backend:
164             while True:
165                 prompt = (
166                     "Select the backend you would like to use: "
167                     "(1 - postgresql, 2 - redis, default - memory) "
168                 )
169                 answer = input(prompt).strip()
170                 try:
171                     backends = {"1": "postgresql", "2": "redis", "": "memory"}
172                     backend = backends[answer]
173                     break
174                 except KeyError:
175                     pass
176 
177         if not cache_backend:
178             while True:
179                 prompt = (
180                     "Select the cache backend you would like to use: "
181                     "(1 - postgresql, 2 - redis, 3 - memcached, default - memory) "
182                 )
183                 answer = input(prompt).strip()
184                 try:
185                     cache_backends = {
186                         "1": "postgresql",
187                         "2": "redis",
188                         "3": "memcached",
189                         "": "memory",
190                     }
191                     cache_backend = cache_backends[answer]
192                     break
193                 except KeyError:
194                     pass
195 
196         init(config_file, backend, cache_backend, parsed_args["host"])
197 
198         # Install postgresql libraries if necessary
199         if backend == "postgresql" or cache_backend == "postgresql":
200             try:
201                 import psycopg2  # NOQA
202             except ImportError:
203                 subprocess.check_call(
204                     [sys.executable, "-m", "pip", "install", "kinto[postgresql]"]
205                 )
206         elif backend == "redis" or cache_backend == "redis":
207             try:
208                 import kinto_redis  # NOQA
209             except ImportError:
210                 subprocess.check_call([sys.executable, "-m", "pip", "install", "kinto[redis]"])
211         elif cache_backend == "memcached":
212             try:
213                 import memcache  # NOQA
214             except ImportError:
215                 subprocess.check_call([sys.executable, "-m", "pip", "install", "kinto[memcached]"])
216 
217     elif which_command == "migrate":
218         dry_run = parsed_args["dry_run"]
219         env = bootstrap(config_file, options={"command": "migrate"})
220         core_scripts.migrate(env, dry_run=dry_run)
221 
222     elif which_command == "delete-collection":
223         env = bootstrap(config_file, options={"command": "delete-collection"})
224         return kinto_scripts.delete_collection(
225             env, parsed_args["bucket"], parsed_args["collection"]
226         )
227 
228     elif which_command == "rebuild-quotas":
229         dry_run = parsed_args["dry_run"]
230         env = bootstrap(config_file, options={"command": "rebuild-quotas"})
231         return kinto_scripts.rebuild_quotas(env, dry_run=dry_run)
232 
233     elif which_command == "create-user":
234         username = parsed_args["username"]
235         password = parsed_args["password"]
236         env = bootstrap(config_file, options={"command": "create-user"})
237         return accounts_scripts.create_user(env, username=username, password=password)
238 
239     elif which_command == "start":
240         pserve_argv = ["pserve"]
241 
242         if parsed_args["reload"]:
243             pserve_argv.append("--reload")
244 
245         if level == logging.DEBUG:
246             pserve_argv.append("-v")
247 
248         if level == logging.CRITICAL:
249             pserve_argv.append("-q")
250 
251         pserve_argv.append(config_file)
252         pserve_argv.append(f"http_port={parsed_args['port']}")
253         pserve.main(argv=pserve_argv)
254 
255     else:
256         print(__version__)
257 
258     return 0
259
```
--- 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/kinto/__main__.py b/kinto/__main__.py
--- a/kinto/__main__.py
+++ b/kinto/__main__.py
@@ -25,15 +25,7 @@
         args = sys.argv[1:]
 
     parser = argparse.ArgumentParser(description="Kinto Command-Line " "Interface")
-    commands = (
-        "init",
-        "start",
-        "migrate",
-        "delete-collection",
-        "version",
-        "rebuild-quotas",
-        "create-user",
-    )
+    commands = ("init", "start", "migrate", "version", "rebuild-quotas", "create-user")
     subparsers = parser.add_subparsers(
         title="subcommands",
         description="Main Kinto CLI commands",
@@ -103,11 +95,6 @@
                 required=False,
                 default=False,
             )
-        elif command == "delete-collection":
-            subparser.add_argument(
-                "--bucket", help="The bucket where the collection " "belongs to.", required=True
-            )
-            subparser.add_argument("--collection", help="The collection to remove.", required=True)
 
         elif command == "rebuild-quotas":
             subparser.add_argument(
@@ -219,12 +206,6 @@
         env = bootstrap(config_file, options={"command": "migrate"})
         core_scripts.migrate(env, dry_run=dry_run)
 
-    elif which_command == "delete-collection":
-        env = bootstrap(config_file, options={"command": "delete-collection"})
-        return kinto_scripts.delete_collection(
-            env, parsed_args["bucket"], parsed_args["collection"]
-        )
-
     elif which_command == "rebuild-quotas":
         dry_run = parsed_args["dry_run"]
         env = bootstrap(config_file, options={"command": "rebuild-quotas"})
diff --git a/kinto/scripts.py b/kinto/scripts.py
--- a/kinto/scripts.py
+++ b/kinto/scripts.py
@@ -3,66 +3,12 @@
 import transaction as current_transaction
 from pyramid.settings import asbool
 
-from kinto.core.storage import exceptions as storage_exceptions
 from kinto.plugins.quotas import scripts as quotas
 
 
 logger = logging.getLogger(__name__)
 
 
-def delete_collection(env, bucket_id, collection_id):
-    registry = env["registry"]
-    settings = registry.settings
-    readonly_mode = asbool(settings.get("readonly", False))
-
-    if readonly_mode:
-        message = "Cannot delete the collection while in readonly mode."
-        logger.error(message)
-        return 31
-
-    bucket = f"/buckets/{bucket_id}"
-    collection = f"/buckets/{bucket_id}/collections/{collection_id}"
-
-    try:
-        registry.storage.get(resource_name="bucket", parent_id="", object_id=bucket_id)
-    except storage_exceptions.ObjectNotFoundError:
-        logger.error(f"Bucket '{bucket}' does not exist.")
-        return 32
-
-    try:
-        registry.storage.get(resource_name="collection", parent_id=bucket, object_id=collection_id)
-    except storage_exceptions.ObjectNotFoundError:
-        logger.error(f"Collection '{collection}' does not exist.")
-        return 33
-
-    deleted = registry.storage.delete_all(
-        resource_name="record", parent_id=collection, with_deleted=False
-    )
-    if len(deleted) == 0:
-        logger.info(f"No records found for '{collection}'.")
-    else:
-        logger.info(f"{len(deleted)} record(s) were deleted.")
-
-    registry.storage.delete(
-        resource_name="collection", parent_id=bucket, object_id=collection_id, with_deleted=False
-    )
-    logger.info(f"'{collection}' collection object was deleted.")
-
-    obj = "/buckets/{bucket_id}/collections/{collection_id}/records/{object_id}"
-    registry.permission.delete_object_permissions(
-        collection,
-        *[
-            obj.format(bucket_id=bucket_id, collection_id=collection_id, object_id=r["id"])
-            for r in deleted
-        ],
-    )
-    logger.info("Related permissions were deleted.")
-
-    current_transaction.commit()
-
-    return 0
-
-
 def rebuild_quotas(env, dry_run=False):
     """Administrative command to rebuild quota usage information.

{"golden_diff": "diff --git a/kinto/__main__.py b/kinto/__main__.py\n--- a/kinto/__main__.py\n+++ b/kinto/__main__.py\n@@ -25,15 +25,7 @@\n         args = sys.argv[1:]\n \n     parser = argparse.ArgumentParser(description=\"Kinto Command-Line \" \"Interface\")\n-    commands = (\n-        \"init\",\n-        \"start\",\n-        \"migrate\",\n-        \"delete-collection\",\n-        \"version\",\n-        \"rebuild-quotas\",\n-        \"create-user\",\n-    )\n+    commands = (\"init\", \"start\", \"migrate\", \"version\", \"rebuild-quotas\", \"create-user\")\n     subparsers = parser.add_subparsers(\n         title=\"subcommands\",\n         description=\"Main Kinto CLI commands\",\n@@ -103,11 +95,6 @@\n                 required=False,\n                 default=False,\n             )\n-        elif command == \"delete-collection\":\n-            subparser.add_argument(\n-                \"--bucket\", help=\"The bucket where the collection \" \"belongs to.\", required=True\n-            )\n-            subparser.add_argument(\"--collection\", help=\"The collection to remove.\", required=True)\n \n         elif command == \"rebuild-quotas\":\n             subparser.add_argument(\n@@ -219,12 +206,6 @@\n         env = bootstrap(config_file, options={\"command\": \"migrate\"})\n         core_scripts.migrate(env, dry_run=dry_run)\n \n-    elif which_command == \"delete-collection\":\n-        env = bootstrap(config_file, options={\"command\": \"delete-collection\"})\n-        return kinto_scripts.delete_collection(\n-            env, parsed_args[\"bucket\"], parsed_args[\"collection\"]\n-        )\n-\n     elif which_command == \"rebuild-quotas\":\n         dry_run = parsed_args[\"dry_run\"]\n         env = bootstrap(config_file, options={\"command\": \"rebuild-quotas\"})\ndiff --git a/kinto/scripts.py b/kinto/scripts.py\n--- a/kinto/scripts.py\n+++ b/kinto/scripts.py\n@@ -3,66 +3,12 @@\n import transaction as current_transaction\n from pyramid.settings import asbool\n \n-from kinto.core.storage import exceptions as storage_exceptions\n from kinto.plugins.quotas import scripts as quotas\n \n \n logger = logging.getLogger(__name__)\n \n \n-def delete_collection(env, bucket_id, collection_id):\n-    registry = env[\"registry\"]\n-    settings = registry.settings\n-    readonly_mode = asbool(settings.get(\"readonly\", False))\n-\n-    if readonly_mode:\n-        message = \"Cannot delete the collection while in readonly mode.\"\n-        logger.error(message)\n-        return 31\n-\n-    bucket = f\"/buckets/{bucket_id}\"\n-    collection = f\"/buckets/{bucket_id}/collections/{collection_id}\"\n-\n-    try:\n-        registry.storage.get(resource_name=\"bucket\", parent_id=\"\", object_id=bucket_id)\n-    except storage_exceptions.ObjectNotFoundError:\n-        logger.error(f\"Bucket '{bucket}' does not exist.\")\n-        return 32\n-\n-    try:\n-        registry.storage.get(resource_name=\"collection\", parent_id=bucket, object_id=collection_id)\n-    except storage_exceptions.ObjectNotFoundError:\n-        logger.error(f\"Collection '{collection}' does not exist.\")\n-        return 33\n-\n-    deleted = registry.storage.delete_all(\n-        resource_name=\"record\", parent_id=collection, with_deleted=False\n-    )\n-    if len(deleted) == 0:\n-        logger.info(f\"No records found for '{collection}'.\")\n-    else:\n-        logger.info(f\"{len(deleted)} record(s) were deleted.\")\n-\n-    registry.storage.delete(\n-        resource_name=\"collection\", parent_id=bucket, object_id=collection_id, with_deleted=False\n-    )\n-    logger.info(f\"'{collection}' collection object was deleted.\")\n-\n-    obj = \"/buckets/{bucket_id}/collections/{collection_id}/records/{object_id}\"\n-    registry.permission.delete_object_permissions(\n-        collection,\n-        *[\n-            obj.format(bucket_id=bucket_id, collection_id=collection_id, object_id=r[\"id\"])\n-            for r in deleted\n-        ],\n-    )\n-    logger.info(\"Related permissions were deleted.\")\n-\n-    current_transaction.commit()\n-\n-    return 0\n-\n-\n def rebuild_quotas(env, dry_run=False):\n     \"\"\"Administrative command to rebuild quota usage information.\n", "issue": "Remove the delete-collection command \nThis command was introduced to fix a very specific use-case a long time ago where we had created a collection with an invalid ID. It could thus not be deleted via the HTTP API. \r\n\r\nI think we can remove it.\r\n\r\n(from #1953)\n", "before_files": [{"content": "import logging\n\nimport transaction as current_transaction\nfrom pyramid.settings import asbool\n\nfrom kinto.core.storage import exceptions as storage_exceptions\nfrom kinto.plugins.quotas import scripts as quotas\n\n\nlogger = logging.getLogger(__name__)\n\n\ndef delete_collection(env, bucket_id, collection_id):\n    registry = env[\"registry\"]\n    settings = registry.settings\n    readonly_mode = asbool(settings.get(\"readonly\", False))\n\n    if readonly_mode:\n        message = \"Cannot delete the collection while in readonly mode.\"\n        logger.error(message)\n        return 31\n\n    bucket = f\"/buckets/{bucket_id}\"\n    collection = f\"/buckets/{bucket_id}/collections/{collection_id}\"\n\n    try:\n        registry.storage.get(resource_name=\"bucket\", parent_id=\"\", object_id=bucket_id)\n    except storage_exceptions.ObjectNotFoundError:\n        logger.error(f\"Bucket '{bucket}' does not exist.\")\n        return 32\n\n    try:\n        registry.storage.get(resource_name=\"collection\", parent_id=bucket, object_id=collection_id)\n    except storage_exceptions.ObjectNotFoundError:\n        logger.error(f\"Collection '{collection}' does not exist.\")\n        return 33\n\n    deleted = registry.storage.delete_all(\n        resource_name=\"record\", parent_id=collection, with_deleted=False\n    )\n    if len(deleted) == 0:\n        logger.info(f\"No records found for '{collection}'.\")\n    else:\n        logger.info(f\"{len(deleted)} record(s) were deleted.\")\n\n    registry.storage.delete(\n        resource_name=\"collection\", parent_id=bucket, object_id=collection_id, with_deleted=False\n    )\n    logger.info(f\"'{collection}' collection object was deleted.\")\n\n    obj = \"/buckets/{bucket_id}/collections/{collection_id}/records/{object_id}\"\n    registry.permission.delete_object_permissions(\n        collection,\n        *[\n            obj.format(bucket_id=bucket_id, collection_id=collection_id, object_id=r[\"id\"])\n            for r in deleted\n        ],\n    )\n    logger.info(\"Related permissions were deleted.\")\n\n    current_transaction.commit()\n\n    return 0\n\n\ndef rebuild_quotas(env, dry_run=False):\n    \"\"\"Administrative command to rebuild quota usage information.\n\n    This command recomputes the amount of space used by all\n    collections and all buckets and updates the quota objects in the\n    storage backend to their correct values. This can be useful when\n    cleaning up after a bug like e.g.\n    https://github.com/Kinto/kinto/issues/1226.\n    \"\"\"\n    registry = env[\"registry\"]\n    settings = registry.settings\n    readonly_mode = asbool(settings.get(\"readonly\", False))\n\n    # FIXME: readonly_mode is not meant to be a \"maintenance mode\" but\n    # rather used with a database user that has read-only permissions.\n    # If we ever introduce a maintenance mode, we should maybe enforce\n    # it here.\n    if readonly_mode:\n        message = \"Cannot rebuild quotas while in readonly mode.\"\n        logger.error(message)\n        return 41\n\n    if \"kinto.plugins.quotas\" not in settings[\"includes\"]:\n        message = \"Cannot rebuild quotas when quotas plugin is not installed.\"\n        logger.error(message)\n        return 42\n\n    quotas.rebuild_quotas(registry.storage, dry_run=dry_run)\n    current_transaction.commit()\n    return 0\n", "path": "kinto/scripts.py"}, {"content": "import argparse\nimport os\nimport subprocess\nimport sys\nimport logging\nimport logging.config\n\nfrom kinto.core import scripts as core_scripts\nfrom kinto import scripts as kinto_scripts\nfrom kinto.plugins.accounts import scripts as accounts_scripts\nfrom pyramid.scripts import pserve\nfrom pyramid.paster import bootstrap\nfrom kinto import __version__\nfrom kinto.config import init\n\nDEFAULT_CONFIG_FILE = os.getenv(\"KINTO_INI\", \"config/kinto.ini\")\nDEFAULT_PORT = 8888\nDEFAULT_LOG_LEVEL = logging.INFO\nDEFAULT_LOG_FORMAT = \"%(levelname)-5.5s  %(message)s\"\n\n\ndef main(args=None):\n    \"\"\"The main routine.\"\"\"\n    if args is None:\n        args = sys.argv[1:]\n\n    parser = argparse.ArgumentParser(description=\"Kinto Command-Line \" \"Interface\")\n    commands = (\n        \"init\",\n        \"start\",\n        \"migrate\",\n        \"delete-collection\",\n        \"version\",\n        \"rebuild-quotas\",\n        \"create-user\",\n    )\n    subparsers = parser.add_subparsers(\n        title=\"subcommands\",\n        description=\"Main Kinto CLI commands\",\n        dest=\"subcommand\",\n        help=\"Choose and run with --help\",\n    )\n    subparsers.required = True\n\n    for command in commands:\n        subparser = subparsers.add_parser(command)\n        subparser.set_defaults(which=command)\n\n        subparser.add_argument(\n            \"--ini\",\n            help=\"Application configuration file\",\n            dest=\"ini_file\",\n            required=False,\n            default=DEFAULT_CONFIG_FILE,\n        )\n\n        subparser.add_argument(\n            \"-q\",\n            \"--quiet\",\n            action=\"store_const\",\n            const=logging.CRITICAL,\n            dest=\"verbosity\",\n            help=\"Show only critical errors.\",\n        )\n\n        subparser.add_argument(\n            \"-v\",\n            \"--debug\",\n            action=\"store_const\",\n            const=logging.DEBUG,\n            dest=\"verbosity\",\n            help=\"Show all messages, including debug messages.\",\n        )\n\n        if command == \"init\":\n            subparser.add_argument(\n                \"--backend\",\n                help=\"{memory,redis,postgresql}\",\n                dest=\"backend\",\n                required=False,\n                default=None,\n            )\n            subparser.add_argument(\n                \"--cache-backend\",\n                help=\"{memory,redis,postgresql,memcached}\",\n                dest=\"cache-backend\",\n                required=False,\n                default=None,\n            )\n            subparser.add_argument(\n                \"--host\",\n                help=\"Host to listen() on.\",\n                dest=\"host\",\n                required=False,\n                default=\"127.0.0.1\",\n            )\n        elif command == \"migrate\":\n            subparser.add_argument(\n                \"--dry-run\",\n                action=\"store_true\",\n                help=\"Simulate the migration operations \" \"and show information\",\n                dest=\"dry_run\",\n                required=False,\n                default=False,\n            )\n        elif command == \"delete-collection\":\n            subparser.add_argument(\n                \"--bucket\", help=\"The bucket where the collection \" \"belongs to.\", required=True\n            )\n            subparser.add_argument(\"--collection\", help=\"The collection to remove.\", required=True)\n\n        elif command == \"rebuild-quotas\":\n            subparser.add_argument(\n                \"--dry-run\",\n                action=\"store_true\",\n                help=\"Simulate the rebuild operation \" \"and show information\",\n                dest=\"dry_run\",\n                required=False,\n                default=False,\n            )\n\n        elif command == \"start\":\n            subparser.add_argument(\n                \"--reload\",\n                action=\"store_true\",\n                help=\"Restart when code or config changes\",\n                required=False,\n                default=False,\n            )\n            subparser.add_argument(\n                \"--port\",\n                type=int,\n                help=\"Listening port number\",\n                required=False,\n                default=DEFAULT_PORT,\n            )\n\n        elif command == \"create-user\":\n            subparser.add_argument(\n                \"-u\", \"--username\", help=\"Superuser username\", required=False, default=None\n            )\n            subparser.add_argument(\n                \"-p\", \"--password\", help=\"Superuser password\", required=False, default=None\n            )\n\n    # Parse command-line arguments\n    parsed_args = vars(parser.parse_args(args))\n\n    config_file = parsed_args[\"ini_file\"]\n    which_command = parsed_args[\"which\"]\n\n    # Initialize logging from\n    level = parsed_args.get(\"verbosity\") or DEFAULT_LOG_LEVEL\n    logging.basicConfig(level=level, format=DEFAULT_LOG_FORMAT)\n\n    if which_command == \"init\":\n        if os.path.exists(config_file):\n            print(f\"{config_file} already exists.\", file=sys.stderr)\n            return 1\n\n        backend = parsed_args[\"backend\"]\n        cache_backend = parsed_args[\"cache-backend\"]\n        if not backend:\n            while True:\n                prompt = (\n                    \"Select the backend you would like to use: \"\n                    \"(1 - postgresql, 2 - redis, default - memory) \"\n                )\n                answer = input(prompt).strip()\n                try:\n                    backends = {\"1\": \"postgresql\", \"2\": \"redis\", \"\": \"memory\"}\n                    backend = backends[answer]\n                    break\n                except KeyError:\n                    pass\n\n        if not cache_backend:\n            while True:\n                prompt = (\n                    \"Select the cache backend you would like to use: \"\n                    \"(1 - postgresql, 2 - redis, 3 - memcached, default - memory) \"\n                )\n                answer = input(prompt).strip()\n                try:\n                    cache_backends = {\n                        \"1\": \"postgresql\",\n                        \"2\": \"redis\",\n                        \"3\": \"memcached\",\n                        \"\": \"memory\",\n                    }\n                    cache_backend = cache_backends[answer]\n                    break\n                except KeyError:\n                    pass\n\n        init(config_file, backend, cache_backend, parsed_args[\"host\"])\n\n        # Install postgresql libraries if necessary\n        if backend == \"postgresql\" or cache_backend == \"postgresql\":\n            try:\n                import psycopg2  # NOQA\n            except ImportError:\n                subprocess.check_call(\n                    [sys.executable, \"-m\", \"pip\", \"install\", \"kinto[postgresql]\"]\n                )\n        elif backend == \"redis\" or cache_backend == \"redis\":\n            try:\n                import kinto_redis  # NOQA\n            except ImportError:\n                subprocess.check_call([sys.executable, \"-m\", \"pip\", \"install\", \"kinto[redis]\"])\n        elif cache_backend == \"memcached\":\n            try:\n                import memcache  # NOQA\n            except ImportError:\n                subprocess.check_call([sys.executable, \"-m\", \"pip\", \"install\", \"kinto[memcached]\"])\n\n    elif which_command == \"migrate\":\n        dry_run = parsed_args[\"dry_run\"]\n        env = bootstrap(config_file, options={\"command\": \"migrate\"})\n        core_scripts.migrate(env, dry_run=dry_run)\n\n    elif which_command == \"delete-collection\":\n        env = bootstrap(config_file, options={\"command\": \"delete-collection\"})\n        return kinto_scripts.delete_collection(\n            env, parsed_args[\"bucket\"], parsed_args[\"collection\"]\n        )\n\n    elif which_command == \"rebuild-quotas\":\n        dry_run = parsed_args[\"dry_run\"]\n        env = bootstrap(config_file, options={\"command\": \"rebuild-quotas\"})\n        return kinto_scripts.rebuild_quotas(env, dry_run=dry_run)\n\n    elif which_command == \"create-user\":\n        username = parsed_args[\"username\"]\n        password = parsed_args[\"password\"]\n        env = bootstrap(config_file, options={\"command\": \"create-user\"})\n        return accounts_scripts.create_user(env, username=username, password=password)\n\n    elif which_command == \"start\":\n        pserve_argv = [\"pserve\"]\n\n        if parsed_args[\"reload\"]:\n            pserve_argv.append(\"--reload\")\n\n        if level == logging.DEBUG:\n            pserve_argv.append(\"-v\")\n\n        if level == logging.CRITICAL:\n            pserve_argv.append(\"-q\")\n\n        pserve_argv.append(config_file)\n        pserve_argv.append(f\"http_port={parsed_args['port']}\")\n        pserve.main(argv=pserve_argv)\n\n    else:\n        print(__version__)\n\n    return 0\n", "path": "kinto/__main__.py"}], "after_files": [{"content": "import logging\n\nimport transaction as current_transaction\nfrom pyramid.settings import asbool\n\nfrom kinto.plugins.quotas import scripts as quotas\n\n\nlogger = logging.getLogger(__name__)\n\n\ndef rebuild_quotas(env, dry_run=False):\n    \"\"\"Administrative command to rebuild quota usage information.\n\n    This command recomputes the amount of space used by all\n    collections and all buckets and updates the quota objects in the\n    storage backend to their correct values. This can be useful when\n    cleaning up after a bug like e.g.\n    https://github.com/Kinto/kinto/issues/1226.\n    \"\"\"\n    registry = env[\"registry\"]\n    settings = registry.settings\n    readonly_mode = asbool(settings.get(\"readonly\", False))\n\n    # FIXME: readonly_mode is not meant to be a \"maintenance mode\" but\n    # rather used with a database user that has read-only permissions.\n    # If we ever introduce a maintenance mode, we should maybe enforce\n    # it here.\n    if readonly_mode:\n        message = \"Cannot rebuild quotas while in readonly mode.\"\n        logger.error(message)\n        return 41\n\n    if \"kinto.plugins.quotas\" not in settings[\"includes\"]:\n        message = \"Cannot rebuild quotas when quotas plugin is not installed.\"\n        logger.error(message)\n        return 42\n\n    quotas.rebuild_quotas(registry.storage, dry_run=dry_run)\n    current_transaction.commit()\n    return 0\n", "path": "kinto/scripts.py"}, {"content": "import argparse\nimport os\nimport subprocess\nimport sys\nimport logging\nimport logging.config\n\nfrom kinto.core import scripts as core_scripts\nfrom kinto import scripts as kinto_scripts\nfrom kinto.plugins.accounts import scripts as accounts_scripts\nfrom pyramid.scripts import pserve\nfrom pyramid.paster import bootstrap\nfrom kinto import __version__\nfrom kinto.config import init\n\nDEFAULT_CONFIG_FILE = os.getenv(\"KINTO_INI\", \"config/kinto.ini\")\nDEFAULT_PORT = 8888\nDEFAULT_LOG_LEVEL = logging.INFO\nDEFAULT_LOG_FORMAT = \"%(levelname)-5.5s  %(message)s\"\n\n\ndef main(args=None):\n    \"\"\"The main routine.\"\"\"\n    if args is None:\n        args = sys.argv[1:]\n\n    parser = argparse.ArgumentParser(description=\"Kinto Command-Line \" \"Interface\")\n    commands = (\"init\", \"start\", \"migrate\", \"version\", \"rebuild-quotas\", \"create-user\")\n    subparsers = parser.add_subparsers(\n        title=\"subcommands\",\n        description=\"Main Kinto CLI commands\",\n        dest=\"subcommand\",\n        help=\"Choose and run with --help\",\n    )\n    subparsers.required = True\n\n    for command in commands:\n        subparser = subparsers.add_parser(command)\n        subparser.set_defaults(which=command)\n\n        subparser.add_argument(\n            \"--ini\",\n            help=\"Application configuration file\",\n            dest=\"ini_file\",\n            required=False,\n            default=DEFAULT_CONFIG_FILE,\n        )\n\n        subparser.add_argument(\n            \"-q\",\n            \"--quiet\",\n            action=\"store_const\",\n            const=logging.CRITICAL,\n            dest=\"verbosity\",\n            help=\"Show only critical errors.\",\n        )\n\n        subparser.add_argument(\n            \"-v\",\n            \"--debug\",\n            action=\"store_const\",\n            const=logging.DEBUG,\n            dest=\"verbosity\",\n            help=\"Show all messages, including debug messages.\",\n        )\n\n        if command == \"init\":\n            subparser.add_argument(\n                \"--backend\",\n                help=\"{memory,redis,postgresql}\",\n                dest=\"backend\",\n                required=False,\n                default=None,\n            )\n            subparser.add_argument(\n                \"--cache-backend\",\n                help=\"{memory,redis,postgresql,memcached}\",\n                dest=\"cache-backend\",\n                required=False,\n                default=None,\n            )\n            subparser.add_argument(\n                \"--host\",\n                help=\"Host to listen() on.\",\n                dest=\"host\",\n                required=False,\n                default=\"127.0.0.1\",\n            )\n        elif command == \"migrate\":\n            subparser.add_argument(\n                \"--dry-run\",\n                action=\"store_true\",\n                help=\"Simulate the migration operations \" \"and show information\",\n                dest=\"dry_run\",\n                required=False,\n                default=False,\n            )\n\n        elif command == \"rebuild-quotas\":\n            subparser.add_argument(\n                \"--dry-run\",\n                action=\"store_true\",\n                help=\"Simulate the rebuild operation \" \"and show information\",\n                dest=\"dry_run\",\n                required=False,\n                default=False,\n            )\n\n        elif command == \"start\":\n            subparser.add_argument(\n                \"--reload\",\n                action=\"store_true\",\n                help=\"Restart when code or config changes\",\n                required=False,\n                default=False,\n            )\n            subparser.add_argument(\n                \"--port\",\n                type=int,\n                help=\"Listening port number\",\n                required=False,\n                default=DEFAULT_PORT,\n            )\n\n        elif command == \"create-user\":\n            subparser.add_argument(\n                \"-u\", \"--username\", help=\"Superuser username\", required=False, default=None\n            )\n            subparser.add_argument(\n                \"-p\", \"--password\", help=\"Superuser password\", required=False, default=None\n            )\n\n    # Parse command-line arguments\n    parsed_args = vars(parser.parse_args(args))\n\n    config_file = parsed_args[\"ini_file\"]\n    which_command = parsed_args[\"which\"]\n\n    # Initialize logging from\n    level = parsed_args.get(\"verbosity\") or DEFAULT_LOG_LEVEL\n    logging.basicConfig(level=level, format=DEFAULT_LOG_FORMAT)\n\n    if which_command == \"init\":\n        if os.path.exists(config_file):\n            print(f\"{config_file} already exists.\", file=sys.stderr)\n            return 1\n\n        backend = parsed_args[\"backend\"]\n        cache_backend = parsed_args[\"cache-backend\"]\n        if not backend:\n            while True:\n                prompt = (\n                    \"Select the backend you would like to use: \"\n                    \"(1 - postgresql, 2 - redis, default - memory) \"\n                )\n                answer = input(prompt).strip()\n                try:\n                    backends = {\"1\": \"postgresql\", \"2\": \"redis\", \"\": \"memory\"}\n                    backend = backends[answer]\n                    break\n                except KeyError:\n                    pass\n\n        if not cache_backend:\n            while True:\n                prompt = (\n                    \"Select the cache backend you would like to use: \"\n                    \"(1 - postgresql, 2 - redis, 3 - memcached, default - memory) \"\n                )\n                answer = input(prompt).strip()\n                try:\n                    cache_backends = {\n                        \"1\": \"postgresql\",\n                        \"2\": \"redis\",\n                        \"3\": \"memcached\",\n                        \"\": \"memory\",\n                    }\n                    cache_backend = cache_backends[answer]\n                    break\n                except KeyError:\n                    pass\n\n        init(config_file, backend, cache_backend, parsed_args[\"host\"])\n\n        # Install postgresql libraries if necessary\n        if backend == \"postgresql\" or cache_backend == \"postgresql\":\n            try:\n                import psycopg2  # NOQA\n            except ImportError:\n                subprocess.check_call(\n                    [sys.executable, \"-m\", \"pip\", \"install\", \"kinto[postgresql]\"]\n                )\n        elif backend == \"redis\" or cache_backend == \"redis\":\n            try:\n                import kinto_redis  # NOQA\n            except ImportError:\n                subprocess.check_call([sys.executable, \"-m\", \"pip\", \"install\", \"kinto[redis]\"])\n        elif cache_backend == \"memcached\":\n            try:\n                import memcache  # NOQA\n            except ImportError:\n                subprocess.check_call([sys.executable, \"-m\", \"pip\", \"install\", \"kinto[memcached]\"])\n\n    elif which_command == \"migrate\":\n        dry_run = parsed_args[\"dry_run\"]\n        env = bootstrap(config_file, options={\"command\": \"migrate\"})\n        core_scripts.migrate(env, dry_run=dry_run)\n\n    elif which_command == \"rebuild-quotas\":\n        dry_run = parsed_args[\"dry_run\"]\n        env = bootstrap(config_file, options={\"command\": \"rebuild-quotas\"})\n        return kinto_scripts.rebuild_quotas(env, dry_run=dry_run)\n\n    elif which_command == \"create-user\":\n        username = parsed_args[\"username\"]\n        password = parsed_args[\"password\"]\n        env = bootstrap(config_file, options={\"command\": \"create-user\"})\n        return accounts_scripts.create_user(env, username=username, password=password)\n\n    elif which_command == \"start\":\n        pserve_argv = [\"pserve\"]\n\n        if parsed_args[\"reload\"]:\n            pserve_argv.append(\"--reload\")\n\n        if level == logging.DEBUG:\n            pserve_argv.append(\"-v\")\n\n        if level == logging.CRITICAL:\n            pserve_argv.append(\"-q\")\n\n        pserve_argv.append(config_file)\n        pserve_argv.append(f\"http_port={parsed_args['port']}\")\n        pserve.main(argv=pserve_argv)\n\n    else:\n        print(__version__)\n\n    return 0\n", "path": "kinto/__main__.py"}]}