Skip to content

Commit 900b741

Browse files
authored
Merge branch 'develop' into modern_rpc_prototype
2 parents 8b6ba6c + 19ae3a0 commit 900b741

File tree

5 files changed

+89
-76
lines changed

5 files changed

+89
-76
lines changed

docs/docs/releases/README.md

+7
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,13 @@
22

33
This is developer documentation to help with release notes. It is not published in our docs guide.
44

5+
## Requirements
6+
7+
- Install [DuckDB](https://duckdb.org/#quickinstall).
8+
- On Macs, the easiest way to do this is via [Homebrew](https://brew.sh/): `brew install duckdb`.
9+
- Install the [GitHub CLI](https://cli.github.com/).
10+
- On Macs, the easiest way to do this is via [Homebrew](https://brew.sh/): `brew install gh`.
11+
512
## How to generate release notes
613

714
1. Run the `find_missing_prs.sh` script, passing the release version number as the only argument.

docs/docs/releases/find_missing_prs.sh

+10-3
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,9 @@ TEMPLATE_FILE=TEMPLATE.md
4444
# If the notes file doesn't yet exist, create one
4545
if [ ! -f $NOTES_FILE ]; then
4646
cp $TEMPLATE_FILE $NOTES_FILE
47-
sed -i "s/__VERSION__/$RELEASE/g" $NOTES_FILE
47+
# Note: We're not using the `-i` option to sed because it's not portable
48+
sed "s/__VERSION__/$RELEASE/g" $NOTES_FILE > $NOTES_FILE.tmp
49+
mv $NOTES_FILE.tmp $NOTES_FILE
4850
fi
4951

5052
PREV_NOTES_FILE=$(ls -1 | sort | grep -B 1 $NOTES_FILE | head -n 1)
@@ -80,12 +82,17 @@ mkdir -p "$CACHE_DIR"
8082
# branch but not included in the master branch.
8183
git log --format=%H --first-parent $PREV_RELEASE..$RELEASE_BRANCH > $COMMITS_FILE
8284

85+
ONE_YEAR_AGO=$(python3 -c "
86+
from datetime import datetime, timedelta
87+
one_year_ago = datetime.utcnow() - timedelta(days=365)
88+
print(one_year_ago.strftime('%Y-%m-%d'))")
89+
8390
# Find and cache details about all the PRs merged within the past year. This
8491
# gets more PRs than we need, but we'll filter it shortly.
8592
gh pr list \
8693
--limit 1000 \
8794
--json additions,author,deletions,mergeCommit,title,url \
88-
--search "is:closed merged:>$(date -d '1 year ago' '+%Y-%m-%d')" \
95+
--search "is:closed merged:>$ONE_YEAR_AGO" \
8996
--jq 'map({
9097
additions: .additions,
9198
mergeCommit: .mergeCommit.oid,
@@ -95,7 +102,7 @@ gh pr list \
95102

96103
# Find and cache the URLs to any PRs that we've already referenced in the
97104
# release notes.
98-
grep -Po 'https://github\.com/mathesar-foundation/mathesar/pull/\d*' \
105+
grep -Eo 'https://github\.com/mathesar-foundation/mathesar/pull/[0-9]+' \
99106
$NOTES_FILE > $INCLUDED_PRS_FILE
100107

101108
# Generate a CSV containing details for PRs that match commits in the release

mathesar/models/query.py

+69-70
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,28 @@
66
from db.transforms.operations.deserialize import deserialize_transformation
77
from db.transforms.operations.serialize import serialize_transformation
88
from db.transforms.base import Summarize
9-
from db.functions.base import Count, ArrayAgg, Sum, Median, Mode, Percentage_True, Max, Min, Mean, PeakTime, PeakMonth
9+
from db.functions.base import (
10+
Count,
11+
ArrayAgg,
12+
Sum,
13+
Median,
14+
Mode,
15+
Percentage_True,
16+
Max,
17+
Min,
18+
Mean,
19+
PeakTime,
20+
PeakMonth,
21+
)
1022
from db.functions.packed import DistinctArrayAgg
1123

1224
from mathesar.api.exceptions.query_exceptions.exceptions import DeletedColumnAccess
13-
from mathesar.models.validators import DictValidator, InitialColumnsValidator, ListOfDictValidator, TransformationsValidator
25+
from mathesar.models.validators import (
26+
DictValidator,
27+
InitialColumnsValidator,
28+
ListOfDictValidator,
29+
TransformationsValidator,
30+
)
1431
from mathesar.state.cached_property import cached_property
1532
from mathesar.models.base import BaseModel, Column
1633
from mathesar.models.relation import Relation
@@ -22,13 +39,10 @@ class UIQuery(BaseModel, Relation):
2239
max_length=128,
2340
)
2441

25-
description = models.TextField(
26-
null=True,
27-
blank=True
28-
)
42+
description = models.TextField(null=True, blank=True)
2943

3044
base_table = models.ForeignKey(
31-
'Table', on_delete=models.CASCADE, related_name='queries'
45+
"Table", on_delete=models.CASCADE, related_name="queries"
3246
)
3347

3448
# sequence of dicts
@@ -82,8 +96,7 @@ def output_columns_described(self):
8296
"""
8397
return tuple(
8498
self._describe_query_column(sa_col)
85-
for sa_col
86-
in self.db_query.sa_output_columns
99+
for sa_col in self.db_query.sa_output_columns
87100
)
88101

89102
@property
@@ -94,16 +107,13 @@ def output_columns_simple(self):
94107
def initial_columns_described(self):
95108
return tuple(
96109
{
97-
'alias': initial_col_alias,
98-
'display_name': self._get_display_name_for_alias(
99-
initial_col_alias
100-
),
101-
'type': dj_col.db_type.id,
102-
'type_options': dj_col._sa_column.type_options,
103-
'display_options': dj_col.display_options
110+
"alias": initial_col_alias,
111+
"display_name": self._get_display_name_for_alias(initial_col_alias),
112+
"type": dj_col.db_type.id,
113+
"type_options": dj_col._sa_column.type_options,
114+
"display_options": dj_col.display_options,
104115
}
105-
for initial_col_alias, dj_col
106-
in self._map_of_initial_col_alias_to_dj_column.items()
116+
for initial_col_alias, dj_col in self._map_of_initial_col_alias_to_dj_column.items()
107117
)
108118

109119
def _describe_query_column(self, sa_col):
@@ -126,17 +136,17 @@ def _describe_query_column(self, sa_col):
126136
)
127137
output = output | optionals
128138
if is_initial_column:
129-
initial_dj_column = _get_dj_column_for_initial_db_column(initial_db_column, self._database)
139+
initial_dj_column = _get_dj_column_for_initial_db_column(
140+
initial_db_column, self._database
141+
)
130142
output = output | dict(
131143
input_column_name=initial_dj_column.name,
132144
input_table_name=initial_dj_column.table.name,
133145
input_table_id=initial_dj_column.table.id,
134146
)
135147
else:
136148
input_alias = self.db_query.get_input_alias_for_output_alias(alias)
137-
output = output | dict(
138-
input_alias=input_alias
139-
)
149+
output = output | dict(input_alias=input_alias)
140150
return output
141151

142152
def _get_db_initial_column_by_alias(self, alias):
@@ -180,8 +190,7 @@ def replace_transformations_with_processed_transformations(self):
180190
def _processed_transformations(self):
181191
return tuple(
182192
serialize_transformation(db_transformation)
183-
for db_transformation
184-
in self._processed_db_transformations
193+
for db_transformation in self._processed_db_transformations
185194
)
186195

187196
@property
@@ -212,25 +221,22 @@ def db_query(self):
212221
engine=self._sa_engine,
213222
transformations=self._db_transformations,
214223
name=self.name,
215-
metadata=get_cached_metadata()
224+
metadata=get_cached_metadata(),
216225
)
217226

218227
# TODO reused; consider using cached_property
219228
@property
220229
def _db_initial_columns(self):
221230
return tuple(
222-
_db_initial_column_from_json(json_col)
223-
for json_col in self.initial_columns
231+
_db_initial_column_from_json(json_col) for json_col in self.initial_columns
224232
)
225233

226234
@property
227235
def _db_transformations(self):
228236
"""No processing necessary."""
229237
if self.transformations:
230238
return tuple(
231-
deserialize_transformation(json)
232-
for json
233-
in self.transformations
239+
deserialize_transformation(json) for json in self.transformations
234240
)
235241

236242
def _get_display_name_for_alias(self, alias):
@@ -248,8 +254,7 @@ def _get_display_options_for_alias(self, alias):
248254
display_options = dj_col.display_options
249255
# Try recursively repeating these steps for its parent alias, if it can be found
250256
if display_options is None:
251-
parent_alias = \
252-
self.db_query.map_of_output_alias_to_input_alias.get(alias)
257+
parent_alias = self.db_query.map_of_output_alias_to_input_alias.get(alias)
253258
if parent_alias:
254259
display_options = self._get_display_options_for_alias(parent_alias)
255260
return display_options
@@ -286,72 +291,72 @@ def _default_display_names(self):
286291
attribute), though they are used when generating some of the default display names.
287292
"""
288293
current_display_names = self.display_names or dict()
289-
default_display_names_for_initial_columns = self._default_display_names_for_initial_columns
290-
current_display_names = \
291-
default_display_names_for_initial_columns \
292-
| current_display_names
293-
default_display_names_for_summarize_transforms = \
294+
default_display_names_for_initial_columns = (
295+
self._default_display_names_for_initial_columns
296+
)
297+
current_display_names = (
298+
default_display_names_for_initial_columns | current_display_names
299+
)
300+
default_display_names_for_summarize_transforms = (
294301
self._get_default_display_names_for_summarize_transforms(
295302
current_display_names
296303
)
297-
default_display_names = \
298-
default_display_names_for_summarize_transforms \
304+
)
305+
default_display_names = (
306+
default_display_names_for_summarize_transforms
299307
| default_display_names_for_initial_columns
308+
)
300309
return default_display_names
301310

302311
@property
303312
def _default_display_names_for_initial_columns(self):
304313
return {
305314
alias: dj_col.name
306-
for alias, dj_col
307-
in self._map_of_initial_col_alias_to_dj_column.items()
315+
for alias, dj_col in self._map_of_initial_col_alias_to_dj_column.items()
308316
}
309317

310-
def _get_default_display_names_for_summarize_transforms(self, current_display_names):
318+
def _get_default_display_names_for_summarize_transforms(
319+
self, current_display_names
320+
):
311321
default_display_names = dict()
312322
if not current_display_names:
313323
return default_display_names
314324
summarize_transforms = [
315325
db_transform
316-
for db_transform
317-
in self.db_query.transformations
326+
for db_transform in self.db_query.transformations
318327
if isinstance(db_transform, Summarize)
319328
]
320329
for summarize_transform in summarize_transforms:
321330
# Find default display names for grouping output aliases
322331
for output_alias in summarize_transform.grouping_output_aliases:
323-
default_display_name = \
324-
_get_default_display_name_for_group_output_alias(
325-
summarize_transform,
326-
output_alias,
327-
current_display_names,
328-
)
332+
default_display_name = _get_default_display_name_for_group_output_alias(
333+
summarize_transform,
334+
output_alias,
335+
current_display_names,
336+
)
329337
if default_display_name:
330338
default_display_names[output_alias] = default_display_name
331339
# Find default display names for aggregation output aliases
332340
for agg_col_spec in summarize_transform.aggregation_col_specs:
333341
input_alias = agg_col_spec.get("input_alias")
334342
output_alias = agg_col_spec.get("output_alias")
335343
agg_function = agg_col_spec.get("function")
336-
default_display_name = \
337-
_get_default_display_name_for_agg_output_alias(
338-
output_alias,
339-
input_alias,
340-
agg_function,
341-
current_display_names,
342-
)
344+
default_display_name = _get_default_display_name_for_agg_output_alias(
345+
output_alias,
346+
input_alias,
347+
agg_function,
348+
current_display_names,
349+
)
343350
if default_display_name:
344351
default_display_names[output_alias] = default_display_name
345352
return default_display_names
346353

347354
@property
348355
def _map_of_initial_col_alias_to_dj_column(self):
349-
dj_column_ids = [col['id'] for col in self.initial_columns]
356+
dj_column_ids = [col["id"] for col in self.initial_columns]
350357
dj_columns = Column.objects.filter(pk__in=dj_column_ids)
351358
initial_col_aliases = [
352-
initial_col['alias']
353-
for initial_col
354-
in self.initial_columns
359+
initial_col["alias"] for initial_col in self.initial_columns
355360
]
356361
return frozendict(
357362
zip(
@@ -383,9 +388,7 @@ def _db_initial_column_from_json(col_json):
383388
attnum = column_pair[1]
384389
alias = col_json["alias"]
385390
jp_path = [
386-
_join_parameter_from_json(jp_json)
387-
for jp_json
388-
in col_json.get("jp_path", [])
391+
_join_parameter_from_json(jp_json) for jp_json in col_json.get("jp_path", [])
389392
]
390393
return InitialColumn(
391394
reloid=reloid,
@@ -441,10 +444,6 @@ def _get_default_display_name_for_group_output_alias(
441444
output_alias,
442445
current_display_names,
443446
):
444-
input_alias = \
445-
summarize_transform\
446-
.map_of_output_alias_to_input_alias[output_alias]
447+
input_alias = summarize_transform.map_of_output_alias_to_input_alias[output_alias]
447448
input_alias_display_name = current_display_names.get(input_alias)
448-
if input_alias_display_name:
449-
suffix_to_add = " group"
450-
return input_alias_display_name + suffix_to_add
449+
return input_alias_display_name

mathesar/tests/api/query/test_query_run_partial_transforms.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ def test_partial_summarize_transform(
113113
'transformations': output_transformations,
114114
'display_names': {
115115
'col1': 'Center',
116-
'col1_grouped': 'Center group',
116+
'col1_grouped': 'Center',
117117
'col2': 'Case Number',
118118
'col2_agged': 'Case Number distinct list',
119119
},
@@ -135,7 +135,7 @@ def test_partial_summarize_transform(
135135
},
136136
'col1_grouped': {
137137
'alias': 'col1_grouped',
138-
'display_name': 'Center group',
138+
'display_name': 'Center',
139139
'display_options': None,
140140
'input_alias': 'col1',
141141
'input_column_name': None,

requirements.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ bidict==0.21.4
33
frozendict==2.1.3
44
charset-normalizer==2.0.7
55
clevercsv==0.6.8
6-
Django==4.2.10
6+
Django==4.2.11
77
dj-database-url==0.5.0
88
django-filter==23.5
99
django-modern-rpc==1.0.3

0 commit comments

Comments
 (0)