How send lists of objects with GAE endpoints? - python

I'm working in a API in GAE and I'm using Endpoints (with python). The data that I want send with response are a few objects that I build in this moment. So, to send this objects, I build a class with ProtoRPC message. And how I want send a list of them I build a class that represent a collections or a list of them.
This is the basis code:
class Greeting(messages.Message):
"""Greeting that stores a message."""
message = messages.StringField(1)
class GreetingCollection(messages.Message):
"""Collection of Greetings."""
items = messages.MessageField(Greeting, 1, repeated=True)
But when I want build a collection, I don't found the way. Obviously, seeing the documentation, I read that I can build a static colection to send it, for example:
STORED_GREETINGS = GreetingCollection(items=[
Greeting(message='hello world!'),
Greeting(message='goodbye world!'),
])
But if I want build this dynamically?
In my case I have a process that return a list of Greetings, and I dont find the way to convert this to a collection of Greeting to send with EndPoints.
return STORED_GREETINGS
Maybe I'm searching something like this:
(only orientative)
for greeting in greetings:
STORED_GREETINGS.add(greeting)
but I don't find how doing.
Any help will be welcome.
Thanks you so much.

Just build a normal list containing the Greeting objects and assign it to the GreetingCollection:
greetingItems = []
greetingItems.append(Greeting(message='hello world!'))
greetingItems.append(Greeting(message='goodbye world!'))
...
STORED_GREETINGS = GreetingCollection(items=greetingItems)

you should be able to just do:
greeting_collection = GreetingCollection()
greeting_collection.items = list_of_greetings
Or, alternatively:
greeting_collection = GreetingCollection()
greeting_collection.items.extend(iterable_of_greetings)

Related

Extract data from notion using python

I'm using Notion to store my data {client name, subscription...} in tables.
I want to extract some data using python but I can't figure out how.
For example count the total number of clients, get the total amount of subscriptions...
Could you please suggest a way to help me.
If you need to do this only once - you can export a notion page (database) to HTML, which will probably be easier to extract from.
If you want this as a weekly/daily/monthly thing - I can't help with doing that in python but zapier and automate.io would be perfect.
For fetching the data you can use notion-client. The great thing about it is that it supports both sync and async interfaces. What it lacks, though, is an easy way to navigate the data's structure (which is quite complicated in Notion)
For that you can use basic-notion. It allows you to use model classes to easily access all the properties and attributes of your Notion objects - kind of like you would with an ORM.
In your case the code might look something like this:
from notion_client import Client
from basic_notion.query import Query
from basic_notion.page import NotionPage, NotionPageList
from basic_notion.field import SelectField, TitleField, NumberField
# First define models
class MyRow(NotionPage):
name = TitleField(property_name='Name')
subscription = SelectField(property_name='Subscription')
some_number = NumberField(property_name='Some Number')
# ... your other fields go here
# See your database's schema and the available field classes
# in basic_notion.field to define this correctly.
class MyData(NotionPageList[MyRow]):
ITEM_CLS = MyRow
# You need to create an integration and get an API token from Notion:
NOTION_TOKEN = '<your-notion-api-token>'
DATABASE_ID = '<your-database-ID>'
# Now you can fetch the data
def get_data(database_id: str) -> MyData:
client = Client(auth=NOTION_TOKEN)
data = client.databases.query(
**Query(database_id=database_id).filter(
# Some filter here
MyRow.name.filter.starts_with('John')
).sorts(
# You can sort it here
MyRow.name.sort.ascending
).serialize()
)
return MyData(data=data)
my_data = get_data()
for row in my_data.items():
print(f'{row.name.get_text()} - {row.some_number.number}')
# Do whatever else you may need to do
For more info, examples and docs see:
notion-client: https://github.com/ramnes/notion-sdk-py
basic-notion: https://github.com/altvod/basic-notion
Notion API Reference: https://developers.notion.com/reference/intro

Make help command print the commands unsorted

Trying to figure out how to use this attribute: sort_commands
Seems like it's there so that I can change its default (True) to False but I can't figure out how to do it.
So far everyone has suggested for me to use bot.remove_command("help") and then implement my own from scratch.
But it seems like it's missing something. This attribute exists for a reason, doesn't it? Must be a better way to use this attribute rather than implement an entire command from scratch.
You're able to create a new instance of a default help command:
from discord.ext import commands
help_command = commands.DefaultHelpCommand(sort_commands=False) # Also set other options here
# And pass in the new help command into the bot so it knows to use it
bot = commands.Bot(command_prefix="!", help_command=help_command)
References:
Bot.help_command
commands.DefaultHelpCommand() - See other options you can edit in here.
I managed to do what I intended in the following way:
I created my own help command which extends (inherits) from DefaultHelpCommand, then I overriden the send_bot_help coroutine and change the sorting to compare by the command description field instead of command name field (I preferred creating my own order field or such, but couldn't find the right way to do it, so I used an existing field).
Then I order my commands like this:
#commands.command(help="A helpful description of cmd1", name="commandName", description='1')
#commands.command(help="A helpful description of cmd2", name="commandName2", description='2')
Following is the class:
class MyHelpCommand(DefaultHelpCommand):
async def send_bot_help(self, mapping):
# ... everything up here copy-pased from original superclass
# This used to be c.name
commands = sorted(commands, key=lambda c: c.description)
# ... The rest is also copy-pasted
Then I use it like suggested:
help_command = MyHelpCommand()
client = commands.Bot(command_prefix=Config.COMMAND_PREFIX, help_command=help_command)

Python - Tweepy - How to use lookup_friendships?

I'm trying to figure out if I'm following a user from which the streaming API just received a tweet. If I don't, then I want to follow him.
I've got something like:
def checkFollow(status):
relationship = api.lookup_friendships("Privacy_Watch_",status.user.id_str)
From there, how do I check if I follow this user already?
The lookup_friendships method will return everyone you follow each time you call it, in blocks of 100 users. Provided you follow a lot of people, that will be highly inefficient and consume a lot of requests.
You can use instead the show_friendship method, it will return a JSON containing information about your relationship with the id provided.
I cannot test it right now, but the following code should do what you want:
def checkFollow(status):
relation = api.show_friendship(source_screen_name=your_user_name, target_screen_name=status.user.id_str)
if relation.target.following: #I'm not sure if it should be "target" or "source" here
return True
return False

Is it OK to send the whole POST as a JSON object?

I am using GAE with python, and I am using many forms. Usually, my code looks something like this:
class Handler(BaseHandler):
#...
def post(self):
name = self.request.get("name")
last_name = self.request.get("last_name")
# More variables...
n = self.request.get("n")
#Do something with the variables, validations, etc.
#Add them to a dictionary
data = dict(name=name, last_name=last_name, n=n)
info = testdb.Test(**data)
info.put()
I have noticed lately that it gets too long when there are many inputs in the form (variables), so I thought maybe I could send a stringified JSON object (which can be treated as a python dictionary using json.loads). Right now it looks like this:
class Handler(BaseHandler):
#...
def post(self):
data = validate_dict(json.loads(self.request.body))
#Use a variable like this: data['last_name']
test = testdb.Test(**data)
test.put()
Which is a lot shorter. I am inclined to do things this way (and stop using self.request.get("something")), but I am worried I may be missing some disadvantage of doing this apart from the client needing javascript for it to even work. Is it OK to do this or is there something I should consider before rearranging my code?
There is absolutely nothing wrong with your short JSON-focused code variant (few web apps today bother supporting clients w/o Javascript anyway:-).
You'll just need to adapt the client-side code preparing that POST, from being just a traditional HTML form, to a JS-richer approach, of course. But, I'm pretty sure you're aware of that -- just spelling it out!-)
BTW, there is nothing here that's App Engine - specific: the same considerations would apply no matter how you chose to deploy your server.

Set/Get user information from a xmpp server: python

I am new in python and I am trying to create a testing python script to test different actions on my XMPP server. I already was able to test the login of my user and now I want to get the information that the server is sending (stanza) and set new information.
I have read several webs and I am not very clear with all this information. The main source has been sleekxmpp.com.
I have my stanza:
<iq type='get' to= 'chat.net' id='id1'>
<aa xmlns='http://myweb.com' />
</iq>
<iq type='result' to= 'chat.net' id='id1'>
<aa xmlns='http://myweb.com' >
<name>My name as included in sent mails<name>
<lang>en</lang>
<mail>My mail as included in sent mails</mail>
</aa>
</iq>
I want to get the information and also set one of the parameters (lets say name) but I don't know how.
class user_info(sleekxmpp.stanza.Iq):
self.get_query()
I must do it in python. Any help appreciated
What you want to do is create a custom stanza class for your stanza. Here's one that will work for the example you have:
from sleekxmpp import Iq
from sleekxmpp.xmlstream import ElementBase, register_stanza_plugin
class AA(ElementBase):
name = 'aa'
namespace = 'http://myweb.com'
plugin_attrib = 'aa'
interfaces = set(['name', 'lang', 'mail'])
sub_interfaces = interfaces
register_stanza_plugin(Iq, AA)
Ok, so what does all of that do? The name field specifies that the XML object's root tag is 'aa', and namespace specifies the root tag's namespace; obvious so far I hope.
The plugin_attrib field is the name that can be used to access this stanza from the parent stanza. For example, you should already be familiar with how you can use iq['type'] or iq['from'] to extract data out of an Iq stanza. With plugin_attrib set to "aa", then you can use iq['aa'] to get a reference to the AA content.
The interfaces set is the set of key names that this stanza provides for extracting information, just like working with dictionaries. For example an Iq stanza has 'to', 'from', 'type', etc in its interfaces set. By default, accessing and modifying these keys will create or modify attributes of the stanza's main element. So, at this point, your stanza would behave like this:
aa = AA()
aa['name'] = 'foo'
print aa
"<aa xmlns='http://myweb.com' name='foo' />"
Now, to instead map interface keys to subelements instead of attributes, they need to be in the sub_interfaces set. So by setting sub_interfaces = interfaces the above example would now work like so:
aa = AA()
aa['name'] = 'foo'
print aa
"<aa xmlns='http://myweb.com'><name>foo</name></aa>"
If you needed something more advanced, you could also define methods of the form get_* / set_* / del_* where * is the interface name which will then be used to extract or modify data.
So, all together, you will be able to do:
iq = Iq()
# ... set iq parameters
iq.enable('aa') # Add an initial, empty aa element.
try:
resp = iq.send()
print(resp['aa']['name'])
# ..., etc
except XMPPError:
print('There was an error')
Also, don't forget that we have the sleek#conference.jabber.org chat room for SleekXMPP help if you need it.

Categories

Resources