How to input via gradio dropdowns using variable information stored in a data frame? - dataframe

I'm trying to input info from an easily editable CSV file where the first row contains the variable names. I am doing this by iterating over the list of variables so each variable is a new dropdown. Using this method everything appears correctly in the interface but something is going wrong when it comes to outputting the selected values. I'm thinking I need another approach but I can't think how to do it short of generating a new gradio interface for each dropdown.
the following code hangs when you click submit:
import gradio as gr
import pandas as pd
df = pd.read_csv(file_path)
# first row of the CSV as the variable names
variables = list(df.columns)
# filter out null values
df = df.dropna()
# rest of the rows as the options for each variable
options = {var: list(df[var]) for var in variables}
def assign_values(**kwargs):
global save_variables
save_variables.update(kwargs)
return kwargs
save_variables = {}
inputs = [gr.inputs.Dropdown(label=var, choices=options[var], type="value") for var in variables]
outputs = ["text"]
gr.Interface(fn=assign_values, inputs=inputs, outputs=outputs, title="Assign Values").launch()

Related

Return elements in SQLAlchemy AppenderBaseQuery object to Flask-WTForm field

I am working on the "edit" functionality for a form. When the form is rendered, the fields should populate with data that is stored in the database. One of this field is returned as a SQlAlchemy AppenderBaseQuery object. This causes a query statement to be pre-populated in the field, instead of the results of the query.
How do I pre-populate the form with elements in the object instead?
form = MyForm(obj=MyObject)
if form.validate_on_submit():
form.populate_obj(MyObject)
The field is defined as a StringField.
Note:
I am passing MyObject to pre-populate the form because there is a thing with WTForm where form.Field.data does not get updated at all.
form = MyForm()
form.Field.data = "test" #Pre-populate Field with "test"
if validate_on_submit():
MyObject.Field = Form.Field.data #Assign data in Field to MyObject
#...
My Object.Field will not be updated with the new Form.Field.data, not sure why.
As suggested by n-Holmes in the comments:
# Do not initiate the form with object
form = MyForm()
# Split logic to 'GET' and 'POST request'
if request.method == 'GET'
MyForm.Field.Data = ', '.join([element.attribute for element in MyForm.Field.all()]
# MyForm.Field is an AppenderBaseQuery Object >> Returns a query statement
# MyForm.Field.all() returns a list of Objects
# The list comprehension returns a list of a specific attribute for each object
# The .join combines the list to a string, separated by ", "
# This entire thing is pre-populated onto the form
# Eg: "Attribute01, Attribute02, Attribute03"
if validate_on_submit:
MyObject.Field = FunctionToUpdateField(form.Field.data)
# form.Field.data will be a string
# FunctionToUpdateField compares above string with what is stored in db ...
# determines which elements to add / remove

How to correct filter fields domain in a model?

I'm getting the following error trying to filter a field by another field value of the same model.
File
"/opt/..../tfutbol/models/partido.py",
line 29, in Partido
figura = fields.Many2one('tfutbol.jugador',domain=[('equipo_id','=',local.id)])
RuntimeError: maximum recursion depth exceeded while calling a Python
object
The line of code trying with the problem is:
figura = fields.Many2one('tfutbol.jugador',domain=[('equipo_id','=',local.id),('equipo_id','=',visitante.id)])
All the relevant code, is above:
class Partido(models.Model):
_name = 'tfutbol.partido'
local = fields.Many2one('tfutbol.equipo')
visitante = fields.Many2one('tfutbol.equipo')
figura = fields.Many2one('tfutbol.jugador',domain=[('equipo_id','=',local.id),('equipo_id','=',visitante.id)])
class Equipo(models.Model):
_name = 'tfutbol.equipo'
name = fields.Char('Nombre')
jugador_ids = fields.One2many('tfutbol.jugador', 'equipo_id', string="Jugadores")
class Jugador(models.Model):
_name = 'tfutbol.jugador'
name = fields.Char('Nombre')
equipo_id = fields.Many2one('tfutbol.equipo')
Thanks for reading!
If you read the docstring on /odoo/fields.py on the Many2one class definition you will see that:
:param domain: an optional domain to set on candidate values on the
client side (domain or string)
That means that you cannot use the dot notation (record.field) to pull in values because this has not been implemented on javascript.
So what you can do to dynamically create a domain like the one you want is:
Create an onchange method that will be invoked every time you set a value on the local and visitante fields and will change the domain on the figura field. For example:
#api.onchange('figura','visitante')
def onchange_method(self):
domain = {}
domain['figura'] = [('equipo_id','=',self.local.id),('equipo_id','=',self.visitante.id)]
return {'domain': domain}
Note: When you do not set an operator in a domain with multiple leafs (parameters) an explicit AND is added, so in your domain you are searching for the equipo_id filed to be equal to self.local.id AND self.visitante.id which will not work, you might want to add an OR like:
['|',('equipo_id','=',self.local.id),('equipo_id','=',self.visitante.id)]

scrapy single spider to pass multiple item classes to pipeline

I am new to scrapy. In items.py, I declare 2 ItemClass called ItemClass1 and ItemClass2. A spider method parseUrl get the html and scrape data and put into lists for respective Item Classes.
e.g:
C1Items = []
C1Item = ItemClass1()
#scrape data
C1Items.append(C1Item)
...
C2Items = []
C2Item = ItemClass2()
#scrape data
C2Items.append(C2Item)
...
finally: C1Items and C2Items contain required data.
return C1Items #will pass ItemClass1 data to pipeline
return C2Items #will pass ItemClass2 data to pipeline
Could you please advise what is the best way to pass both C1Items, C2Items to pipeline.
Either combine all the items of different classes into one list and return that list, or use yield statement:
C1Item = ItemClass1()
#scrape data
yield C1Item
...
C2Item = ItemClass2()
#scrape data
yield C2Item
Just combine the arrays into one big array and return that:
return C1Items + C2Items
or alternatively you could turn parseUrl into a generator function with:
yield C1Items
yield C2Items

Import a dictionary into the current scope as variables

I have a .mat file in which I put data previously processed. When I perform
dict = scipy.io.loadmat('training_data.mat')
I get back a dict that is like this
{'encoders' : ......, 'decoders' : ........, 'stuff' : .....}
I want to selectively import the encoders and decoders variables into my current scope. The effect is the same as:
encoders = dict['encoders']
decoders = dict['decoders']
How do I cleanly do this without typing 10-15 lines?
You could import a dictionary d into the global scope using
globals().update(d)
The same thing is impossible for local scopes, since modifying the dictionary returned by locals() results in undefined behaviour.
A slightly hacky trick you could use in this situation is to import the names into the dictionary of an on-the-fly created type:
d = {"encoders": 1, "decoders": 2}
t = type("", (), d)
print t.encoders
print t.decoders
This will at least be slightly more convenient than using d["decoders"] etc.
Alternatively, you could use exec statements to create your variables:
d = {"encoders": 1, "decoders": 2}
for k, v in d.iteritems():
exec k + " = v"
This could also be done selectively.

Add extra field in Django QuerySet as timedelta type

I have the following model:
class UptimeManager(models.Manager):
def with_length(self):
"""Get querySet of uptimes sorted by length including the current one. """
extra_length = Uptime.objects.extra(select={'length':
"""
SELECT
IF (end is null,
timestampdiff(second,begin,now()),
timestampdiff(second,begin,end))
FROM content_uptime c
WHERE content_uptime.id = c.id
"""
})
return extra_length
class Uptime(models.Model):
begin = models.DateTimeField('beginning')
end = models.DateTimeField('end', null=True) I call
host = models.ForeignKey("Host")
objects = UptimeManager()
...
then I call Uptime.objects.with_length().order_by('-length')[:10] to get list of longest uptimes.
But the length in template is of integer type. How to modify my code as the length of object returned by manager would be accessible in template as timedelta object?
I almost could do it by returning a list and converting number of seconds to timedelta objects, but then I have to do sorting, filtering etc. in my Python code which is rather ineffective in comparison to one well done SQL query.
Add a property to the model that looks at the actual field and converts it to the appropriate type.
My solution is to create a filter that determines type of length var and returns timedelta in case it's some integer type
from django import template
import datetime
register = template.Library()
def timedelta(value):
if isinstance(value, (long,int)):
return datetime.timedelta(seconds=value)
elif isinstance(value, datetime.timedelta):
return value
else: raise UnsupportedOperation
register.filter('timedelta',timedelta)
and use in template it's trivial
{{ uptime.length|timedelta }}