updated from Atlas

This commit is contained in:
Luciano Ramalho
2015-04-15 04:48:25 -03:00
parent f4cdee2447
commit f86aee2785
78 changed files with 587 additions and 333 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -1,60 +0,0 @@
"""
explore1.py: Script to explore the OSCON schedule feed
# BEGIN EXPLORE1_DEMO
>>> from osconfeed import load
>>> raw_feed = load()
>>> feed = FrozenJSON(raw_feed) # <1>
>>> len(feed.Schedule.speakers) # <2>
357
>>> sorted(feed.Schedule.keys()) # <3>
['conferences', 'events', 'speakers', 'venues']
>>> for key, value in sorted(feed.Schedule.items()): # <4>
... print('{:3} {}'.format(len(value), key))
...
1 conferences
484 events
357 speakers
53 venues
>>> feed.Schedule.speakers[-1].name # <5>
'Carina C. Zona'
>>> talk = feed.Schedule.events[40] # <6>
>>> talk.name
'There *Will* Be Bugs'
>>> talk.speakers # <7>
[3471, 5199]
>>> talk.flavor # <8>
Traceback (most recent call last):
...
KeyError: 'flavor'
# END EXPLORE1_DEMO
"""
# BEGIN EXPLORE1
from collections import abc
class FrozenJSON:
"""A read-only façade for navigating a JSON-like object
using attribute notation
"""
def __init__(self, mapping):
self.__data = dict(mapping) # <1>
def __getattr__(self, name): # <2>
if hasattr(self.__data, name):
return getattr(self.__data, name) # <3>
else:
return FrozenJSON.build(self.__data[name]) # <4>
@classmethod
def build(cls, obj): # <5>
if isinstance(obj, abc.Mapping): # <6>
return cls(obj)
elif isinstance(obj, abc.MutableSequence): # <7>
return [cls.build(item) for item in obj]
else: # <8>
return obj
# END EXPLORE1

View File

@@ -1,50 +0,0 @@
"""
explore2.py: Script to explore the OSCON schedule feed
>>> from osconfeed import load
>>> raw_feed = load()
>>> feed = FrozenJSON(raw_feed)
>>> len(feed.Schedule.speakers)
357
>>> sorted(feed.Schedule.keys())
['conferences', 'events', 'speakers', 'venues']
>>> feed.Schedule.speakers[-1].name
'Carina C. Zona'
>>> talk = feed.Schedule.events[40]
>>> talk.name
'There *Will* Be Bugs'
>>> talk.speakers
[3471, 5199]
>>> talk.flavor
Traceback (most recent call last):
...
KeyError: 'flavor'
"""
# BEGIN EXPLORE2
from collections import abc
class FrozenJSON:
"""A read-only façade for navigating a JSON-like object
using attribute notation
"""
def __new__(cls, arg): # <1>
if isinstance(arg, abc.Mapping):
return super().__new__(cls) # <2>
elif isinstance(arg, abc.MutableSequence): # <3>
return [cls(item) for item in arg]
else:
return arg
def __init__(self, mapping):
self.__data = dict(mapping)
def __getattr__(self, name):
if hasattr(self.__data, name):
return getattr(self.__data, name)
else:
return FrozenJSON(self.__data[name]) # <4>
# END EXPLORE2

View File

@@ -1,32 +0,0 @@
{ "Schedule":
{ "conferences": [{"serial": 115 }],
"events": [
{ "serial": 34505,
"name": "Why Schools Don´t Use Open Source to Teach Programming",
"event_type": "40-minute conference session",
"time_start": "2014-07-23 11:30:00",
"time_stop": "2014-07-23 12:10:00",
"venue_serial": 1462,
"description": "Aside from the fact that high school programming...",
"website_url": "http://oscon.com/oscon2014/public/schedule/detail/34505",
"speakers": [157509],
"categories": ["Education"] }
],
"speakers": [
{ "serial": 157509,
"name": "Robert Lefkowitz",
"photo": null,
"url": "http://sharewave.com/",
"position": "CTO",
"affiliation": "Sharewave",
"twitter": "sharewaveteam",
"bio": "Robert ´r0ml´ Lefkowitz is the CTO at Sharewave, a startup..." }
],
"venues": [
{ "serial": 1462,
"name": "F151",
"category": "Conference Venues" }
]
}
}

View File

@@ -1,49 +0,0 @@
"""
osconfeed.py: Script to download the OSCON schedule feed
# BEGIN OSCONFEED_DEMO
>>> feed = load() # <1>
>>> sorted(feed['Schedule'].keys()) # <2>
['conferences', 'events', 'speakers', 'venues']
>>> for key, value in sorted(feed['Schedule'].items()):
... print('{:3} {}'.format(len(value), key)) # <3>
...
1 conferences
484 events
357 speakers
53 venues
>>> feed['Schedule']['speakers'][-1]['name'] # <4>
'Carina C. Zona'
>>> feed['Schedule']['speakers'][-1]['serial'] # <5>
141590
>>> feed['Schedule']['events'][40]['name']
'There *Will* Be Bugs'
>>> feed['Schedule']['events'][40]['speakers'] # <6>
[3471, 5199]
# END OSCONFEED_DEMO
"""
# BEGIN OSCONFEED
from urllib.request import urlopen
import warnings
import os
import json
URL = 'http://www.oreilly.com/pub/sc/osconfeed'
JSON = 'data/osconfeed.json'
def load():
if not os.path.exists(JSON):
msg = 'downloading {} to {}'.format(URL, JSON)
warnings.warn(msg) # <1>
with urlopen(URL) as remote, open(JSON, 'wb') as local: # <2>
local.write(remote.read())
with open(JSON) as fp:
return json.load(fp) # <3>
# END OSCONFEED

View File

@@ -1,45 +0,0 @@
"""
schedule1.py: traversing OSCON schedule data
# BEGIN SCHEDULE1_DEMO
>>> import shelve
>>> db = shelve.open(DB_NAME) # <1>
>>> if CONFERENCE not in db: # <2>
... load_db(db) # <3>
...
>>> speaker = db['speaker.3471'] # <4>
>>> type(speaker) # <5>
<class 'schedule1.Record'>
>>> speaker.name, speaker.twitter # <6>
('Anna Martelli Ravenscroft', 'annaraven')
>>> db.close() # <7>
# END SCHEDULE1_DEMO
"""
# BEGIN SCHEDULE1
import warnings
import osconfeed # <1>
DB_NAME = 'data/schedule1_db'
CONFERENCE = 'conference.115'
class Record:
def __init__(self, **kwargs):
self.__dict__.update(kwargs) # <2>
def load_db(db):
raw_data = osconfeed.load() # <3>
warnings.warn('loading ' + DB_NAME)
for collection, rec_list in raw_data['Schedule'].items(): # <4>
record_type = collection[:-1] # <5>
for record in rec_list:
key = '{}.{}'.format(record_type, record['serial']) # <6>
record['serial'] = key # <7>
db[key] = Record(**record) # <8>
# END SCHEDULE1

View File

@@ -1,132 +0,0 @@
"""
schedule2.py: traversing OSCON schedule data
>>> import shelve
>>> db = shelve.open(DB_NAME)
>>> if CONFERENCE not in db: load_db(db)
# BEGIN SCHEDULE2_DEMO
>>> DbRecord.set_db(db) # <1>
>>> event = DbRecord.fetch('event.33950') # <2>
>>> event # <3>
<Event 'There *Will* Be Bugs'>
>>> event.venue # <4>
<DbRecord serial='venue.1449'>
>>> event.venue.name # <5>
'Portland 251'
>>> for spkr in event.speakers: # <6>
... print('{0.serial}: {0.name}'.format(spkr))
...
speaker.3471: Anna Martelli Ravenscroft
speaker.5199: Alex Martelli
# END SCHEDULE2_DEMO
>>> db.close()
"""
# BEGIN SCHEDULE2_RECORD
import warnings
import inspect # <1>
import osconfeed
DB_NAME = 'data/schedule2_db' # <2>
CONFERENCE = 'conference.115'
class Record:
def __init__(self, **kwargs):
self.__dict__.update(kwargs)
def __eq__(self, other): # <3>
if isinstance(other, Record):
return self.__dict__ == other.__dict__
else:
return NotImplemented
# END SCHEDULE2_RECORD
# BEGIN SCHEDULE2_DBRECORD
class MissingDatabaseError(RuntimeError):
"""Raised when a database is required but was not set.""" # <1>
class DbRecord(Record): # <2>
__db = None # <3>
@staticmethod # <4>
def set_db(db):
DbRecord.__db = db # <5>
@staticmethod # <6>
def get_db():
return DbRecord.__db
@classmethod # <7>
def fetch(cls, ident):
db = cls.get_db()
try:
return db[ident] # <8>
except TypeError:
if db is None: # <9>
msg = "database not set; call '{}.set_db(my_db)'"
raise MissingDatabaseError(msg.format(cls.__name__))
else: # <10>
raise
def __repr__(self):
if hasattr(self, 'serial'): # <11>
cls_name = self.__class__.__name__
return '<{} serial={!r}>'.format(cls_name, self.serial)
else:
return super().__repr__() # <12>
# END SCHEDULE2_DBRECORD
# BEGIN SCHEDULE2_EVENT
class Event(DbRecord): # <1>
@property
def venue(self):
key = 'venue.{}'.format(self.venue_serial)
return self.__class__.fetch(key) # <2>
@property
def speakers(self):
if not hasattr(self, '_speaker_objs'): # <3>
spkr_serials = self.__dict__['speakers'] # <4>
fetch = self.__class__.fetch # <5>
self._speaker_objs = [fetch('speaker.{}'.format(key))
for key in spkr_serials] # <6>
return self._speaker_objs # <7>
def __repr__(self):
if hasattr(self, 'name'): # <8>
cls_name = self.__class__.__name__
return '<{} {!r}>'.format(cls_name, self.name)
else:
return super().__repr__() # <9>
# END SCHEDULE2_EVENT
# BEGIN SCHEDULE2_LOAD
def load_db(db):
raw_data = osconfeed.load()
warnings.warn('loading ' + DB_NAME)
for collection, rec_list in raw_data['Schedule'].items():
record_type = collection[:-1] # <1>
cls_name = record_type.capitalize() # <2>
cls = globals().get(cls_name, DbRecord) # <3>
if inspect.isclass(cls) and issubclass(cls, DbRecord): # <4>
factory = cls # <5>
else:
factory = DbRecord # <6>
for record in rec_list: # <7>
key = '{}.{}'.format(record_type, record['serial'])
record['serial'] = key
db[key] = factory(**record) # <8>
# END SCHEDULE2_LOAD