| OLD | NEW |
| (Empty) |
| 1 # -*- test-case-name: twisted.scripts.test.test_mktap -*- | |
| 2 # Copyright (c) 2001-2008 Twisted Matrix Laboratories. | |
| 3 # See LICENSE for details. | |
| 4 | |
| 5 import warnings, sys, os | |
| 6 | |
| 7 | |
| 8 from twisted.application import service, app | |
| 9 from twisted.persisted import sob | |
| 10 from twisted.python import usage, util, plugin as oldplugin | |
| 11 from twisted import plugin as newplugin | |
| 12 from twisted.python.util import uidFromString, gidFromString | |
| 13 | |
| 14 # API COMPATIBILITY | |
| 15 IServiceMaker = service.IServiceMaker | |
| 16 _tapHelper = service.ServiceMaker | |
| 17 | |
| 18 warnings.warn( | |
| 19 "mktap and related support modules are deprecated as of Twisted 8.0. " | |
| 20 "Use Twisted Application Plugins with the 'twistd' command directly, " | |
| 21 "as described in 'Writing a Twisted Application Plugin for twistd' " | |
| 22 "chapter of the Developer Guide.", DeprecationWarning, stacklevel=2) | |
| 23 | |
| 24 | |
| 25 | |
| 26 def getid(uid, gid): | |
| 27 """ | |
| 28 Convert one or both of a string representation of a UID and GID into | |
| 29 integer form. On platforms where L{pwd} and L{grp} is available, user and | |
| 30 group names can be converted. | |
| 31 | |
| 32 @type uid: C{str} or C{NoneType} | |
| 33 @param uid: A string giving the base-ten representation of a UID or the | |
| 34 name of a user which can be converted to a UID via L{pwd.getpwnam}, | |
| 35 or None if no UID value is to be obtained. | |
| 36 | |
| 37 @type gid: C{str} or C{NoneType} | |
| 38 @param uid: A string giving the base-ten representation of a GID or the | |
| 39 name of a group which can be converted to a GID via | |
| 40 L{grp.getgrnam}, or None if no UID value is to be obtained. | |
| 41 | |
| 42 @return: A two-tuple giving integer UID and GID information for | |
| 43 whichever (or both) parameter is provided with a non-C{None} value. | |
| 44 | |
| 45 @raise ValueError: If a user or group name is supplied and L{pwd} or L{grp} | |
| 46 is not available. | |
| 47 """ | |
| 48 if uid is not None: | |
| 49 uid = uidFromString(uid) | |
| 50 if gid is not None: | |
| 51 gid = gidFromString(gid) | |
| 52 return (uid, gid) | |
| 53 | |
| 54 | |
| 55 | |
| 56 def loadPlugins(debug = None, progress = None): | |
| 57 tapLookup = {} | |
| 58 | |
| 59 plugins = oldplugin._getPlugIns("tap", debug, progress) | |
| 60 for plug in plugins: | |
| 61 if hasattr(plug, 'tapname'): | |
| 62 shortTapName = plug.tapname | |
| 63 else: | |
| 64 shortTapName = plug.module.split('.')[-1] | |
| 65 tapLookup[shortTapName] = plug | |
| 66 | |
| 67 plugins = newplugin.getPlugins(IServiceMaker) | |
| 68 for plug in plugins: | |
| 69 tapLookup[plug.tapname] = plug | |
| 70 | |
| 71 return tapLookup | |
| 72 | |
| 73 def addToApplication(ser, name, append, procname, type, encrypted, uid, gid): | |
| 74 if append and os.path.exists(append): | |
| 75 a = service.loadApplication(append, 'pickle', None) | |
| 76 else: | |
| 77 a = service.Application(name, uid, gid) | |
| 78 if procname: | |
| 79 service.IProcess(a).processName = procname | |
| 80 ser.setServiceParent(service.IServiceCollection(a)) | |
| 81 sob.IPersistable(a).setStyle(type) | |
| 82 passphrase = app.getSavePassphrase(encrypted) | |
| 83 if passphrase: | |
| 84 append = None | |
| 85 sob.IPersistable(a).save(filename=append, passphrase=passphrase) | |
| 86 | |
| 87 class FirstPassOptions(usage.Options): | |
| 88 synopsis = """Usage: mktap [options] <command> [command options] """ | |
| 89 | |
| 90 recursing = 0 | |
| 91 params = () | |
| 92 | |
| 93 optParameters = [ | |
| 94 ['uid', 'u', None, "The uid to run as.", uidFromString], | |
| 95 ['gid', 'g', None, "The gid to run as.", gidFromString], | |
| 96 ['append', 'a', None, | |
| 97 "An existing .tap file to append the plugin to, rather than " | |
| 98 "creating a new one."], | |
| 99 ['type', 't', 'pickle', | |
| 100 "The output format to use; this can be 'pickle', 'xml', " | |
| 101 "or 'source'."], | |
| 102 ['appname', 'n', None, "The process name to use for this application."] | |
| 103 ] | |
| 104 | |
| 105 optFlags = [ | |
| 106 ['encrypted', 'e', "Encrypt file before writing " | |
| 107 "(will make the extension of the resultant " | |
| 108 "file begin with 'e')"], | |
| 109 ['debug', 'd', "Show debug information for plugin loading"], | |
| 110 ['progress', 'p', "Show progress information for plugin loading"], | |
| 111 ['help', 'h', "Display this message"], | |
| 112 ] | |
| 113 #zsh_altArgDescr = {"foo":"use this description for foo instead"} | |
| 114 #zsh_multiUse = ["foo", "bar"] | |
| 115 #zsh_mutuallyExclusive = [("foo", "bar"), ("bar", "baz")] | |
| 116 zsh_actions = {"append":'_files -g "*.tap"', | |
| 117 "type":"(pickle xml source)"} | |
| 118 zsh_actionDescr = {"append":"tap file to append to", "uid":"uid to run as", | |
| 119 "gid":"gid to run as", "type":"output format"} | |
| 120 | |
| 121 def init(self, tapLookup): | |
| 122 sc = [] | |
| 123 for (name, module) in tapLookup.iteritems(): | |
| 124 if IServiceMaker.providedBy(module): | |
| 125 sc.append(( | |
| 126 name, None, lambda m=module: m.options(), module.description
)) | |
| 127 else: | |
| 128 sc.append(( | |
| 129 name, None, lambda obj=module: obj.load().Options(), | |
| 130 getattr(module, 'description', ''))) | |
| 131 | |
| 132 sc.sort() | |
| 133 self.subCommands = sc | |
| 134 | |
| 135 def parseArgs(self, *rest): | |
| 136 self.params += rest | |
| 137 | |
| 138 def _reportDebug(self, info): | |
| 139 print 'Debug: ', info | |
| 140 | |
| 141 def _reportProgress(self, info): | |
| 142 s = self.pb(info) | |
| 143 if s: | |
| 144 print '\rProgress: ', s, | |
| 145 if info == 1.0: | |
| 146 print '\r' + (' ' * 79) + '\r', | |
| 147 | |
| 148 def postOptions(self): | |
| 149 if self.recursing: | |
| 150 return | |
| 151 debug = progress = None | |
| 152 if self['debug']: | |
| 153 debug = self._reportDebug | |
| 154 if self['progress']: | |
| 155 progress = self._reportProgress | |
| 156 self.pb = util.makeStatBar(60, 1.0) | |
| 157 try: | |
| 158 self.tapLookup = loadPlugins(debug, progress) | |
| 159 except IOError: | |
| 160 raise usage.UsageError("Couldn't load the plugins file!") | |
| 161 self.init(self.tapLookup) | |
| 162 self.recursing = 1 | |
| 163 self.parseOptions(self.params) | |
| 164 if not hasattr(self, 'subOptions') or self['help']: | |
| 165 raise usage.UsageError(str(self)) | |
| 166 if hasattr(self, 'subOptions') and self.subOptions.get('help'): | |
| 167 raise usage.UsageError(str(self.subOptions)) | |
| 168 if not self.tapLookup.has_key(self.subCommand): | |
| 169 raise usage.UsageError("Please select one of: "+ | |
| 170 ' '.join(self.tapLookup)) | |
| 171 | |
| 172 | |
| 173 def run(): | |
| 174 options = FirstPassOptions() | |
| 175 try: | |
| 176 options.parseOptions(sys.argv[1:]) | |
| 177 except usage.UsageError, e: | |
| 178 print e | |
| 179 sys.exit(2) | |
| 180 except KeyboardInterrupt: | |
| 181 sys.exit(1) | |
| 182 | |
| 183 plg = options.tapLookup[options.subCommand] | |
| 184 if not IServiceMaker.providedBy(plg): | |
| 185 plg = plg.load() | |
| 186 ser = plg.makeService(options.subOptions) | |
| 187 addToApplication(ser, | |
| 188 options.subCommand, options['append'], options['appname'], | |
| 189 options['type'], options['encrypted'], | |
| 190 options['uid'], options['gid']) | |
| OLD | NEW |