-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathproject.py
executable file
·162 lines (128 loc) · 5.93 KB
/
project.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
#! /usr/bin/env python3
# ruff: noqa: S605
import argparse
import os
import shlex
import sys
PROJECT_ROOT = os.path.dirname(os.path.realpath(__file__))
PROJECT_NAME = "cartable"
LOCAL_ENV_FILE = f"{PROJECT_ROOT}/.envs/.local/.cartable"
LOCAL_ENV_TEMPLATE = (
"# This file contains environment variables local to this setup.\n"
"# You can also use it to overwrite environment variables only on your machine.\n\n"
)
def parse_args(arguments): # noqa
parser = argparse.ArgumentParser(
prog="project.py",
description="Helper script to simplify the docker workflow."
)
subparsers = parser.add_subparsers(dest="command")
run_parser = subparsers.add_parser(
"start", help="Start the Web Server containers Use `project.py -d start` to run them in the background."
)
run_parser.add_argument("-d", "--deamon-mode", help="Run the containers in the background", action="store_true")
run_parser.add_argument("-b", "--build", help="Rebuild the image before running", action="store_true")
subparsers.add_parser("stop", help="Stop the running container.")
restart_parser = subparsers.add_parser("restart", help="Restart the running container.")
restart_parser.add_argument("action", help="The service to restart", nargs=argparse.REMAINDER)
logs_parser = subparsers.add_parser("logs", help="View logs of the project")
logs_parser.add_argument("-f", "--follow-logs", help="Follow logs", action="store_true")
subparsers.add_parser(
"shell", help=(
"Start an interactive shell to access the inside of the "
"container. This only works if the server's container has "
"already been started using `project.py start`."
),
)
subparsers.add_parser("populate", help="Populate Project with basic data.")
django_parser = subparsers.add_parser("django", help="Run a manage.py command, e.g.: `./project.py django migrate`")
django_parser.add_argument("action", help="The django manage.py command to execute", nargs=argparse.REMAINDER)
exec_parser = subparsers.add_parser("exec", help="Run command in the container.")
exec_parser.add_argument("action", help="The command to run", nargs=argparse.REMAINDER)
setup_parser = subparsers.add_parser("setup", help="Setup the local development environment.")
setup_parser.add_argument(
"-f", "--force",
help="Force setup, even if the local environment is already set up. This may result in a loss of data.",
action="store_true"
)
subparsers.add_parser("mypy", help="Run mypy tool on project files.")
args = parser.parse_args(arguments)
if not args.command:
parser.print_help()
exit()
return args
class Interpreter:
@classmethod
def interpret(cls, args: argparse.Namespace):
command_name = args.command.replace("-", "_")
if not hasattr(cls, command_name):
raise NotImplementedError(f"The command `{args.command}` is not found.")
getattr(cls, command_name)(args)
@classmethod
def setup(cls, args: argparse.Namespace | None = None):
"""Setup the local development environment"""
if (args and args.force) or not os.path.isfile(LOCAL_ENV_FILE):
print(f"Setting up {LOCAL_ENV_FILE} file...")
with open(LOCAL_ENV_FILE, "w+") as f:
f.write(LOCAL_ENV_TEMPLATE)
@classmethod
def start(cls, args: argparse.Namespace):
if not os.path.isfile(LOCAL_ENV_FILE):
cls.setup()
command = ["docker-compose", f"-p {shlex.quote(PROJECT_NAME)}", "-f local.yml", "up"]
if args.deamon_mode:
command.append("-d")
if args.build:
command.append("--build")
os.system(" ".join(command))
@classmethod
def stop(cls, args: argparse.Namespace):
command = ["docker-compose", f"-p {shlex.quote(PROJECT_NAME)}", "-f local.yml", "down"]
os.system(" ".join(command))
@classmethod
def restart(cls, args: argparse.Namespace):
command = [
"docker-compose", f"-p {shlex.quote(PROJECT_NAME)}", "-f local.yml", "restart", " ".join(args.action)
]
os.system(" ".join(command))
@classmethod
def logs(cls, args: argparse.Namespace):
command = ["docker-compose", f"-p {shlex.quote(PROJECT_NAME)}", "-f local.yml", "logs"]
if args.follow_logs:
command.append("-f")
os.system(" ".join(command))
@classmethod
def shell(cls, args: argparse.Namespace):
command = ["docker-compose", f"-p {shlex.quote(PROJECT_NAME)}", "-f local.yml", "exec", "cartable", "bash"]
os.system(" ".join(command))
@classmethod
def exec(cls, args: argparse.Namespace):
command = [
"docker-compose", f"-p {shlex.quote(PROJECT_NAME)}", "-f local.yml", "exec", "cartable",
" ".join(args.action),
]
os.system(" ".join(command))
@classmethod
def django(cls, args: argparse.Namespace):
command = [
"docker-compose", f"-p {shlex.quote(PROJECT_NAME)}", "-f local.yml", "exec", "cartable", "python manage.py",
" ".join(args.action)
]
os.system(" ".join(command))
@classmethod
def populate(cls, args: argparse.Namespace):
base_command = ["docker-compose", f"-p {shlex.quote(PROJECT_NAME)}", "-f local.yml", "exec", "cartable"]
load_database_data_command = [
*base_command, "python manage.py loaddata fixtures/data.json"
]
os.system(" ".join(load_database_data_command))
@classmethod
def mypy(cls, args: argparse.Namespace):
command = [
"docker-compose", f"-p {shlex.quote(PROJECT_NAME)}", "-f local.yml", "exec", "-w /app/core", "-T",
"cartable", "mypy --explicit-package-bases . --config-file=mypy.ini"
]
os.system(" ".join(command))
if __name__ == "__main__":
arguments = parse_args(sys.argv[1:])
Interpreter.interpret(arguments)