def read_all_docs(fld): rst_files = glob.glob(fld + '/*.txt') mapfile_dict = {} dict_items = [] ignore_list = [ "expressions", "geomtransform", "encoding", "fontset", "include", "index", "template", "union", "xml_mapfile", "xmp_metadata" ] # fontset is a MAP parameter for fn in rst_files: #[:1]: class_name = os.path.splitext(os.path.basename(fn))[0].lower() if class_name not in ignore_list: # and class_name in ["layer"]: print("--------%s----------" % class_name) kwds = {} # add a key for each MapServer class # and then set its value to a list of associated keywords mapfile_dict[class_name] = kwds read_doc(fn, kwds) #pprint.pprint(mapfile_dict) composite_names = mapfile_dict.keys() keywords = [] parameters = [] for k, v in mapfile_dict.items(): for kwd, params in v.items(): keywords.append(kwd) for p in params: parameters.append(p) mappyfile_keywords = COMPOSITE_NAMES.union(ATTRIBUTE_NAMES).union( SINGLETON_COMPOSITE_NAMES) docs_keywords = composite_names + keywords + parameters for p in sorted(set(parameters)): print(p) functions = set(spatial_functions + string_functions + arithmetic_functions + geotransform_functions) print("Missing from mappyfile:") mappyfile_composites = set( COMPOSITE_NAMES.union(SINGLETON_COMPOSITE_NAMES)) print(sorted(list(set(docs_keywords) - mappyfile_composites - functions))) print("Missing from docs:") missing = sorted( list( set(mappyfile_keywords) - set(docs_keywords) - functions - missing_list - missing_deprecated)) print(missing)
def read_all_docs(fld): rst_files = glob.glob(fld + '/*.txt') mapfile_dict = {} dict_items = [] ignore_list = ["expressions","geomtransform","encoding","fontset","include","index", "template","union","xml_mapfile","xmp_metadata"] # fontset is a MAP parameter for fn in rst_files: #[:1]: class_name = os.path.splitext(os.path.basename(fn))[0].lower() if class_name not in ignore_list: # and class_name in ["layer"]: print("--------%s----------" % class_name) kwds = {} # add a key for each MapServer class # and then set its value to a list of associated keywords mapfile_dict[class_name] = kwds read_doc(fn, kwds) #pprint.pprint(mapfile_dict) composite_names = mapfile_dict.keys() keywords = [] parameters = [] for k, v in mapfile_dict.items(): for kwd, params in v.items(): keywords.append(kwd) for p in params: parameters.append(p) mappyfile_keywords = COMPOSITE_NAMES.union(ATTRIBUTE_NAMES).union(SINGLETON_COMPOSITE_NAMES) docs_keywords = composite_names + keywords + parameters for p in sorted(set(parameters)): print(p) functions = set(spatial_functions + string_functions + arithmetic_functions + geotransform_functions) print("Missing from mappyfile:") mappyfile_composites = set(COMPOSITE_NAMES.union(SINGLETON_COMPOSITE_NAMES)) print(sorted(list(set(docs_keywords) - mappyfile_composites - functions))) print("Missing from docs:") missing = sorted(list(set(mappyfile_keywords) - set(docs_keywords) - functions - missing_list - missing_deprecated)) print(missing)
def _format(self, composite, level=0): lines = [] type_ = None # get any comments associated with the composite comments = composite.get("__comments__", {}) if isinstance(composite, dict) and '__type__' in composite: type_ = composite['__type__'] assert type_ in COMPOSITE_NAMES.union(SINGLETON_COMPOSITE_NAMES) is_hidden = False self._add_type_comment(level, comments, lines) s = self.whitespace(level, 0) + type_.upper() lines.append(s) for attr, value in composite.items(): if self.__is_metadata(attr): # skip hidden attributes continue elif self.is_hidden_container(attr, value): # now recursively print all the items in the container for v in value: lines += self._format(v, level + 1) elif attr == "pattern": lines += self.format_pair_list(attr, value, level) elif attr in ("metadata", "validation", "values", "connectionoptions"): # metadata and values are also composites # but will be processed here lines += self.process_key_dict(attr, value, level) elif attr == "projection": lines += self.process_projection(attr, value, level) elif attr in REPEATED_KEYS: lines += self.process_repeated_list(attr, value, level) elif attr == "points": lines += self.format_repeated_pair_list(attr, value, level) elif attr == "config": lines += self.process_config_dict(attr, value, level) elif self.is_composite(value): lines += self._format(value, level + 1) # recursively add the child class else: # standard key value pair if not type_: raise UnboundLocalError( "The Mapfile object is missing a __type__ attribute") line = self.process_attribute(type_, attr, value, level) line += self.process_attribute_comment(comments, attr) lines.append(line) if not is_hidden: # close the container block with an END lines.append(self.add_end_line(level, 0, type_)) return lines
def _format(self, composite, level=0): lines = [] # get any comments associated with the composite comments = composite.get("__comments__", {}) if isinstance(composite, dict) and '__type__' in composite.keys(): type_ = composite['__type__'] assert (type_ in COMPOSITE_NAMES.union(SINGLETON_COMPOSITE_NAMES)) is_hidden = False comment = self.process_comment(comments, '__type__') if comment: lines.append(comment) s = self.whitespace(level, 0) + type_.upper() lines.append(s) for attr, value in composite.items(): if attr in ("__type__", "__comments__", "__position__"): # skip hidden attributes continue elif self.is_hidden_container(attr, value): # now recursively print all the items in the container for v in value: lines += self._format(v, level + 1) elif attr == "pattern": lines += self.format_pair_list(attr, value, level) elif attr in ("metadata", "validation", "values"): # metadata and values are also composites # but will be processed here lines += self.process_key_dict(attr, value, level) elif attr == "projection": lines += self.process_projection(attr, value, level) elif attr in ("processing", "formatoption", "include"): lines += self.process_repeated_list(attr, value, level) elif attr == "points": lines += self.format_repeated_pair_list(attr, value, level) elif attr == "config": lines += self.process_config_dict(attr, value, level) elif self.is_composite(value): lines += self._format(value, level + 1) # recursively add the child class else: # standard key value pair line = self.process_attribute(type_, attr, value, level) line += self.process_comment(comments, attr) lines.append(line) if not is_hidden: # close the container block with an END lines.append(self.add_end_line(level, 0)) return lines
def _format(self, composite, level=0): """ TODO Refactor this and create functions for each unique type """ lines = [] if isinstance(composite, dict) and '__type__' in composite.keys(): type_ = composite['__type__'] assert(type_ in COMPOSITE_NAMES.union(SINGLETON_COMPOSITE_NAMES)) is_hidden = False s = self.whitespace(level, 0) + type_ .upper() lines.append(s) # we can now filter out the type property so the rest of the # values are displayed items = ((k, v) for k, v in composite.items() if k != '__type__') else: # hidden container assert(len(composite.keys()) == 1) is_hidden = True items = enumerate(composite.values()[0]) for key, value in items: if self.is_hidden_container(key, value): # HiddenContainer # now recursively print all the items in the container if self.is_block_list(value): k = self.singular(key) lines += self.process_list(k, value, level) else: for v in value: lines += self._format(v, level + 1) elif self.is_composite(value): # Container lines += self._format(value, level + 1) else: if key in SINGLETON_COMPOSITE_NAMES: lines += self.process_dict(key, value, level) elif isinstance(value, dict): if key == "config": # config declaration allows for pairs of values value = ["%s %s" % (self.format_key(k), self.format_attribute(v)) for k,v in value.items()] key = self.format_key(key) # format the "parent" key for v in value: # keys and values are already formatted so do not format them again lines.append(self.__format_line(self.whitespace(level, 1), key, v)) elif isinstance(value, list): if self.is_list_of_lists(value): # value is list of lists, so create composite type for each list e.g. several POINTS in a FEATURE for l in value: lines += self.process_list(key, [l], level) else: lines += self.process_list(key, value, level) else: comp_type = composite.get("__type__", "") if comp_type == "metadata": # don't add quotes to key or value, but standardise them if present key = self.standardise_quotes(key) value = self.standardise_quotes(value) lines.append(self.__format_line(self.whitespace(level, 1), key, value)) else: lines.append(self.format_line(self.whitespace(level, 1), key, value)) if not is_hidden: # Container # close the container block with an END s = self.whitespace(level, 0) + self.end lines.append(s) return lines
import sys is_python3 = sys.version_info.major == 3 if is_python3: unicode = str from mappyfile.tokens import COMPOSITE_NAMES, ATTRIBUTE_NAMES, SINGLETON_COMPOSITE_NAMES, REPEATED_KEYS ALL_KEYWORDS = COMPOSITE_NAMES.union(ATTRIBUTE_NAMES).union(SINGLETON_COMPOSITE_NAMES) class PrettyPrinter(object): def __init__(self, indent=4, spacer=" ", quote='"', newlinechar="\n"): """ Option use "\t" for spacer with an indent of 1 """ assert (quote == "'" or quote == '"') self.indent = indent self.spacer = spacer * self.indent self.newlinechar = newlinechar self.quote = quote self.end = u"END" if self.quote == "'": self.altquote = '"' else: self.altquote = "'" def whitespace(self, level, indent):
def composite(self, t): """ Handle the composite types e.g. CLASS..END [Tree(composite_type, [Token(__CLASS8, 'CLASS')]), Tree(composite_body, [('attr', u'name', "'test'")])] """ if len(t) == 3: # Parser artifact. See LINE-BREAK FLUIDITY in parsing_decisions.txt type_, attr, body = t elif len(t) == 2: type_, body = t attr = None else: assert (len(t) == 1) type_, attr, body = t[0] #print type_, attr, body if attr in ("metadata", "validation"): body['__type__'] = attr return ('composite', attr, body) if isinstance(body, tuple): assert body[0] == 'attr' or body[1] == 'points' or body[ 1] == 'pattern', body # Parser artefacts body = [body] else: body = body.children type_ = type_.children[0].lower() assert type_ in COMPOSITE_NAMES.union(SINGLETON_COMPOSITE_NAMES) if attr: body = [attr] + body for x in body: assert isinstance(x, tuple), x composites = DefaultOrderedDict(list) d = DefaultOrderedDict(OrderedDict) for itemtype, k, v in body: if itemtype == 'attr': # TODO tidy-up the code below if k in REPEATED_KEYS: d = self.repeated_key(d, k, v) elif k == 'config': # CONFIG can be repeated, but with pairs of strings as a value if 'config' not in d.keys(): d[k] = OrderedDict() d[k][v[0]] = v[1] else: d[k] = v elif itemtype == 'composite' and k in SINGLETON_COMPOSITE_NAMES: # there can only ever be one instance of these composites[k] = v # defaultdict using list elif itemtype == 'composite': composites[k].append(v) else: raise ValueError("Itemtype '%s' unknown", itemtype) for k, v in composites.items( ): # collection of all items e.g. at the map level this is status, metadata etc. if k in SINGLETON_COMPOSITE_NAMES: d[k] = v else: d[plural(k)] = v d['__type__'] = type_ return ('composite', type_, d)