Skip to content

Commit 66096b5

Browse files
committed
fix: fix inspectdb
1 parent 806a01c commit 66096b5

File tree

2 files changed

+43
-47
lines changed

2 files changed

+43
-47
lines changed

.github/workflows/base-test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ jobs:
1313
strategy:
1414
fail-fast: false
1515
matrix:
16-
python-version: ["3.8", "3.9", "3.10", "3.11"]
16+
python-version: ["3.8", "3.11"]
1717
django-version: ["3.2", "4.0", "4.1", "4.2"]
1818
clickhouse-version: ["23.8", "latest"]
1919
include:

clickhouse_backend/management/commands/inspectdb.py

Lines changed: 42 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@
88

99

1010
class Command(DCommand):
11-
db_module = "clickhouse_backend"
12-
1311
def handle_inspection(self, options):
1412
connection = connections[options["database"]]
13+
if connection.vendor != "clickhouse":
14+
return super().handle_inspection(options)
1515
# 'table_name_filter' is a stealth option
1616
table_name_filter = options.get("table_name_filter")
1717

@@ -31,7 +31,7 @@ def table2model(table_name):
3131
"# Feel free to rename the models, but don't rename db_table values or "
3232
"field names."
3333
)
34-
yield "from %s import models" % self.db_module
34+
yield "from clickhouse_backend import models"
3535
known_models = []
3636
# Determine types of tables and/or views to be introspected.
3737
types = {"t"}
@@ -45,24 +45,18 @@ def table2model(table_name):
4545
if not table_name_filter(table_name):
4646
continue
4747
try:
48-
try:
49-
constraints = connection.introspection.get_constraints(
50-
cursor, table_name
51-
)
52-
except NotImplementedError:
53-
constraints = {}
5448
table_description = connection.introspection.get_table_description(
5549
cursor, table_name
5650
)
5751
except Exception as e:
58-
yield "# Unable to inspect table '%s'" % table_name
59-
yield "# The error was: %s" % e
52+
yield f"# Unable to inspect table '{table_name}'"
53+
yield f"# The error was: {e}"
6054
continue
6155

6256
model_name = table2model(table_name)
6357
yield ""
6458
yield ""
65-
yield "class %s(models.ClickhouseModel):" % model_name
59+
yield f"class {model_name}(models.ClickhouseModel):"
6660
known_models.append(model_name)
6761
used_column_names = [] # Holds column names used in the table so far
6862
column_to_field_name = {} # Maps column names to names of model fields
@@ -88,9 +82,7 @@ def table2model(table_name):
8882
extra_params["db_comment"] = row.comment
8983

9084
if extra_params:
91-
param = ", ".join(
92-
"%s=%r" % (k, v) for k, v in extra_params.items()
93-
)
85+
param = ", ".join(f"{k}={v!r}" for k, v in extra_params.items())
9486
else:
9587
param = ""
9688

@@ -100,46 +92,45 @@ def table2model(table_name):
10092
field_desc = f"{att_name} = {field_define}"
10193
if comment_notes:
10294
field_desc += " # " + " ".join(comment_notes)
103-
yield " %s" % field_desc
95+
yield f" {field_desc}"
96+
10497
comment = None
98+
managed_comment = ""
10599
if info := table_info.get(table_name):
106-
is_view = info.type == "v"
100+
if info.type == "v":
101+
managed_comment = " # Created from a view. Don't remove."
107102
if connection.features.supports_comments:
108103
comment = info.comment
109-
else:
110-
is_view = False
111-
yield from self.get_meta(
112-
table_name,
113-
constraints,
114-
column_to_field_name,
115-
is_view,
116-
False,
117-
comment,
118-
)
104+
105+
yield ""
106+
yield " class Meta:"
107+
yield f" managed = False{managed_comment}"
108+
yield f" db_table = {table_name!r}"
109+
if compat.dj_ge42 and comment:
110+
yield f" db_table_comment = {comment!r}"
119111

120112
def inspect_field_type(self, column_type, param=""):
121113
column_type = ensure_str(column_type)
122-
123-
if column_type.startswith("LowCardinality"): # LowCardinality(Int16)
114+
# LowCardinality(Int16)
115+
if column_type.startswith("LowCardinality"):
124116
param = self.merge_params(param, "low_cardinality=True")
125117
remain = yield from self.inspect_field_type(column_type[15:], param)
126118
return remain[1:]
127-
elif column_type.startswith("Nullable"): # Nullable(Int16)
119+
# Nullable(Int16)
120+
elif column_type.startswith("Nullable"):
128121
param = self.merge_params(param, "null=True", "blank=True")
129-
remain = yield from self.inspect_field_type(
130-
column_type[9:], param
131-
) # Nullable(Int16)
122+
remain = yield from self.inspect_field_type(column_type[9:], param)
132123
return remain[1:]
133-
elif column_type.startswith("FixedString"): # FixedString(20)
124+
# FixedString(20)
125+
elif column_type.startswith("FixedString"):
134126
i = 12
135127
while column_type[i].isdigit():
136128
i += 1
137129
param = self.merge_params(param, f"max_bytes={column_type[12:i]}")
138130
yield f"models.FixedStringField({param})"
139131
return column_type[i + 1 :]
140-
elif column_type.startswith(
141-
"DateTime64"
142-
): # DateTime64(6, 'UTC') or DateTime64(9)
132+
# DateTime64(6, 'UTC') or DateTime64(9)
133+
elif column_type.startswith("DateTime64"):
143134
if int(column_type[11]) != models.DateTime64Field.DEFAULT_PRECISION:
144135
param = self.merge_params(param, f"precision={column_type[11]}")
145136
yield f"models.DateTime64Field({param})"
@@ -150,15 +141,17 @@ def inspect_field_type(self, column_type, param=""):
150141
i += 1
151142
return column_type[i + 2 :]
152143
return column_type[13:]
153-
elif column_type.startswith("DateTime"): # DateTime('UTC') or DateTime
144+
# DateTime('UTC') or DateTime
145+
elif column_type.startswith("DateTime"):
154146
yield f"models.DateTimeField({param})"
155147
if len(column_type) > 8 and column_type[8] == "(":
156148
i = 10
157149
while column_type[i] != "'":
158150
i += 1
159151
return column_type[i + 2 :]
160152
return column_type[8:]
161-
elif column_type.startswith("Decimal"): # Decimal(9, 3)
153+
# Decimal(9, 3)
154+
elif column_type.startswith("Decimal"):
162155
i = 8
163156
while column_type[i].isdigit():
164157
i += 1
@@ -171,7 +164,8 @@ def inspect_field_type(self, column_type, param=""):
171164
param = self.merge_params(param, max_digits, decimal_places)
172165
yield f"models.DecimalField({param})"
173166
return column_type[i + 1 :]
174-
elif column_type.startswith("Enum"): # Enum8('a' = 1, 'b' = 2)
167+
# Enum8('a' = 1, 'b' = 2)
168+
elif column_type.startswith("Enum"):
175169
i = 4
176170
while column_type[i].isdigit():
177171
i += 1
@@ -185,16 +179,16 @@ def inspect_field_type(self, column_type, param=""):
185179
param = self.merge_params(param, f"choices=[{', '.join(choices)}]")
186180
yield f"models.{typ}Field({param})"
187181
return remain[1:]
188-
elif column_type.startswith(
189-
"Array"
190-
): # Array(Tuple(String, Enum8('a' = 1, 'b' = 2)))
182+
# Array(Tuple(String, Enum8('a' = 1, 'b' = 2)))
183+
elif column_type.startswith("Array"):
191184
yield "models.ArrayField("
192185
remain = yield from self.inspect_field_type(column_type[6:])
193186
if param:
194187
yield f", {param}"
195188
yield ")"
196189
return remain[1:]
197-
elif column_type.startswith("Tuple"): # Tuple(String, Enum8('a' = 1, 'b' = 2))
190+
# Tuple(String, Enum8('a' = 1, 'b' = 2))
191+
elif column_type.startswith("Tuple"):
198192
yield "models.TupleField(["
199193
remain = yield from self.inspect_field_type(column_type[6:])
200194
while remain[0] == ",":
@@ -205,7 +199,8 @@ def inspect_field_type(self, column_type, param=""):
205199
yield f", {param}"
206200
yield ")"
207201
return remain[1:]
208-
elif column_type.startswith("Map"): # Map(String, Int8)
202+
# Map(String, Int8)
203+
elif column_type.startswith("Map"):
209204
yield "models.MapField("
210205
remain = yield from self.inspect_field_type(column_type[4:])
211206
yield ", "
@@ -225,7 +220,8 @@ def inspect_field_type(self, column_type, param=""):
225220
yield f"models.{column_type[:i]}Field({param})"
226221
return column_type[i:]
227222

228-
def consume_enum_choice(self, s): # 'a' = 1
223+
def consume_enum_choice(self, s):
224+
# 'a' = 1
229225
has_bytes = False
230226
i = 1
231227
while True:

0 commit comments

Comments
 (0)