Python list add variables in rows - python-3.x

im trying to add variables to a list that i created. Got a result from a session.execute.
i´ve done this:
def machine_id(session, machine_serial):
stmt_raw = '''
SELECT
id
FROM
machine
WHERE
machine.serial = :machine_serial_arg
'''
utc_now = datetime.datetime.utcnow()
utc_now_iso = pytz.utc.localize(utc_now).isoformat()
utc_start = datetime.datetime.utcnow() - datetime.timedelta(days = 30)
utc_start_iso = pytz.utc.localize(utc_start).isoformat()
stmt_args = {
'machine_serial_arg': machine_serial,
}
stmt = text(stmt_raw).columns(
#ts_insert = ISODateTime
)
result = session.execute(stmt, stmt_args)
ts = utc_now_iso
ts_start = utc_start_iso
ID = []
for row in result:
ID.append({
'id': row[0],
'ts': ts,
'ts_start': ts_start,
})
return ID
In trying to get the result over api like this:
def form_response(response, session):
result_machine_id = machine_id(session, machine_serial)
if not result_machine_id:
response['Error'] = 'Seriennummer nicht vorhanden/gefunden'
return
response['id_timerange'] = result_machine_id
Output looks fine.
{
"id_timerange": [
{
"id": 1,
"ts": "2020-08-13T08:32:25.835055+00:00",
"ts_start": "2020-07-14T08:32:25.835089+00:00"
}
]
}
Now i only want the id from it as a parameter for another function. Problem is i think its not a list. I cant select the first element. result_machine_id[0] result is like the posted Output. I think in my first function i only add ts & ts_start to the first row? Is it possible to add emtpy rows and then add 'ts':ts as value?
Help would be nice

If I have understood your question correctly ...
Your output looks like dict. so access its id_timerange key which gives you a list. Access the first element which gives you another dict. On this dict you have an id key:
result_machine_id["id_timerange"][0]["id"]

Related

Create sublist from list

I have following list named svc_tk_input
['4505/tcp', '4506/tcp', '80/tcp', '4505/udp', '4506/udp', '80/udp']
and i have following service so defined:
svc_a = [port_x/udp]
svc_b = [port_y/tcp]
svc_c = [port_x/udp, port_x/tcp]
svc_d = [port_x/tcp, port_x/udp]
svc_e = [port_y/udp, port_y/tcp]
svc_f = [port_y/tcp, port_y/udp]
svc_g = [port_x/tcp, port_y/tcp]
svc_h = [port_x/udp, port_y/udp]
svc_i = [port_y/tcp, port_x/tcp]
svc_l = [port_y/udp, port_x/udp]
svc_m = [port_x/tcp, port_y/udp]
svc_n = [port_x/udp, port_y/tcp]
svc_o = [port_y/tcp, port_x/udp]
svc_p = [port_y/udp, port_x/tcp]
Final target is to see if any service is defined given the port/protocol in svc_tk_input.
Idea:
create a second list svc_tk_input_mod
svc_tk_input_mod list has all combination of input port/protocol
svc_tk_input_mod = [('4505/tcp'), ('4505/udp'), ('4506/tcp'), ('4506/udp'),...,('4505/tcp' ,'4505/udp'), ('4505/tcp' ,'80/udp'),... ]
check at the end if any service is defined (out of scope here and this part is already covered)
I try to create the list svc_tk_input_mod by using itertools permutations but list that i get contains such combination
[('4505/tcp', '4506/tcp', '4505/udp', '4506/udp'), ('4505/tcp', '4506/tcp', '4506/udp', '4505/udp'), ('4505/tcp', '4505/udp', '4506/tcp', '4506/udp'), (...)]
As you can see each single element never can match the definition of service (service is a list of max 2 element)
Any suggestion on how can i improve the above?
Update here my code
list_protocols = str(policy_dict[term_name]["protocol"]).split(",") # (udp tcp)
list_ports = str(policy_dict[term_name][port_item]).split(",") # (53, 22, 1024-65535)
svc_tk_val_input = [ ]
svc_tk_val_input = build_svc_tk_val_input.build_svc_tk_val(list_protocols, list_ports,svc_tk_val_input)
svc_tk_val_input_permutation = [ ]
svc_tk_val_input_permutation = build_svc_tk_val_input.build_svc_tk_val_permutation(svc_tk_val_input, svc_tk_val_input_permutation)
svc_tk_val_input_permutation_2 = [ ]
if len(list_ports)>2:
svc_tk_val_input_permutation_2 =
build_svc_tk_val_input.build_svc_tk_val_permutation_with_len(svc_tk_val_input, svc_tk_val_input_permutation,2)
def build_svc_tk_val(list_protocols, list_ports,svc_tk_val_input):
for protocol in list_protocols:
for port in list_ports:
ppp_item = port+"/"+protocol
print(ppp_item)
# Token that we want
svc_tk_val_input.append(ppp_item)
return svc_tk_val_input
def build_svc_tk_val_permutation(svc_tk_val_input,svc_tk_val_input_permutation):
svc_tk_val_permutation = permutations(svc_tk_val_input)
for svc_tk_id_item_permutation in list(svc_tk_val_permutation):
#print(f"Combination {svc_tk_id_item_permutation}")
svc_tk_val_input_permutation.append(svc_tk_id_item_permutation)
return svc_tk_val_input_permutation
def build_svc_tk_val_permutation_with_len(svc_tk_val_input,svc_tk_val_input_permutation,permutation_len):
svc_tk_val_permutation = permutations(svc_tk_val_input,permutation_len)
for svc_tk_id_item_permutation in list(svc_tk_val_permutation):
#print(f"Combination {svc_tk_id_item_permutation}")
svc_tk_val_input_permutation.append(svc_tk_id_item_permutation)
return svc_tk_val_input_permutation

write attribute_line_ids in product.tempate in odoo 12

i am getting fields data from xls file and creating product
everything work fine except one2many field of variant in product.template
how can i achieve this.
here is my code.
main_product = self.env["product.template"].create(product_data)
attribute_ids = self.env["product.attribute"].search([])
attrib_id_set = set(ids.name for ids in attribute_ids)
product_attrib_ids = sheet.cell(suits, 13).value.split(",")
attrib_id_list = []; exist_attribute_list = []
for name in product_attrib_ids:
if name not in attrib_id_set:
attrib_id = self.env["product.attribute"].create({'name':name})
attrib_id_list.append(attrib_id)
else:
exist_attribute = self.env["product.attribute"].search([('name','=',name)])
exist_attribute_list.append(exist_attribute)
union_list = list(set(attrib_id_list).union(exist_attribute_list))
exist_attribute_values = self.env["product.attribute.value"].search([])
exist_attrib_val_list = [attrib_name.name for attrib_name in exist_attribute_values]
product_attrib_id_values = sheet.cell(suits, 14).value.split(",")
for value in product_attrib_id_values:
if value not in exist_attrib_val_list:
for ids in union_list:
attrib_value_id = self.env["product.attribute.value"].create({
'attribute_id':ids.id,
'name':value
})
main_product.write({
'attribute_line_ids':[(0,0,{
'attribute_id':ids.id, 'value_ids':(4,attrib_value_id.id)
})]
})
product_data is my dictionary for fields like name,sale_ok,type,catag_id etc.
this works, product is created, attribute_id and attribute values even works
but i can not write one2many of variant in product.template.
--EDIT--
values_lst=[]
for value in product_attrib_id_values:
if value not in exist_attrib_val_list:
for ids in union_list:
attrib_value_id = self.env["product.attribute.value"].create({
'attribute_id':ids.id,
'name':value
})
else:
for ids in exist_attribute_values:
if value == ids.name:
attrib_value_id =self.env["product.attribute.value"].browse(ids.id)
if attrib_value_id not in values_lst:
values_lst.append(attrib_value_id)

Server side previous page call not working

I configured the server-side processing of datatables. On the server side I use python3 and mongodb.
I think my paging logic is good as you can see from the code:
PYTHON:
#bp.route('/_ajax_products', methods=['GET', 'POST'])
#login_required
def ajax_products():
num = int(request.args.get('page_num')) + 1
total_items = product_db.count()
items_to_show = 100
result = {"draw": num, "recordsTotal": total_items, "recordsFiltered": total_items}
list_prod = product_db.find().sort([("Code", 1)]).skip(items_to_show * (num - 1)).limit(items_to_show)
final_list = []
for i in list_prod:
# iteration on products and addition to the final list
result['data'] = final_list
return jsonify(result)
DATATABLE INITIALISATION:
$('#ProductsList').DataTable({
"dom": 'Brlf<t><"clear">p',
"pageLength": 100,
select: true,
"processing": true,
"serverSide": true,
"ajax": {
url:"/_ajax_products",
data: function ( d ) {
var datatable = $('#ProductsList').DataTable();
var currentPage = datatable.page.info().page;
d.page_num = currentPage;
}
},
"columns":[...]
...
})
The data loads well in my datatable. When I call the next page either there is no problem.
The problem appears when I call a previous page.
The display starts on page 1. when I press for example the pagination button 3, I can see in my console:
"GET /_ajax_products?draw=3&
But when I try to go back to page 1, the draw parameter goes to 4:
"GET /_ajax_products?draw=4&
... and it continues to increment.
On the server side the good data are found but they are not displayed in the datatable.
How can I solve this problem?
I finally found a solution. The error came from a misunderstanding of what the draw option was doing.
Indeed I thought that the value of draw corresponded to the page to be displayed, which is not the case.
Here is the new version of the code in case it can help someone:
#bp.route('/_ajax_products', methods=['GET', 'POST'])
#login_required
def ajax_products():
num = int(request.args.get('page_num')) + 1
total_items = product_db.count()
items_to_show = 100
result = {"recordsTotal": total_items, "recordsFiltered": total_items}
list_prod = product_db.find().sort([("Code", 1)]).skip(items_to_show * (num - 1)).limit(items_to_show)
final_list = []
for i in list_prod:
# iteration on products and addition to the final list
result['data'] = final_list
return jsonify(result)

Updating multiple line plots dynamically in callback in bokeh

I have a use case where I have multiple line plots (with legends), and I need to update the line plots based on a column condition. Below is an example of two data set, based on the country, the column data source changes. But the issue I am facing is, the number of columns is not fixed for the data source, and even the types can vary. So, when I update the data source based on a callback when there is a new country selected, I get this error:
Error: attempted to retrieve property array for nonexistent field 'pay_conv_7d.content'.
I am guessing because in the new data source, the pay_conv_7d.content column doesn't exist, but in my plot those lines were already there. I have been trying to fix this issue by various means (making common columns for all country selection - adding the missing column in the data source in callback, but still get issues.
Is there any clean way to have multiple line plots updating using callback, and not do a lot of hackish way? Any insights or help would be really appreciated. Thanks much in advance! :)
def setup_multiline_plots(x_axis, y_axis, title_text, data_source, plot):
num_categories = len(data_source.data['categories'])
legends_list = list(data_source.data['categories'])
colors_list = Spectral11[0:num_categories]
# xs = [data_source.data['%s.'%x_axis].values] * num_categories
# ys = [data_source.data[('%s.%s')%(y_axis,column)] for column in data_source.data['categories']]
# data_source.data['x_series'] = xs
# data_source.data['y_series'] = ys
# plot.multi_line('x_series', 'y_series', line_color=colors_list,legend='categories', line_width=3, source=data_source)
plot_list = []
for (colr, leg, column) in zip(colors_list, legends_list, data_source.data['categories']):
xs, ys = '%s.'%x_axis, ('%s.%s')%(y_axis,column)
plot.line(xs,ys, source=data_source, color=colr, legend=leg, line_width=3, name=ys)
plot_list.append(ys)
data_source.data['plot_names'] = data_source.data.get('plot_names',[]) + plot_list
plot.title.text = title_text
def update_plot(country, timeseries_df, timeseries_source,
aggregate_df, aggregate_source, category,
plot_pay_7d, plot_r_pay_90d):
aggregate_metrics = aggregate_df.loc[aggregate_df.country == country]
aggregate_metrics = aggregate_metrics.nlargest(10, 'cost')
category_types = list(aggregate_metrics[category].unique())
timeseries_df = timeseries_df[timeseries_df[category].isin(category_types)]
timeseries_multi_line_metrics = get_multiline_column_datasource(timeseries_df, category, country)
# len_series = len(timeseries_multi_line_metrics.data['time.'])
# previous_legends = timeseries_source.data['plot_names']
# current_legends = timeseries_multi_line_metrics.data.keys()
# common_legends = list(set(previous_legends) & set(current_legends))
# additional_legends_list = list(set(previous_legends) - set(current_legends))
# for legend in additional_legends_list:
# zeros = pd.Series(np.array([0] * len_series), name=legend)
# timeseries_multi_line_metrics.add(zeros, legend)
# timeseries_multi_line_metrics.data['plot_names'] = previous_legends
timeseries_source.data = timeseries_multi_line_metrics.data
aggregate_source.data = aggregate_source.from_df(aggregate_metrics)
def get_multiline_column_datasource(df, category, country):
df_country = df[df.country == country]
df_pivoted = pd.DataFrame(df_country.pivot_table(index='time', columns=category, aggfunc=np.sum).reset_index())
df_pivoted.columns = df_pivoted.columns.to_series().str.join('.')
categories = list(set([column.split('.')[1] for column in list(df_pivoted.columns)]))[1:]
data_source = ColumnDataSource(df_pivoted)
data_source.data['categories'] = categories
Recently I had to update data on a Multiline glyph. Check my question if you want to take a look at my algorithm.
I think you can update a ColumnDataSource in three ways at least:
You can create a dataframe to instantiate a new CDS
cds = ColumnDataSource(df_pivoted)
data_source.data = cds.data
You can create a dictionary and assign it to the data attribute directly
d = {
'xs0': [[7.0, 986.0], [17.0, 6.0], [7.0, 67.0]],
'ys0': [[79.0, 69.0], [179.0, 169.0], [729.0, 69.0]],
'xs1': [[17.0, 166.0], [17.0, 116.0], [17.0, 126.0]],
'ys1': [[179.0, 169.0], [179.0, 1169.0], [1729.0, 169.0]],
'xs2': [[27.0, 276.0], [27.0, 216.0], [27.0, 226.0]],
'ys2': [[279.0, 269.0], [279.0, 2619.0], [2579.0, 2569.0]]
}
data_source.data = d
Here if you need different sizes of columns or empty columns you can fill the gaps with NaN values in order to keep column sizes. And I think this is the solution to your question:
import numpy as np
d = {
'xs0': [[7.0, 986.0], [17.0, 6.0], [7.0, 67.0]],
'ys0': [[79.0, 69.0], [179.0, 169.0], [729.0, 69.0]],
'xs1': [[17.0, 166.0], [np.nan], [np.nan]],
'ys1': [[179.0, 169.0], [np.nan], [np.nan]],
'xs2': [[np.nan], [np.nan], [np.nan]],
'ys2': [[np.nan], [np.nan], [np.nan]]
}
data_source.data = d
Or if you only need to modify a few values then you can use the method patch. Check the documentation here.
The following example shows how to patch entire column elements. In this case,
source = ColumnDataSource(data=dict(foo=[10, 20, 30], bar=[100, 200, 300]))
patches = {
'foo' : [ (slice(2), [11, 12]) ],
'bar' : [ (0, 101), (2, 301) ],
}
source.patch(patches)
After this operation, the value of the source.data will be:
dict(foo=[11, 22, 30], bar=[101, 200, 301])
NOTE: It is important to make the update in one go to avoid performance issues

Need to Update XML Tag value at run time

In the code below I'm trying to update one of the tag value. My problem is that which tag value I need to update, I know only at run time.
Below code does not work to update the tag value even though I'm able to get the tag value by this code.
def temp1="""
<TradeRecord>
<TradeId>1000</TradeId>
<SecurityId>10382456</SecurityId>
<TradeType>SELLL</TradeType>
<TradeDate>2014-03-21</TradeDate>
<Broker>100</Broker>
<Exchange>1</Exchange>
<Status>INIT</Status>
<Quantity>12765</Quantity>
<ApprovedBy />
</TradeRecord>
"""
def records = new XmlParser().parseText(temp1)
childRecords = records.children()
j = childRecords.size()
def tagname = 'Quantity'
for (int i=0; i<j; i++){
if (childRecords[i].name() == tagname) {
log.info childRecords[i].text()
childRecords[i].text() = "9999"
log.info childRecords[i].text()
}
}
You can not assign to the text()-getter, but there is the value, which has a setter; e.g.:
childRecords[i].value = "9999"
But this also can be done more groovy:
def temp1="""
<TradeRecord>
<TradeId>1000</TradeId>
<SecurityId>10382456</SecurityId>
<TradeType>SELLL</TradeType>
<TradeDate>2014-03-21</TradeDate>
<Broker>100</Broker>
<Exchange>1</Exchange>
<Status>INIT</Status>
<Quantity>12765</Quantity>
<ApprovedBy />
</TradeRecord>
"""
def records = new XmlParser().parseText(temp1)
final tagname = 'Quantity'
records."$tagname".each{
it.value = '9999'
}
println groovy.xml.XmlUtil.serialize(records)

Resources