dynamic attributes, descriptors and first concurrency examples
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
"serial": 33451,
|
||||
"name": "Migrating to the Web Using Dart and Polymer - A Guide for Legacy OOP Developers",
|
||||
"event_type": "40-minute conference session",
|
||||
|
||||
|
||||
"time_start": "2014-07-23 17:00:00",
|
||||
"time_stop": "2014-07-23 17:40:00",
|
||||
"venue_serial": 1458,
|
||||
@@ -13304,4 +13304,4 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
23
metaprog/oscon-schedule/demo_schedule2.py
Normal file
23
metaprog/oscon-schedule/demo_schedule2.py
Normal file
@@ -0,0 +1,23 @@
|
||||
import shelve
|
||||
|
||||
from schedule2 import DB_NAME, CONFERENCE, load_db
|
||||
from schedule2 import DbRecord, Event
|
||||
|
||||
with shelve.open(DB_NAME) as db:
|
||||
if CONFERENCE not in db:
|
||||
load_db(db)
|
||||
|
||||
DbRecord.set_db(db)
|
||||
event = DbRecord.fetch('event.33950')
|
||||
print(event)
|
||||
print(event.venue)
|
||||
print(event.venue.name)
|
||||
for spkr in event.speakers:
|
||||
print('{0.serial}: {0.name}'.format(spkr))
|
||||
|
||||
print(repr(Event.venue))
|
||||
|
||||
event2 = DbRecord.fetch('event.33451')
|
||||
print(event2)
|
||||
print(event2.fetch)
|
||||
print(event2.venue)
|
||||
@@ -9,14 +9,21 @@ explore1.py: Script to explore the OSCON schedule feed
|
||||
357
|
||||
>>> sorted(feed.Schedule.keys()) # <3>
|
||||
['conferences', 'events', 'speakers', 'venues']
|
||||
>>> feed.Schedule.speakers[-1].name # <4>
|
||||
>>> 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] # <5>
|
||||
>>> talk = feed.Schedule.events[40] # <6>
|
||||
>>> talk.name
|
||||
'There *Will* Be Bugs'
|
||||
>>> talk.speakers # <6>
|
||||
>>> talk.speakers # <7>
|
||||
[3471, 5199]
|
||||
>>> talk.flavor # <7>
|
||||
>>> talk.flavor # <8>
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
KeyError: 'flavor'
|
||||
@@ -34,13 +41,13 @@ class FrozenJSON:
|
||||
"""
|
||||
|
||||
def __init__(self, mapping):
|
||||
self._data = dict(mapping) # <1>
|
||||
self.__data = dict(mapping) # <1>
|
||||
|
||||
def __getattr__(self, name): # <2>
|
||||
if hasattr(self._data, name):
|
||||
return getattr(self._data, name) # <3>
|
||||
if hasattr(self.__data, name):
|
||||
return getattr(self.__data, name) # <3>
|
||||
else:
|
||||
return FrozenJSON.build(self._data[name]) # <4>
|
||||
return FrozenJSON.build(self.__data[name]) # <4>
|
||||
|
||||
@classmethod
|
||||
def build(cls, obj): # <5>
|
||||
|
||||
@@ -40,11 +40,11 @@ class FrozenJSON:
|
||||
return arg
|
||||
|
||||
def __init__(self, mapping):
|
||||
self._data = dict(mapping)
|
||||
self.__data = dict(mapping)
|
||||
|
||||
def __getattr__(self, name):
|
||||
if hasattr(self._data, name):
|
||||
return getattr(self._data, name)
|
||||
if hasattr(self.__data, name):
|
||||
return getattr(self.__data, name)
|
||||
else:
|
||||
return FrozenJSON(self._data[name]) # <4>
|
||||
return FrozenJSON(self.__data[name]) # <4>
|
||||
# END EXPLORE2
|
||||
|
||||
@@ -10,10 +10,8 @@ schedule1.py: traversing OSCON schedule data
|
||||
>>> speaker = db['speaker.3471'] # <4>
|
||||
>>> type(speaker) # <5>
|
||||
<class 'schedule1.Record'>
|
||||
>>> speaker.name # <6>
|
||||
'Anna Martelli Ravenscroft'
|
||||
>>> speaker.twitter
|
||||
'annaraven'
|
||||
>>> speaker.name, speaker.twitter # <6>
|
||||
('Anna Martelli Ravenscroft', 'annaraven')
|
||||
>>> db.close() # <7>
|
||||
|
||||
# END SCHEDULE1_DEMO
|
||||
@@ -23,7 +21,7 @@ schedule1.py: traversing OSCON schedule data
|
||||
# BEGIN SCHEDULE1
|
||||
import warnings
|
||||
|
||||
import osconfeed
|
||||
import osconfeed # <1>
|
||||
|
||||
DB_NAME = 'data/schedule1_db'
|
||||
CONFERENCE = 'conference.115'
|
||||
@@ -31,17 +29,17 @@ CONFERENCE = 'conference.115'
|
||||
|
||||
class Record:
|
||||
def __init__(self, **kwargs):
|
||||
self.__dict__.update(kwargs) # <1>
|
||||
self.__dict__.update(kwargs) # <2>
|
||||
|
||||
|
||||
def load_db(db):
|
||||
raw_data = osconfeed.load() # <2>
|
||||
raw_data = osconfeed.load() # <3>
|
||||
warnings.warn('loading ' + DB_NAME)
|
||||
for collection, rec_list in raw_data['Schedule'].items(): # <3>
|
||||
record_type = collection[:-1] # <4>
|
||||
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']) # <5>
|
||||
record['serial'] = key # <6>
|
||||
db[key] = Record(**record) # <7>
|
||||
key = '{}.{}'.format(record_type, record['serial']) # <6>
|
||||
record['serial'] = key # <7>
|
||||
db[key] = Record(**record) # <8>
|
||||
|
||||
# END SCHEDULE1
|
||||
|
||||
@@ -56,15 +56,15 @@ class MissingDatabaseError(RuntimeError):
|
||||
|
||||
class DbRecord(Record): # <2>
|
||||
|
||||
_db = None # <3>
|
||||
__db = None # <3>
|
||||
|
||||
@staticmethod # <4>
|
||||
def set_db(db):
|
||||
DbRecord._db = db # <5>
|
||||
DbRecord.__db = db # <5>
|
||||
|
||||
@staticmethod # <6>
|
||||
def get_db():
|
||||
return DbRecord._db
|
||||
return DbRecord.__db
|
||||
|
||||
@classmethod # <7>
|
||||
def fetch(cls, ident):
|
||||
@@ -93,22 +93,23 @@ class Event(DbRecord): # <1>
|
||||
@property
|
||||
def venue(self):
|
||||
key = 'venue.{}'.format(self.venue_serial)
|
||||
return self.fetch(key) # <2>
|
||||
return self.__class__.fetch(key) # <2>
|
||||
|
||||
@property
|
||||
def speakers(self):
|
||||
if not hasattr(self, '_speaker_objs'): # <3>
|
||||
spkr_serials = self.__dict__['speakers'] # <4>
|
||||
self._speaker_objs = [self.fetch('speaker.{}'.format(key))
|
||||
for key in spkr_serials] # <5>
|
||||
return self._speaker_objs # <6>
|
||||
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'): # <7>
|
||||
if hasattr(self, 'name'): # <8>
|
||||
cls_name = self.__class__.__name__
|
||||
return '<{} {!r}>'.format(cls_name, self.name)
|
||||
else:
|
||||
return super().__repr__() # <8>
|
||||
return super().__repr__() # <9>
|
||||
# END SCHEDULE2_EVENT
|
||||
|
||||
|
||||
@@ -127,5 +128,5 @@ def load_db(db):
|
||||
for record in rec_list: # <7>
|
||||
key = '{}.{}'.format(record_type, record['serial'])
|
||||
record['serial'] = key
|
||||
db[key] = factory(**record) # <>
|
||||
db[key] = factory(**record) # <8>
|
||||
# END SCHEDULE2_LOAD
|
||||
|
||||
Reference in New Issue
Block a user