Upgrade to PRO for Only $50/Year—Limited-Time Offer! 🔥
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Libsaas: one API to rule them all
Search
Aitor Guevara
May 29, 2014
Technology
0
190
Libsaas: one API to rule them all
APIdays Mediterranea May 2014, Barcelona
Aitor Guevara
May 29, 2014
Tweet
Share
More Decks by Aitor Guevara
See All by Aitor Guevara
Concurrent IO & Python
aitorciki
8
1k
From pull to push: towards a real-time web
aitorciki
4
330
Ducksboard's architecture, a real-time online dashboard
aitorciki
12
2.7k
Ducksboard - Betabeers BCN
aitorciki
1
190
Other Decks in Technology
See All in Technology
Playwrightのソースコードに見る、自動テストを自動で書く技術
yusukeiwaki
2
880
21st ACRi Webinar - AMD Presentation Slide (Nao Sumikawa)
nao_sumikawa
0
200
翻訳・対話・越境で強いチームワークを作ろう! / Building Strong Teamwork through Interpretation, Dialogue, and Border-Crossing
ar_tama
4
1.6k
たかが特別な時間の終わり / It's Only the End of Special Time
watany
2
540
安いGPUレンタルサービスについて
aratako
1
1.8k
命名から始めるSpec Driven
kuruwic
3
830
技術以外の世界に『越境』しエンジニアとして進化を遂げる 〜Kotlinへの愛とDevHRとしての挑戦を添えて〜
subroh0508
1
110
【5分でわかる】セーフィー エンジニア向け会社紹介
safie_recruit
0
37k
セキュリティAIエージェントの現在と未来 / PSS #2 Takumi Session
flatt_security
3
1.4k
Claude Code はじめてガイド -1時間で学べるAI駆動開発の基本と実践-
oikon48
42
25k
手動から自動へ、そしてその先へ
moritamasami
0
180
私のRails開発環境
yahonda
0
180
Featured
See All Featured
The Hidden Cost of Media on the Web [PixelPalooza 2025]
tammyeverts
1
79
Design and Strategy: How to Deal with People Who Don’t "Get" Design
morganepeng
132
19k
[RailsConf 2023] Rails as a piece of cake
palkan
58
6.1k
What's in a price? How to price your products and services
michaelherold
246
12k
Save Time (by Creating Custom Rails Generators)
garrettdimon
PRO
32
1.8k
Documentation Writing (for coders)
carmenintech
76
5.2k
The Myth of the Modular Monolith - Day 2 Keynote - Rails World 2024
eileencodes
26
3.2k
Optimising Largest Contentful Paint
csswizardry
37
3.5k
Why Our Code Smells
bkeepers
PRO
340
57k
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
508
140k
Facilitating Awesome Meetings
lara
57
6.7k
Connecting the Dots Between Site Speed, User Experience & Your Business [WebExpo 2025]
tammyeverts
10
700
Transcript
libsaas one API to rule them all Aitor Guevara •
@aitorciki
Context
business data spread across cloud services
Ducksboard consumes SaaS APIs to collect and visualize data
None
None
REST APIs
heterogeneous implementations headers, query params, auth, mime types, versioning, error
handling…
ad-hoc vendor libraries data structures, HTTP handling, sync/async IO, Python
versions
Enter libsaas
abstraction layer on top of heterogeneous SaaS APIs URLs generation,
parameters serialization, authentication, …
uniform interface Python methods and objects supports Python 2.x, Python
3.x, PyPy
extensible implement services as modules base classes, decorators, helpers, documentation
auto-generation
agnostic isolates modelling from networking
Architecture
service / resources hierarchy of Python classes
filters reusable requests modifiers e.g. pre-built authentication mechanisms
executors pluggable HTTP handlers urllib2, Requests, Twisted
parsers know how to deserialize responses JSON, XML
Example: service definition
1 import json 2 from libsaas import http 3 from
libsaas.filters import auth 4 from libsaas.services import base 5 from . import repos 6 7 class GitHub(base.Resource): 8 9 def __init__(self, token_or_username, password=None): 10 self.apiroot = 'https://api.github.com' 11 12 self.add_filter(self.use_json) 13 14 if password is None: 15 self.oauth_token = token_or_username 16 self.add_filter(self.add_authorization) 17 else: 18 self.add_filter(auth.BasicAuth(token_or_username, password)) 19 20 def add_authorization(self, request): 21 request.headers['Authorization'] = 'token {0}'.format(self.oauth_token) 22 23 def use_json(self, request): 24 if request.method.upper() not in http.URLENCODE_METHODS: 25 request.params = json.dumps(request.params) 26 27 def get_url(self): 28 return self.apiroot 29 30 @base.resource(repos.Repo) 31 def repo(self, user, repo): 32 return repos.Repo(self, user, repo) filters definition child resource
1 from libsaas import http 2 from libsaas.services import base
3 from . import resource, repocommits 4 5 class Repo(resource.GitHubResource): 6 7 def __init__(self, parent, user, repo): 8 self.parent = parent 9 self.user = http.quote_any(user) 10 self.repo = http.quote_any(repo) 11 12 def get_url(self): 13 return '{0}/repos/{1}/{2}'.format(self.parent.get_url(), 14 self.user, self.repo) 15 16 def require_collection(self): 17 return False 18 19 def require_item(self): 20 return True 21 22 @base.resource(repocommits.RepoCommits) 23 def commits(self): 24 return repocommits.RepoCommits(self) child resource resource URL
1 from libsaas import http, parsers 2 from libsaas.services import
base 3 4 class GitHubResource(base.RESTResource): 5 6 @base.apimethod 7 def get(self, page=None, per_page=None): 8 params = base.get_params(('page', 'per_page'), locals()) 9 request = http.Request('GET', self.get_url(), params) 10 11 return request, parsers.parse_json 12 13 @base.apimethod 14 def update(self, obj): 15 self.require_item() 16 # GitHub uses PATCH for updates 17 request = http.Request('PATCH', self.get_url(), self.wrap_object(obj)) 18 19 return request, parsers.parse_json parse response as JSON
1 from __future__ import print_function 2 from libsaas.services import github
3 4 gh = github.GitHub('my_token') 5 6 repo = gh.repo('aitorciki', 'apidays-demo') 7 8 for commit in repo.commits().get(): 9 msg = commit['commit']['message'] 10 author = commit['commit']['author']['name'] 11 date = commit['commit']['author']['date'] 12 13 print('{0} by {1} on {2}'.format(msg, author, date)) resources tree Python dict HTTP method
Questions? Thanks! Aitor Guevara • @aitorciki http://libsaas.net/