1 """Commands for the TurboGears command line tool."""
2
3 import optparse
4 import sys
5 import os
6 import os.path
7 import glob
8
9 import pkg_resources
10 import dispatch
11
12 import configobj
13
14 import turbogears
15 from turbogears.util import get_model, load_project_config, \
16 get_project_config, get_package_name
17 from turbogears.identity import SecureObject, from_any_host
18 from turbogears import config, database
19 from sacommand import sacommand
20
21 sys.path.insert(0, os.getcwd())
22
23 no_connection_param = ["help", "list"]
24 no_model_param = ["help"]
25
27 """
28 Tries to remove file FNAME but mutes any error that may happen.
29
30 Returns True if file was actually removed and false otherwise
31 """
32 try:
33 os.remove(fname)
34 return True
35 except os.error:
36 pass
37 return False
38
40 "Base class for commands that need to use the database"
41 config = None
42
45
47 """Chooses the config file, trying to guess whether this is a
48 development or installed project."""
49 load_project_config(self.config)
50 self.dburi = config.get("sqlobject.dburi", None)
51 if self.dburi and self.dburi.startswith("notrans_"):
52 self.dburi = self.dburi[8:]
53
54
55 -class SQL(CommandWithDB):
56 """
57 Wrapper command for sqlobject-admin, and provide some sqlalchemy support.
58
59 This automatically supplies sqlobject-admin with the database that
60 is found in the config file. Will also supply the model module as
61 appropriate."""
62
63 desc = "Run the database provider manager"
64 need_project = True
65
67 if len(sys.argv) == 1 or sys.argv[1][0] == "-":
68 parser = optparse.OptionParser(
69 usage="%prog sql [command]\n\n" \
70 "hint: '%prog sql help' will list the sqlobject " \
71 "commands",
72 version="%prog " + version)
73 parser.add_option("-c", "--config", help="config file",
74 dest="config")
75 (options, args) = parser.parse_args(sys.argv[1:3])
76
77 if not options.config:
78 parser.error("Please provide a valid option or command.")
79 self.config = options.config
80
81 if not args:
82 del sys.argv[1:3]
83 else:
84 del sys.argv[1]
85
86 self.find_config()
87
89 "Executes the sqlobject-admin code."
90 if not "--egg" in sys.argv and not turbogears.util.get_project_name():
91 print "this don't look like a turbogears project"
92 return
93 else:
94 command = sys.argv[1]
95
96 if config.get("sqlalchemy.dburi"):
97 try:
98 sacommand(command, sys.argv)
99 except dispatch.interfaces.NoApplicableMethods:
100 sacommand("help", [])
101 return
102
103 sqlobjcommand = command
104 if sqlobjcommand not in no_connection_param:
105 if not self.dburi:
106 print """Database URI not specified in the config file (%s).
107 Please be sure it's on the command line.""" % self.config
108 else:
109 print "Using database URI %s" % self.dburi
110 sys.argv.insert(2, self.dburi)
111 sys.argv.insert(2, "-c")
112
113 if sqlobjcommand not in no_model_param:
114 if not "--egg" in sys.argv:
115 eggname = glob.glob("*.egg-info")
116 if not eggname or not \
117 os.path.exists(os.path.join(eggname[0], "sqlobject.txt")):
118 eggname = self.fix_egginfo(eggname)
119 eggname = eggname[0].replace(".egg-info", "")
120 if not "." in sys.path:
121 sys.path.append(".")
122 pkg_resources.working_set.add_entry(".")
123 sys.argv.insert(2, eggname)
124 sys.argv.insert(2, "--egg")
125
126 from sqlobject.manager import command
127 command.the_runner.run(sys.argv)
128
130 print """
131 This project seems incomplete. In order to use the sqlobject commands
132 without manually specifying a model, there needs to be an
133 egg-info directory with an appropriate sqlobject.txt file.
134
135 I can fix this automatically. Would you like me to?
136 """
137 dofix = raw_input("Enter [y] or n: ")
138 if not dofix or dofix.lower()[0] == 'y':
139 oldargs = sys.argv
140 sys.argv = ["setup.py", "egg_info"]
141 import imp
142 imp.load_module("setup", *imp.find_module("setup", ["."]))
143 sys.argv = oldargs
144
145 import setuptools
146 package = setuptools.find_packages()[0]
147 eggname = glob.glob("*.egg-info")
148 sqlobjectmeta = open(os.path.join(eggname[0], "sqlobject.txt"), "w")
149 sqlobjectmeta.write("""db_module=%(package)s.model
150 history_dir=$base/%(package)s/sqlobject-history
151 """ % dict(package=package))
152 else:
153 sys.exit(0)
154 return eggname
155
156
157 -class Shell(CommandWithDB):
158 """Convenient version of the Python interactive shell.
159 This shell attempts to locate your configuration file and model module
160 so that it can import everything from your model and make it available
161 in the Python shell namespace."""
162
163 desc = "Start a Python prompt with your database available"
164 need_project = True
165
167 "Run the shell"
168 self.find_config()
169
170 mod = get_model()
171 if mod:
172 locals = mod.__dict__
173 else:
174 locals = dict(__name__="tg-admin")
175
176 if config.get("sqlalchemy.dburi"):
177 using_sqlalchemy = True
178 database.get_engine()
179 locals.update(dict(session=database.session,
180 metadata=database.metadata))
181 else:
182 using_sqlalchemy = False
183
184 try:
185
186 import IPython
187
188 class CustomIPShell(IPython.iplib.InteractiveShell):
189 def raw_input(self, *args, **kw):
190 try:
191 return IPython.iplib.InteractiveShell.raw_input(self,
192 *args, **kw)
193 except EOFError:
194 r = raw_input("Do you wish to commit your "
195 "database changes? [yes]")
196 if not r.lower().startswith("n"):
197 if using_sqlalchemy:
198 self.push("session.flush()")
199 else:
200 self.push("hub.commit()")
201 raise EOFError
202
203 shell = IPython.Shell.IPShell(user_ns=locals,
204 shell_class=CustomIPShell)
205 shell.mainloop()
206 except ImportError:
207 import code
208
209 class CustomShell(code.InteractiveConsole):
210 def raw_input(self, *args, **kw):
211 try:
212 import readline
213 except ImportError:
214 pass
215 try:
216 r = code.InteractiveConsole.raw_input(self,
217 *args, **kw)
218 for encoding in (getattr(sys.stdin, 'encoding', None),
219 sys.getdefaultencoding(), 'utf-8', 'latin-1'):
220 if encoding:
221 try:
222 return r.decode(encoding)
223 except UnicodeError:
224 pass
225 return r
226 except EOFError:
227 r = raw_input("Do you wish to commit your "
228 "database changes? [yes]")
229 if not r.lower().startswith("n"):
230 if using_sqlalchemy:
231 self.push("session.flush()")
232 else:
233 self.push("hub.commit()")
234 raise EOFError
235
236 shell = CustomShell(locals=locals)
237 shell.interact()
238
312
313 commands = None
314
316 "Main command runner. Manages the primary command line arguments."
317
318 commands = {}
319 for entrypoint in pkg_resources.iter_entry_points("turbogears.command"):
320 command = entrypoint.load()
321 commands[entrypoint.name] = (command.