gibson-cli 0.7.4__py3-none-any.whl → 0.7.6__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. bin/gibson +26 -0
  2. gibson/api/BaseApi.py +1 -1
  3. gibson/api/Cli.py +1 -1
  4. gibson/command/Build.py +6 -6
  5. gibson/command/Conf.py +1 -2
  6. gibson/command/Count.py +1 -1
  7. gibson/command/Dev.py +5 -8
  8. gibson/command/Forget.py +1 -1
  9. gibson/command/Help.py +112 -47
  10. gibson/command/Modify.py +2 -4
  11. gibson/command/Question.py +2 -4
  12. gibson/command/Remove.py +2 -2
  13. gibson/command/Show.py +3 -5
  14. gibson/command/Version.py +1 -1
  15. gibson/command/auth/Auth.py +3 -3
  16. gibson/command/code/Code.py +10 -10
  17. gibson/command/code/Entity.py +67 -33
  18. gibson/command/code/Model.py +2 -4
  19. gibson/command/code/Schema.py +9 -8
  20. gibson/command/code/Test.py +1 -3
  21. gibson/command/importer/Import.py +8 -8
  22. gibson/command/importer/OpenApi.py +1 -1
  23. gibson/command/list/Entities.py +25 -37
  24. gibson/command/list/List.py +3 -3
  25. gibson/command/list/Projects.py +23 -13
  26. gibson/command/new/Module.py +2 -2
  27. gibson/command/new/New.py +4 -4
  28. gibson/command/rename/Rename.py +1 -1
  29. gibson/command/rewrite/Rewrite.py +1 -1
  30. gibson/core/Colors.py +34 -7
  31. gibson/core/CommandRouter.py +0 -1
  32. gibson/core/Configuration.py +8 -3
  33. gibson/core/Conversation.py +17 -24
  34. gibson/core/Diff.py +34 -0
  35. gibson/core/Memory.py +1 -0
  36. gibson/core/Spinner.py +8 -3
  37. gibson/display/Header.py +3 -1
  38. gibson/display/WorkspaceHeader.py +2 -2
  39. gibson/display/tests/test_display_Header.py +2 -2
  40. gibson/display/tests/test_display_WorkspaceHeader.py +1 -1
  41. {gibson_cli-0.7.4.dist-info → gibson_cli-0.7.6.dist-info}/METADATA +16 -7
  42. {gibson_cli-0.7.4.dist-info → gibson_cli-0.7.6.dist-info}/RECORD +45 -44
  43. {gibson_cli-0.7.4.dist-info → gibson_cli-0.7.6.dist-info}/WHEEL +1 -1
  44. gibson/command/WarGames.py +0 -34
  45. {gibson_cli-0.7.4.dist-info → gibson_cli-0.7.6.dist-info}/entry_points.txt +0 -0
  46. {gibson_cli-0.7.4.dist-info → gibson_cli-0.7.6.dist-info}/top_level.txt +0 -0
@@ -1,3 +1,5 @@
1
+ from __future__ import annotations
2
+
1
3
  import os
2
4
  import sys
3
5
  from string import Template
@@ -5,11 +7,13 @@ from string import Template
5
7
  import gibson.core.Colors as Colors
6
8
  from gibson.api.Cli import Cli
7
9
  from gibson.command.BaseCommand import BaseCommand
10
+ from gibson.command.code.Base import Base
8
11
  from gibson.command.code.Model import Model
9
12
  from gibson.command.code.Schema import Schema
10
13
  from gibson.command.code.Test import Test
11
14
  from gibson.command.Merge import Merge
12
15
  from gibson.core.Configuration import Configuration
16
+ from gibson.core.Diff import additions, diff
13
17
  from gibson.core.Spinner import ComputingSpinner, Spinner
14
18
  from gibson.display.Header import Header
15
19
  from gibson.display.WorkspaceFooter import WorkspaceFooter
@@ -60,34 +64,15 @@ class Entity(BaseCommand):
60
64
 
61
65
  return True
62
66
 
63
- def configure_definition(self):
64
- existing_entity = self.memory.recall_entity(sys.argv[3])
65
- if existing_entity is not None:
66
- return existing_entity["definition"]
67
-
68
- parts = sys.argv[3].split("_")
69
- if len(parts) > 1 and parts[1] == "ref":
70
- # This is a reference table implementation. We will handle this here.
71
- with open(self.get_default_ref_table_template_path()) as f:
72
- definition = Template(f.read()).substitute({"entity_name": sys.argv[3]})
73
-
74
- self.memory.append_last({"definition": definition, "name": sys.argv[3]})
75
-
76
- self.conversation.type(
77
- "Reference table created and stored in last memory. What's next?\n"
78
- )
79
- self.conversation.newline()
80
-
81
- exit(1)
82
-
83
- with open(self.get_default_table_template_path()) as f:
84
- return Template(f.read()).substitute({"entity_name": sys.argv[3]})
85
-
86
67
  def execute(self):
87
68
  cli = Cli(self.configuration)
88
-
89
- self.configuration.require_project()
90
- definition = self.configure_definition()
69
+ entity_name = sys.argv[3]
70
+ existing_entity = self.memory.recall_entity(entity_name)
71
+ definition = (
72
+ existing_entity["definition"]
73
+ if existing_entity
74
+ else self.template_definition(entity_name)
75
+ )
91
76
 
92
77
  with ComputingSpinner():
93
78
  self.__context = CodeContextSchemaManager().from_code_writer_schema_context(
@@ -104,10 +89,20 @@ class Entity(BaseCommand):
104
89
  .instantiate(self.configuration.project.datastore.type)
105
90
  .import_from_struct(data)
106
91
  )
92
+ original_entity = entity if existing_entity else None
93
+ original_model_code = (
94
+ data["code"][0]["definition"] if existing_entity else None
95
+ )
107
96
 
108
97
  while True:
109
98
  try:
110
- self.__render_workspace(entity, data["code"][0]["definition"])
99
+ self.__render_workspace(
100
+ original_entity,
101
+ entity,
102
+ data["code"][0]["name"],
103
+ original_model_code,
104
+ data["code"][0]["definition"],
105
+ )
111
106
  input_ = input("> ")
112
107
  if input_.lower() in [":q", ":q!", ":wq"]:
113
108
  self.conversation.newline()
@@ -133,12 +128,16 @@ class Entity(BaseCommand):
133
128
  Schema(self.configuration).execute(entity_name=entity.name)
134
129
  Test(self.configuration).execute(entity_name=entity.name)
135
130
 
131
+ if original_entity is None:
132
+ # We need to ensure the testing.py file is updated to import the new entity
133
+ Base(self.configuration).execute()
134
+
136
135
  self.conversation.unmute()
137
136
  self.conversation.type(
138
- f"\nAll code for the {Colors.violet(entity.name)} entity has been written 🎉\n\n"
137
+ f"\nAll code for the {Colors.entity(entity.name)} entity has been written 🎉\n\n"
139
138
  )
140
139
  exit()
141
- elif input_ == "":
140
+ elif input_ == "" or input_.startswith(":"):
142
141
  continue
143
142
 
144
143
  with ComputingSpinner():
@@ -185,8 +184,25 @@ class Entity(BaseCommand):
185
184
  + "/default-table.tmpl"
186
185
  )
187
186
 
188
- def __render_workspace(self, entity: StructureEntity, model):
187
+ def __render_workspace(
188
+ self,
189
+ original_entity: StructureEntity | None,
190
+ entity: StructureEntity,
191
+ model_name: str,
192
+ original_model_code: str | None,
193
+ model_code: str,
194
+ ):
189
195
  self.configuration.platform.cmd_clear()
196
+ create_table_statement_diff = (
197
+ diff(original_entity.create_statement(), entity.create_statement())
198
+ if original_entity
199
+ else additions(entity.create_statement())
200
+ )
201
+ model_code_diff = (
202
+ diff(original_model_code, model_code)
203
+ if original_model_code
204
+ else additions(model_code)
205
+ )
190
206
 
191
207
  print("")
192
208
  print(WorkspaceHeader().render(self.configuration.project.name))
@@ -194,11 +210,29 @@ class Entity(BaseCommand):
194
210
  print("")
195
211
  print(Header().render("SQL", Colors.cyan))
196
212
  print("")
197
- print(Colors.table(entity.create_statement(), entity.name))
213
+ print(Colors.table(create_table_statement_diff, entity.name))
198
214
 
199
215
  print("")
200
216
  print(Header().render("Model", Colors.yellow))
201
217
  print("")
202
- print(Colors.model(model, entity.name))
203
-
218
+ print(Colors.model(model_code_diff, model_name, entity.name))
204
219
  print(WorkspaceFooter().render())
220
+
221
+ def template_definition(self, entity_name):
222
+ parts = entity_name.split("_")
223
+ if len(parts) > 1 and parts[1] == "ref":
224
+ # This is a reference table implementation. We will handle this here.
225
+ with open(self.get_default_ref_table_template_path()) as f:
226
+ definition = Template(f.read()).substitute({"entity_name": entity_name})
227
+
228
+ self.memory.append_last({"definition": definition, "name": entity_name})
229
+
230
+ self.conversation.type(
231
+ "Reference table created and stored in last memory. What's next?\n"
232
+ )
233
+ self.conversation.newline()
234
+
235
+ exit(1)
236
+
237
+ with open(self.get_default_table_template_path()) as f:
238
+ return Template(f.read()).substitute({"entity_name": entity_name})
@@ -14,14 +14,12 @@ class Model(BaseCommand):
14
14
  self.configuration.require_project()
15
15
  entity = self.memory.recall_stored_entity(entity_name)
16
16
  if entity is None:
17
- self.conversation.not_sure_no_entity(
18
- self.configuration.project.name, entity_name
19
- )
17
+ self.conversation.not_sure_no_entity(self.configuration, entity_name)
20
18
  exit(1)
21
19
 
22
20
  time_keeper = TimeKeeper()
23
21
 
24
- with Spinner("Gibson is writing the models...", "Models written"):
22
+ with Spinner("Gibson is writing the model...", "Model written"):
25
23
  cli = Cli(self.configuration)
26
24
  response = cli.code_models([entity["name"]])
27
25
  Dev(self.configuration).model(
@@ -14,9 +14,7 @@ class Schema(BaseCommand):
14
14
  self.configuration.require_project()
15
15
  entity = self.memory.recall_stored_entity(entity_name)
16
16
  if entity is None:
17
- self.conversation.not_sure_no_entity(
18
- self.configuration.project.name, entity_name
19
- )
17
+ self.conversation.not_sure_no_entity(self.configuration, entity_name)
20
18
  exit(1)
21
19
 
22
20
  time_keeper = TimeKeeper()
@@ -24,15 +22,18 @@ class Schema(BaseCommand):
24
22
  with Spinner("Gibson is writing the schemas...", "Schemas written"):
25
23
  cli = Cli(self.configuration)
26
24
  response = cli.code_schemas([entity["name"]])
27
- Dev(self.configuration).schema(
28
- response["code"][0]["entity"]["name"], response["code"][0]["definition"]
29
- )
25
+ code = response["code"][0] if len(response["code"]) > 0 else None
26
+ if code:
27
+ Dev(self.configuration).schema(
28
+ code["entity"]["name"], code["definition"]
29
+ )
30
30
 
31
- if self.configuration.project.dev.active is True:
31
+ if code and self.configuration.project.dev.active is True:
32
32
  self.conversation.type(
33
33
  f"\nGibson wrote the following {Colors.argument('schema')} code to your project:\n"
34
34
  )
35
35
 
36
36
  if not self.conversation.muted():
37
- print(response["code"][0]["definition"])
37
+ if code:
38
+ print(code["definition"])
38
39
  time_keeper.display()
@@ -14,9 +14,7 @@ class Test(BaseCommand):
14
14
  self.configuration.require_project()
15
15
  entity = self.memory.recall_stored_entity(entity_name)
16
16
  if entity is None:
17
- self.conversation.not_sure_no_entity(
18
- self.configuration.project.name, entity_name
19
- )
17
+ self.conversation.not_sure_no_entity(self.configuration, entity_name)
20
18
  exit(1)
21
19
 
22
20
  time_keeper = TimeKeeper()
@@ -56,7 +56,7 @@ class Import(BaseCommand):
56
56
  self.conversation.type("Building schema...\n")
57
57
 
58
58
  for entity in response["project"]["entities"]:
59
- self.conversation.type(f" {entity['name']}\n", delay=0.002)
59
+ self.conversation.type(f" {entity['name']}\n")
60
60
 
61
61
  return response["project"]["entities"]
62
62
 
@@ -74,7 +74,7 @@ class Import(BaseCommand):
74
74
  entities = []
75
75
  for table in tables:
76
76
  if table[0] not in table_exceptions:
77
- self.conversation.type(f" {table[0]}\n", delay=0.002)
77
+ self.conversation.type(f" {table[0]}\n")
78
78
 
79
79
  create_statement = session.execute(
80
80
  f"show create table {table[0]}"
@@ -139,7 +139,7 @@ class Import(BaseCommand):
139
139
 
140
140
  entities = []
141
141
  for table_name, definition in tables.items():
142
- self.conversation.type(f" {table_name}\n", delay=0.002)
142
+ self.conversation.type(f" {table_name}\n")
143
143
 
144
144
  definition[-1] = definition[-1].rstrip(",")
145
145
 
@@ -160,19 +160,19 @@ class Import(BaseCommand):
160
160
  else ""
161
161
  )
162
162
  self.conversation.type(
163
- f"usage: {Colors.command(self.configuration.command)} {Colors.subcommand('import')} {Colors.arguments(['api', 'mysql', 'pg_dump', 'openapi'])} {Colors.hint('import entities')}\n"
163
+ f"usage: {Colors.command(self.configuration.command, 'import', args=['api', 'mysql', 'pg_dump', 'openapi'], hint='import entities')}\n"
164
164
  )
165
165
  self.conversation.type(
166
- f" {Colors.command(self.configuration.command)} {Colors.subcommand('import')} {Colors.argument('api')} {Colors.hint(f'import all entities from your project created on {Colors.link(self.configuration.app_domain())}')}\n"
166
+ f" {Colors.command(self.configuration.command, 'import', args='api', hint=f'import all entities from your project created on {Colors.link(self.configuration.app_domain())}')}\n"
167
167
  )
168
168
  self.conversation.type(
169
- f" {Colors.command(self.configuration.command)} {Colors.subcommand('import')} {Colors.argument('mysql')} {Colors.hint('import all entities from your MySQL database')} ({Colors.link(datastore_uri)})\n"
169
+ f" {Colors.command(self.configuration.command, 'import', args='mysql', hint='import all entities from your MySQL database')} ({Colors.link(datastore_uri)})\n"
170
170
  )
171
171
  self.conversation.type(
172
- f" {Colors.command(self.configuration.command)} {Colors.subcommand('import')} {Colors.argument('pg_dump')} {Colors.input('path/to/pg_dump.sql')} {Colors.hint('import all entities from a pg_dump file')}\n"
172
+ f" {Colors.command(self.configuration.command, 'import', args='pg_dump', inputs='path/to/pg_dump.sql', hint='import all entities from a pg_dump file')}\n"
173
173
  )
174
174
  self.conversation.type(
175
- f" {Colors.command(self.configuration.command)} {Colors.subcommand('import')} {Colors.argument('openapi')} {Colors.input('path/to/openapi.json')} {Colors.hint('import all entities from an OpenAPI spec file')}\n"
175
+ f" {Colors.command(self.configuration.command, 'import', args='openapi', inputs='path/to/openapi.json', hint='import all entities from an OpenAPI spec file')}\n"
176
176
  )
177
177
  self.conversation.newline()
178
178
  exit(1)
@@ -46,7 +46,7 @@ class OpenApi(BaseCommand):
46
46
 
47
47
  i = 0
48
48
  for path in path_list:
49
- self.conversation.type(f" {i}: ".rjust(10) + path + "\n", delay=0.0009)
49
+ self.conversation.type(f" {i}: ".rjust(10) + path + "\n")
50
50
  i += 1
51
51
 
52
52
  self.conversation.newline()
@@ -1,5 +1,10 @@
1
1
  import sys
2
2
 
3
+ from rich import box
4
+ from rich.console import Console
5
+ from rich.table import Table
6
+ from rich.text import Text
7
+
3
8
  from gibson.command.BaseCommand import BaseCommand
4
9
 
5
10
 
@@ -8,44 +13,27 @@ class Entities(BaseCommand):
8
13
  self.configuration.require_project()
9
14
  self.configuration.display_project()
10
15
 
11
- entities = {"last": [], "stored": []}
12
-
13
- last = self.memory.recall_last()
14
- if last is not None:
15
- for entity in last["entities"]:
16
- entities["last"].append(entity["name"])
17
-
18
- stored = self.memory.recall_entities()
19
- if stored is not None:
20
- for entity in stored:
21
- entities["stored"].append(entity["name"])
16
+ last = self.memory.recall_last() or []
17
+ stored = self.memory.recall_entities() or []
22
18
 
23
- if len(entities["last"]) == 0 and len(entities["stored"]) == 0:
19
+ if len(last) == 0 and len(stored) == 0:
24
20
  self.conversation.nothing_to_list(sys.argv[2])
25
21
  self.conversation.newline()
26
22
  else:
27
- self.conversation.type(" Name".ljust(60), delay=0.0001)
28
- self.conversation.type("Memory", delay=0.002)
29
- self.conversation.newline()
30
- self.conversation.type(" ----".ljust(60), delay=0.0001)
31
- self.conversation.type("------", delay=0.002)
32
- self.conversation.newline()
33
-
34
- entities["last"].sort()
35
- entities["stored"].sort()
36
-
37
- if len(entities["stored"]) > 0:
38
- for entity in entities["stored"]:
39
- self.conversation.type(f" {entity}".ljust(60), delay=0.0001)
40
- self.conversation.type("[stored]", delay=0.002)
41
- self.conversation.newline()
42
-
43
- self.conversation.newline()
44
-
45
- if len(entities["last"]) > 0:
46
- for entity in entities["last"]:
47
- self.conversation.type(f" {entity}".ljust(60), delay=0.0001)
48
- self.conversation.type("[last]", delay=0.002)
49
- self.conversation.newline()
50
-
51
- self.conversation.newline()
23
+ console = Console()
24
+ table = Table(
25
+ title="Entities",
26
+ header_style="bold",
27
+ box=box.ROUNDED,
28
+ leading=1,
29
+ )
30
+ table.add_column("Name", style="magenta", header_style="magenta")
31
+ table.add_column("Memory")
32
+
33
+ for entity in sorted(stored, key=lambda x: x["name"]):
34
+ table.add_row(entity["name"], Text("stored", style="green"))
35
+
36
+ for entity in sorted(last, key=lambda x: x["name"]):
37
+ table.add_row(entity["name"], Text("last", style="yellow"))
38
+
39
+ console.print(table)
@@ -18,13 +18,13 @@ class List(BaseCommand):
18
18
  def usage(self):
19
19
  self.configuration.display_project()
20
20
  self.conversation.type(
21
- f"usage: {Colors.command(self.configuration.command)} {Colors.subcommand('list')} {Colors.arguments(['entities', 'projects'])}\n"
21
+ f"usage: {Colors.command(self.configuration.command, 'list', args=['entities', 'projects'])}\n"
22
22
  )
23
23
  self.conversation.type(
24
- f" {Colors.command(self.configuration.command)} {Colors.subcommand('list')} {Colors.argument('entities')} {Colors.hint('list all entities')}\n"
24
+ f" {Colors.command(self.configuration.command, 'list', args='entities', hint='list all entities')}\n"
25
25
  )
26
26
  self.conversation.type(
27
- f" {Colors.command(self.configuration.command)} {Colors.subcommand('list')} {Colors.argument('projects')} {Colors.hint('list all projects')}\n"
27
+ f" {Colors.command(self.configuration.command, 'list', args='projects', hint='list all projects')}\n"
28
28
  )
29
29
  self.conversation.newline()
30
30
  exit(1)
@@ -1,31 +1,41 @@
1
- import re
1
+ from rich import box
2
+ from rich.console import Console
3
+ from rich.table import Table
2
4
 
3
5
  import gibson.core.Colors as Colors
4
6
  from gibson.api.ProjectApi import ProjectApi
5
7
  from gibson.command.BaseCommand import BaseCommand
8
+ from gibson.core.Spinner import DisappearingSpinner
6
9
 
7
10
 
8
11
  class Projects(BaseCommand):
9
12
  def execute(self):
10
13
  self.configuration.require_login()
11
- projects = ProjectApi(self.configuration).all_projects()
14
+
15
+ with DisappearingSpinner():
16
+ projects = ProjectApi(self.configuration).all_projects()
12
17
 
13
18
  if len(projects) == 0:
14
19
  self.conversation.type(
15
- f"No projects found. Create one with {Colors.command('gibson')} {Colors.subcommand('new')} {Colors.argument('project')}\n"
20
+ f"No projects found. Create one with {Colors.command(self.configuration.command, 'new', args='project')}\n"
16
21
  )
17
22
  exit(1)
18
23
 
19
- self.conversation.type("Name".ljust(40))
20
- self.conversation.type("ID")
21
- self.conversation.newline()
22
- self.conversation.type("----".ljust(40))
23
- self.conversation.type("-" * 36)
24
- self.conversation.newline()
24
+ console = Console()
25
+ table = Table(
26
+ title="Projects",
27
+ header_style="bold magenta",
28
+ box=box.ROUNDED,
29
+ leading=1,
30
+ )
31
+ table.add_column("Name")
32
+ table.add_column("ID", min_width=36)
25
33
 
26
34
  for project in projects:
27
35
  name = project["name"] if project["name"] is not None else "Untitled"
28
- name = re.sub(r"^(.{36}).*$", "\g<1>...", name).ljust(40)
29
- self.conversation.type(f"{Colors.command(name)}")
30
- self.conversation.type(f"{project['uuid']}")
31
- self.conversation.newline()
36
+ table.add_row(
37
+ name,
38
+ project["uuid"],
39
+ )
40
+
41
+ console.print(table)
@@ -34,7 +34,7 @@ class Module(BaseCommand):
34
34
  self.conversation.newline()
35
35
  self.conversation.type(f"If you want to persist these new entities run:\n")
36
36
  self.conversation.type(
37
- f"{Colors.command(self.configuration.command)} {Colors.subcommand('merge')}\n"
37
+ f"{Colors.command(self.configuration.command, 'merge')}\n"
38
38
  )
39
39
 
40
40
  self.conversation.newline()
@@ -42,5 +42,5 @@ class Module(BaseCommand):
42
42
  f"Afterwards, you can modify any of these entities by running:\n"
43
43
  )
44
44
  self.conversation.type(
45
- f"{Colors.command(self.configuration.command)} {Colors.subcommand('modify')} {Colors.argument('[entity name]')} {Colors.input('[instructions]')}\n"
45
+ f"{Colors.command(self.configuration.command, 'modify', inputs=['[entity name]', '[instructions]'])}\n"
46
46
  )
gibson/command/new/New.py CHANGED
@@ -21,16 +21,16 @@ class New(BaseCommand):
21
21
  def usage(self):
22
22
  self.configuration.display_project()
23
23
  self.conversation.type(
24
- f"usage: {Colors.command(self.configuration.command)} {Colors.subcommand('new')} {Colors.arguments(['project', 'module', 'entity'])} {Colors.hint('create something new')}\n"
24
+ f"usage: {Colors.command(self.configuration.command, 'new', args=['project', 'module', 'entity'], hint='create something new')}\n"
25
25
  )
26
26
  self.conversation.type(
27
- f" {Colors.command(self.configuration.command)} {Colors.subcommand('new')} {Colors.argument('project')} {Colors.hint('create a new project')}\n"
27
+ f" {Colors.command(self.configuration.command, 'new', args='project', hint='create a new project')}\n"
28
28
  )
29
29
  self.conversation.type(
30
- f" {Colors.command(self.configuration.command)} {Colors.subcommand('new')} {Colors.argument('module')} {Colors.hint('create a new module')}\n"
30
+ f" {Colors.command(self.configuration.command, 'new', args='module', hint='create a new module')}\n"
31
31
  )
32
32
  self.conversation.type(
33
- f" {Colors.command(self.configuration.command)} {Colors.subcommand('new')} {Colors.argument('entity')} {Colors.input('[entity name]')} {Colors.hint('create a new entity')}\n"
33
+ f" {Colors.command(self.configuration.command, 'new', args='entity', inputs='[entity name]', hint='create a new entity')}\n"
34
34
  )
35
35
  self.conversation.newline()
36
36
  exit(1)
@@ -15,7 +15,7 @@ class Rename(BaseCommand):
15
15
  def usage(self):
16
16
  self.configuration.display_project()
17
17
  self.conversation.type(
18
- f"usage: {Colors.command(self.configuration.command)} {Colors.subcommand('rename')} {Colors.argument('entity')} {Colors.input('[existing name]')} {Colors.input('[new name]')} {Colors.hint('rename an entity')}\n"
18
+ f"usage: {Colors.command(self.configuration.command, 'rename', args='entity', inputs=['[existing name]', '[new name]'], hint='rename an entity')}\n"
19
19
  )
20
20
  self.conversation.newline()
21
21
  exit(1)
@@ -115,7 +115,7 @@ class Rewrite(BaseCommand):
115
115
  def usage(self):
116
116
  self.configuration.display_project()
117
117
  self.conversation.type(
118
- f"usage: {Colors.command(self.configuration.command)} {Colors.subcommand('rewrite')} {Colors.hint('rewrite all code')}\n"
118
+ f"usage: {Colors.command(self.configuration.command, 'rewrite', hint='rewrite all code')}\n"
119
119
  )
120
120
  self.conversation.newline()
121
121
  exit(1)
gibson/core/Colors.py CHANGED
@@ -46,8 +46,30 @@ def colorize(text, color):
46
46
 
47
47
 
48
48
  # Colorize a command
49
- def command(text):
50
- return green(text)
49
+ def command(
50
+ command,
51
+ sub=None,
52
+ args=None,
53
+ inputs=None,
54
+ hint=None,
55
+ ):
56
+ parts = [green(command)]
57
+ if sub:
58
+ parts.append(subcommand(sub))
59
+ if args:
60
+ if isinstance(args, list):
61
+ parts.append(arguments(args))
62
+ else:
63
+ parts.append(argument(args))
64
+ if inputs:
65
+ if isinstance(inputs, list):
66
+ for input_ in inputs:
67
+ parts.append(user_input(input_))
68
+ else:
69
+ parts.append(user_input(inputs))
70
+ if hint:
71
+ parts.append(grey(hint))
72
+ return " ".join(parts)
51
73
 
52
74
 
53
75
  # Colorize a subcommand
@@ -66,7 +88,7 @@ def arguments(list):
66
88
 
67
89
 
68
90
  # Colorize user input
69
- def input(text):
91
+ def user_input(text):
70
92
  return white(text)
71
93
 
72
94
 
@@ -90,15 +112,20 @@ def link(text):
90
112
  return underline(blue(text))
91
113
 
92
114
 
115
+ # Colorize an entity name
116
+ def entity(text):
117
+ return bold(violet(text))
118
+
119
+
93
120
  # Colorize the table name in a SQL statement
94
121
  def table(sql, name):
95
- return sql.replace(name, violet(name))
122
+ return sql.replace(name, entity(name), 1)
96
123
 
97
124
 
98
125
  # Colorize the table name in model code
99
- def model(code, name):
100
- return code.replace(
101
- f'__tablename__ = "{name}"', f'__tablename__ = "{violet(name)}"'
126
+ def model(code, model_name, entity_name):
127
+ return code.replace(model_name, entity(model_name), 1).replace(
128
+ f'__tablename__ = "{entity_name}"', f'__tablename__ = "{entity(entity_name)}"'
102
129
  )
103
130
 
104
131
 
@@ -20,7 +20,6 @@ from gibson.command.rewrite.Rewrite import Rewrite
20
20
  from gibson.command.Show import Show
21
21
  from gibson.command.Tree import Tree
22
22
  from gibson.command.Version import Version
23
- from gibson.command.WarGames import WarGames
24
23
  from gibson.core.Configuration import Configuration
25
24
  from gibson.core.Conversation import Conversation
26
25
  from gibson.core.Env import Env
@@ -313,7 +313,7 @@ class Configuration:
313
313
 
314
314
  def require_login(self):
315
315
  if self.get_access_token() is None:
316
- self.conversation.message_login_required()
316
+ self.conversation.message_login_required(self)
317
317
  exit(1)
318
318
 
319
319
  return self
@@ -329,9 +329,12 @@ class Configuration:
329
329
 
330
330
  return self
331
331
 
332
- def require_project_key(self):
332
+ def require_project_key_or_id(self):
333
+ if self.project.id:
334
+ return self
335
+
333
336
  if not self.project.api.key or self.project.api.key == "FIXME":
334
- self.conversation.project_api_key_not_set(self.app_domain())
337
+ self.conversation.project_api_key_not_set(self)
335
338
  exit(1)
336
339
 
337
340
  return self
@@ -345,6 +348,7 @@ class Configuration:
345
348
  with open(f"{self.paths.auth}/{self.API_ENV}", "w") as f:
346
349
  data = {"access_token": access_token, "refresh_token": refresh_token}
347
350
  json.dump(data, f, indent=2)
351
+ f.write("\n")
348
352
 
349
353
  def set_config_paths(self):
350
354
  config_path = os.environ.get("GIBSONAI_CONFIG_PATH", None)
@@ -448,6 +452,7 @@ class Configuration:
448
452
 
449
453
  with open(self.paths.config, "w") as f:
450
454
  json.dump(self.settings, f, indent=2)
455
+ f.write("\n")
451
456
 
452
457
  self.read_config()
453
458