''' Command line module for making Team Fortress 2 macro scripts from YAML source code. ''' __all__ = ['parseFile'] __author__ = 'Nicholas Hope (dict, dict): '''Parse, verify, and do the conversion.''' config = yaml.safe_load(inputFile) # See verify.py config, defaults = verify.verifyConfig(config) if 'warnings' in config: for cclass, messages in config.pop('warnings').items(): print(f'Warning in {cclass}:', file=stderr) for msg in messages: print(f' {msg}', file=stderr) if 'errors' in config: for cclass, messages in config['errors'].items(): print(f'Error in {cclass}:', file=stderr) for msg in messages: print(f' {msg}', file=stderr) return None, None else: return config, defaults def parseConfig(config, defaults): '''With validated data structure, write out all the files.''' global args global targetDir if isdir(targetDir) == False: mkdir(targetDir) if args.debug: print( f'DEBUG: Created directory {targetDir}', file=stderr) tempsAndReals = {} if defaults is not None: config.update({'default': defaults}) for class_ in config: stringToWrite = makeCFG( config[class_], default=(class_ == 'default') ) replaceDict = writing.writeOutput(stringToWrite, class_, args) tempsAndReals.update(replaceDict) return tempsAndReals def parseCLI(): # Handle command line parser = argparse.ArgumentParser( description='Parse YAML file and produce TF2 config script.' ) parser.add_argument( '-d', '--debug', action='store_true', help='Enable debugging messages.') parser.add_argument( '-n', '--dry-run', action='store_true', help='Parse input file, but don\'t write anything.') parser.add_argument( '-f', '--force', action='store_true', help='Force tfscript to continue until catastrophic failure') parser.add_argument( '-D', '--directory', action='store', type=str, help='Change output directory') # warnings parseWarnNames = [ 'implicit-release', 'implicit-off', 'implicit-primary', 'implicit-secondary', 'implicit' ] for warnName in parseWarnNames: splitWarnName = ' '.join(warnName.split('-')) parser.add_argument( '-W' + warnName, action='store_true', help=f'Generate warning on {splitWarnName} creation') # positional argument: first non-hyphenated argument is input file parser.add_argument( 'infile', type=argparse.FileType('r'), help='File containing YAML to convert.') return parser def getTargetDir(systemName): if systemName == 'Darwin': if float( '.'.join( GetOSRelease().split('.')[0:2] ) ) >= 10.15: warn( 'As of macOS Catalina (v10.15), 32-bit applications' + ' like TF2 do not run. tfscript will run, but you can\'t run TF2' + ' on this system', category=RuntimeWarning ) return expanduser('~/Library/Application Support/Steam') if systemName == 'Windows': # oh god why do we have to use the registry accessReg = ConnectRegistry(None, HKEY_LOCAL_MACHINE) accessKey = OpenKey(accessReg, 'SOFTWARE\\WOW6432Node\\Valve\\Steam') keyNum = 0 while True: try: accessSubkeyName, data, _ = EnumValue(accessKey, keyNum) except EnvironmentError: break else: if accessSubkeyName == 'InstallPath': return data keyNum += 1 return None if systemName == 'Linux': homedir = expanduser('~') for potentialdir in ['.steam/steam', '.local/share/Steam']: fullTargetPath = normpath(f'{homedir}/{potentialdir}') if isdir(fullTargetPath): return fullTargetPath return None if systemName == 'Java': warn('Java-based OSes are not supported yet by tfscript.', category=RuntimeWarning) return None def main() -> int: ''' Command line interface. ''' global args global targetDir parser = parseCLI() args = parser.parse_args() systemName = GetOSName() if args.directory is not None: targetDir = normpath(args.directory) + dirsep else: targetDir = getTargetDir(systemName) if targetDir is not None: # Supported OS: add steamapps path targetDir += normpath('/steamapps/common/Team Fortress 2/tf/cfg') + dirsep elif args.force: # Unsupported OS but -f specified if args.debug: print('DEBUG: forced to continue, output set to current directory', file=stderr) targetDir = '.' else: # Unsupported OS and not forced to continue return 2 config, defaults = parseFile(args.infile) if config is None: return 2 fileNames = parseConfig(config, defaults) fileList = writing.replaceFiles(targetDir, fileNames, args) defaultsGiven = (defaults is not None) writing.appendToActuals(targetDir, fileList, defaultsGiven, args) return 0 if __name__ == '__main__': exit(main())