915 class simplekeyvaluefile(object): |
915 class simplekeyvaluefile(object): |
916 """A simple file with key=value lines |
916 """A simple file with key=value lines |
917 |
917 |
918 Keys must be alphanumerics and start with a letter, values must not |
918 Keys must be alphanumerics and start with a letter, values must not |
919 contain '\n' characters""" |
919 contain '\n' characters""" |
|
920 firstlinekey = '__firstline' |
920 |
921 |
921 def __init__(self, vfs, path, keys=None): |
922 def __init__(self, vfs, path, keys=None): |
922 self.vfs = vfs |
923 self.vfs = vfs |
923 self.path = path |
924 self.path = path |
924 |
925 |
925 def read(self): |
926 def read(self, firstlinenonkeyval=False): |
|
927 """Read the contents of a simple key-value file |
|
928 |
|
929 'firstlinenonkeyval' indicates whether the first line of file should |
|
930 be treated as a key-value pair or reuturned fully under the |
|
931 __firstline key.""" |
926 lines = self.vfs.readlines(self.path) |
932 lines = self.vfs.readlines(self.path) |
|
933 d = {} |
|
934 if firstlinenonkeyval: |
|
935 if not lines: |
|
936 e = _("empty simplekeyvalue file") |
|
937 raise error.CorruptedState(e) |
|
938 # we don't want to include '\n' in the __firstline |
|
939 d[self.firstlinekey] = lines[0][:-1] |
|
940 del lines[0] |
|
941 |
927 try: |
942 try: |
928 # the 'if line.strip()' part prevents us from failing on empty |
943 # the 'if line.strip()' part prevents us from failing on empty |
929 # lines which only contain '\n' therefore are not skipped |
944 # lines which only contain '\n' therefore are not skipped |
930 # by 'if line' |
945 # by 'if line' |
931 d = dict(line[:-1].split('=', 1) for line in lines if line.strip()) |
946 updatedict = dict(line[:-1].split('=', 1) for line in lines |
|
947 if line.strip()) |
|
948 if self.firstlinekey in updatedict: |
|
949 e = _("%r can't be used as a key") |
|
950 raise error.CorruptedState(e % self.firstlinekey) |
|
951 d.update(updatedict) |
932 except ValueError as e: |
952 except ValueError as e: |
933 raise error.CorruptedState(str(e)) |
953 raise error.CorruptedState(str(e)) |
934 return d |
954 return d |
935 |
955 |
936 def write(self, data): |
956 def write(self, data, firstline=None): |
937 """Write key=>value mapping to a file |
957 """Write key=>value mapping to a file |
938 data is a dict. Keys must be alphanumerical and start with a letter. |
958 data is a dict. Keys must be alphanumerical and start with a letter. |
939 Values must not contain newline characters.""" |
959 Values must not contain newline characters. |
|
960 |
|
961 If 'firstline' is not None, it is written to file before |
|
962 everything else, as it is, not in a key=value form""" |
940 lines = [] |
963 lines = [] |
|
964 if firstline is not None: |
|
965 lines.append('%s\n' % firstline) |
|
966 |
941 for k, v in data.items(): |
967 for k, v in data.items(): |
|
968 if k == self.firstlinekey: |
|
969 e = "key name '%s' is reserved" % self.firstlinekey |
|
970 raise error.ProgrammingError(e) |
942 if not k[0].isalpha(): |
971 if not k[0].isalpha(): |
943 e = "keys must start with a letter in a key-value file" |
972 e = "keys must start with a letter in a key-value file" |
944 raise error.ProgrammingError(e) |
973 raise error.ProgrammingError(e) |
945 if not k.isalnum(): |
974 if not k.isalnum(): |
946 e = "invalid key name in a simple key-value file" |
975 e = "invalid key name in a simple key-value file" |