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

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]

Related

Dictionary and string indexing issue with vin number project

I am working on a project for a python class, where we have to create a vin number look up tool. This code below works so far for country and year made. However I am having an issue with how I am indexing the user input.
Sometimes a country is the first two characters, and other times the country code is only the first character. I do not how to get around this problem, I tried using an if else kind of method while iterating through the dictionary, but it did not work.
class vinfo():
def __init__(self):
""" Get user input """
vin = input("Enter Vin: ")
""" Stupidity check """
unaccepted_chars = [
"-","/",".",","," ","?",
"^","$","*","(",")","[",
"]","{","}","#","!","_",
"+","'","=","|","#","<",
">","`","~","&"
]
for char in vin:
if char in unaccepted_chars:
vin = vin.replace(char, "")
else:
print("", end = "")
""" Length check and index """
if len(vin) == 17:
self.country_filt1 = vin[0]
self.country_filt2 = vin[0:2]
self.engine_filt = vin[7]
self.year_filt = vin[9]
self.manufact_filt = vin[1:3]
self.manufact_filt1 = vin[1:4]
else:
print("You must've entered something really stupid.\n(must be 17 characters, letters are uppercase)")
""" Vin Code Data """
# each manufacturer seems to have multiple vins for different car styles
# and for different countries
manufact_codes = {
"1G1":"Chevy",
"":"",
}
year_codes = {
"M":"2021","L":"2020","K":"2019",
"J":"2018","H":"2017","G":"2016",
"F":"2015","E":"2014","D":"2013",
"C":"2012","B":"2011","A":"2010",
"9":"2009","8":"2008","7":"2007",
"6":"2006","5":"2005","4":"2004",
"3":"2003","2":"2002","1":"2001",
"Y":"2000","X":"1999","W":"1998",
"V":"1997","T":"1996","S":"1995",
"R":"1994","P":"1993","N":"1992",
"M":"1991","L":"1990","K":"1989",
"J":"1988","H":"1987","G":"1986",
"F":"1985","E":"1984","D":"1983",
"C":"1982","B":"1981","A":"1980"
}
country_codes = {
"1": "USA",
"4": "USA",
"5": "USA",
"7F": "USA",
"3X": "Mexico",
"37": "Mexico",
"3A": "Canada",
"3W": "Canada",
"W": "Germany",
"SA": "United Kingdom",
"SM": "United Kingdom",
"J": "Japan",
"KL": "Korea",
"KR": "Korea"
}
engine_codes = {
}
""" Define the vehicles attributes using the find() function below """
self.year = self.find(self.year_filt, year_codes)[0]
# self.country = self.find(self.country_filt, country_codes)[0]
# self.manufact = self.find(self.manufact_filt, manufact_codes)
self.engine = self.find(self.engine_filt, engine_codes)
""" Find country (different lengths of country codes) """
for key, value in country_codes.items():
if key == self.country_filt1:
country = value
elif key == self.country_filt2:
country = value
else:
country = "Unsupported code"
""" Same for manufacturer """
for key, value in manufact_codes.items():
if key == self.manufact_filt:
manufact = value
elif key == self.manufact_filt1:
manufact = value
else:
manufact = "Unsupported code"
self.info = print(f"Year: {self.year}\nManufacturer: {manufact}\nCountry: {country}\nEngine: {self.engine}")
""" search through the dictionaries """
def find(self, filt, dict_of_codes):
try:
info = [value for key, value in dict_of_codes.items() if key == filt]
except:
info = "Unsupported"
if len(info) > 1:
info += " (Could be any of these)"
return info

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

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

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.

Python API JSON dictionary loop

My code is working, but I know there has to be a more efficient way to accomplish it and better exception handling.
API data format per item:
{
u'logEnd':False,
u'logBegin':True,
u'links':{
u'self': u'https://192.168.15.140/api/fmc_config/v1/domain/e276abec-e0f2-11e3-8169-6d9ed49b625f/policy/accesspolicies/00505689-7E52-0ed3-0000-184683643989/accessrules/00505689-7E52-0ed3-0000-000268439552'
},
'sourceNetworks':'any-src',
u'name':u'Peer-to-Peer Blocking',
'sourceZones':'any-src-zn',
u'enabled':True,
'sourcePorts':'any-src-port',
u'logFiles':False,
u'vlanTags':{ },
u'applications':{
u'applications':[
{
u'type':u'Application',
u'id':u'61',
u'name':u'BitTorrent'
},
{
u'type':u'Application',
u'id':u'571',
u'name':u'BitTorrent tracker'
},
{
u'type':u'Application',
u'id':u'1214',
u'name':u'ExtraTorrent'
}
]
},
u'sendEventsToFMC':True,
u'action':u'BLOCK',
'destinationPorts':'any-dest-port',
'destinationNetworks':'any-dest',
u'variableSet':{
u'type':u'VariableSet',
u'name':u'Default Set',
u'id':u'76fa83ea-c972-11e2-8be8-8e45bb1343c0'
},
u'type':u'AccessRule',
u'id':u'00505689-7E52-0ed3-0000-000268439552',
'destinationZones':'any-dst-zn',
u'metadata':{
u'category':u'--Undefined--',
u'accessPolicy':{
u'type':u'AccessPolicy',
u'name':u'PVmain1-ACPolicy-201610251131',
u'id':u'00505689-7E52-0ed3-0000-184683643989'
},
u'section':u'Mandatory',
u'domain':{
u'type':u'Domain',
u'name':u'Global',
u'id':u'e276abec-e0f2-11e3-8169-6d9ed49b625f'
},
u'timestamp':1482339574186
}
}
Working Python Script
for i in results:
response = requests.request("GET", i, headers=headers, verify=False)
raw=response.json()
raw.setdefault('name', "noname_rule")
raw.setdefault('action', "no_action")
raw.setdefault('sourceNetworks', "any-src")
raw.setdefault('destinationNetworks', "any-dest")
raw.setdefault('sourcePorts', "any-src-port")
raw.setdefault('destinationPorts', "any-dest-port")
raw.setdefault('sourceZones', "any-src-zn")
raw.setdefault('destinationZones', "any-dst-zn")
interesting_keys = ('name', 'action','sourceZones', 'sourceNetworks', 'sourcePorts', 'destinationZones', 'destinationNetworks', 'destinationPorts' )
subdict = {x: raw.get(x, "any") for x in interesting_keys if x in raw}
if 'objects' in subdict['sourceZones']:
srczn = subdict['sourceZones']['objects'][0]['name']
elif 'literals' in subdict['sourceZones']:
srczn = subdict['sourceZones']['literals'][0]['port']
else :
srczn = subdict['sourceZones']
if 'objects' in subdict['sourceNetworks']:
srcnet = subdict['sourceNetworks']['objects'][0]['name']
elif 'literals' in subdict['sourceNetworks']:
srcnet = subdict['sourceNetworks']['literals'][0]['value']
else :
srcnet = subdict['sourceNetworks']
if 'objects' in subdict['sourcePorts']:
srcprt = subdict['sourcePorts']['objects'][0]['name']
elif 'literals' in subdict['sourcePorts']:
srcprt = subdict['sourcePorts']['literals'][0]['port']
else :
srcprt = subdict['sourcePorts']
if 'objects' in subdict['destinationZones']:
dstzn = subdict['destinationZones']['objects'][0]['name']
elif 'literals' in subdict['destinationZones']:
dstzn = subdict['destinationZones']['literals'][0]['port']
else :
dstzn = subdict['destinationZones']
if 'objects' in subdict['destinationNetworks']:
dstnet = subdict['destinationNetworks']['objects'][0]['name']
elif 'literals' in subdict['destinationNetworks']:
dstnet = subdict['destinationNetworks']['literals'][0]['value']
else :
dstnet = subdict['destinationNetworks']
if 'objects' in subdict['destinationPorts']:
dstprt = subdict['destinationPorts']['objects'][0]['name']
elif 'literals' in subdict['destinationPorts']:
try:
dstprt = subdict['destinationPorts']['literals'][0]['port']
except KeyError:
dstprt = "0"
else :
dstprt = subdict['destinationPorts']
#print >> target, "%d,%s,%s,%s,%s,%s,%s,%s,%s" %(number, subdict['name'],subdict['action'],srczn,srcnet,srcprt,dstzn,dstnet,dstprt)
#print "%d,%s,%s,%s,%s,%s,%s,%s,%s" %(number, subdict['name'],subdict['action'],srczn,srcnet,srcprt,dstzn,dstnet,dstprt)
number+=1
time.sleep(.5)
print raw
Can you suggest other ways that would improve error handling, performance, readability, etc?
Whenever you see repeated code, perhaps it could be collapsed into one function that can reused over and over? Refactoring the code this way probably doesn't make it faster, but it does make it easier to read and understand.
def getSubdictData(subdict, fieldname, prop2):
if 'objects' in subdict[fieldname]:
return subdict[fieldname]['objects'][0]['name']
elif 'literals' in subdict[fieldname]:
if prop2 in subdict[fieldname]['literals'][0]
return subdict[fieldname]['literals'][0][prop2]
else:
return "0"
else :
return subdict[fieldname]
for i in results:
...
srczn = getSubdictData(subdict, 'sourceZones', 'port')
srcnet = getSubdictData(subdict, 'sourceNetworks', 'value')
srcprt = getSubdictData(subdict, 'sourcePorts', 'port')
dstzn = getSubdictData(subdict, 'destinationZones', 'port')
dstnet = getSubdictData(subdict, 'destinationNetworks', 'value')
dstnet = getSubdictData(subdict, 'destinationPorts', 'port')
...
Also note that I removed the try-catch you were using to detect if a field existed or not. If the object/code provides a way for you to determine that this field existed or not, we should use that instead of relying on a sloppy try catch to perform our logical operations. Try catches used like this are hard to read and perform badly. In this case it wouldn't matter, but its good practice not to abuse try catches like this.

Python utility for parsing blocks?

I have a file that starts something like:
databaseCons = {
main = {
database = "readable_name",
hostname = "hostdb1.serv.com",
instances= {
slaves = {
conns = "8"
}
}
maxconns = "5",
user = "user",
pass = "pass"
}
}
So, what I'd like to do is parse this out into a dict of sub-dicts, something like:
{'main': {'database': 'readable_name', 'hostname': 'hostdb1.serv.com', 'maxconns': '5', 'instances': {'slave': {'maxCount': '8'}}, 'user': 'user', 'pass': 'pass'}}
I think the above makes sense... but please feel free to edit this if it doesn't. Basically I want the equivalent of:
conns = '8'
slave = dict()
slave['maxCount'] = conns
instances = dict()
instances['slave'] = slave
database = 'readable_name'
hostname = 'hostdb1.serv.com'
maxconns = '5'
user = 'user'
pas = 'pass'
main = dict()
main['database'] = database
main['hostname'] = hostname
main['instances'] = instances
main['maxconns'] = maxconns
main['user'] = user
main['pass'] = pas
databaseCons = dict()
databaseCons['main'] = main
Are there any modules out there that can handle this sort of parsing? Even what I've suggested above looks messy.. there's got to be a better way I'd imagine.
Here is a pyparsing parser for your config file:
from pyparsing import *
def to_dict(t):
return {k:v for k,v in t}
series = Forward()
struct = Suppress('{') + series + Suppress('}')
value = quotedString.setParseAction(removeQuotes) | struct
token = Word(alphanums)
assignment = Group(token + Suppress('=') + value + Suppress(Optional(",")))
series << ZeroOrMore(assignment).setParseAction(to_dict)
language = series + stringEnd
def config_file_to_dict(filename):
return language.parseFile(filename)[0]
if __name__=="__main__":
from pprint import pprint
pprint(config_file_to_dict('config.txt'))

Categories

Resources