Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Columns meta rpc patch #3653

Merged
merged 8 commits into from
Jul 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/docs/api/rpc.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,9 @@ To use an RPC function:
options:
members:
- list_
- patch
- ColumnMetaData
- SettableColumnMetaData

## Responses

Expand Down
67 changes: 66 additions & 1 deletion mathesar/rpc/columns/metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from modernrpc.auth.basic import http_basic_auth_login_required

from mathesar.rpc.exceptions.handlers import handle_rpc_exceptions
from mathesar.utils.columns import get_columns_meta_data
from mathesar.utils.columns import get_columns_meta_data, patch_columns_meta_data


class ColumnMetaData(TypedDict):
Expand Down Expand Up @@ -73,6 +73,42 @@ def from_model(cls, model):
)


class SettableColumnMetaData(TypedDict):
"""
Settable metadata fields for a column in a table.

Attributes:
attnum: The attnum of the column in the table.
bool_input: How the input for a boolean column should be shown.
bool_true: A string to display for `true` values.
bool_false: A string to display for `false` values.
num_min_frac_digits: Minimum digits shown after the decimal point.
num_max_frac_digits: Maximum digits shown after the decimal point.
num_show_as_perc: Whether to show a numeric value as a percentage.
mon_currency_symbol: The currency symbol shown for money value.
mon_currency_location: Where the currency symbol should be shown.
time_format: A string representing the format of time values.
date_format: A string representing the format of date values.
duration_min: The smallest unit for displaying durations.
duration_max: The largest unit for displaying durations.
duration_show_units: Whether to show the units for durations.
"""
attnum: int
bool_input: Optional[Literal["dropdown", "checkbox"]]
bool_true: Optional[str]
bool_false: Optional[str]
num_min_frac_digits: Optional[int]
num_max_frac_digits: Optional[int]
num_show_as_perc: Optional[bool]
mon_currency_symbol: Optional[str]
mon_currency_location: Optional[Literal["after-minus", "end-with-space"]]
time_format: Optional[str]
date_format: Optional[str]
duration_min: Optional[str]
duration_max: Optional[str]
duration_show_units: Optional[bool]


@rpc_method(name="columns.metadata.list")
@http_basic_auth_login_required
@handle_rpc_exceptions
Expand All @@ -91,3 +127,32 @@ def list_(*, table_oid: int, database_id: int, **kwargs) -> list[ColumnMetaData]
return [
ColumnMetaData.from_model(model) for model in columns_meta_data
]


@rpc_method(name="columns.metadata.patch")
@http_basic_auth_login_required
@handle_rpc_exceptions
def patch(
*,
column_meta_data_list: list[SettableColumnMetaData],
table_oid: int,
database_id: int,
**kwargs
) -> list[ColumnMetaData]:
"""
Alter metadata settings associated with columns of a table for a database.

Args:
column_meta_data_list: A list describing desired metadata alterations.
table_oid: Identity of the table whose metadata we'll modify.
database_id: The Django id of the database containing the table.

Returns:
List of altered metadata objects.
"""
columns_meta_data = patch_columns_meta_data(
column_meta_data_list, table_oid, database_id
)
return [
ColumnMetaData.from_model(model) for model in columns_meta_data
]
54 changes: 54 additions & 0 deletions mathesar/tests/rpc/columns/test_c_metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,57 @@ def mock_get_columns_meta_data(_table_oid, _database_id):
]
actual_metadata_list = metadata.list_(table_oid=table_oid, database_id=database_id)
assert actual_metadata_list == expect_metadata_list


# TODO consider mocking out ColumnMetaData queryset for this test
def test_columns_meta_data_patch(monkeypatch):
database_id = 2
table_oid = 123456
expect_metadata_list = [
metadata.ColumnMetaData(
database_id=database_id, table_oid=table_oid, attnum=2,
bool_input="dropdown", bool_true="TRUE", bool_false="FALSE",
num_min_frac_digits=5, num_max_frac_digits=10, num_show_as_perc=False,
mon_currency_symbol="EUR", mon_currency_location="end-with-space",
time_format=None, date_format=None,
duration_min=None, duration_max=None, duration_show_units=True,
),
metadata.ColumnMetaData(
database_id=database_id, table_oid=table_oid, attnum=8,
bool_input="checkbox", bool_true="true", bool_false="false",
num_min_frac_digits=2, num_max_frac_digits=8, num_show_as_perc=True,
mon_currency_symbol="$", mon_currency_location="after-minus",
time_format=None, date_format=None,
duration_min=None, duration_max=None, duration_show_units=True,
),
]

def mock_patch_columns_meta_data(column_meta_data_list, _table_oid, _database_id):
server_model = Server(id=2, host='example.com', port=5432)
db_model = Database(id=_database_id, name='mymathesardb', server=server_model)
return [
ColumnMetaData(
database=db_model, table_oid=_table_oid, attnum=2,
bool_input="dropdown", bool_true="TRUE", bool_false="FALSE",
num_min_frac_digits=5, num_max_frac_digits=10, num_show_as_perc=False,
mon_currency_symbol="EUR", mon_currency_location="end-with-space",
time_format=None, date_format=None,
duration_min=None, duration_max=None, duration_show_units=True,
),
ColumnMetaData(
database=db_model, table_oid=_table_oid, attnum=8,
bool_input="checkbox", bool_true="true", bool_false="false",
num_min_frac_digits=2, num_max_frac_digits=8, num_show_as_perc=True,
mon_currency_symbol="$", mon_currency_location="after-minus",
time_format=None, date_format=None,
duration_min=None, duration_max=None, duration_show_units=True,
)
]

monkeypatch.setattr(metadata, "patch_columns_meta_data", mock_patch_columns_meta_data)
actual_metadata_list = metadata.patch(
column_meta_data_list=expect_metadata_list,
table_oid=table_oid,
database_id=database_id
)
assert actual_metadata_list == expect_metadata_list
5 changes: 5 additions & 0 deletions mathesar/tests/rpc/test_endpoints.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@
"columns.metadata.list",
[user_is_authenticated]
),
(
columns.metadata.patch,
"columns.metadata.patch",
[user_is_authenticated]
),
(
connections.add_from_known_connection,
"connections.add_from_known_connection",
Expand Down
19 changes: 17 additions & 2 deletions mathesar/utils/columns.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,20 @@
from mathesar.models.base import ColumnMetaData
from mathesar.models.base import ColumnMetaData, Database


def get_columns_meta_data(table_oid, database_id):
return ColumnMetaData.filter(database__id=database_id, table_oid=table_oid)
return ColumnMetaData.objects.filter(
database__id=database_id, table_oid=table_oid
)


def patch_columns_meta_data(column_meta_data_list, table_oid, database_id):
db_model = Database.objects.get(id=database_id)
for meta_data_dict in column_meta_data_list:
# TODO decide if this is worth the trouble of doing in bulk.
ColumnMetaData.objects.update_or_create(
database=db_model,
table_oid=table_oid,
attnum=meta_data_dict["attnum"],
defaults=meta_data_dict
)
return get_columns_meta_data(table_oid, database_id)
Loading