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

RPC endpoint for column info with metadata #3703

Merged
merged 2 commits into from
Jul 24, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
7 changes: 4 additions & 3 deletions docs/docs/api/rpc.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ To use an RPC function:
- add
- patch
- delete
- list_with_metadata
- ColumnInfo
- ColumnListReturn
- CreatableColumnInfo
Expand All @@ -148,9 +149,9 @@ To use an RPC function:
options:
members:
- list_
- patch
- ColumnMetaData
- SettableColumnMetaData
- set_
- ColumnMetaDataRecord
- ColumnMetaDataBlob

## Types

Expand Down
24 changes: 24 additions & 0 deletions mathesar/rpc/columns/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@
from db.columns.operations.create import add_columns_to_table
from db.columns.operations.drop import drop_columns_from_table
from db.columns.operations.select import get_column_info_for_table
from mathesar.rpc.columns.metadata import ColumnMetaDataBlob
from mathesar.rpc.exceptions.handlers import handle_rpc_exceptions
from mathesar.rpc.utils import connect
from mathesar.utils.columns import get_columns_meta_data


class TypeOptions(TypedDict, total=False):
Expand Down Expand Up @@ -282,3 +284,25 @@ def delete(
user = kwargs.get(REQUEST_KEY).user
with connect(database_id, user) as conn:
return drop_columns_from_table(table_oid, column_attnums, conn)


@rpc_method(name="columns.list_with_metadata")
@http_basic_auth_login_required
@handle_rpc_exceptions
def list_with_metadata(*, table_oid: int, database_id: int, **kwargs) -> list:
"""
List information about columns for a table, along with the metadata associated with each column.
Args:
table_oid: Identity of the table in the user's database.
database_id: The Django id of the database containing the table.
Returns:
A list of column details.
"""
user = kwargs.get(REQUEST_KEY).user
with connect(database_id, user) as conn:
column_info = get_column_info_for_table(table_oid, conn)
column_metadata = get_columns_meta_data(table_oid, database_id)
metadata_map = {
c.attnum: ColumnMetaDataBlob.from_model(c) for c in column_metadata
}
return [col | {"metadata": metadata_map.get(col["id"])} for col in column_info]
57 changes: 35 additions & 22 deletions mathesar/rpc/columns/metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@
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, patch_columns_meta_data
from mathesar.utils.columns import get_columns_meta_data, set_columns_meta_data


class ColumnMetaData(TypedDict):
class ColumnMetaDataRecord(TypedDict):
"""
Metadata for a column in a table.

Expand Down Expand Up @@ -73,9 +73,9 @@ def from_model(cls, model):
)


class SettableColumnMetaData(TypedDict):
class ColumnMetaDataBlob(TypedDict):
"""
Settable metadata fields for a column in a table.
The metadata fields which can be set for a column in a table.

Attributes:
attnum: The attnum of the column in the table.
Expand Down Expand Up @@ -108,11 +108,30 @@ class SettableColumnMetaData(TypedDict):
duration_max: Optional[str]
duration_show_units: Optional[bool]

@classmethod
def from_model(cls, model):
return cls(
attnum=model.attnum,
bool_input=model.bool_input,
bool_true=model.bool_true,
bool_false=model.bool_false,
num_min_frac_digits=model.num_min_frac_digits,
num_max_frac_digits=model.num_max_frac_digits,
num_show_as_perc=model.num_show_as_perc,
mon_currency_symbol=model.mon_currency_symbol,
mon_currency_location=model.mon_currency_location,
time_format=model.time_format,
date_format=model.date_format,
duration_min=model.duration_min,
duration_max=model.duration_max,
duration_show_units=model.duration_show_units
)


@rpc_method(name="columns.metadata.list")
@http_basic_auth_login_required
@handle_rpc_exceptions
def list_(*, table_oid: int, database_id: int, **kwargs) -> list[ColumnMetaData]:
def list_(*, table_oid: int, database_id: int, **kwargs) -> list[ColumnMetaDataRecord]:
"""
List metadata associated with columns for a table. Exposed as `list`.

Expand All @@ -125,34 +144,28 @@ def list_(*, table_oid: int, database_id: int, **kwargs) -> list[ColumnMetaData]
"""
columns_meta_data = get_columns_meta_data(table_oid, database_id)
return [
ColumnMetaData.from_model(model) for model in columns_meta_data
ColumnMetaDataRecord.from_model(model) for model in columns_meta_data
]


@rpc_method(name="columns.metadata.patch")
@rpc_method(name="columns.metadata.set")
@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]:
def set_(
*,
column_meta_data_list: list[ColumnMetaDataBlob],
table_oid: int,
database_id: int,
**kwargs
) -> None:
"""
Alter metadata settings associated with columns of a table for a database.
Set metadata associated with columns of a table for a database. Exposed as `set`.

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(
set_columns_meta_data(
column_meta_data_list, table_oid, database_id
)
return [
ColumnMetaData.from_model(model) for model in columns_meta_data
]
58 changes: 2 additions & 56 deletions mathesar/tests/rpc/columns/test_c_metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,15 @@ def mock_get_columns_meta_data(_table_oid, _database_id):
monkeypatch.setattr(metadata, "get_columns_meta_data", mock_get_columns_meta_data)

expect_metadata_list = [
metadata.ColumnMetaData(
metadata.ColumnMetaDataRecord(
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(
metadata.ColumnMetaDataRecord(
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,
Expand All @@ -57,57 +57,3 @@ 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
9 changes: 7 additions & 2 deletions mathesar/tests/rpc/test_endpoints.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,14 +64,19 @@
"columns.add",
[user_is_authenticated]
),
(
columns.list_with_metadata,
"columns.list_with_metadata",
[user_is_authenticated]
),
(
columns.metadata.list_,
"columns.metadata.list",
[user_is_authenticated]
),
(
columns.metadata.patch,
"columns.metadata.patch",
columns.metadata.set_,
"columns.metadata.set",
[user_is_authenticated]
),
(
Expand Down
2 changes: 1 addition & 1 deletion mathesar/utils/columns.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ def get_columns_meta_data(table_oid, database_id):
)


def patch_columns_meta_data(column_meta_data_list, table_oid, database_id):
def set_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.
Expand Down
Loading