This repository has been archived on 2024-07-04. You can view files and clone it, but cannot push or open issues or pull requests.
worblehat-old/cli/fileformat.py
oysteini e0aa1d53d2 Såvidt begynt på nytt kommandolinjegrensesnitt.
* Kopiert inn noe dokumentasjon (filformat og kommandolinjeargumenter)
  fra forrige forsøk (som var i python-katalogen).

* Kopiert implementajonen av filformatet fra forrige forsøk.

* Kopiert nyttige ting fra mdboh, samt noe fra forrige inkarnasjon av
  kommandolinjegrensesnittet her, til util.py

* Skrevet litt testkode i worblehat.py.
2011-10-08 09:06:15 +00:00

181 lines
5.6 KiB
Python

import types
# The possible fields for each type of object.
#
# Each field is a tuple (fieldname, fieldtype). Fieldtype is either
# 's' (string), 'd' (dictionary, where the values are lists of
# strings), 'l' (list of strings).
fields = {
'book':
[('isbn', 's'), ('title', 's'), ('category', 's'),
('subtitle', 's'), ('persons', 'd'), ('publisher', 's'),
('published_year', 'i'), ('edition', 'i'), ('num_pages', 'i'),
('series', 's'), ('description', 's'), # TODO picture, thumbnail
('references', 'd')],
'person':
[('id', 's'), ('first_name', 's'), ('last_name', 's')],
'category':
[('id', 's'), ('name', 's'), ('placement', 'l')] }
# Fields associated with each action.
#
# The 'type' is a key in the fields dictionary, indicating the set of
# fields which can be used with the action. The 'required' list is a
# list of fields which must be present for the action to be accepted.
action_fields = {
'new-book':
{ 'type': 'book',
'required': ['isbn', 'title', 'category'] },
'edit-book':
{ 'type': 'book',
'required': ['isbn'] },
'delete-book':
{ 'type': 'book',
'required': ['isbn'] },
'new-person':
{ 'type': 'person',
'required': ['id', 'first_name', 'last_name'] },
'edit-person':
{ 'type': 'person',
'required': ['id'] },
'delete-person':
{ 'type': 'person',
'required': ['id'] },
'new-category':
{ 'type': 'category',
'required': ['id', 'name'] },
'edit-category':
{ 'type': 'category',
'required': ['id'] },
'delete-category':
{ 'type': 'category',
'required': ['id'] } }
class CommitFormatSyntaxError(Exception):
pass
def read_field_value_str(val):
return '\n'.join(map(lambda x: x.strip(), val.split('\n'))).strip()
def read_field_value_int(val):
if val.strip() == '':
return None
return int(val.strip())
def read_field_value_dict(val):
d = {}
if val.strip() == '':
return d
for line in val.strip().split('\n'):
key, value = line.strip().split(' ', 1)
if key in d:
d[key].append(value)
else:
d[key] = [value]
return d
def read_field_value_list(val):
return val.strip().split(' ')
def read_action(text):
'''
Parse text as an action, returning a dictionary.
'''
lines = text.split('\n')
print 'reading action'
print 'lines:'
print lines
d = {}
lastfield = None
for line in lines:
if len(line) == 0:
raise CommitFormatSyntaxError('Empty line in action')
if line[0] in [' ', '\t']: # continuation line
if not lastfield:
raise CommitFormatSyntaxError('First line is continuation line: ' + line)
d[lastfield] = d[lastfield] + '\n' + line.strip()
else:
field, value = line.split(':', 1)
d[field] = value.strip()
lastfield = field
if 'action' not in d:
raise CommitFormatSyntaxError('Missing \'action\' field')
action = d['action']
print 'dict:'
print d
for field in action_fields[action]['required']:
if field not in d:
raise CommitFormatSyntaxError('Missing required field \'%s\' in \'%s\' action' % (field, action))
data_type = action_fields[action]['type']
result = { 'action': action }
for field, ftype in fields[data_type]:
if field in d:
reader = { 's': read_field_value_str,
'i': read_field_value_int,
'd': read_field_value_dict,
'l': read_field_value_list }[ftype]
result[field] = reader(d[field])
return result
def read_actionlist(text):
'''
Parse text as a list of actions.
The result is a list of dictionaries.
'''
return map(lambda x: read_action(x.strip()),
text.split('\n\n'))
def write_field_value_str(val):
lines = ''
if not val:
val = ''
val = unicode(val)
value_lines = val.split('\n')
for l in value_lines:
lines += ' ' + l + '\n'
return lines
def write_field_value_dict(val):
lines = '\n'
for (key,values) in val.items():
for single_value in values:
lines += ' ' + key + ' ' + unicode(single_value) + '\n'
return lines
def write_field_value_list(val):
lines = ''
for single_value in val:
lines += ' ' + unicode(single_value)
return lines
def make_comment(s):
return '\n'.join(map(lambda x: '# ' + x,
s.split('\n'))) + '\n'
def write_action(d):
if type(d) in types.StringTypes:
return make_comment(d)
lines = ''
if 'comment' in d:
lines += make_comment(d['comment'])
action = d['action']
lines += 'action: ' + action + '\n'
data_type = action_fields[action]['type']
for field, ftype in fields[data_type]:
if field in d:
value_writer = {'s': write_field_value_str,
'i': write_field_value_str,
'd': write_field_value_dict,
'l': write_field_value_list}[ftype]
lines += field + ':' + value_writer(d[field])
return lines
def write_actionlist(actions):
return '\n'.join(map(write_action, actions))
# test: print write_actionlist([{'comment':'Foo!\nBar!','action':'new-book','isbn':'434545'},{'action':'edit-book','isbn':'654654745','persons':{'author':['ab','foo'],'illustrator':['moo']}},'This\nis\na\ncomment.',{'action':'edit-category','id':'matematikk','name':'Matematikk','placement':['T10','T11']}])