pydocumentdb CosmosDb Python - How to add several entries to the same document - python

I try to add several entries tho the same document in Cosmo Db with Python using the library pydocumentdb
I thought that was possible with the function CreateDocuments
Creation of the Document with one entry works
def GetSalesOrder(document_id):
# notice new fields have been added to the sales order
order2 = {'id' : document_id,
'account_number' : 'Account2',
'purchase_order_number' : 'PO15428132599',
'order_date' : datetime.date(2005,7,11).strftime('%c'),
'due_date' : datetime.date(2005,7,21).strftime('%c'),
'shipped_date' : datetime.date(2005,7,15).strftime('%c'),
'subtotal' : 6107.0820,
'tax_amount' : 586.1203,
'freight' : 183.1626,
'discount_amt' : 1982.872,
'total_due' : 4893.3929,
'items' : [
{'order_qty' : 3,
'product_code' : 'A-123', # notice how in item details we no longer reference a ProductId
'product_name' : 'Product 1', # instead we have decided to denormalise our schema and include
'currency_symbol' : '$', # the Product details relevant to the Order on to the Order directly
'currecny_code' : 'USD', # this is a typical refactor that happens in the course of an application
'unit_price' : 17.1, # that would have previously required schema changes and data migrations etc.
'line_price' : 5.7
}
],
'ttl' : 60 * 60 * 24 * 30
}
return order2
coll_link = database_link + '/colls/sales'
print('\n1.2 Creating collection\n')
collection = client.CreateCollection(database_link,
{ 'id': "sales" })
print('\n1.2 Creating document\n')
sales_order = DocumentManagement.GetSalesOrder("SalesOrder")
client.CreateDocument(coll_link, sales_order)
Then i try to reuse this code with a different entry into the same document but my program fails with :
Top level Error: args:('document is None.',), message:N/A
Thanks for your help
The complete code that fails
import pydocumentdb.documents as documents
import pydocumentdb.document_client as document_client
import pydocumentdb.errors as errors
import datetime
import config as cfg
HOST = cfg.settings['host']
MASTER_KEY = cfg.settings['master_rw_key']
DATABASE_ID = cfg.settings['database_id']
COLLECTION_ID = cfg.settings['collection_id']
database_link = 'dbs/' + DATABASE_ID
collection_link = database_link + '/colls/' + COLLECTION_ID
class IDisposable:
""" A context manager to automatically close an object with a close method
in a with statement. """
def __init__(self, obj):
self.obj = obj
def __enter__(self):
return self.obj # bound to target
def __exit__(self, exception_type, exception_val, trace):
# extra cleanup in here
self = None
class DocumentManagement:
#staticmethod
def CreateDocuments(client):
coll_link = database_link + '/colls/sales'
print('\n1.2 Creating collection\n')
collection = client.CreateCollection(database_link,
{ 'id': "sales" })
print('\n1.2 Creating document\n')
sales_order = DocumentManagement.GetSalesOrder("SalesOrder")
client.CreateDocument(coll_link, sales_order)
#staticmethod
def AddEntry(client):
coll_link = database_link + '/colls/sales' #+ '/docs/SalesOrder'
print('\n1.2 Creating row\n')
sales_order = DocumentManagement.GetSalesOrder2("SalesOrder")
client.CreateDocument(coll_link, sales_order)
#staticmethod
def CreateStoredProcedure(client):
coll_link = database_link + '/colls/sales'
sproc1 = {
'id': 'countDocuments',
'body': (
'function () {' +
' var collection = getContext().getCollection(); ' +
' collection.queryDocuments(' +
' collection.getSelfLink(),' +
' \'SELECT VALUE COUNT(SalesOrder.id) FROM SalesOrder\',' +
' function(error, result) {' +
' if (error) throw error;' +
' var count = result[0];' +
' getContext().getResponse().setBody(count);' +
' }' +
' );' +
' }'
)
}
print('\n1.2 Creating sproc\n')
retrieved_sproc = client.CreateStoredProcedure(coll_link, sproc1)
#staticmethod
def CountEntries(client):
coll_link = database_link + '/colls/sales'
sproc_link = coll_link + '/sprocs/countDocuments'
print('\n1.2 Counting rows\n')
#sales_order = DocumentManagement.getSalesOrder2("SalesOrder")
#client.CreateDocument(coll_link, sales_order)
params = {}
options = {}
options['enableCrossPartitionQuery'] = True
result = client.ExecuteStoredProcedure(sproc_link, params, options)
print(result)
#staticmethod
def DeleteCollection(client):
coll_link = database_link + '/colls/sales'
print('\n1.2 Delete collection\n')
client.DeleteCollection(coll_link)
#staticmethod
def DeleteDocument(client, doc_id):
coll_link = database_link + '/colls/sales'
print('\n1.2 Deleting Document by Id\n')
doc_link = coll_link + '/docs/' + doc_id
client.DeleteDocument(doc_link)
#staticmethod
def GetSalesOrder(document_id):
# notice new fields have been added to the sales order
order2 = {'id' : document_id,
'account_number' : 'Account2',
'purchase_order_number' : 'PO15428132599',
'order_date' : datetime.date(2005,7,11).strftime('%c'),
'due_date' : datetime.date(2005,7,21).strftime('%c'),
'shipped_date' : datetime.date(2005,7,15).strftime('%c'),
'subtotal' : 6107.0820,
'tax_amount' : 586.1203,
'freight' : 183.1626,
'discount_amt' : 1982.872,
'total_due' : 4893.3929,
'items' : [
{'order_qty' : 3,
'product_code' : 'A-123', # notice how in item details we no longer reference a ProductId
'product_name' : 'Product 1', # instead we have decided to denormalise our schema and include
'currency_symbol' : '$', # the Product details relevant to the Order on to the Order directly
'currecny_code' : 'USD', # this is a typical refactor that happens in the course of an application
'unit_price' : 17.1, # that would have previously required schema changes and data migrations etc.
'line_price' : 5.7
}
],
'ttl' : 60 * 60 * 24 * 30
}
return order2
#staticmethod
def GetSalesOrder2(document_id):
order = {'id' : document_id, 'account_number' : 'Account3',#
'purchase_order_number' : 'PO15428132601',
'order_date' : datetime.date(2005,7,11).strftime('%c'),
'due_date' : datetime.date(2005,7,21).strftime('%c'),
'shipped_date' : datetime.date(2005,7,15).strftime('%c'),
'subtotal' : 6107.0820,
'tax_amount' : 586.1203,
'freight' : 183.1626,
'discount_amt' : 1982.872,
'total_due' : 4893.3929,
'items' : [
{'order_qty' : 3,
'product_code' : 'A-123', # notice how in item details we no longer reference a ProductId
'product_name' : 'Product 1', # instead we have decided to denormalise our schema and include
'currency_symbol' : '$', # the Product details relevant to the Order on to the Order directly
'currecny_code' : 'USD', # this is a typical refactor that happens in the course of an application
'unit_price' : 17.1, # that would have previously required schema changes and data migrations etc.
'line_price' : 5.7
}
],
'ttl' : 60 * 60 * 24 * 30
}
def run_sample():
with IDisposable(document_client.DocumentClient(HOST, {'masterKey': MASTER_KEY} )) as client:
try:
DocumentManagement.CreateDocuments(client)
DocumentManagement.CreateStoredProcedure(client)
DocumentManagement.CountEntries(client)
DocumentManagement.AddEntry(client)
DocumentManagement.CountEntries(client)
DocumentManagement.DeleteDocument(client,'SalesOrder')
DocumentManagement.DeleteCollection(client)
except errors.HTTPFailure as e:
print('\nrun_sample has caught an error. {0}'.format(e.message))
finally:
print("\nrun_sample done")
if __name__ == '__main__':
try:
run_sample()
except Exception as e:
print("Top level Error: args:{0}, message:N/A".format(e.args))

The reason your code is failing is because your GetSalesOrder2 method is not returning anything (or in other words returning an undefined object). If you look closely it is missing return statement. Please change this method to something like:
def GetSalesOrder2(document_id):
order = {'id' : document_id, 'account_number' : 'Account3',#
'purchase_order_number' : 'PO15428132601',
'order_date' : datetime.date(2005,7,11).strftime('%c'),
'due_date' : datetime.date(2005,7,21).strftime('%c'),
'shipped_date' : datetime.date(2005,7,15).strftime('%c'),
'subtotal' : 6107.0820,
'tax_amount' : 586.1203,
'freight' : 183.1626,
'discount_amt' : 1982.872,
'total_due' : 4893.3929,
'items' : [
{'order_qty' : 3,
'product_code' : 'A-123', # notice how in item details we no longer reference a ProductId
'product_name' : 'Product 1', # instead we have decided to denormalise our schema and include
'currency_symbol' : '$', # the Product details relevant to the Order on to the Order directly
'currecny_code' : 'USD', # this is a typical refactor that happens in the course of an application
'unit_price' : 17.1, # that would have previously required schema changes and data migrations etc.
'line_price' : 5.7
}
],
'ttl' : 60 * 60 * 24 * 30
}
return order
Also, each document in a collection need to have a unique id so please define a different id for this document.

Related

How can I extract data and append it to current object in scrapy?

So my problem is this :
I have a webpage with list of products.
Every product has a lot of things defined in the attibutes of each div.
However, one of the field is ambigous so I decided to open the product page and get it from there where I also found some other data which I thought might be useful in my analysis.
However, when I merge the data, some columns are the same while others seem to be updated.
Here's the code :
import scrapy
from scrapy.utils.response import open_in_browser
class getSalesData(scrapy.Spider):
name = 'getsalesdata'
start_urls = ['https://link']
def __init__(self):
self.params = ['data-id-cod', 'id', 'data-name','data-area' ,'data-zone' ,'data-items','data-ssellertype' ,
'data-surface' ,'price' ,'tva' ,'mobile-container-url']
self.item = { "id_cod" : 'null',
"id" : 'null',
"tip_prop" : 'null',
"area" : 'null',
"zone" : 'null',
"no_items" : 'null',
"seller_type" : 'null',
"surface" : 'null',
"surface_orig" : 'null',
"price" : 'null',
"currency" : 'null',
"url" : 'null'
}
self.columns = { "data-id-cod" : 'id_cod',
"id" : 'id',
"data-name" : 'tip_prop',
"data-area" : 'area',
"data-zone" : 'zone',
"data-items" : 'nr_items',
"data-ssellertype" : 'seller_type',
"data-surface" : 'surface',
"price" : 'price',
"tva" : 'valuta',
"mobile-container-url" : 'url'
}
def parse(self, response):
item = self.item
for listing in response.css("div.box-an"):
if not 'box-an ' in listing.attrib['class']:
for parameter in self.params:
if parameter in ['price', 'tva']:
item[self.columns[parameter]] = \
(listing.css('span.' + parameter + '::text').get()).replace('.','') \
if (parameter in listing.get()) else item[self.columns[parameter]]
elif parameter in 'mobile-container-url':
url = listing.css('a.visible-xs.' + parameter).attrib['href'] \
if (parameter in listing.get()) else item[self.columns[parameter]]
#self.logger.info('----->>> At URL : ' + url)
item[self.columns[parameter]] = url
elif parameter in 'data-surface':
item['surface'] = str(int(listing.attrib[parameter])/100) \
if (int(listing.attrib[parameter])>1000) else listing.attrib[parameter]
item['surface_orig'] = listing.attrib[parameter] \
if (parameter in listing.get()) else item[self.columns[parameter]]
else:
item[self.columns[parameter]] = \
listing.attrib[parameter] if (parameter in listing.get()) else item[self.columns[parameter]]
request = scrapy.Request(url=item['url'],
callback=self.parseNextPage,
meta={'item' : item})
yield request
def parseNextPage(self, response):
item = response.meta['item']
self.logger.info('Running on : ' + item['url'])
#for spec in response.css('li.list-group-item.specificatii-oferta__lista--item'):
for spec in response.css('ul.list-tab'):
for lst in spec.css('li'):
field = lst.css('li::text').get()
#self.logger.info('Adding ' + field + '\n')
item[field] = lst.css('span::text').get()
return item
Here's the data (see the starred items which are the same):
id_cod id tip_prop no_items surface surface_all
*A2Q00LMBUS9 *XA2Q0001E *prodType1 2 41,21 mp *46.89 mp
*A2Q00LMBUS9 *XA2Q0001E *prodType1 3 140 mp *46.89 mp
I have a feeling that I don't understand how the self.item is updated and some data is being kept from previous run, maybe ?
UPDATE:
This is strange.
if I use this code :
request = scrapy.Request(url=item['url'],
callback=self.parseNextPage,
meta={'item' : {'id' : item['id'] ,
'id_cod' : item['id_cod'],
'area' : item['area'],
'nr_items' : item['nr_items'],
'seller_type' : item['seller_type'],
'surface' : item['suprafata'],
'tip_prop' : item['tip_prop'],
'url' : item['url'],
'currency' : item['valuta'],
'area' : item['zona']
}
}
)
It works fine. But if I use this code :
request = scrapy.Request(url=item['url'],
callback=self.parseNextPage,
meta={'item' : item})
It doesn't work anymore. Item and the dictionary I am passing above are identical.
Because item is passed to Request's meta as a reference and the memory it's referring to is reused between all products, that is being overwritten all the time.
To fix that remove declaring self.item in the constructor and simply create new item in the loop:
...
def init_item(self):
return { "id_cod" : 'null',
"id" : 'null',
"tip_prop" : 'null',
"area" : 'null',
"zone" : 'null',
"no_items" : 'null',
"seller_type" : 'null',
"surface" : 'null',
"surface_orig" : 'null',
"price" : 'null',
"currency" : 'null',
"url" : 'null'
}
def parse(self, response):
for listing in response.css("div.box-an"):
item = self.init_item()
if not 'box-an ' in listing.attrib['class']:
...

json response to python variable

In the following code (a html response), do I need to remove the "M18.high_52 = {" in the beginning and the "}" (in the very end) in order to assign it under a python json variable? Thanks!
Update:
I just want to get the securityCode and securityShortName. Both already done and I just want to see it could be simply it and not using the
x = r.text.replace("M18.high_52 = " ,"")
to assign to json.
M18.high_52 = {
"stockBeans" : [
{
"securityCode" : "00176",
"yearHigh" : "0.218",
"yearLow" : "0.121",
"percentageChange" : 14.737,
"priceChange" : 0.028,
"securityShortName" : "SUPERACTIVE GP",
"securityNameGCCS" : "先機企業集團",
"previousClosingPrice" : "0.19",
"nominalPrice" : "0.218",
"sharesTraded" : "400000",
"turnover" : "80726",
"highPrice" : "0.22",
"lowPrice" : "0.19"
}
,{
"securityCode" : "00532",
"yearHigh" : "0.71",
"yearLow" : "0.49",
"percentageChange" : 20.339,
"priceChange" : 0.12,
"securityShortName" : "WKK INTL (HOLD)",
"securityNameGCCS" : "王氏港建國際",
"previousClosingPrice" : "0.59",
"nominalPrice" : "0.71",
"sharesTraded" : "1122000",
"turnover" : "749480",
"highPrice" : "0.72",
"lowPrice" : "0.63"
}
],
"stockBeans.size" : 37
}
Update:
import json
import requests
###
def update52wHigh():
r = requests.get("http://money18.on.cc/js/real/52highlow/high_securityCode_b5_asc.js")
r.encoding = 'big5-hkscs'
x = r.text.replace("M18.high_52 = " ,"")
j = json.loads(x)
print (j["stockBeans"][0]["securityNameGCCS"])
importList = []
stockList = []
x=0
for stockBean in j["stockBeans"]:
stockName = stockBean["securityNameGCCS"]
stockNo = stockBean["securityCode"]
stockPrice = stockBean["nominalPrice"]
stockTurnover = stockBean["turnover"]
stockPercentageChange = stockBean["percentageChange"]
print (stockNo + " " +stockName)
if float(stockPrice) > 1:
stockList.append([])
stockList[x].append(stockNo)
stockList[x].append(stockPrice)
importList.append((stockNo,stockName,stockPrice,stockTurnover,stockPercentageChange))
x=x+1
update52wHigh()
No need to remove anything..You already have a response
This show work
import json
import requests
string_res = response.read().decode('utf-8')
json_object = json.loads(string_res)

How to create dependent dropdowns using Jupyter Widgets to get data from dict?

I am trying to assign two variables with values using Jupyter Dropdowns where the first dropdown is a data center, and the second is a site available within this data center so that I can use these variables further in the code.
I tried multiple examples from different articles, but I cannot find what I am missing.
I have the following Dict:
data_center_environments = {
'US': {
'data_center': 'us..com',
'api_keys': {
'sandbox' : '3_EV',
'dev_parent' : '3_hK',
'stage' :'3_GE',
'prod' : '3_NL',
}
},
'RU': {
'data_center': 'ru..com',
'api_keys': {
'stage_parent' : '3_sN',
'prod_parent' : '3_R9',
}
},
'CN': {
'data_center': 'cn..cn',
'api_keys': {
'stage_parent' : '3_3k',
'prod_parent' : '3_MH',
}
},
'EU': {
'data_center': 'eu..com',
'api_keys': {
'sandbox' : '3_7h',
}
},
}
I created two functions to get datacenter and site:
def get_dc(dc_select=None):
dc = data_center_environments.get(dc_select)['data_center']
return dc
def get_site_api_key(dc_select=None, site_select=None):
site_api_key = data_center_environments[dc_select]['api_keys'][site_select]
return site_api_key
Here I describe two dropdowns:
dc_s = widgets.Dropdown(
options = data_center_environments.keys(),
description = 'Data Center:',
disabled = False,
)
site_s = widgets.Dropdown(
options=list(data_center_environments[dc_s.value]['api_keys']),
description = 'API Key:',
disabled = False,
)
def on_value_change(change):
dc = change.new
site_s.options = data_center_environments[dc_s.value]['api_keys']
dc_s.observe(on_value_change, 'value')
This is how I invoke them on a Jupyter Notebook page:
domain = interactive(get_dc, dc_select = dc_s)
site = interactive(get_site_api_key, dc_select = dc_s, site_select = site_s)
display(domain)
display(site)
Issues:
0. I have 3 dropdowns instead of two
1. I am getting an exception when I change datacenter value
2. When I am trying to print "domain", "domain.value" I am getting "None" as an output
What I am trying to achieve:
In:
domain =
site =
print(domain, site)
Out:
Select Datacenter [Drop Down: 'US', 'CN', 'RU', etc] -> pick 'US'
Select Site [Dropdown 'US': 'prod', 'stage', 'dev_parent', 'sandbox'] -> select 'prod'
'us..com' , '3_NL'
What am I doing wrong? How to change my code to make it work?
Thank you!
I end up writing a function that returns a dict, and I just get values from it.
The code below is a textbook example from the Widgets Guide.
Solution:
dc = 'US'
domain = widgets.Dropdown(
options = list(data_center_environments),
description = 'Data Center:',
disabled = False,
)
site = widgets.Dropdown(
options=list(data_center_environments[dc]['api_keys']),
description = 'API Key:',
disabled = False,
)
def on_value_change(change):
dc = change.new
site.options = data_center_environments[dc]['api_keys']
domain.observe(on_value_change, 'value')
def creds(data_center, api_key, use_secret):
data_center = data_center_environments[domain.value]['data_center']
api_key = site.value
creds = dict()
creds['data_center'] = data_center
creds['api_key'] = api_key
return creds

How do I URL encode this

Need this:
POST&https%3A%2F%2Fsecure.trademe.co.nz%2FOauth%2FRequestToken&oauth_callback%3Dhttp%253A%252F%252Fwww.website-tm-access.co.nz%252Ftrademe-callback%26oauth_consumer_key%3DC74CD73FDBE37D29BDD21BAB54BC70E422%26oauth_nonce%3D7O3kEe%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1285532322%26oauth_version%3D1.0%26scope%3DMyTradeMeRead%252CMyTradeMeWrite
Myattempt:
New_base_string ="POST&https%3A%2F%2Fsecure.trademe.co.nz%2FOauth%2FRequestToken&oauth_callback%3Dhttp%253A%252F%252Fwww.website-tm-access.co.nz%252Ftrademe-callback%26oauth_consumer_key%" + str(consumer_key) +"3DC74CD73FDBE37D29BDD21BAB54BC70E422%26oauth_nonce%3" + str(nonce) + "%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3" + str(time) + "%26oauth_version%3D1.0%26scope%3DMyTradeMeRead%252CMyTradeMeWrite"
I just tried to append it to the end, will this work or will i need to append to a list and then encode?
so like this:
headers = { my_variable + other_variable }
authorization = '5C82CC6BC7C6472154FBC9CAB24A29A2 ' + ', '.join([key + '="' + urllib.parse.quote_plus(str(value)) + '"' for key, value in headers.items()])
General
If you want to URL encode parameters to your POST request the best way is:
import urllib
f = { 'eventName' : 'myEvent',
'eventDescription' : 'cool event',
'url' : 'http://www.google.com'}
print 'POST&%s' % urllib.urlencode(f)
Output:
POST&eventName=myEvent&url=http%3A%2F%2Fwww.google.com&eventDescription=cool+event
with Dictionary its not ordered if you want to order it just use a list
import urllib
f = [ ('eventName', 'myEvent'),
('eventDescription', 'cool event'),
('url', 'http://www.google.com')]
print 'POST&%s' % urllib.urlencode(f)
Output
POST&eventName=myEvent&eventDescription=cool+event&url=http%3A%2F%2Fwww.google.com
How to get your need this string (Python 3.5)
While the general example is tested in python 2.7, I wrote your example with python 3.5 code.
import urllib.parse
method = "POST"
url = "https://secure.trademe.co.nz/Oauth/RequestToken"
params = [('oauth_callback', 'http://www.website-tm-access.co.nz/trademe-callback'),
('oauth_consumer_key', 'C74CD73FDBE37D29BDD21BAB54BC70E422'),
('oauth_nonce', '7O3kEe'),
('oauth_signature_method', 'HMAC-SHA1'),
('oauth_timestamp', 1285532322),
('oauth_version', 1.0),
('scope', "MyTradeMeRead,MyTradeMeWrite")]
print('POST&%(url)s&%(params)s' % { 'url' : urllib.parse.quote_plus(url), 'params' : urllib.parse.quote_plus(urllib.parse.urlencode(params)) })
Output
POST&https%3A%2F%2Fsecure.trademe.co.nz%2FOauth%2FRequestToken&oauth_callback%3Dhttp%253A%252F%252Fwww.website-tm-access.co.nz%252Ftrademe-callback%26oauth_consumer_key%3DC74CD73FDBE37D29BDD21BAB54BC70E422%26oauth_nonce%3D7O3kEe%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1285532322%26oauth_version%3D1.0%26scope%3DMyTradeMeRead%252CMyTradeMeWrite

Recursive variable definitions in Python and F# (probably OCaml, too)

Given these F# type declarations...
type Message =
| MessageA
| MessageB
| MessageC
| MessageD
type State = {
Name:string
NextStateMap: Map<Message,State>
}
...is there an equally expressive definition of this specific state machine...
let rec state0 = { Name = "0"; NextStateMap = Map.ofList [ (MessageA,state1); (MessageB,state2)] }
and state1 = { Name = "1"; NextStateMap = Map.ofList [ (MessageB,state3)] }
and state2 = { Name = "2"; NextStateMap = Map.ofList [ (MessageA,state3)] }
and state3 = { Name = "3"; NextStateMap = Map.ofList [ (MessageC,state4)] }
and state4 = { Name = "4"; NextStateMap = Map.ofList [ (MessageD,state5)] }
and state5 = { Name = "5"; NextStateMap = Map.empty}
...with Python?
Note that via the "rec", we didn't have to do assignments in an order defined by a topological sort... (e.g. state0 is defined in terms of state1, even though state1 is defined later on).
P.S. The option of using strings as state identifiers...
stateMachine = {
"0" : { "A":"1", "B":"2"},
"1" : { "B":"3" },
...
...leaves open the case of invalid keys (i.e. invalid message specifiers in the state machine).
In Python I think you'd define the states and then set the map. Pseudo-code like:
state0 = State("0")
state1 = State("1")
... and so on ...
state0.next_states = {message_a: state1, message_b: state2 }
state1.next_states = {message_b: state3}
... and so on ...
## a generic state machine framework ###################
class Message(object):
"""
This represents a message being passed to the
state machine.
"""
def __init__(self, name):
self.name = name
def __str__(self):
return "Message(%r)" % self.name
def __call__(self, smap):
try:
return smap[self]
except KeyError:
raise Exception("invalid message: %s vs %s"
% (self, smap))
class MessageFactory(object):
"""
Since python doesn't have symbols, this automagically
creates the messages for you. (It's purely for
convenience, and you could just as easily instantiate
each message by hand.
"""
cache = {}
def __getattr__(self, name):
return self.cache.setdefault(name, Message(name))
class StateMachine(object):
"""
This keeps track of the state, of course. :)
"""
def __init__(self, state):
self.state = state
def __call__(self, msg):
self.state = self.state(msg)
## how to set it up: ###################################
msg = MessageFactory()
state =\
{
0 : lambda m: m({ msg.A : state[1],
msg.B : state[2] }),
1 : lambda m: m({ msg.B : state[3] }),
2 : lambda m: m({ msg.A : state[3] }),
3 : lambda m: m({ msg.C : state[4] }),
4 : lambda m: m({ msg.D : state[5] }),
5 : lambda m: m({ }),
}
## how to use it: ######################################
s = StateMachine(state[0])
s(msg.A)
assert s.state is state[1]

Categories

Resources