Add redis (live layers)

Add base for geo_api (WIP)
This commit is contained in:
phil 2023-12-16 00:49:01 +05:30
parent 049b8c9927
commit 4048e61221
11 changed files with 694 additions and 55 deletions

View file

@ -6,6 +6,7 @@ import importlib
import pkgutil
from collections import defaultdict
from importlib.metadata import entry_points
from typing import Any, ClassVar
from pydantic import create_model
from sqlalchemy import inspect, text
@ -19,6 +20,7 @@ from .config import conf
from .models import (misc, category as category_module,
project, reconcile, map_bases, tags)
from .models.geo_models_base import (
LiveGeoModel,
PlottableModel,
GeoModel,
RawSurveyBaseModel,
@ -68,6 +70,8 @@ class ModelRegistry:
Maintains registries for all kind of model types, eg. geom, data, values...
Provides tools to get the models from their names, table names, etc.
"""
stores: pd.DataFrame
def __init__(self):
"""
Get geo models
@ -75,6 +79,8 @@ class ModelRegistry:
"""
self.geom_custom = {}
self.geom_custom_store = {}
self.geom_live: dict[str, LiveGeoModel] = {}
self.geom_live_defs: dict[str, dict[str, Any]] = {}
self.values = {}
self.other = {}
self.misc = {}
@ -125,12 +131,11 @@ class ModelRegistry:
raw_store_name = f'{raw_survey.schema}.RAW_{category.table_name}'
raw_survey_field_definitions = {
## FIXME: RawSurveyBaseModel.category should be a Category, not category.name
'category_name': (str, category.name),
'category_name': (ClassVar[str], category.name),
## FIXME: Same for RawSurveyBaseModel.group
'group_name': (str, category.category_group.name),
'viewable_role': (str, category.viewable_role),
'store_name': (str, raw_store_name),
# 'icon': (str, ''),
'group_name': (ClassVar[str], category.category_group.name),
'viewable_role': (ClassVar[str], category.viewable_role),
'store_name': (ClassVar[str], raw_store_name),
# 'icon': (str, ''),
}
## Raw survey points
@ -142,14 +147,14 @@ class ModelRegistry:
'table': True,
'metadata': raw_survey,
'__tablename__': category.raw_survey_table_name,
## FIXME: RawSurveyBaseModel.category should be a Category, not category.name
'category_name': category.name,
## FIXME: Same for RawSurveyBaseModel.group
'group_name': category.category_group.name,
'viewable_role': category.viewable_role,
'store_name': raw_store_name,
# ## FIXME: RawSurveyBaseModel.category should be a Category, not category.name
# 'category_name': category.name,
# ## FIXME: Same for RawSurveyBaseModel.group
# 'group_name': category.category_group.name,
# 'viewable_role': category.viewable_role,
# 'store_name': raw_store_name,
},
# **raw_survey_field_definitions
**raw_survey_field_definitions
)
except Exception as err:
logger.exception(err)
@ -162,11 +167,11 @@ class ModelRegistry:
try:
if model_class:
survey_field_definitions = {
'category_name': (str, category.name),
'group_name': (str, category.category_group.name),
'raw_store_name': (str, raw_store_name),
'viewable_role': (str, category.viewable_role),
'symbol': (str, category.symbol),
'category_name': (ClassVar[str], category.name),
'group_name': (ClassVar[str], category.category_group.name),
'raw_store_name': (ClassVar[str], raw_store_name),
'viewable_role': (ClassVar[str], category.viewable_role),
'symbol': (ClassVar[str], category.symbol),
#'raw_model': (str, self.raw_survey_models.get(raw_store_name)),
# 'icon': (str, f'{survey.schema}-{category.table_name}'),
}
@ -177,13 +182,13 @@ class ModelRegistry:
'table': True,
'metadata': survey,
'__tablename__': category.table_name,
'category_name': category.name,
'group_name': category.category_group.name,
'raw_store_name': raw_store_name,
'viewable_role': category.viewable_role,
'symbol': category.symbol,
# 'category_name': category.name,
# 'group_name': category.category_group.name,
# 'raw_store_name': raw_store_name,
# 'viewable_role': category.viewable_role,
# 'symbol': category.symbol,
},
# **survey_field_definitions,
**survey_field_definitions,
)
except Exception as err:
logger.warning(err)
@ -519,13 +524,15 @@ class ModelRegistry:
row.model.mapbox_type, # or None,
row.model.base_gis_type,
row.model.z_index,
row.model.attribution,
)
# self.stores['icon'],\
# self.stores['symbol'],\
self.stores['mapbox_type_default'],\
self.stores['base_gis_type'],\
self.stores['z_index']\
self.stores['mapbox_type_default'], \
self.stores['base_gis_type'], \
self.stores['z_index'], \
self.stores['attribution'] \
= zip(*self.stores.apply(fill_columns_from_model, axis=1))
#self.stores['mapbox_type_custom'] = self.stores['mapbox_type_custom'].replace('', np.nan).fillna(np.nan)
@ -614,27 +621,61 @@ class ModelRegistry:
# return store_df.gql_object_type.to_list()
#def update_live_layers(self, live_models: List[GeomModel]):
#raise ToMigrate('make_model_gql_object_type')
def update_live_layers(self, live_models):
def update_live_layers(self):
"""
Update the live layers in the registry, using the provided list of GeomModel
Update the live layers, using the list of model definitions found in
self.geom_live_defs, which is normally updated by the redis store
"""
## Remove existing live layers
self.stores.drop(self.stores[self.stores.is_live==True].index, inplace=True)
## Add provided live layers
## Ideally, should be vectorized
for model in live_models:
self.stores.loc[model.store] = {
'description': model.description,
'group': model.group,
'name': model.name,
'gql_object_type': model,
'is_live': True,
'is_db': False,
'custom': True,
self.geom_live = {}
self.stores.drop(self.stores[self.stores.is_live == True].index, # noqa: E712
inplace=True)
df_live = pd.DataFrame.from_dict(self.geom_live_defs.values(),
orient='columns'
).set_index('store')
## Adjust column names
## and add columns, to make sure pandas dtypes are not changed when the
## dataframes are concat
## TODO: standardize names across the whole workflow,
## then remove the rename below:
df_live.rename(
columns={
'live': 'is_live',
'zIndex': 'z_index',
'gisType': 'model_type',
'type': 'mapbox_type',
'viewableRole': 'viewable_role',
}, inplace=True
)
## Add columns
df_live['auto_import'] = False
df_live['base_gis_type'] = df_live['model_type']
df_live['custom'] = False
df_live['group'] = ''
df_live['in_menu'] = True
df_live['is_db'] = False
df_live['is_line_work'] = False
df_live['long_name'] = df_live['name']
df_live['mapbox_type_custom'] = df_live['mapbox_type']
df_live['minor_group_1'] = ''
df_live['minor_group_2'] = ''
df_live['status'] = 'E'
df_live['style'] = None
df_live['title'] = df_live['name']
registry.stores = pd.concat([registry.stores, df_live])
for store, model_info in self.geom_live_defs.items():
## Add provided live layers in the stores df
# Create the pydantic model
# NOTE: Unused at this point, but might be usedful
field_definitions = {
k: (ClassVar[v.__class__], v)
for k, v in model_info.items()
}
self.geom_live[store] = create_model(
__model_name=store,
__base__= LiveGeoModel,
**field_definitions
)
# Accessible as global
registry: ModelRegistry = ModelRegistry()