qualifying GET requests github api - github-api

Is there a way to filter github events using the GET request?
For example can I preform a GET that returns a subset (ForkEvents) of a repo's events?:
pseudo-request (though this doesn't work):
GET /repos/:owner/:repo/events?type=ForkEvent
More generally is there any way to implicitly filter the response data in the GET request i.e. before the data reaches my code? (I am new to the github-api and RESTful APIs in general, so I apologize in advance if this is a clueless question)
Thanks

If the Events Documentation is correct, it would appear this is in fact not possible. If you're new to the GitHub API you should probably try to use a library that exists for it. For example, if you were using python and github3.py then you might do something like:
import github3
g = github3.login("nelag", "nelag's password")
r = g.repository("nelag", "nelags_repo")
forks = filter(lambda event: event.type == 'ForkEvent', r.iter_events())
Nice and simple and you will have the added benefit of your code being lazy.

Related

How to forward messages to Sentry with a clean scope (no runtime information)

I'm forwarding alert messages from a AWS Lambda function to Sentry using the sentry_sdk in Python.
The problem is that even if I use scope.clear() before capture_message() the events I receive in sentry are enriched with information about the runtime environment where the message is captured in (the AWS lambda python environment) - which in this scenario is completly unrelated to the actual alert I'm forwarding.
My Code:
sentry_sdk.init(dsn, environment="name-of-stage")
with sentry_sdk.push_scope() as scope:
# Unfortunately this does not get rid of lambda specific context information.
scope.clear()
# here I set relevant information which works just fine.
scope.set_tag("priority", "high")
result = sentry_sdk.capture_message("mymessage")
The behaviour does not change if I pass scope as an argument to capture_message().
The tag I set manually is beeing transmitted just fine. But I also receive information about the Python runtime - therefore scope.clear() either does not behave like I expect it to OR capture_message gathers additional information itself.
Can someone explain how to only capture the information I'm actively assigning to the scope with set_tag and similar functions and surpress everything else?
Thank you very much
While I didn't find an explaination for the behaviour I was able to solve my problem (Even though it' a little bit hacky).
The solution was to use the sentry before_send hook in the init step like so:
sentry_sdk.init(dsn, environment="test", before_send=cleanup_event)
with sentry_sdk.push_scope() as scope:
sentry_sdk.capture_message(message, state, scope)
# when using sentry from lambda don't forget to flush otherwise messages can get lost.
sentry_sdk.flush()
Then in the cleanup_event function it gets a little bit ugly. I basically iterate over the keys of the event and remove the ones I do not want to show up. Since some Keys hold objects and some (like "tags") are a list with [key, value] entries this was quite some hassle.
KEYS_TO_REMOVE = {
"platform": [],
"modules": [],
"extra": ["sys.argv"],
"contexts": ["runtime"],
}
TAGS_TO_REMOVE = ["runtime", "runtime.name"]
def cleanup_event(event, hint):
for (k, v) in KEYS_TO_REMOVE.items():
with suppress(KeyError):
if v:
for i in v:
del event[k][i]
else:
del event[k]
for t in event["tags"]:
if t[0] in TAGS_TO_REMOVE:
event["tags"].remove(t)
return event

How do I acquire and return the date using an AWS lamba function

I am a unity developer who has been hired to make a game on the amazon alexa. It has been a mostly smooth process so far, but I now need to call the day's date into my IDE (pullstring), and was told by pullstring support that the solution is to make an endpoint api call to a lambda function that I will create and host.
I have tried finding some basic tutorials along the lines of making a very basic lambda function, but most of the videos and tutorials I've found assume I am already a web developer and know my way around node js and amazon's service environment, which I do not.
The function that I need is simple enough (I think?), as I just need to call the current date as a number and then look up that date on a json I have set up (which is working, I just need to get the actual real date instead of a dummy variable) and have written this:
let dateObj = new Date();
let day = dateObj.getDate();
but within how a lambda function works, I'm unsure how to set up the service and call this date (day) to be returned.
Does anyone have any resources that outline constructing and using a lambda function in the most basic, most essential way possible? Will the code I wrote serve the purpose I need?
I'm a little out of my element and just need a few gaps filled in before I can learn the rest on my own.
Thank you!
This Node.js/Lambda tutorial might help get you going: https://dev.to/adnanrahic/getting-started-with-aws-lambda-and-nodejs-1kcf

How to determine which events are connected in Matplotlib?

Is there a function or method in Matplotlib that will tell you
which events have been connected, and perhaps what code is being called by that listener? I've looked all over, no joy. I'm looking preferably for a generic solution, not one that is backend specific, but I will take what I can get.
In these situations, don't be afraid of the matplotlib codebase - it is quite reasonably pythonic and legible for the most part (with perhaps one or two skeletons here and there).
I'm going to talk you through the steps I'm going to take to understand what is going on and what you can get access to.
First off, start at a tagged version of matplotlib on GitHub - it will make all the links consistent (and not rot as code moves around). https://github.com/matplotlib/matplotlib/tree/v3.0.2
Our entry point is that we attach events through the mpl_connect method. A quick search for this (using "def mpl_connect", including the quotes) in the matplotlib codebase turns up https://github.com/matplotlib/matplotlib/blob/v3.0.2/lib/matplotlib/backend_bases.py#L2134-L2180.
self.callbacks.connect(s, func)
So now we need to figure out what self.callbacks actually is on this object. I did a ctrl+f to find the text self.callbacks = in this file.
https://github.com/matplotlib/matplotlib/blob/v3.0.2/lib/matplotlib/backend_bases.py#L1621
# a dictionary from event name to a dictionary that maps cid->func
self.callbacks = cbook.CallbackRegistry()
We are making progress now, and getting a little deeper each time :)
Following the imports logically, we now need to find out what matplotlib.cbook.CallbackRegistry looks like. https://github.com/matplotlib/matplotlib/blob/v3.0.2/lib/matplotlib/cbook/init.py#L88.
Specifically, we were calling the CallbackRegistry.connect method: https://github.com/matplotlib/matplotlib/blob/v3.0.2/lib/matplotlib/cbook/init.py#L162-L177. Implementation at time of writing:
def connect(self, s, func):
"""Register *func* to be called when signal *s* is generated.
"""
self._func_cid_map.setdefault(s, {})
try:
proxy = WeakMethod(func, self._remove_proxy)
except TypeError:
proxy = _StrongRef(func)
if proxy in self._func_cid_map[s]:
return self._func_cid_map[s][proxy]
cid = next(self._cid_gen)
self._func_cid_map[s][proxy] = cid
self.callbacks.setdefault(s, {})
self.callbacks[s][cid] = proxy
return cid
Rather than trying to read all of that, I'm looking for public data structures (those that don't start with a _) to see if there is anything I can query. It is starting to look like CallbackRegistry.callbacks is a dictionary that maps event names to some form of collection containing those event functions.
Indeed, this is supported by trying it out:
In [6]: fig.canvas.callbacks.callbacks
Out[6]:
{'button_press_event': {0: <weakref at 0x117bcff98; to 'FigureCanvasTkAgg' at 0x117c0f860>,
4: <matplotlib.cbook._StrongRef at 0x117c0f550>,
5: <matplotlib.cbook._StrongRef at 0x119686dd8>},
'scroll_event': {1: <weakref at 0x117be4048; to 'FigureCanvasTkAgg' at 0x117c0f860>},
'key_press_event': {2: <weakref at 0x117be43c8; to 'FigureManagerTk' at 0x117c0fe10>},
'motion_notify_event': {3: <weakref at 0x117be4438; to 'NavigationToolbar2Tk' at 0x117c0fe48>}}
What is interesting is that in this particular case, I've personally only added one event handler (button_press_event), but I've clearly got more events than that. What were seeing here is actually all of the events that are running in your backend too. Ever wondered how to disable some of those (like the keyboard shortcuts)? It is just a dictionary of events, and there is nothing stopping from just trashing them:
# Delete / remove the keyboard press event handlers.
fig.canvas.callbacks.callbacks.pop('key_press_event')
If you want to get a reference to the underlying function, a little bit of introspection suggests you can do something like:
In [37]: for cid, func_ref in fig.canvas.callbacks.callbacks['button_press_event'].items():
...: func = func_ref()
...: print(cid, func)
Out[37]: 5 <function onclick at 0x114d7e620>

Kivy: adding widgets from another thread

I've been stuck on this same issue for short of a week now:
the program should add widgets based on a http request. However, that request may take some time depending on user's internet connection, so I decided to thread that request and add a spinner to indicate that something is being done.
Here lies the issue. Some piece of code:
#mainthread
def add_w(self, parent, widget):
parent.add_widget(widget)
def add_course():
# HTTP Request I mentioned
course = course_manager.get_course(textfield_text)
courses_stack_layout = constructor_screen.ids.added_courses_stack_layout
course_information_widget = CourseInformation(coursename_label=course.name)
self.add_w(courses_stack_layout, course_information_widget)
constructor_screen.ids.spinner.active = False
add_course is being called from a thread, and spinner.active is being set True before calling this function. Here's the result, sometimes: messed up graphical interface
I also tried solving this with clock.schedule_once and clock.schedule_interval with a queue. The results were the same. Sometimes it works, sometimes it doesn't. The spinner does spin while getting the request, which is great.
Quite frankly, I would've never thought that implementing a spinner would be so hard.
How to implement that spinner? Maybe another alternative to threading? Maybe another alternative to urllib to make a request?
edit: any feedback on how I should've posted this so I can get more help? Is is too long? Maybe I could've been more clear?
The problem here was simply that widgets must also be created within the mainthread.
Creating another function marqued with #mainthread and calling that from the threaded one solved the issue.
Thanks for those who contributed.

Avoiding repetition with Flask - but is it too DRY?

Let us assume I serve data to colleagues in-office with a small Flask app, and let us also assume that it is a project I am not explicitly 'paid to do' so I don't have all the time in the world to write code.
It has occurred to me in my experimentation with pet projects at home that instead of decorating every last route with #app.route('/some/local/page') that I can do the following:
from flask import Flask, render_template, url_for, redirect, abort
from collections import OrderedDict
goodURLS = OrderedDict([('/index','Home'), ##can be passed to the template
('/about', 'About'), ##to create the navigation bar
('/foo', 'Foo'),
('/bar', 'Bar'), ##hence the use of OrderedDict
('/eggs', 'Eggs'), ##to have a set order for that navibar
('/spam', 'Spam')])
app = Flask(__name__)
#app.route('/<destination>')
def goThere(destination):
availableRoutes = goodURLS.keys():
if "/" + destination in availableRoutes:
return render_template('/%s.html' % destination, goodURLS=goodURLS)
else:
abort(404)
#app.errorhandler(404)
def notFound(e):
return render_template('/notFound.html'), 404
Now all I need to do is update my one list, and both my navigation bar and route handling function are lock-step.
Alternatively, I've written a method to determine the viable file locations by using os.walk in conjunction with file.endswith('.aGivenFileExtension') to locate every file which I mean to make accessible. The user's request can then be compared against the list this function returns (which obviously changes the serveTheUser() function.
from os import path, walk
def fileFinder(directory, extension=".html"):
"""Returns a list of files with a given file extension at a given path.
By default .html files are returned.
"""
foundFilesList = []
if path.exists(directory):
for p, d, files in walk(directory):
for file in files:
if file.endswith(extension):
foundFilesList.append(file)
return foundFilesList
goodRoutes = fileFinder('./templates/someFolderWithGoodRoutes/')
The question is, Is This Bad?
There are many aspects of Flask I'm just not using (mainly because I haven't needed to know about them yet) - so maybe this is actually limiting, or redundant when compared against a built-in feature of Flask. Does my lack of explicitly decorating each route rob me of a great feature of Flask?
Additionally, is either of these methods more or less safe than the other? I really don't know much about web security - and like I said, right now this is all in-office stuff, the security of my data is assured by our IT professional and there are no incoming requests from outside the office - but in a real-world setting, would either of these be detrimental? In particular, if I am using the backend to os.walk a location on the server's local disk, I'm not asking to have it abused by some ne'er-do-well am I?
EDIT: I've offered this as a bounty, because if it is not a safe or constructive practice I'd like to avoid using it for things that I'd want to like push to Heroku or just in general publicly serve for family, etc. It just seems like decorating every viable route with app.route is a waste of time.
There isn't anything really wrong with your solution, in my opinion. The problem is that with this kind of setup the things you can do are pretty limited.
I'm not sure if you simplified your code to show here, but if all you are doing in your view function is to gather some data and then select one of a few templates to render it then you might as well render the whole thing in a single page and maybe use a Javascript tab control to divide it up in sections on the client.
If each template requires different data, then the logic that obtains and processes the data for each template will have to be in your view function, and that is going to look pretty messy because you'll have a long chain of if statements to handle each template. Between that and separate view functions per template I think the latter will be quicker, even more so if you also consider the maintenance effort.
Update: based on the conversion in the comments I stand by my answer, with some minor reservations.
I think your solution works and has no major problems. I don't see a security risk because you are validating the input that comes from the client before you use it.
You are just using Flask to serve files that can be considered static if you ignore the navigation bar at the top. You should consider compiling the Flask app into a set of static files using an extension like Frozen-Flask, then you just host the compiled files with a regular web server. And when you need to add/remove routes you can modify the Flask app and compile it again.
Another thought is that your Flask app structure will not scale well if you need to add server-side logic. Right now you don't have any logic in the server, everything is handled by jQuery in the browser, so having a single view function works just fine. If at some point you need to add server logic for these pages then you will find that this structure isn't convenient.
I hope this helps.
I assume based on your code that all the routes have a corresponding template file of the same name (destination to destination.html) and that the goodURL menu bar is changed manually. An easier method would be to try to render the template at request and return your 404 page if it doesn't exist.
from jinja2 import TemplateNotFound
from werkzeug import secure_filename
....
#app.route('/<destination>')
def goThere(destination):
destTemplate = secure_filename("%s.html" % destination)
try:
return render_template(destTemplate, goodURLS=goodURLS)
except TemplateNotFound:
abort(404)
#app.errorhandler(404)
def notFound(e):
return render_template('/notFound.html'), 404
This is adapted from the answer to Stackoverflow: How do I create a 404 page?.
Edit: Updated to make use of Werkzeug's secure_filename to clean user input.

Resources