You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

167 lines
5.3 KiB

3 years ago
2 years ago
2 years ago
3 years ago
2 years ago
2 years ago
3 years ago
2 years ago
3 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
  1. import argparse
  2. import multiprocessing
  3. import os
  4. import platform
  5. import sys
  6. from pathlib import Path
  7. import django
  8. from django.core import management
  9. from environs import Env
  10. from .config.celery import app
  11. env = Env()
  12. DOCCANO_HOME = os.path.expanduser(os.environ.get("DOCCANO_HOME", "~/doccano"))
  13. Path(DOCCANO_HOME).mkdir(parents=True, exist_ok=True)
  14. env.bool("DEBUG", False)
  15. os.environ["STANDALONE"] = "True"
  16. os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings.production")
  17. os.environ.setdefault("DATABASE_URL", os.path.join(f"sqlite:///{DOCCANO_HOME}", "db.sqlite3"))
  18. os.environ.setdefault("MEDIA_ROOT", os.path.join(DOCCANO_HOME, "media"))
  19. base = os.path.abspath(os.path.dirname(__file__))
  20. sys.path.append(base)
  21. parser = argparse.ArgumentParser(description="doccano, text annotation for machine learning practitioners.")
  22. def number_of_workers():
  23. return (multiprocessing.cpu_count() * 2) + 1
  24. def is_windows():
  25. return platform.system() == "Windows"
  26. def run_on_nix(args):
  27. import gunicorn.app.base
  28. import gunicorn.util
  29. class StandaloneApplication(gunicorn.app.base.BaseApplication):
  30. def __init__(self, options=None):
  31. self.options = options or {}
  32. super().__init__()
  33. def load_config(self):
  34. config = {
  35. key: value for key, value in self.options.items() if key in self.cfg.settings and value is not None
  36. }
  37. for key, value in config.items():
  38. self.cfg.set(key.lower(), value)
  39. def load(self):
  40. return gunicorn.util.import_app("config.wsgi")
  41. options = {
  42. "bind": "%s:%s" % ("0.0.0.0", args.port),
  43. "workers": args.workers,
  44. "chdir": base,
  45. "capture_output": True,
  46. "loglevel": "debug",
  47. }
  48. StandaloneApplication(options).run()
  49. def run_on_windows(args):
  50. from waitress import serve
  51. from config.wsgi import application
  52. serve(application, port=args.port)
  53. def command_db_init(args):
  54. print("Setup Database.")
  55. management.call_command("wait_for_db")
  56. management.call_command("migrate")
  57. management.call_command("create_roles")
  58. def command_user_create(args):
  59. print("Create admin user.")
  60. management.call_command(
  61. "create_admin", "--noinput", username=args.username, password=args.password, email=args.email
  62. )
  63. def command_migrate(args):
  64. print("Start migration.")
  65. management.call_command("migrate")
  66. def command_run_webserver(args):
  67. print(f"Starting server with port {args.port}.")
  68. if is_windows():
  69. run_on_windows(args)
  70. else:
  71. run_on_nix(args)
  72. def command_run_task_queue(args):
  73. print("Starting task queue.")
  74. argv = [
  75. "--app=config",
  76. "--workdir={}".format(base),
  77. "worker",
  78. "--loglevel=info",
  79. "--concurrency={}".format(args.concurrency),
  80. ]
  81. if is_windows():
  82. argv.append("--pool=solo")
  83. app.worker_main(argv=argv)
  84. def command_help(args):
  85. print(parser.parse_args([args.command, "--help"]))
  86. def main():
  87. # Create a command line parser.
  88. subparsers = parser.add_subparsers()
  89. # Create a parser for db initialization.
  90. parser_init = subparsers.add_parser("init", help="see `init -h`")
  91. parser_init.set_defaults(handler=command_db_init)
  92. # Create a parser for migration.
  93. parser_migration = subparsers.add_parser("migrate", help="Updates database schema.")
  94. parser_migration.set_defaults(handler=command_migrate)
  95. # Create a parser for user creation.
  96. parser_create_user = subparsers.add_parser("createuser", help="see `createuser -h`")
  97. parser_create_user.add_argument("--username", type=str, default="admin", help="admin username")
  98. parser_create_user.add_argument("--password", type=str, default="password", help="admin password")
  99. parser_create_user.add_argument("--email", type=str, default="example@example.com", help="admin email")
  100. parser_create_user.set_defaults(handler=command_user_create)
  101. # Create a parser for web server.
  102. parser_server = subparsers.add_parser("webserver", help="see `webserver -h`")
  103. parser_server.add_argument("--port", type=int, default=8000, help="port number")
  104. parser_server.add_argument("--workers", type=int, default=number_of_workers(), help="the number of workers")
  105. parser_server.add_argument("--env_file", type=str, help="read in a file of environment variables")
  106. parser_server.set_defaults(handler=command_run_webserver)
  107. # Create a parser for task queue.
  108. parser_queue = subparsers.add_parser("task", help="see `task -h`")
  109. parser_queue.add_argument("--concurrency", type=int, default=2, help="concurrency")
  110. parser_queue.add_argument("--env_file", type=str, help="read in a file of environment variables")
  111. parser_queue.set_defaults(handler=command_run_task_queue)
  112. # Create a parser for help.
  113. parser_help = subparsers.add_parser("help", help="see `help -h`")
  114. parser_help.add_argument("command", help="command name which help is shown")
  115. parser_help.set_defaults(handler=command_help)
  116. # Dispatch handler.
  117. args = parser.parse_args()
  118. if hasattr(args, "env_file"):
  119. env.read_env(args.env_file, recurse=False, override=True)
  120. if hasattr(args, "handler"):
  121. django.setup()
  122. args.handler(args)
  123. else:
  124. # If specified unknown command, show help.
  125. parser.print_help()
  126. if __name__ == "__main__":
  127. main()