SlideShare a Scribd company logo
Retro
 web services made easy

        Sébastien Pierre, Datalicious
       @Montréal Python 7, May. 2009
www.datalicious.ca | github.com/sebastien/retro
Why another
Framework
 Toolkit ?
Things have Changed


            The 90s
  “ Golden Spinning Logo Era”

Web = Pages + Animated GIFs


                                3
Things have Changed


                The 00s
    “ Social Startup AJAX 2.0 Era”

Web = Model +View + Controller


                                     4
Things have Changed


             Now
    “ The Web of Data Era*”
       * aka “ semantic linked RDF data 3.0” ;)




Web = Data + Interfaces

                                                  5
Shifting our Perspective


  Web services are
 the new interfaces
for the “ web of data”


                           6
On Retro : Key Concepts



Web services are APIs exposed over HTTP
   Web Service = HTTP data bus


                                          7
Retro : An example
                                  Population             GDP                 Land Area (hectares)
British Columbia                           4,113,487           $164,583.00                91,837,000
Yukon                                           30,372           $1,452.00                47,890,000
Alberta                                    3,290,350           $187,493.00                 61,400,000
Northwest Territories                           41,464           $4,138.00               112,984,000



          Exposing data through
Saskatchewan                                   968,157          $39,834.00                58,939,000
Manitoba                                   1,148,401            $41,662.00                 54,029,000
Nunavut                                         29,474           $1,115.00               192,138,000
Ontario
Quebec
              A web service               12,160,282
                                           7,546,131
                                                               $536,340.00
                                                               $265,888.00
                                                                                          88,303,000
                                                                                         132,970,000
New Brunswick                                  729,997          $23,669.00                  7,133,000
Prince Edward Island                           135,851             $4,149                    564,000
Nova Scotia                                    913,462          $28,803.00                  5,277,000
Newfoundland and Labrador                      505,469          $19,696.00                35,498,000


                                                                                                        8
Step 1: Getting the data
;quot;Populationquot;;quot;GDPquot;;quot;Land Area (hectares)quot;
quot;British Columbiaquot;;quot;4,113,487quot;;quot;$164,583.00quot;;quot;91,837,000quot;
quot;Yukonquot;;quot;30,372quot;;quot;$1,452.00quot;;quot;47,890,000quot;
quot;Albertaquot;;quot;3,290,350quot;;quot;$187,493.00quot;;quot;61,400,000quot;
quot;Northwest Territoriesquot;;quot;41,464quot;;quot;$4,138.00quot;;quot;112,984,000quot;
quot;Saskatchewanquot;;quot;968,157quot;;quot;$39,834.00quot;;quot;58,939,000quot;
quot;Manitobaquot;;quot;1,148,401quot;;quot;$41,662.00quot;;quot;54,029,000quot;
quot;Nunavutquot;;quot;29,474quot;;quot;$1,115.00quot;;quot;192,138,000quot;
quot;Ontarioquot;;quot;12,160,282quot;;quot;$536,340.00quot;;quot;88,303,000quot;
quot;Quebecquot;;quot;7,546,131quot;;quot;$265,888.00quot;;quot;132,970,000quot;
quot;New Brunswickquot;;quot;729,997quot;;quot;$23,669.00quot;;quot;7,133,000quot;
quot;Prince Edward Islandquot;;quot;135,851quot;;quot;$4,149quot;;quot;564,000quot;
quot;Nova Scotiaquot;;quot;913,462quot;;quot;$28,803.00quot;;quot;5,277,000quot;
quot;Newfoundland and Labradorquot;;quot;505,469quot;;quot;$19,696.00quot;;quot;35,498,000quot;


DATA = list(csv.reader(open(quot;provinces.csvquot;),delimiter=quot;;quot;))[1:]


                                                                   9
Step 2: Writing the API
class ProvincesAPI:

     def __init__( self, data ):
          self.data = data

     def list( self ):
           return list(l[0] for l in self.data)

     def province( self, name ):
          return ([l for l in self.data if l[0] == name] or [None])[0]

     def population( self, province ):
          return self.province(province)[1]

     def gdp( self, province ):
          return self.province(province)[2]

     def landArea( self, province ):
           return self.province(province)[3]
                                                                         10
Step 3: Testing it
              if __name__ == quot;__main__quot;:
                   api = ProvincesAPI(DATA)
                   for p in api.list():
                         print quot;Province:quot;, p
                         print quot;­ gdp     :quot;,    api.gdp(p)
                         print quot;­ population :quot;, api.population(p)
                         print quot;­ land area :quot;, api.landArea(p)

Province: British Columbia                 Province: Saskatchewan                Province: New Brunswick
­ gdp                : $164,583.00         ­ gdp               : $39,834.00      ­ gdp               : $23,669.00
 ­ population : 4,113,487                   ­ population : 968,157                ­ population : 729,997
  ­ land area : 91,837,000                   ­ land area : 58,939,000              ­ land area : 7,133,000
   Province: Yukon                            Province: Manitoba                    Province: Prince Edward Island
   ­ gdp             : $1,452.00
                                              ­ gdp            : $41,662.00         ­ gdp            : $4,149
    ­ population : 30,372
     ­ land area : 47,890,000                  ­ population : 1,148,401              ­ population : 135,851
      Province: Alberta                         ­ land area : 54,029,000              ­ land area : 564,000
      ­ gdp          : $187,493.00               Province: Nunavut                     Province: Nova Scotia
       ­ population : 3,290,350                  ­ gdp         : $1,115.00             ­ gdp         : $28,803.00
        ­ land area : 61,400,000                  ­ population : 29,474                 ­ population : 913,462
         Province: Northwest Territories           ­ land area : 192,138,000             ­ land area : 5,277,000
         ­ gdp       : $4,138.00                    Province: Ontario                     Province: Newfoundland and Labrador
          ­ population : 41,464                     ­ gdp      : $536,340.00              ­ gdp      : $19,696.00
           ­ land area : 112,984,000                 ­ population : 12,160,282             ­ population : 505,469
                                                                                                                                11
Step 4 : Exposing it
from retro import *

class ProvincesAPI(Component):

     def __init__( self, data ):
          Component.__init__(self)
          self.data = data

     @expose(GET=quot;/api/provinces/allquot;)
     def list( self ):
           return list(l[0] for l in self.data)

     @expose(GET=quot;/api/province/{name:string}quot;)
     def province( self, name ):
          name = name.lower().replace(quot; quot;,quot;quot;)
          return ([l for l in self.data if l[0].lower().replace(quot; quot;,quot;quot;) == name] or [None])[0]



                                                                                                 12
Step 4 : Exposing it
      Import retro


from retro import *

class ProvincesAPI(Component):

     def __init__( self, data ):
          Component.__init__(self)
          self.data = data

     @expose(GET=quot;/api/provinces/allquot;)
     def list( self ):
           return list(l[0] for l in self.data)

     @expose(GET=quot;/api/province/{name:string}quot;)
     def province( self, name ):
          name = name.lower().replace(quot; quot;,quot;quot;)
          return ([l for l in self.data if l[0].lower().replace(quot; quot;,quot;quot;) == name] or [None])[0]



                                                                                                 13
Step 4 : Exposing it
       from retro import *

       class ProvincesAPI(Component):

Decorate the def __init__( self, data ):
             method to
                  Component.__init__(self)
 expose it over HTTP
                  self.data = data

            @expose(GET=quot;/api/provinces/allquot;)
            def list( self ):
                  return list(l[0] for l in self.data)

            @expose(GET=quot;/api/province/{name:string}quot;)
            def province( self, name ):
                 name = name.lower().replace(quot; quot;,quot;quot;)
                 return ([l for l in self.data if l[0].lower().replace(quot; quot;,quot;quot;) == name] or [None])[0]



                                                                                                        14
Step 4 : Exposing it
from retro import *

class ProvincesAPI(Component):

  Use HTTP methodsself, data ):
      def __init__(
as keyword Component.__init__(self)
           arguments
           self.data = data

     @expose(GET=quot;/api/provinces/allquot;)
     def list( self ):
           return list(l[0] for l in self.data)

     @expose(GET=quot;/api/province/{name:string}quot;)
     def province( self, name ):
          name = name.lower().replace(quot; quot;,quot;quot;)
          return ([l for l in self.data if l[0].lower().replace(quot; quot;,quot;quot;) == name] or [None])[0]



                                                                                                 15
Step 4 : Exposing it
from retro import *

class ProvincesAPI(Component):

     def __init__( self, data ):
                          Specify URL to respond to
          Component.__init__(self)
          self.data = data

     @expose(GET=quot;/api/provinces/allquot;)
     def list( self ):
           return list(l[0] for l in self.data)

     @expose(GET=quot;/api/province/{name:string}quot;)
     def province( self, name ):
          name = name.lower().replace(quot; quot;,quot;quot;)
          return ([l for l in self.data if l[0].lower().replace(quot; quot;,quot;quot;) == name] or [None])[0]



                                                                                                 16
Step 4 : Exposing it
from retro import *

class ProvincesAPI(Component):

     def __init__( self, data ):
          Component.__init__(self)
          self.data = data

     @expose(GET=quot;/api/provinces/allquot;)Pass parameters from URL
     def list( self ):                     to Python method
           return list(l[0] for l in self.data)

     @expose(GET=quot;/api/province/{name:string}quot;)
     def province( self, name ):
          name = name.lower().replace(quot; quot;,quot;quot;)
          return ([l for l in self.data if l[0].lower().replace(quot; quot;,quot;quot;) == name] or [None])[0]



                                                                                                 17
Step 4 : Exposing it

@expose(GET=quot;/api/province/{province:string}/populationquot;)
def population( self, province ):
     return self.province(province)[1]

@expose(GET=quot;/api/province/{province:string}/gdpquot;)
def gdp( self, province ):
     return self.province(province)[2]

@expose(GET=quot;/api/province/{province:string}/landAreaquot;)
def landArea( self, province ):
      return self.province(province)[3]


  Don't change a line in your
         existing code



                                                            18
Step 5 : Running it
if __name__ == quot;__main__quot;:
      run(components=[ProvincesAPI(DATA)],port=8000)



curl localhost:8000/api/provinces/all
[quot;British Columbiaquot;,quot;Yukonquot;,quot;Albertaquot;,quot;Northwest
Territoriesquot;,quot;Saskatchewanquot;,quot;Manitobaquot;,quot;Nunavutquot;,quot;Ontarioquot;,quot;Quebecquot;,quot;New Brunswickquot;,
quot;Prince Edward Islandquot;,quot;Nova Scotiaquot;,quot;Newfoundland and Labradorquot;]

curl localhost:8000/api/province/quebec/gdp
quot;$265,888.00quot;

curl localhost:8000/api/province/quebec/population
quot;7,546,131quot;

curl localhost:8000/api/province/quebec/landArea
quot;132,970,000quot;

                                                                                       19
Step 5 : Running it
if __name__ == quot;__main__quot;:
      run(components=[ProvincesAPI(DATA)],port=8000)


   Runs the Retro embedded
curl localhost:8000/api/provinces/all
           web server
[quot;British Columbiaquot;,quot;Yukonquot;,quot;Albertaquot;,quot;Northwest
Territoriesquot;,quot;Saskatchewanquot;,quot;Manitobaquot;,quot;Nunavutquot;,quot;Ontarioquot;,quot;Quebecquot;,quot;New Brunswickquot;,
quot;Prince Edward Islandquot;,quot;Nova Scotiaquot;,quot;Newfoundland and Labradorquot;]

curl localhost:8000/api/province/quebec/gdp
quot;$265,888.00quot;

curl localhost:8000/api/province/quebec/population
quot;7,546,131quot;

curl localhost:8000/api/province/quebec/landArea
quot;132,970,000quot;

                                                                                       20
Step 5 : Running it
if __name__ == quot;__main__quot;:
      run(components=[ProvincesAPI(DATA)],port=8000)



curl localhost:8000/api/provinces/all
[quot;British Columbiaquot;,quot;Yukonquot;,quot;Albertaquot;,quot;Northwest
Territoriesquot;,quot;Saskatchewanquot;,quot;Manitobaquot;,quot;Nunavutquot;,quot;Ontarioquot;,quot;Quebecquot;,quot;New Brunswickquot;,
quot;Prince Edward Islandquot;,quot;Nova Scotiaquot;,quot;Newfoundland and Labradorquot;]

curl localhost:8000/api/province/quebec/gdp
quot;$265,888.00quot;                                              Data is returned as
                                                                  JSON
curl localhost:8000/api/province/quebec/population
quot;7,546,131quot;

curl localhost:8000/api/province/quebec/landArea
quot;132,970,000quot;

                                                                                       21
Step 6 : Surprise !
    if __name__ == quot;__main__quot;:
         api = ProvincesAPI(DATA)
         for p in api.list():
               print quot;Province:quot;, p
               print quot;­ gdp     :quot;, api.gdp(p)
               print quot;­ population :quot;, api.population(p)
               print quot;­ land area :quot;, api.landArea(p)
         run(components=[api],port=8000)




Your API object remains usable as it was
before in Python


                                                           22
Retro in a Nutshell

WSGI­based
  Works with CGI, FCGI, SCGI, WSGI on Apache, Lighttpd, Nginx

HTTP Streaming
  Uses WSGI generator (yield) support

Standalone
  Comes with embedded web server and event reactor

Lightweight
  Minimal API, small footprint

                                                                23
The end



    Thank you !
www.github.com/sebastien/retro
        www.datalicious.ca
      sebastien@datalicious.ca

More Related Content

Similar to Retro - Web Services Made Easy

New automated techniques to validate and populate property valuations
New automated techniques to validate and populate property valuationsNew automated techniques to validate and populate property valuations
New automated techniques to validate and populate property valuations
Rob Carroll
 
Google Q4 2012 Quarterly Earnings Summary
Google Q4 2012 Quarterly Earnings SummaryGoogle Q4 2012 Quarterly Earnings Summary
Google Q4 2012 Quarterly Earnings Summary
Kit Seeborg
 
Google Q4 2012 Quarterly Earnings Summary
Google Q4 2012 Quarterly Earnings SummaryGoogle Q4 2012 Quarterly Earnings Summary
Google Q4 2012 Quarterly Earnings Summary
Kamaldeep Singh SEO
 
Chapter 10generac flujo caja
Chapter 10generac flujo cajaChapter 10generac flujo caja
Chapter 10generac flujo caja
federicoblanco
 
PythonCERR_2014
PythonCERR_2014PythonCERR_2014
PythonCERR_2014
Elizabeth McDowell
 
MA AMTA 52st Annual Meeting
MA AMTA 52st Annual MeetingMA AMTA 52st Annual Meeting
MA AMTA 52st Annual Meeting
Curran Consulting
 
Assessing carbon value
Assessing carbon valueAssessing carbon value
Assessing carbon value
Peter Weisberg
 
Canada
CanadaCanada
Canada
Vanzippee
 
New gprs franchise presentation copy
New gprs franchise presentation   copyNew gprs franchise presentation   copy
New gprs franchise presentation copy
mary jane amatos
 
Retirement Day has not yet Arrived: The Introduction to RDA, FRBR & the Ass...
Retirement Day has not yet Arrived:The Introduction to RDA, FRBR & the Ass...Retirement Day has not yet Arrived:The Introduction to RDA, FRBR & the Ass...
Retirement Day has not yet Arrived: The Introduction to RDA, FRBR & the Ass...
William Fee
 
Three Rivers TIFA Update Ex Sum 12.4.12
Three Rivers TIFA Update Ex Sum  12.4.12Three Rivers TIFA Update Ex Sum  12.4.12
Three Rivers TIFA Update Ex Sum 12.4.12
Chuck Eckenstahler
 
Project
ProjectProject
Project
Jaewan An
 
Intertech Public Land Management Report Tables: Nevada
Intertech Public Land Management Report Tables: NevadaIntertech Public Land Management Report Tables: Nevada
Intertech Public Land Management Report Tables: Nevada
American Lands Council
 
Energy Conservation & Sustainability
Energy Conservation & Sustainability  Energy Conservation & Sustainability
Energy Conservation & Sustainability
Meg Thompson
 
Budget Work Example
Budget Work ExampleBudget Work Example
Budget Work Example
David Urbia
 
Sample cba contact center upgrade project
Sample cba   contact center upgrade projectSample cba   contact center upgrade project
Sample cba contact center upgrade project
Ken Hicks
 
Americaspony
AmericasponyAmericaspony
Americaspony
guest7ea69ea
 
Python and the CERR Challenge Process
Python and the CERR Challenge ProcessPython and the CERR Challenge Process
Python and the CERR Challenge Process
GeCo in the Rockies
 
Nv intertech-preliminary-draft-public-land-mgmt-task-force-report-tables
Nv intertech-preliminary-draft-public-land-mgmt-task-force-report-tablesNv intertech-preliminary-draft-public-land-mgmt-task-force-report-tables
Nv intertech-preliminary-draft-public-land-mgmt-task-force-report-tables
American Lands Council
 
Canada tax sumury 2012
Canada tax sumury 2012Canada tax sumury 2012
Canada tax sumury 2012
Daya Dayarayan Canada
 

Similar to Retro - Web Services Made Easy (20)

New automated techniques to validate and populate property valuations
New automated techniques to validate and populate property valuationsNew automated techniques to validate and populate property valuations
New automated techniques to validate and populate property valuations
 
Google Q4 2012 Quarterly Earnings Summary
Google Q4 2012 Quarterly Earnings SummaryGoogle Q4 2012 Quarterly Earnings Summary
Google Q4 2012 Quarterly Earnings Summary
 
Google Q4 2012 Quarterly Earnings Summary
Google Q4 2012 Quarterly Earnings SummaryGoogle Q4 2012 Quarterly Earnings Summary
Google Q4 2012 Quarterly Earnings Summary
 
Chapter 10generac flujo caja
Chapter 10generac flujo cajaChapter 10generac flujo caja
Chapter 10generac flujo caja
 
PythonCERR_2014
PythonCERR_2014PythonCERR_2014
PythonCERR_2014
 
MA AMTA 52st Annual Meeting
MA AMTA 52st Annual MeetingMA AMTA 52st Annual Meeting
MA AMTA 52st Annual Meeting
 
Assessing carbon value
Assessing carbon valueAssessing carbon value
Assessing carbon value
 
Canada
CanadaCanada
Canada
 
New gprs franchise presentation copy
New gprs franchise presentation   copyNew gprs franchise presentation   copy
New gprs franchise presentation copy
 
Retirement Day has not yet Arrived: The Introduction to RDA, FRBR & the Ass...
Retirement Day has not yet Arrived:The Introduction to RDA, FRBR & the Ass...Retirement Day has not yet Arrived:The Introduction to RDA, FRBR & the Ass...
Retirement Day has not yet Arrived: The Introduction to RDA, FRBR & the Ass...
 
Three Rivers TIFA Update Ex Sum 12.4.12
Three Rivers TIFA Update Ex Sum  12.4.12Three Rivers TIFA Update Ex Sum  12.4.12
Three Rivers TIFA Update Ex Sum 12.4.12
 
Project
ProjectProject
Project
 
Intertech Public Land Management Report Tables: Nevada
Intertech Public Land Management Report Tables: NevadaIntertech Public Land Management Report Tables: Nevada
Intertech Public Land Management Report Tables: Nevada
 
Energy Conservation & Sustainability
Energy Conservation & Sustainability  Energy Conservation & Sustainability
Energy Conservation & Sustainability
 
Budget Work Example
Budget Work ExampleBudget Work Example
Budget Work Example
 
Sample cba contact center upgrade project
Sample cba   contact center upgrade projectSample cba   contact center upgrade project
Sample cba contact center upgrade project
 
Americaspony
AmericasponyAmericaspony
Americaspony
 
Python and the CERR Challenge Process
Python and the CERR Challenge ProcessPython and the CERR Challenge Process
Python and the CERR Challenge Process
 
Nv intertech-preliminary-draft-public-land-mgmt-task-force-report-tables
Nv intertech-preliminary-draft-public-land-mgmt-task-force-report-tablesNv intertech-preliminary-draft-public-land-mgmt-task-force-report-tables
Nv intertech-preliminary-draft-public-land-mgmt-task-force-report-tables
 
Canada tax sumury 2012
Canada tax sumury 2012Canada tax sumury 2012
Canada tax sumury 2012
 

Recently uploaded

GraphSummit Singapore | The Art of the Possible with Graph - Q2 2024
GraphSummit Singapore | The Art of the  Possible with Graph - Q2 2024GraphSummit Singapore | The Art of the  Possible with Graph - Q2 2024
GraphSummit Singapore | The Art of the Possible with Graph - Q2 2024
Neo4j
 
National Security Agency - NSA mobile device best practices
National Security Agency - NSA mobile device best practicesNational Security Agency - NSA mobile device best practices
National Security Agency - NSA mobile device best practices
Quotidiano Piemontese
 
Microsoft - Power Platform_G.Aspiotis.pdf
Microsoft - Power Platform_G.Aspiotis.pdfMicrosoft - Power Platform_G.Aspiotis.pdf
Microsoft - Power Platform_G.Aspiotis.pdf
Uni Systems S.M.S.A.
 
Serial Arm Control in Real Time Presentation
Serial Arm Control in Real Time PresentationSerial Arm Control in Real Time Presentation
Serial Arm Control in Real Time Presentation
tolgahangng
 
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdfUnlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
Malak Abu Hammad
 
20240607 QFM018 Elixir Reading List May 2024
20240607 QFM018 Elixir Reading List May 202420240607 QFM018 Elixir Reading List May 2024
20240607 QFM018 Elixir Reading List May 2024
Matthew Sinclair
 
Climate Impact of Software Testing at Nordic Testing Days
Climate Impact of Software Testing at Nordic Testing DaysClimate Impact of Software Testing at Nordic Testing Days
Climate Impact of Software Testing at Nordic Testing Days
Kari Kakkonen
 
TrustArc Webinar - 2024 Global Privacy Survey
TrustArc Webinar - 2024 Global Privacy SurveyTrustArc Webinar - 2024 Global Privacy Survey
TrustArc Webinar - 2024 Global Privacy Survey
TrustArc
 
Video Streaming: Then, Now, and in the Future
Video Streaming: Then, Now, and in the FutureVideo Streaming: Then, Now, and in the Future
Video Streaming: Then, Now, and in the Future
Alpen-Adria-Universität
 
Uni Systems Copilot event_05062024_C.Vlachos.pdf
Uni Systems Copilot event_05062024_C.Vlachos.pdfUni Systems Copilot event_05062024_C.Vlachos.pdf
Uni Systems Copilot event_05062024_C.Vlachos.pdf
Uni Systems S.M.S.A.
 
Pushing the limits of ePRTC: 100ns holdover for 100 days
Pushing the limits of ePRTC: 100ns holdover for 100 daysPushing the limits of ePRTC: 100ns holdover for 100 days
Pushing the limits of ePRTC: 100ns holdover for 100 days
Adtran
 
Best 20 SEO Techniques To Improve Website Visibility In SERP
Best 20 SEO Techniques To Improve Website Visibility In SERPBest 20 SEO Techniques To Improve Website Visibility In SERP
Best 20 SEO Techniques To Improve Website Visibility In SERP
Pixlogix Infotech
 
Driving Business Innovation: Latest Generative AI Advancements & Success Story
Driving Business Innovation: Latest Generative AI Advancements & Success StoryDriving Business Innovation: Latest Generative AI Advancements & Success Story
Driving Business Innovation: Latest Generative AI Advancements & Success Story
Safe Software
 
Introduction to CHERI technology - Cybersecurity
Introduction to CHERI technology - CybersecurityIntroduction to CHERI technology - Cybersecurity
Introduction to CHERI technology - Cybersecurity
mikeeftimakis1
 
みなさんこんにちはこれ何文字まで入るの?40文字以下不可とか本当に意味わからないけどこれ限界文字数書いてないからマジでやばい文字数いけるんじゃないの?えこ...
みなさんこんにちはこれ何文字まで入るの?40文字以下不可とか本当に意味わからないけどこれ限界文字数書いてないからマジでやばい文字数いけるんじゃないの?えこ...みなさんこんにちはこれ何文字まで入るの?40文字以下不可とか本当に意味わからないけどこれ限界文字数書いてないからマジでやばい文字数いけるんじゃないの?えこ...
みなさんこんにちはこれ何文字まで入るの?40文字以下不可とか本当に意味わからないけどこれ限界文字数書いてないからマジでやばい文字数いけるんじゃないの?えこ...
名前 です男
 
HCL Notes und Domino Lizenzkostenreduzierung in der Welt von DLAU
HCL Notes und Domino Lizenzkostenreduzierung in der Welt von DLAUHCL Notes und Domino Lizenzkostenreduzierung in der Welt von DLAU
HCL Notes und Domino Lizenzkostenreduzierung in der Welt von DLAU
panagenda
 
Let's Integrate MuleSoft RPA, COMPOSER, APM with AWS IDP along with Slack
Let's Integrate MuleSoft RPA, COMPOSER, APM with AWS IDP along with SlackLet's Integrate MuleSoft RPA, COMPOSER, APM with AWS IDP along with Slack
Let's Integrate MuleSoft RPA, COMPOSER, APM with AWS IDP along with Slack
shyamraj55
 
Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!
Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!
Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!
SOFTTECHHUB
 
Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...
Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...
Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...
SOFTTECHHUB
 
UiPath Test Automation using UiPath Test Suite series, part 5
UiPath Test Automation using UiPath Test Suite series, part 5UiPath Test Automation using UiPath Test Suite series, part 5
UiPath Test Automation using UiPath Test Suite series, part 5
DianaGray10
 

Recently uploaded (20)

GraphSummit Singapore | The Art of the Possible with Graph - Q2 2024
GraphSummit Singapore | The Art of the  Possible with Graph - Q2 2024GraphSummit Singapore | The Art of the  Possible with Graph - Q2 2024
GraphSummit Singapore | The Art of the Possible with Graph - Q2 2024
 
National Security Agency - NSA mobile device best practices
National Security Agency - NSA mobile device best practicesNational Security Agency - NSA mobile device best practices
National Security Agency - NSA mobile device best practices
 
Microsoft - Power Platform_G.Aspiotis.pdf
Microsoft - Power Platform_G.Aspiotis.pdfMicrosoft - Power Platform_G.Aspiotis.pdf
Microsoft - Power Platform_G.Aspiotis.pdf
 
Serial Arm Control in Real Time Presentation
Serial Arm Control in Real Time PresentationSerial Arm Control in Real Time Presentation
Serial Arm Control in Real Time Presentation
 
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdfUnlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
 
20240607 QFM018 Elixir Reading List May 2024
20240607 QFM018 Elixir Reading List May 202420240607 QFM018 Elixir Reading List May 2024
20240607 QFM018 Elixir Reading List May 2024
 
Climate Impact of Software Testing at Nordic Testing Days
Climate Impact of Software Testing at Nordic Testing DaysClimate Impact of Software Testing at Nordic Testing Days
Climate Impact of Software Testing at Nordic Testing Days
 
TrustArc Webinar - 2024 Global Privacy Survey
TrustArc Webinar - 2024 Global Privacy SurveyTrustArc Webinar - 2024 Global Privacy Survey
TrustArc Webinar - 2024 Global Privacy Survey
 
Video Streaming: Then, Now, and in the Future
Video Streaming: Then, Now, and in the FutureVideo Streaming: Then, Now, and in the Future
Video Streaming: Then, Now, and in the Future
 
Uni Systems Copilot event_05062024_C.Vlachos.pdf
Uni Systems Copilot event_05062024_C.Vlachos.pdfUni Systems Copilot event_05062024_C.Vlachos.pdf
Uni Systems Copilot event_05062024_C.Vlachos.pdf
 
Pushing the limits of ePRTC: 100ns holdover for 100 days
Pushing the limits of ePRTC: 100ns holdover for 100 daysPushing the limits of ePRTC: 100ns holdover for 100 days
Pushing the limits of ePRTC: 100ns holdover for 100 days
 
Best 20 SEO Techniques To Improve Website Visibility In SERP
Best 20 SEO Techniques To Improve Website Visibility In SERPBest 20 SEO Techniques To Improve Website Visibility In SERP
Best 20 SEO Techniques To Improve Website Visibility In SERP
 
Driving Business Innovation: Latest Generative AI Advancements & Success Story
Driving Business Innovation: Latest Generative AI Advancements & Success StoryDriving Business Innovation: Latest Generative AI Advancements & Success Story
Driving Business Innovation: Latest Generative AI Advancements & Success Story
 
Introduction to CHERI technology - Cybersecurity
Introduction to CHERI technology - CybersecurityIntroduction to CHERI technology - Cybersecurity
Introduction to CHERI technology - Cybersecurity
 
みなさんこんにちはこれ何文字まで入るの?40文字以下不可とか本当に意味わからないけどこれ限界文字数書いてないからマジでやばい文字数いけるんじゃないの?えこ...
みなさんこんにちはこれ何文字まで入るの?40文字以下不可とか本当に意味わからないけどこれ限界文字数書いてないからマジでやばい文字数いけるんじゃないの?えこ...みなさんこんにちはこれ何文字まで入るの?40文字以下不可とか本当に意味わからないけどこれ限界文字数書いてないからマジでやばい文字数いけるんじゃないの?えこ...
みなさんこんにちはこれ何文字まで入るの?40文字以下不可とか本当に意味わからないけどこれ限界文字数書いてないからマジでやばい文字数いけるんじゃないの?えこ...
 
HCL Notes und Domino Lizenzkostenreduzierung in der Welt von DLAU
HCL Notes und Domino Lizenzkostenreduzierung in der Welt von DLAUHCL Notes und Domino Lizenzkostenreduzierung in der Welt von DLAU
HCL Notes und Domino Lizenzkostenreduzierung in der Welt von DLAU
 
Let's Integrate MuleSoft RPA, COMPOSER, APM with AWS IDP along with Slack
Let's Integrate MuleSoft RPA, COMPOSER, APM with AWS IDP along with SlackLet's Integrate MuleSoft RPA, COMPOSER, APM with AWS IDP along with Slack
Let's Integrate MuleSoft RPA, COMPOSER, APM with AWS IDP along with Slack
 
Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!
Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!
Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!
 
Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...
Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...
Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...
 
UiPath Test Automation using UiPath Test Suite series, part 5
UiPath Test Automation using UiPath Test Suite series, part 5UiPath Test Automation using UiPath Test Suite series, part 5
UiPath Test Automation using UiPath Test Suite series, part 5
 

Retro - Web Services Made Easy

  • 1. Retro web services made easy Sébastien Pierre, Datalicious @Montréal Python 7, May. 2009 www.datalicious.ca | github.com/sebastien/retro
  • 3. Things have Changed The 90s “ Golden Spinning Logo Era” Web = Pages + Animated GIFs 3
  • 4. Things have Changed The 00s “ Social Startup AJAX 2.0 Era” Web = Model +View + Controller 4
  • 5. Things have Changed Now “ The Web of Data Era*” * aka “ semantic linked RDF data 3.0” ;) Web = Data + Interfaces 5
  • 6. Shifting our Perspective Web services are the new interfaces for the “ web of data” 6
  • 7. On Retro : Key Concepts Web services are APIs exposed over HTTP Web Service = HTTP data bus 7
  • 8. Retro : An example Population GDP Land Area (hectares) British Columbia 4,113,487 $164,583.00 91,837,000 Yukon 30,372 $1,452.00 47,890,000 Alberta 3,290,350 $187,493.00 61,400,000 Northwest Territories 41,464 $4,138.00 112,984,000 Exposing data through Saskatchewan 968,157 $39,834.00 58,939,000 Manitoba 1,148,401 $41,662.00 54,029,000 Nunavut 29,474 $1,115.00 192,138,000 Ontario Quebec A web service 12,160,282 7,546,131 $536,340.00 $265,888.00 88,303,000 132,970,000 New Brunswick 729,997 $23,669.00 7,133,000 Prince Edward Island 135,851 $4,149 564,000 Nova Scotia 913,462 $28,803.00 5,277,000 Newfoundland and Labrador 505,469 $19,696.00 35,498,000 8
  • 9. Step 1: Getting the data ;quot;Populationquot;;quot;GDPquot;;quot;Land Area (hectares)quot; quot;British Columbiaquot;;quot;4,113,487quot;;quot;$164,583.00quot;;quot;91,837,000quot; quot;Yukonquot;;quot;30,372quot;;quot;$1,452.00quot;;quot;47,890,000quot; quot;Albertaquot;;quot;3,290,350quot;;quot;$187,493.00quot;;quot;61,400,000quot; quot;Northwest Territoriesquot;;quot;41,464quot;;quot;$4,138.00quot;;quot;112,984,000quot; quot;Saskatchewanquot;;quot;968,157quot;;quot;$39,834.00quot;;quot;58,939,000quot; quot;Manitobaquot;;quot;1,148,401quot;;quot;$41,662.00quot;;quot;54,029,000quot; quot;Nunavutquot;;quot;29,474quot;;quot;$1,115.00quot;;quot;192,138,000quot; quot;Ontarioquot;;quot;12,160,282quot;;quot;$536,340.00quot;;quot;88,303,000quot; quot;Quebecquot;;quot;7,546,131quot;;quot;$265,888.00quot;;quot;132,970,000quot; quot;New Brunswickquot;;quot;729,997quot;;quot;$23,669.00quot;;quot;7,133,000quot; quot;Prince Edward Islandquot;;quot;135,851quot;;quot;$4,149quot;;quot;564,000quot; quot;Nova Scotiaquot;;quot;913,462quot;;quot;$28,803.00quot;;quot;5,277,000quot; quot;Newfoundland and Labradorquot;;quot;505,469quot;;quot;$19,696.00quot;;quot;35,498,000quot; DATA = list(csv.reader(open(quot;provinces.csvquot;),delimiter=quot;;quot;))[1:] 9
  • 10. Step 2: Writing the API class ProvincesAPI: def __init__( self, data ): self.data = data def list( self ): return list(l[0] for l in self.data) def province( self, name ): return ([l for l in self.data if l[0] == name] or [None])[0] def population( self, province ): return self.province(province)[1] def gdp( self, province ): return self.province(province)[2] def landArea( self, province ): return self.province(province)[3] 10
  • 11. Step 3: Testing it if __name__ == quot;__main__quot;: api = ProvincesAPI(DATA) for p in api.list(): print quot;Province:quot;, p print quot;­ gdp :quot;, api.gdp(p) print quot;­ population :quot;, api.population(p) print quot;­ land area :quot;, api.landArea(p) Province: British Columbia Province: Saskatchewan Province: New Brunswick ­ gdp : $164,583.00 ­ gdp : $39,834.00 ­ gdp : $23,669.00 ­ population : 4,113,487 ­ population : 968,157 ­ population : 729,997 ­ land area : 91,837,000 ­ land area : 58,939,000 ­ land area : 7,133,000 Province: Yukon Province: Manitoba Province: Prince Edward Island ­ gdp : $1,452.00 ­ gdp : $41,662.00 ­ gdp : $4,149 ­ population : 30,372 ­ land area : 47,890,000 ­ population : 1,148,401 ­ population : 135,851 Province: Alberta ­ land area : 54,029,000 ­ land area : 564,000 ­ gdp : $187,493.00 Province: Nunavut Province: Nova Scotia ­ population : 3,290,350 ­ gdp : $1,115.00 ­ gdp : $28,803.00 ­ land area : 61,400,000 ­ population : 29,474 ­ population : 913,462 Province: Northwest Territories ­ land area : 192,138,000 ­ land area : 5,277,000 ­ gdp : $4,138.00 Province: Ontario Province: Newfoundland and Labrador ­ population : 41,464 ­ gdp : $536,340.00 ­ gdp : $19,696.00 ­ land area : 112,984,000 ­ population : 12,160,282 ­ population : 505,469 11
  • 12. Step 4 : Exposing it from retro import * class ProvincesAPI(Component): def __init__( self, data ): Component.__init__(self) self.data = data @expose(GET=quot;/api/provinces/allquot;) def list( self ): return list(l[0] for l in self.data) @expose(GET=quot;/api/province/{name:string}quot;) def province( self, name ): name = name.lower().replace(quot; quot;,quot;quot;) return ([l for l in self.data if l[0].lower().replace(quot; quot;,quot;quot;) == name] or [None])[0] 12
  • 13. Step 4 : Exposing it Import retro from retro import * class ProvincesAPI(Component): def __init__( self, data ): Component.__init__(self) self.data = data @expose(GET=quot;/api/provinces/allquot;) def list( self ): return list(l[0] for l in self.data) @expose(GET=quot;/api/province/{name:string}quot;) def province( self, name ): name = name.lower().replace(quot; quot;,quot;quot;) return ([l for l in self.data if l[0].lower().replace(quot; quot;,quot;quot;) == name] or [None])[0] 13
  • 14. Step 4 : Exposing it from retro import * class ProvincesAPI(Component): Decorate the def __init__( self, data ): method to Component.__init__(self) expose it over HTTP self.data = data @expose(GET=quot;/api/provinces/allquot;) def list( self ): return list(l[0] for l in self.data) @expose(GET=quot;/api/province/{name:string}quot;) def province( self, name ): name = name.lower().replace(quot; quot;,quot;quot;) return ([l for l in self.data if l[0].lower().replace(quot; quot;,quot;quot;) == name] or [None])[0] 14
  • 15. Step 4 : Exposing it from retro import * class ProvincesAPI(Component): Use HTTP methodsself, data ): def __init__( as keyword Component.__init__(self) arguments self.data = data @expose(GET=quot;/api/provinces/allquot;) def list( self ): return list(l[0] for l in self.data) @expose(GET=quot;/api/province/{name:string}quot;) def province( self, name ): name = name.lower().replace(quot; quot;,quot;quot;) return ([l for l in self.data if l[0].lower().replace(quot; quot;,quot;quot;) == name] or [None])[0] 15
  • 16. Step 4 : Exposing it from retro import * class ProvincesAPI(Component): def __init__( self, data ): Specify URL to respond to Component.__init__(self) self.data = data @expose(GET=quot;/api/provinces/allquot;) def list( self ): return list(l[0] for l in self.data) @expose(GET=quot;/api/province/{name:string}quot;) def province( self, name ): name = name.lower().replace(quot; quot;,quot;quot;) return ([l for l in self.data if l[0].lower().replace(quot; quot;,quot;quot;) == name] or [None])[0] 16
  • 17. Step 4 : Exposing it from retro import * class ProvincesAPI(Component): def __init__( self, data ): Component.__init__(self) self.data = data @expose(GET=quot;/api/provinces/allquot;)Pass parameters from URL def list( self ): to Python method return list(l[0] for l in self.data) @expose(GET=quot;/api/province/{name:string}quot;) def province( self, name ): name = name.lower().replace(quot; quot;,quot;quot;) return ([l for l in self.data if l[0].lower().replace(quot; quot;,quot;quot;) == name] or [None])[0] 17
  • 18. Step 4 : Exposing it @expose(GET=quot;/api/province/{province:string}/populationquot;) def population( self, province ): return self.province(province)[1] @expose(GET=quot;/api/province/{province:string}/gdpquot;) def gdp( self, province ): return self.province(province)[2] @expose(GET=quot;/api/province/{province:string}/landAreaquot;) def landArea( self, province ): return self.province(province)[3] Don't change a line in your existing code 18
  • 19. Step 5 : Running it if __name__ == quot;__main__quot;: run(components=[ProvincesAPI(DATA)],port=8000) curl localhost:8000/api/provinces/all [quot;British Columbiaquot;,quot;Yukonquot;,quot;Albertaquot;,quot;Northwest Territoriesquot;,quot;Saskatchewanquot;,quot;Manitobaquot;,quot;Nunavutquot;,quot;Ontarioquot;,quot;Quebecquot;,quot;New Brunswickquot;, quot;Prince Edward Islandquot;,quot;Nova Scotiaquot;,quot;Newfoundland and Labradorquot;] curl localhost:8000/api/province/quebec/gdp quot;$265,888.00quot; curl localhost:8000/api/province/quebec/population quot;7,546,131quot; curl localhost:8000/api/province/quebec/landArea quot;132,970,000quot; 19
  • 20. Step 5 : Running it if __name__ == quot;__main__quot;: run(components=[ProvincesAPI(DATA)],port=8000) Runs the Retro embedded curl localhost:8000/api/provinces/all web server [quot;British Columbiaquot;,quot;Yukonquot;,quot;Albertaquot;,quot;Northwest Territoriesquot;,quot;Saskatchewanquot;,quot;Manitobaquot;,quot;Nunavutquot;,quot;Ontarioquot;,quot;Quebecquot;,quot;New Brunswickquot;, quot;Prince Edward Islandquot;,quot;Nova Scotiaquot;,quot;Newfoundland and Labradorquot;] curl localhost:8000/api/province/quebec/gdp quot;$265,888.00quot; curl localhost:8000/api/province/quebec/population quot;7,546,131quot; curl localhost:8000/api/province/quebec/landArea quot;132,970,000quot; 20
  • 21. Step 5 : Running it if __name__ == quot;__main__quot;: run(components=[ProvincesAPI(DATA)],port=8000) curl localhost:8000/api/provinces/all [quot;British Columbiaquot;,quot;Yukonquot;,quot;Albertaquot;,quot;Northwest Territoriesquot;,quot;Saskatchewanquot;,quot;Manitobaquot;,quot;Nunavutquot;,quot;Ontarioquot;,quot;Quebecquot;,quot;New Brunswickquot;, quot;Prince Edward Islandquot;,quot;Nova Scotiaquot;,quot;Newfoundland and Labradorquot;] curl localhost:8000/api/province/quebec/gdp quot;$265,888.00quot; Data is returned as JSON curl localhost:8000/api/province/quebec/population quot;7,546,131quot; curl localhost:8000/api/province/quebec/landArea quot;132,970,000quot; 21
  • 22. Step 6 : Surprise ! if __name__ == quot;__main__quot;: api = ProvincesAPI(DATA) for p in api.list(): print quot;Province:quot;, p print quot;­ gdp :quot;, api.gdp(p) print quot;­ population :quot;, api.population(p) print quot;­ land area :quot;, api.landArea(p) run(components=[api],port=8000) Your API object remains usable as it was before in Python 22
  • 23. Retro in a Nutshell WSGI­based Works with CGI, FCGI, SCGI, WSGI on Apache, Lighttpd, Nginx HTTP Streaming Uses WSGI generator (yield) support Standalone Comes with embedded web server and event reactor Lightweight Minimal API, small footprint 23
  • 24. The end Thank you ! www.github.com/sebastien/retro www.datalicious.ca sebastien@datalicious.ca