fastapi multiple select in open api parameter - fastapi

Is it possible to add multiple select for a dropdown in fastapi openapi?
I only manage to select one.
if I set Optional[List] it wont run, the enum?).
if I set {[ids]}in the routes openapi says it is a array and no dropdown.
#app.get("/schedules")
#app.get("/schedules/{ids}", include_in_schema=False)
#app.get("/schedules/{ids}/{active}")
async def GetScedules(
ids:Optional[str]=Query(None, enum=[str(id) for id in appconfig['projectids']]),
active:Optional[str]=Query(None, enum=["active", "notactive"])):
""" list gitlab schedules sorted on projectids """
if isinstance(ids, str): # convert str to list
if ',' in ids:
ids = ids.split(',')
else:
ids = [ids]

Related

Is there a way to input multiple environment variables into a url for testing on Postman?

I am testing an endpoint in Postman using a url like this, {{api_url}}/stackoverflow/help/{{customer_id}}/{{client_id}}.
I have the api_url, customer_id, and client_id stored in my environment variables. I would like to test multiple customer_id and client_id without having to change the environment variables manually each time. I created a csv to store a list of customer_id and one to store client_id. When I go to run collection, it will only allow me to add one file. Is there another way to do this if I want to iterate through my tests to automate them?
You can add both customer_id & client_id in one csv file. Postman will iterate n times (n = number of csv lines, except header)
you can use postman.setNextRequest to control the flow. The below code runs the request with different values in the arr variable
url:
{{api_url}}/stackoverflow/help/{{customer_id}}/{{client_id}}
now add pre-request:
// add values for the variable in an array
const tempArraycustomer_id = pm.variables.get("tempArraycustomer_id")
const tempArrayclient_id = pm.variables.get("tempArrayclient_id")
//modify the array to the values you want
const arrcustomer_id = tempArraycustomer_id ? tempArraycustomer_id : ["value1", "value2", "value3"]
const arrclient_id = tempArrayclient_id ? tempArrayclient_id : ["value1", "value2", "value3"]
// testing variable to each value of the array and sending the request until all values are used
pm.variables.set("customer_id", arrcustomer_id.pop())
pm.variables.set("client_id", arrclient_id.pop())
pm.variables.set("tempArraycustomer_id", arrcustomer_id)
pm.variables.set("tempArrayclient_id", arrclient_id)
//end iteration when no more elements are there
if (arrcustomer_id.length !== 0) {
postman.setNextRequest(pm.info.requestName)
}

Airflow: How to push xcom value from BigQueryOperator?

This is my operator:
bigquery_check_op = BigQueryOperator(
task_id='bigquery_check',
bql=SQL_QUERY,
use_legacy_sql = False,
bigquery_conn_id=CONNECTION_ID,
trigger_rule='all_success',
xcom_push=True,
dag=dag
)
When I check the Render page in the UI. Nothing appears there.
When I run the SQL in the console it return value 1400 which is correct.
Why the operator doesn't push the XCOM?
I can't use BigQueryValueCheckOperator. This operator is designed to FAIL against a check of value. I don't want nothing to fail. I simply want to branch the code based on the return value from the query.
Here is how you might be able to accomplish this with the BigQueryHook and the BranchPythonOperator:
from airflow.operators.python_operator import BranchPythonOperator
from airflow.contrib.hooks import BigQueryHook
def big_query_check(**context):
sql = context['templates_dict']['sql']
bq = BigQueryHook(bigquery_conn_id='default_gcp_connection_id',
use_legacy_sql=False)
conn = bq.get_conn()
cursor = conn.cursor()
results = cursor.execute(sql)
# Do something with results, return task_id to branch to
if results == 0:
return "task_a"
else:
return "task_b"
sql = "SELECT COUNT(*) FROM sales"
branching = BranchPythonOperator(
task_id='branching',
python_callable=big_query_check,
provide_context= True,
templates_dict = {"sql": sql}
dag=dag,
)
First we create a python callable that we can use to execute the query and select which task_id to branch too. Second, we create the BranchPythonOperator.
The simplest answer is because xcom_push is not one of the params in BigQueryOperator nor BaseOperator nor LoggingMixin.
The BigQueryGetDataOperator does return (and thus push) some data but it works by table and column name. You could chain this behavior by making the query you run output to a uniquely named table (maybe use {{ds_nodash}} in the name), and then use the table as a source for this operator, and then you can branch with the BranchPythonOperator.
You might instead try to use the BigQueryHook's get_conn().cursor() to run the query and work with some data inside the BranchPythonOperator.
Elsewhere we chatted and came up with something along the lines of this for putting in the callable of a BranchPythonOperator:
cursor = BigQueryHook(bigquery_conn_id='connection_name').get_conn().cursor()
# one of these two:
cursor.execute(SQL_QUERY) # if non-legacy
cursor.job_id = cursor.run_query(bql=SQL_QUERY, use_legacy_sql=False) # if legacy
result=cursor.fetchone()
return "task_one" if result[0] is 1400 else "task_two" # depends on results format

Scrapy Data Table extract

I am trying to scrape "https://www.expireddomains.net/deleted-com-domains/"
for the expired domain data list.
I always get empty item fields for the following
class ExpiredSpider(BaseSpider):
name = "expired"
allowed_domains = ["example.com"]
start_urls = ['https://www.expireddomains.net/deleted-com-domains/']
def parse(self, response):
log.msg('parse(%s)' % response.url, level = log.DEBUG)
rows = response.xpath('//table[#class="base1"]/tbody/tr')
for row in rows:
item = DomainItem()
item['domain'] = row.xpath('td[1]/text()').extract()
item['bl'] = row.xpath('td[2]/text()').extract()
yield item
Can somebody point out what is wrong? Thanks.
As a first note, you should use scrapy.Spider instead of BaseSpider which is deprecated
Secondly, .extract() method returns a list rather than a single element.
This is how the item extraction should look like
item['domain'] = row.xpath('td[1]/text()').extract_first()
item['bl'] = row.xpath('td[2]/text()').extract_first()
Also,
You should use the built in python logging library
import logging
logging.debug("parse("+response.url+")")

What's wrong with my filter query to figure out if a key is a member of a list(db.key) property?

I'm having trouble retrieving a filtered list from google app engine datastore (using python for server side). My data entity is defined as the following
class Course_Table(db.Model):
course_name = db.StringProperty(required=True, indexed=True)
....
head_tags_1=db.ListProperty(db.Key)
So the head_tags_1 property is a list of keys (which are the keys to a different entity called Headings_1).
I'm in the Handler below to spin through my Course_Table entity to filter the courses that have a particular Headings_1 key as a member of the head_tags_1 property. However, it doesn't seem like it is retrieving anything when I know there is data there to fulfill the request since it never displays the logs below when I go back to iterate through the results of my query (below). Any ideas of what I'm doing wrong?
def get(self,level_num,h_key):
path = []
if level_num == "1":
q = Course_Table.all().filter("head_tags_1 =", h_key)
for each in q:
logging.info('going through courses with this heading name')
logging.info("course name filtered is %s ", each.course_name)
MANY MANY THANK YOUS
I assume h_key is key of headings_1, since head_tags_1 is a list, I believe what you need is IN operator. https://developers.google.com/appengine/docs/python/datastore/queries
Note: your indentation inside the for loop does not seem correct.
My bad apparently '=' for list is already check membership. Using = to check membership is working for me, can you make sure h_key is really a datastore key class?
Here is my example, the first get produces result, where the 2nd one is not
import webapp2 from google.appengine.ext import db
class Greeting(db.Model):
author = db.StringProperty()
x = db.ListProperty(db.Key)
class C(db.Model): name = db.StringProperty()
class MainPage(webapp2.RequestHandler):
def get(self):
ckey = db.Key.from_path('C', 'abc')
dkey = db.Key.from_path('C', 'def')
ekey = db.Key.from_path('C', 'ghi')
Greeting(author='xxx', x=[ckey, dkey]).put()
x = Greeting.all().filter('x =',ckey).get()
self.response.write(x and x.author or 'None')
x = Greeting.all().filter('x =',ekey).get()
self.response.write(x and x.author or 'None')
app = webapp2.WSGIApplication([('/', MainPage)],
debug=True)

Plone and Dexterity: default values for "relation" field

In one of my Plone sites, I have a few dexterity models that I use to generate letters. The models are: "Model" (the base content of the letter), "Contact" (that contains the contact information, such as name, address etc) and "Merge" (which is a Model object rendered, in which we substitute some parts of the model with the recipients information).
The schema of the "Merge" object is the following:
class IMergeSchema(form.Schema):
"""
"""
title = schema.TextLine(
title=_p(u"Title"),
)
form.widget(text='plone.app.z3cform.wysiwyg.WysiwygFieldWidget')
text = schema.Text(
title=_p(u"Text"),
required=False,
)
form.widget(recipients=MultiContentTreeFieldWidget)
recipients = schema.List(
title=_('label_recipients',
default='Recipients'),
value_type=schema.Choice(
title=_('label_recipients',
default='Recipients'),
# Note that when you change the source, a plone.reload is
# not enough, as the source gets initialized on startup.
source=UUIDSourceBinder(portal_type='Contact')),
)
form.widget(model=ContentTreeFieldWidget)
form.mode(model='display')
model = schema.Choice(
title=_('label_model',
default='Model'),
source=UUIDSourceBinder(portal_type='Model'),
)
When creating a new "Merge" object, I want to have the "recipients" fields be preset with all contacts available in the folder where the new object is created.
I followed Martin Aspelli's guide to add a default value for a field: http://plone.org/products/dexterity/documentation/manual/developer-manual/reference/default-value-validator-adaptors
It works fine for text input fields, but I can't have it working for the "recipients" field. The method to generate the default values is the following (with some debug info with ugly print, but they'll be removed later ;) ):
#form.default_value(field=IMergeSchema['recipients'])
def all_recipients(data):
contacts = [x for x in data.context.contentValues()
if IContact.providedBy(x)]
paths = [u'/'.join(c.getPhysicalPath()) for c in contacts]
uids = [IUUID(c, None) for c in contacts]
print 'Contacts: %s' % contacts
print 'Paths: %s' % paths
print 'UIDs: %s' % uids
return paths
I tried to return the objects directly, their relative path (in the add view, when accessing "self.widgets['recipients'].value", I get this type of data) their UIDs but none of the solution as any effect.
I also tried to return tuples instead of lists or even generators, but still no effect at all.
The method is called for sure, as I see traces in the instance log.
I think you need to get the "int_id" of the related content. That's how dexterity relation fields store relation info::
from zope.component import getUtility
from zope.intid.interfaces import IIntIds
#form.default_value(field=IMergeSchema['recipients'])
def all_recipients(data):
contacts = [x for x in data.context.contentValues()
if IContact.providedBy(x)]
intids = getUtility(IIntIds)
# The following gets the int_id of the object and turns it into
# RelationValue
values = [RelationValue(intids.getId(c)) for c in contacts]
print 'Contacts: %s' % contacts
print 'Values: %s' % values
return values

Resources