Преглед на файлове

more work on dataeditor. EditorLoadFieldset now dynamically builds a subform for dynamic dataset parameterization

master
phryk преди 8 месеца
родител
ревизия
b2aa94dcb6
променени са 5 файла, в които са добавени 208 реда и са изтрити 25 реда
  1. +1
    -1
      example.py
  2. +1
    -0
      poobrains/__init__.py
  3. +3
    -3
      poobrains/form/__init__.py
  4. +10
    -0
      poobrains/form/types.py
  5. +193
    -21
      poobrains/svg/plot.py

+ 1
- 1
example.py Целия файл

@@ -184,7 +184,7 @@ class StockWeekly(poobrains.svg.plot.Dataset):

class ConstrainedRandom(poobrains.svg.plot.Dataset):

def fill(self, magnitude=2, length=16):
def fill(self, magnitude: int = 2, length: int = 16) -> None:
#app.debugger.set_trace()
magnitude, length = int(magnitude), int(length)



+ 1
- 0
poobrains/__init__.py Целия файл

@@ -131,6 +131,7 @@ class DummySession(werkzeug.datastructures.CallbackDict, flask.sessions.SessionM
modified = False
accessed = False


new_session_funcs = set()
def new_session(f):



+ 3
- 3
poobrains/form/__init__.py Целия файл

@@ -119,8 +119,9 @@ class BaseForm(poobrains.rendering.Renderable, metaclass=FormMeta):

elif isinstance(value, fields.BaseField) or isinstance(value, Fieldset):
value.name = name
value.prefix = "%s.%s" % (self.prefix, self.name) if self.prefix else self.name
self.fields[name] = value
#value.prefix = "%s.%s" % (self.prefix, self.name) if self.prefix else self.name
#self.fields[name] = value
self.add_field(value)

elif isinstance(value, Button):
value.name = name
@@ -410,7 +411,6 @@ class Fieldset(BaseForm):
self.errors = []
super(Fieldset, self).__init__(*args, **kw)


def render(self, mode=None):



+ 10
- 0
poobrains/form/types.py Целия файл

@@ -76,3 +76,13 @@ class DateTimeParamType(ParamType):
self.fail("'%s' is not a valid datetime. Expected format '%Y-%m-%d %H:%M:%S' or '%Y-%m-%d %H:%M:%S.%f'" % value)

DATETIME = DateTimeParamType()


lookup_table = {
int: IntParamType,
float: FloatParamType,
str: StringParamType,
bool: BoolParamType,
datetime.datetime: DateTimeParamType,
datetime.date: DateParamType
}

+ 193
- 21
poobrains/svg/plot.py Целия файл

@@ -3,9 +3,10 @@ import math
import time
import datetime
import json
import inspect
import pandas

from poobrains import Markup, app, request, abort, redirect, g, session, locked_cached_property, new_session
from poobrains import Markup, app, request, abort, flash, redirect, g, session, locked_cached_property, new_session

import poobrains.helpers
import poobrains.errors
@@ -27,6 +28,13 @@ def dynamic_datasets():
return datasets


#def get_dataset_parameters(dataset_name):
# """ get parameters for dynamic datasets' `fill` function """





def load_dataset(handle):
if handle.startswith('_'): # underscore marks dynamic datasets in URLs

@@ -162,7 +170,7 @@ class StoredDataset(Dataset, poobrains.commenting.Commentable):
if name == 'data':
if self._data is None:
#self._data = pandas.DataFrame.from_dict(json.loads(self.data))
self._data = pandas.DataFrame.from_dict(super(StoredDataset, self).__getattribute__('data'))
self._data = pandas.DataFrame.from_dict(json.loads(super(StoredDataset, self).__getattribute__('data')))
return self._data
return super(StoredDataset, self).__getattribute__(name)

@@ -511,7 +519,7 @@ def new_editor_handle():

handle = poobrains.helpers.random_string_light()

if 'editor-sessions' not in session or handle not in session['editor-sessions']:
if handle not in session['editor-sessions']:
return handle

return new_editor_handle()
@@ -536,51 +544,215 @@ def dataset_choices():
choices = [(dynamic, 'Dynamic Datasets'), (stored, 'Stored Datasets')]
return choices

def dynamic_dataset_parameters(dataset_class):

r = {}
signature = inspect.signature(dataset_class.fill)
for param in signature.parameters.values():

if param.name == 'self':
continue # next loop iteration

if param.annotation == param.empty:
param_type = str

else:
param_type = param.annotation

r[param.name] = param_type

return r


def validate_handle_not_in_session(handle):
if handle in session['editor-sessions']:
raise poobrains.errors.ValidationError("Editor Session named '%s' already exists!" % handle)


class EditorNewSessionFieldset(poobrains.form.Fieldset):

handle = poobrains.form.fields.Text(required=True, validators=[validate_handle_not_in_session])
#new_session = poobrains.form.Button(label='Create session', type='submit')

def process(self, submit, instance):

app.debugger.set_trace()

handle = self.fields['handle'].value

session['editor-sessions'][handle] = {
'handle': handle,
'action': None,
'action_data': None,
'data': None
}

return redirect(DataEditor.url(handle=handle, mode='full'))


class EditorLoadFieldset(poobrains.form.Fieldset):

dataset = poobrains.form.fields.Select(choices=dataset_choices)
load_dataset = poobrains.form.Button(label="Load", type="submit")
load_dataset = poobrains.form.Button(label='Load', type='submit')


def __init__(self, editor_handle, **kwargs):

app.debugger.set_trace()
datasets = dynamic_datasets()

super(EditorLoadFieldset, self).__init__(**kwargs)

self.editor_handle = editor_handle
action = session['editor-sessions'][self.editor_handle]['action']

if action.startswith('load.dynamic.'):

dataset_name = action.split('.')[2]
self.fields['dataset'].value = '_%s' % dataset_name
self.fields['dataset'].readonly = True

if dataset_name in datasets:

dataset_class = datasets[dataset_name]
self.summon_parameter_fieldset(dataset_class)


else:
flash('Unknown dynamic dataset: %s' % dataset_name, 'error')

def summon_parameter_fieldset(self, dataset_class):

subform = poobrains.form.Fieldset(name='dynamic')
params = dynamic_dataset_parameters(dataset_class)

for param_name, param_type in params.items():
param_type = poobrains.form.types.lookup_table[param_type]()
subform.add_field(poobrains.form.fields.Text(name=param_name, label=param_name, type=param_type))

subform.cancel = poobrains.form.Button(type='submit', label='Cancel')

self.add_field(subform)


def process(self, submit, instance):
if submit == '%s.%s' % (self.name, 'load_dataset'):
instance.dataset = load_dataset(self.fields['dataset'].value)
session['editor-sessions'][instance.handle_string] = instance.dataset.data.to_dict()

app.debugger.set_trace()

datasets = dynamic_datasets()
action = session['editor-sessions'][self.editor_handle]['action']
dataset_name = self.fields['dataset'].value
if action == 'load':
if submit == '%s.load_dataset' % self.name:

if dataset_name.startswith('_'):

dataset_name = dataset_name[1:]
if not dataset_name in datasets:
flash('Unknown dynamic dataset: %s' % dataset_name, 'error')
else:
session['editor-sessions'][instance.handle_string]['action'] = 'load.dynamic.%s' % dataset_name
self.summon_parameter_fieldset(datasets[dataset_name])
self.fields['dataset'].readonly = True
else: # directly loadable dataset

try:
dataset = StoredDataset.load(dataset_name)
dataset.permissions['read'].check(g.user)
instance.dataset = dataset
session['editor-sessions'][instance.handle_string]['data'] = instance.dataset.data.to_dict()
session['editor-sessions'][instance.handle_string]['action'] = None
except StoredDataset.DoesNotExist:
flash('Unknown stored dataset: %s' % dataset_name, 'error')

if action.startswith('load.dynamic.'):

if submit == '%s.dynamic.cancel' % self.name:
session['editor-sessions'][instance.handle_string]['action'] = 'load'
del(self.fields['dynamic']) # actively remove the fieldset so it doesn't get rendered in the response directly to this request
self.fields['dataset'].readonly = False

elif submit == '%s.load_dataset' % self.name:

dataset_name = dataset_name[1:]
dataset_class = datasets[dataset_name]
params = dynamic_dataset_parameters(dataset_class)

param_values = {}
for param_name in params:
if param_name in self.fields['dynamic'].fields:
param_values[param_name] = self.fields['dynamic'].fields[param_name].value

if len(param_values) == len(params):

dataset = dataset_class()
dataset.fill(**param_values)

dataset.permissions['read'].check(g.user)
instance.dataset = dataset
session['editor-sessions'][instance.handle_string]['data'] = instance.dataset.data.to_dict()
session['editor-sessions'][instance.handle_string]['action'] = None
del(self.fields['dynamic'])
self.fields['dataset'].readonly = False

else:
flash('Incomplete parameters for dynamic dataset %s!' % dataset_name, 'error')


@app.expose('/svg/plot/editor/', force_secure=True)
class DataEditor(poobrains.auth.ProtectedForm):

save_dataset = poobrains.form.Button(label="Save", type="submit")

def __init__(self, handle=None, mode=None, **kwargs):

app.debugger.set_trace()
super(DataEditor, self).__init__(handle=handle, mode=mode, **kwargs)
self.dataset = None
#self.fields['load_fieldset'] = EditorLoadFieldset(prefix=self.name, name='load_fieldset')
self.add_field(EditorLoadFieldset())
self.menu_actions = poobrains.rendering.Menu('data-editor-sessions', title='Editor sessions')
for editor_session_id in session['editor-sessions'].keys():
self.menu_actions.append(self.__class__.url(mode='full', handle=editor_session_id), editor_session_id)


@poobrains.helpers.themed
def view(self, mode='full', **kwargs):
if not self.handle_string or not self.handle_string in session['editor-sessions']: # new editor session
self.add_field(EditorNewSessionFieldset(self.handle_string))

if not self.handle_string:
return redirect(type(self)(handle=new_editor_handle()).url('full'))
else:

if self.handle_string in session:
#self.dataset = session[self.handle_string]
editor_session = session['editor-sessions'][self.handle_string]
self.dataset = Dataset()
self.dataset.data = pandas.DataFrame.from_dict(session['editor-sessions'][self.handle_string])
self.dataset.data = pandas.DataFrame.from_dict(editor_session['data'])

if editor_session['action'] is None:
editor_session['action'] = 'load'

if editor_session['action'].startswith('load'):
self.add_field(EditorLoadFieldset(self.handle_string))


return poobrains.helpers.ThemedPassthrough(super(DataEditor, self).view(mode=mode, **kwargs))
#@poobrains.helpers.themed
#def view(self, mode='full', **kwargs):

#if not self.handle_string:
# return redirect(type(self)(handle=new_editor_handle()).url('full'))

#if self.handle_string and self.handle_string in session:
# #self.dataset = session[self.handle_string]
# self.dataset = Dataset()
# self.dataset.data = pandas.DataFrame.from_dict(session['editor-sessions'][self.handle_string])

#return poobrains.helpers.ThemedPassthrough(super(DataEditor, self).view(mode=mode, **kwargs))


def process(self, submit):

if submit.startswith('EditorLoadFieldset.'):
app.debugger.set_trace()
if submit.startswith('EditorNewSessionFieldset.'):
return self.fields['EditorNewSessionFieldset'].process(submit, self)

elif submit.startswith('EditorLoadFieldset.'):
self.fields['EditorLoadFieldset'].process(submit, self)
#session[self.handle_string] = self.data



Loading…
Отказ
Запис