v50 Steam/Premium information for editors
- v50 information can now be added to pages in the main namespace. v0.47 information can still be found in the DF2014 namespace. See here for more details on the new versioning policy.
- Use this page to report any issues related to the migration.
This notice may be cached—the current version can be found here.
User:Button/BAMM
Jump to navigation
Jump to search
About
Features
Planned Features
Usage Instructions
Download
You can download the script from GitHub.
Python 3
Configuration
Button's Workspace
Sometimes I'm on a computer I can't put a git client on.
_is_logging_initialized = False # TODO Allow file to be passed in, or possibly even a dict? def load_run_config(): """Load config information from the default file. Also initializes loggers if they haven't been already. """ print("Loading run configuration...") global runconfig runconfig_file = open(runconfig, 'r') global properties for line in runconfig_file: uncommented = line.strip().split('#')[0] props = uncommented.strip().split('=') if len(props) == 0 or (len(props) == 1 and len(props[0]) == 0): continue elif len(props) != 2: print('Line "', line, '" in ', runconfig, ' is improperly configured. Please format properties thus: \ "propertyname=value" (without quotes).') elif not _property_has_format_error(props[0], props[1]): set_property(props[0], props[1]) else: print ('Line "', line, '" in', runconfig, 'is improperly configured. Please format properties thus: \ "propertyname=value" (without quotes).') runconfig_file.close() initialize_logging() userlog.info("**********") modderslog.info("**********") userlog.info("Run configuration loaded.") userlog.debug("Properties:") for propname in properties.keys(): userlog.debug("Property %s:", propname) for item in properties[propname]: userlog.debug("\t%s", item) # TODO implement parameters with defaults (and update docstring) def initialize_logging() """Initialize loggers config.userlog and config.modderslog Will not double-initialize. """ global _is_logging_initialized if _is_logging_initialized: return else: _is_logging_initialized = True # Logging fmt = logging.Formatter('%(message)s') userhandler = logging.FileHandler(properties[USERSLOG][1]) userhandler.setFormatter(fmt) userlog.addHandler(userhandler) if properties[DEBUG][1]: userlog.setLevel(logging.DEBUG) else: userlog.setLevel(logging.INFO) modderhandler = logging.FileHandler(properties[MODDERSLOG][1]) modderhandler.setFormatter(fmt) modderslog.addHandler(modderhandler) modderslog.setLevel(logging.INFO) def _property_has_format_error(propkey, value): """Returns True if the property is formatted incorrectly. * propkey is the "name" of the property, and is expected to be one of the CONFIG.X module variables declared up above. * value is the value you wish to check for compatibility with the property in question. Returns True if: * The property key is not recognized * The property's type is IS_BOOL and the value is not 'True' or 'False * The property's type is IS_DIR and the value is an existing (non-directory) file * The property's type is IS_FILE and the value is an existing directory. Otherwise, returns False. """ return (propkey not in properties.keys() or (properties[propkey][0] == IS_DIR and os.path.exists(value) and not os.path.isdir(value)) or (properties[propkey][0] == IS_FILE and os.path.exists(value) and not os.path.isfile(value)) or (properties[propkey][0] == IS_BOOL and value not in ('True', 'False'))) def set_property(prop_id, value): """ Sets property prop_id to value. """ global properties if prop_id not in properties.keys(): pass elif not _property_has_format_error(prop_id, value): properties[prop_id] = properties[prop_id][:1] if properties[prop_id][0] == IS_REGEX_LIST: properties[prop_id].extend(value.split(',')) elif properties[prop_id][0] == IS_BOOL: if value == 'True': properties[prop_id].append(True) elif value == 'False': properties[prop_id].append(False) else: properties[prop_id].append(value) def escape_problematic_literals(line): """ Returns line with its char literals replaced with their cp437 codes. Char literals are usually used for defining tiles, and are two single quotes around a character, so: '*'. Since this is the only case in which the DF raw characters ']', '[' and ':' are allowed within a tag outside their uses, and since cp437 codes are equally valid, replacing these with their cp437 codes is harmless and streamlines lexing considerably. """ global ascii_codes # Replace literal key characters with number codes # Literal colons are going to require some special processing, because of # the following case: GROWTH:'r':'x': etc. That's why we can't just use # a blind replaceAll. # If odd, we are inside a tag. If even, we are outside a tag. bracketscount = 0 count = 0 # Where we are in the string quotescount = 0 while count < len(line)-2: # Going from inside a tag to outside or vice versa if (((bracketscount % 2 == 0 and line[count] == "[") or (bracketscount % 2 == 1 and line[count] == "]"))): bracketscount += 1 # We are inside a tag and we have discovered a ' character beginning a # literal value, with another 2 characters down on the other side. elif (quotescount % 2 == 0 and bracketscount % 2 == 1 and line[count:count+3] in ascii_codes.keys()): # If the character could be a problem for later processing, replace # it with its ascii code. line = line[:count] + ascii_codes[line[count:count+3]] + \ line[count+3:] elif line[count] == "'": quotescount += 1 elif bracketscount % 2 == 1 and line[count] == ':': quotescount = 0 count += 1 # line has now had its literal "use this tile" versions of its special # characters replaced with their numbers. return line def path_compatible(full_path, allowed_paths): """Return True if full_path regex matches anything in allowed_paths, or False otherwise.""" full_path = full_path.replace('\\', '/') for allowed_path in allowed_paths: allowed_path = allowed_path.replace('\\', '/') match = re.match(allowed_path, full_path) if match is not None: return True return False # TODO overhaul. def load_all_templates(templatefile): """ Loads config information from templatefile. * templatefile is a pipe-delimited, one-graphics-tag-per-line config file which should not be changed by users unless you REALLY know what you're doing. This initializes the scaffolding for all future raw parsing, which is stored in graphics.template_tree . """