def get(self): pdb = Projects() project_list = pdb.list_projects() self.render('projdb/project_list.html', project_list=project_list, version=__version__)
def __init__(self, options): self.options = options user_dir = get_user_dir() # initialize some settings database = os.path.join(user_dir, 'projects.db') if options.reset or not os.path.exists(database): print "Resetting project database..." if os.path.exists(database): print "Deleting existing project database..." os.remove(database) pdb = Projects(database) pdb.create() options.orig_port = options.port if (options.port < 1): options.port = get_unused_ip_port() # save secret between restarts secret_file = os.path.join(user_dir, 'secret') if os.path.exists(secret_file): secret = open(secret_file, 'rb').read() else: secret = os.urandom(1024) open(secret_file, 'wb').write(secret) self.app = App(secret, options.external)
def get(self, project_id): ''' Browser download of a project file ''' pdb = Projects() project = pdb.get(project_id) if project['filename']: filename = os.path.join(self.get_project_dir(), project['filename']) if os.path.exists(filename): proj_file = file(filename,'rb') self.set_header('content_type', 'application/octet-stream') self.set_header('Content-Length', str(os.path.getsize(filename))) form_proj = clean_filename(project['projectname']) form_ver = clean_filename(project['version']) form_date = strftime('%Y-%m-%d_%H%M%S') self.set_header('Content-Disposition', 'attachment; filename=%s-%s-%s.proj' % (form_proj, form_ver, form_date)) try: self.write(proj_file.read()) finally: proj_file.close() else: raise HTTPError(filename, 403, "%s is not a file" % filename, None, None) else: raise HTTPError(filename, 403, "no file found for %s" % \ project['projectname'], None, None)
def get(self, project_id): ''' Browser download of a project file ''' pdb = Projects() project = pdb.get(project_id) if project['filename']: filename = os.path.join(self.get_project_dir(), project['filename']) if os.path.exists(filename): proj_file = file(filename, 'rb') self.set_header('content_type', 'application/octet-stream') self.set_header('Content-Length', str(os.path.getsize(filename))) form_proj = clean_filename(project['projectname']) form_ver = clean_filename(project['version']) form_date = strftime('%Y-%m-%d_%H%M%S') self.set_header('Content-Disposition', 'attachment; filename=%s-%s-%s.proj' % (form_proj, form_ver, form_date)) try: self.write(proj_file.read()) finally: proj_file.close() else: raise HTTPError(filename, 403, "%s is not a file" % filename, None, None) else: raise HTTPError(filename, 403, "no file found for %s" % \ project['projectname'], None, None)
def post(self, project_id): forms = {} for field in ['projectname', 'description', 'version']: if field in self.request.arguments.keys(): forms[field] = self.request.arguments[field][0] pdb = Projects() # Existing project. if int(project_id) != pdb.predict_next_rowid(): project = pdb.get(project_id) project_is_new = False # New project else: project = {} project['active'] = 0 project['projpath'] = None project_is_new = True if 'projectname' not in forms or \ len(forms['projectname']) == 0: project['projectname'] = "Unnamed Project" else: project['projectname'] = forms['projectname'].strip() if 'description' in forms: project['description'] = forms['description'].strip() else: project['description'] = '' if 'version' in forms: project['version'] = forms['version'].strip() else: project['version'] = '' # if there's no proj dir yet, create an empty one if not project['projpath']: directory = self.get_project_dir() pname = project['projectname'] project['projpath'] = _get_unique_name(directory, pname) if project_is_new: pdb.new(project) os.mkdir(project['projpath']) else: for key, value in project.iteritems(): pdb.set(project_id, key, value) pdb.modified(project_id) # Update project settings. proj = Project(project['projpath']) dummy = proj.get_info() # Just to get required keys. info = {} for key in dummy: info[key] = project[key] proj.set_info(info) self.redirect("/workspace/project?projpath=" + project['projpath'])
def get(self, project_id): pdb = Projects() project = pdb.get(project_id) if project['projpath']: dirname = str(project['projpath']) if os.path.isdir(dirname): shutil.rmtree(dirname, onerror=onerror) pdb.remove(project_id) self.redirect('/')
def post(self, project_id): pdb = Projects() project = pdb.get(project_id) if project['filename']: filename = os.path.join(self.get_project_dir(), str(project['filename'])) if os.path.exists(filename): os.remove(filename) pdb.remove(project_id) self.redirect('/')
def post(self, project_id): pdb = Projects() project = pdb.get(project_id) if project['projpath']: dirname = str(project['projpath']) if os.path.isdir(dirname): try: shutil.rmtree(dirname, onerror=onerror) except Exception as err: raise HTTPError(dirname, 403, err, None, None) else: pdb.remove(project_id) self.redirect('/')
def get(self): pdb = Projects() project = {} project['id'] = pdb.predict_next_rowid() project['projectname'] = 'New Project '+strftime("%Y-%m-%d_%H%M%S") project['version'] = '' project['description'] = '' project['created'] = 'New Project' project['modified'] = 'New Project' project['projpath'] = '' project['active'] = '' self.render('projdb/project_detail.html', project=project, delete=False)
def get(self): pdb = Projects() project = {} project['id'] = pdb.predict_next_rowid() project['projectname'] = 'New Project '+strftime("%Y-%m-%d_%H%M%S") project['version'] = '' project['description'] = '' project['created'] = 'New Project' project['modified'] = 'New Project' project['filename'] = '' project['active'] = '' self.render('projdb/project_detail.html', project=project, delete=False)
def post(self): pdb = Projects() forms = {} for field in ['projectname', 'description', 'version']: if field in self.request.arguments.keys(): forms[field] = self.request.arguments[field][0] project = {} project['projectname'] = forms['projectname'].strip() project['description'] = forms['description'].strip() project['version'] = forms['version'].strip() project['id'] = pdb.predict_next_rowid() project['active'] = 1 # figure out a unique directory name for the project using # the project name and version string directory = self.get_project_dir() version = project['version'] pname = project['projectname'] if len(version): filename = clean_filename('%s-%s' % (pname, version)) else: filename = clean_filename(pname) unique = filename i = 1 while os.path.exists(os.path.join(directory, unique)): unique = '%s_%s' % (filename, str(i)) i = i + 1 project['projpath'] = os.path.join(directory, unique) pdb.new(project) os.mkdir(project['projpath']) # Update project settings. proj = Project(project['projpath']) dummy = proj.get_info() # Just to get required keys. info = {} for key in dummy: info[key] = project[key] proj.set_info(info) self.redirect("/workspace/project?projpath=" + quote_plus(project['projpath']))
def post(self): pdb = Projects() forms = {} for field in ['projectname', 'description', 'version']: if field in self.request.arguments.keys(): forms[field] = self.request.arguments[field][0] project = {} project['projectname'] = forms['projectname'].strip() project['description'] = forms['description'].strip() project['version'] = forms['version'].strip() project['id'] = pdb.predict_next_rowid() project['active'] = 1 # figure out a unique directory name for the project using # the project name and version string directory = self.get_project_dir() version = project['version'] pname = project['projectname'] if len(version): filename = clean_filename('%s-%s' % (pname, version)) else: filename = clean_filename(pname) unique = filename i = 1 while os.path.exists(os.path.join(directory, unique)): unique = '%s_%s' % (filename, str(i)) i = i+1 project['projpath'] = os.path.join(directory, unique) pdb.new(project) os.mkdir(project['projpath']) # Update project settings. proj = Project(project['projpath']) dummy = proj.get_info() # Just to get required keys. info = {} for key in dummy: info[key] = project[key] proj.set_info(info) self.redirect("/workspace/project?projpath=" + project['projpath'])
def post(self): sourcefile = self.request.files['myfile'][0] if sourcefile: filename = sourcefile['filename'] if len(filename) > 0: unique = _get_unique_name(self.get_project_dir(), parse_archive_name(filename)) pdb = Projects() project = {} project['id'] = pdb.predict_next_rowid() project['version'] = '' project['description'] = '' project['active'] = 1 project['projectname'] = parse_archive_name(unique) project['projpath'] = unique os.mkdir(unique) buff = StringIO.StringIO(sourcefile['body']) archive = tarfile.open(fileobj=buff, mode='r:gz') archive.extractall(path=unique) vcslist = find_vcs() if vcslist: vcs = vcslist[0](unique) else: vcs = DumbVCS(unique) vcs.init_repo() # TODO: look for project config and retrieve project db info from it pdb.new(project) self.redirect('/projects/' + str(project['id'])) self.redirect('')
def post(self): sourcefile = self.request.files['myfile'][0] if sourcefile: filename = sourcefile['filename'] if len(filename) > 0: unique = _get_unique_name(self.get_project_dir(), parse_archive_name(filename)) pdb = Projects() project = {} project['id'] = pdb.predict_next_rowid() project['version'] = '' project['description'] = '' project['active'] = 1 project['projectname'] = parse_archive_name(unique) project['projpath'] = unique os.mkdir(unique) buff = StringIO.StringIO(sourcefile['body']) archive = tarfile.open(fileobj=buff, mode='r:gz') archive.extractall(path=unique) vcslist = find_vcs() if vcslist: vcs = vcslist[0](unique) else: vcs = DumbVCS(unique) vcs.init_repo() # TODO: look for project config and retrieve project db info from it pdb.new(project) self.redirect('/projects/'+str(project['id'])) self.redirect('')
def get(self, project_id): ''' Browser download of a project file ''' pdb = Projects() project = pdb.get(project_id) if project['projpath']: dirname = project['projpath'] if os.path.isdir(dirname): proj = Project(dirname) tdir = mkdtemp() try: filename = proj.export(destdir=tdir) proj_file = open(filename, 'rb') self.set_header('content_type', 'application/octet-stream') self.set_header('Content-Length', str(os.path.getsize(filename))) form_proj = clean_filename(project['projectname']) form_ver = clean_filename(project['version']) form_date = strftime('%Y-%m-%d_%H%M%S') self.set_header( 'Content-Disposition', 'attachment; filename=%s-%s-%s.proj' % (form_proj, form_ver, form_date)) try: self.write(proj_file.read()) finally: proj_file.close() finally: try: shutil.rmtree(tdir, onerror=onerror) except: pass else: raise HTTPError(dirname, 403, "%s is not a directory" % dirname, None, None) else: raise HTTPError(filename, 403, "no file found for %s" % project['projectname'], None, None)
def post(self): sourcefile = self.request.files['myfile'][0] if sourcefile: filename = sourcefile['filename'] if len(filename) > 0: pdb = Projects() timestring = strftime("%Y-%m-%d_%H%M%S") project = {} project['id'] = pdb.predict_next_rowid() project['version'] = '' project['description'] = '' project['active'] = 1 if filename[-5:] == '.proj': filename = filename[:-5] project['projectname'] = 'Added_%s' % (filename) unique = '%s.proj' % filename i = 1 while os.path.exists(os.path.join(self.get_project_dir(), \ unique)): unique = '%s_%s.proj' % (filename, str(i)) i = i+1 with open(os.path.join(self.get_project_dir(), unique), 'wb') as out: out.write(sourcefile['body']) out.close() project['filename'] = unique pdb.new(project) self.redirect('/projects/'+str(project['id'])) self.redirect('')
def get(self, project_id): ''' Browser download of a project file ''' pdb = Projects() project = pdb.get(project_id) if project['projpath']: dirname = project['projpath'] if os.path.isdir(dirname): proj = Project(dirname) tdir = mkdtemp() try: filename = proj.export(destdir=tdir) proj_file = open(filename, 'rb') self.set_header('content_type', 'application/octet-stream') self.set_header('Content-Length', str(os.path.getsize(filename))) form_proj = clean_filename(project['projectname']) form_ver = clean_filename(project['version']) form_date = strftime('%Y-%m-%d_%H%M%S') self.set_header('Content-Disposition', 'attachment; filename=%s-%s-%s.proj' % (form_proj, form_ver, form_date)) try: self.write(proj_file.read()) finally: proj_file.close() finally: try: shutil.rmtree(tdir) except: pass else: raise HTTPError(dirname, 403, "%s is not a directory" % dirname, None, None) else: raise HTTPError(filename, 403, "no file found for %s" % \ project['projectname'], None, None)
def post(self): sourcefile = self.request.files['myfile'][0] if sourcefile: filename = sourcefile['filename'] if len(filename) > 0: pdb = Projects() project = {} project['id'] = pdb.predict_next_rowid() project['version'] = '' project['description'] = '' project['active'] = 1 if filename[-5:] == '.proj': filename = filename[:-5] project['projectname'] = 'Added_%s' % (filename) unique = '%s.proj' % filename i = 1 while os.path.exists(os.path.join(self.get_project_dir(), \ unique)): unique = '%s_%s.proj' % (filename, str(i)) i = i+1 with open(os.path.join(self.get_project_dir(), unique), 'wb') as out: out.write(sourcefile['body']) out.close() project['filename'] = unique pdb.new(project) self.redirect('/projects/'+str(project['id'])) self.redirect('')
def get(self): path = self.get_argument('projpath', default=None) if path: self.set_secure_cookie('projpath', path) else: path = self.get_secure_cookie('projpath') if path: self.delete_server() cserver = self.get_server() name = Projects().get_by_path(path)['projectname'] cserver.set_current_project(name) path = os.path.join(self.get_project_dir(), path) self.redirect(self.application.reverse_url('workspace')) else: self.redirect('/')
def get(self): path = self.get_argument('projpath', default=None) if path: self.set_secure_cookie('projpath', path) else: path = self.get_secure_cookie('projpath') if path: self.delete_server() cserver = self.get_server() proj = Projects().get_by_path(path) if proj is None: # Shouldn't happen. print >> sys.stderr, "ProjectHandler: no project for %r" % path args = dict(path=path) self.render('workspace/oops.html', **args) else: name = proj['projectname'] cserver.set_current_project(name) path = os.path.join(self.get_project_dir(), path) self.redirect(self.application.reverse_url('workspace')) else: self.redirect('/')
def post(self, project_id): forms = {} for field in ['projectname', 'description', 'version']: if field in self.request.arguments.keys(): forms[field] = self.request.arguments[field][0] pdb = Projects() # Existing project. if int(project_id) != pdb.predict_next_rowid(): project = pdb.get(project_id) project_is_new = False # New project else: project = {} project['active'] = 0 project['projpath'] = None project_is_new = True if 'projectname' not in forms or \ len(forms['projectname']) == 0: project['projectname'] = "Unnamed Project" else: project['projectname'] = forms['projectname'].strip() if 'description' in forms: project['description'] = forms['description'].strip() else: project['description'] = '' if 'version' in forms: project['version'] = forms['version'].strip() else: project['version'] = '' directory = forms.get('directory', self.get_project_dir()) # if there's no proj dir yet, create an empty one if not project['projpath']: version = project['version'] pname = project['projectname'] if len(version): filename = clean_filename('%s-%s' % (pname, version)) else: filename = clean_filename(pname) unique = filename i = 1 while os.path.exists(os.path.join(directory, unique)): unique = '%s_%s' % (filename, str(i)) i = i+1 project['projpath'] = os.path.join(directory, unique) if project_is_new: pdb.new(project) os.mkdir(project['projpath']) else: for key, value in project.iteritems(): pdb.set(project_id, key, value) pdb.modified(project_id) # Update project settings. proj = Project(project['projpath']) dummy = proj.get_info() # Just to get required keys. info = {} for key in dummy: info[key] = project[key] proj.set_info(info) self.redirect("/workspace/project?projpath=" + project['projpath'])
def post(self): if not self.request.arguments.has_key( "projectname" ): # First step in the import process. # Just get the name, description and version of the # project the user wants to import. # Then pass this to the form so the user can change it. # Go through the process of creating a new project directory # so we can read the name, description and version from the # settings file. sourcefile = self.request.files['projectfile'][0] if sourcefile: filename = sourcefile['filename'] if len(filename) > 0: unique = _get_unique_name(self.get_project_dir(), parse_archive_name(filename)) os.mkdir(unique) buff = StringIO.StringIO(sourcefile['body']) archive = tarfile.open(fileobj=buff, mode='r:gz') archive.extractall(path=unique) vcslist = find_vcs() if vcslist: vcs = vcslist[0](unique) else: vcs = DumbVCS(unique) vcs.init_repo() # Update project dict with info section of config file. proj = Project(unique) shutil.rmtree(unique) project_info = proj.get_info() self.render('projdb/import-metadata-fields.html', projectname=parse_archive_name(unique), description=project_info['description'], version=project_info['version'] ) self.redirect("/") else: forms = {} for field in ['projectname', 'description', 'version']: if field in self.request.arguments.keys(): forms[field] = self.request.arguments[field][0] sourcefile = self.request.files['projectfile'][0] if sourcefile: filename = sourcefile['filename'] if len(filename) > 0: unique = _get_unique_name(self.get_project_dir(), parse_archive_name(filename)) pdb = Projects() project = {} project['id'] = pdb.predict_next_rowid() project['active'] = 1 project['projectname'] = forms['projectname'].strip() project['description'] = forms['description'].strip() project['version'] = forms['version'].strip() project['projpath'] = unique os.mkdir(unique) buff = StringIO.StringIO(sourcefile['body']) archive = tarfile.open(fileobj=buff, mode='r:gz') archive.extractall(path=unique) vcslist = find_vcs() if vcslist: vcs = vcslist[0](unique) else: vcs = DumbVCS(unique) vcs.init_repo() # Update project settings. proj = Project(project['projpath']) dummy = proj.get_info() # Just to get required keys. info = {} for key in dummy: info[key] = project[key] proj.set_info(info) pdb.new(project) self.redirect("/workspace/project?projpath=" + project['projpath']) self.redirect("/")
def post(self): # The project file is uploaded once to extract the metadata. # It is then deleted and the metadata is used to populate another # import dialog, giving the user an opportunity to edit the # info before importing or cancel the import. if not 'projectname' in self.request.arguments: # First upload sourcefile = self.request.files['projectfile'][0] try: filename = sourcefile['filename'] if len(filename) > 0: unique = _get_unique_name(self.get_project_dir(), parse_archive_name(filename)) tdir = mkdtemp(prefix=unique) buff = StringIO.StringIO(sourcefile['body']) archive = tarfile.open(fileobj=buff, mode='r:gz') archive.extractall(path=tdir) proj = Project(tdir) project_info = proj.get_info() try: shutil.rmtree(tdir, onerror=onerror) except: pass self.render('projdb/import-metadata-fields.html', projectname=parse_archive_name(unique), description=project_info['description'], version=project_info['version']) except Exception as err: print 'ERROR: could not get metadata from', sourcefile exc_type, exc_value, exc_traceback = sys.exc_info() traceback.print_exception(exc_type, exc_value, exc_traceback) self.redirect('/') else: # second upload forms = {} for field in ['projectname', 'description', 'version']: if field in self.request.arguments.keys(): forms[field] = self.request.arguments[field][0] sourcefile = self.request.files['projectfile'][0] try: filename = sourcefile['filename'] if len(filename) > 0: unique = _get_unique_name(self.get_project_dir(), parse_archive_name(filename)) pdb = Projects() project = {} project['id'] = pdb.predict_next_rowid() project['active'] = 1 project['projectname'] = forms['projectname'].strip() project['description'] = forms['description'].strip() project['version'] = forms['version'].strip() project['projpath'] = unique os.mkdir(unique) buff = StringIO.StringIO(sourcefile['body']) archive = tarfile.open(fileobj=buff, mode='r:gz') archive.extractall(path=unique) vcslist = find_vcs() if vcslist: vcs = vcslist[0](unique) else: vcs = DumbRepo(unique) vcs.init_repo() # Update project settings. proj = Project(project['projpath']) dummy = proj.get_info() # Just to get required keys. info = {} for key in dummy: info[key] = project[key] proj.set_info(info) pdb.new(project) self.redirect("/workspace/project?projpath=" + quote_plus(project['projpath'])) except Exception as err: print 'ERROR: could not get import project from', sourcefile exc_type, exc_value, exc_traceback = sys.exc_info() traceback.print_exception(exc_type, exc_value, exc_traceback) self.redirect('/')
def get(self, project_id): pdb = Projects() project = pdb.get(project_id) self.render('projdb/project_detail.html', project=project, delete=True)
def post(self, project_id): forms = {} for field in ['projectname', 'description', 'version']: if field in self.request.arguments.keys(): forms[field] = self.request.arguments[field][0] pdb = Projects() # Existing project. if int(project_id) != pdb.predict_next_rowid(): project = pdb.get(project_id) project_is_new = False # New project else: project = {} project['active'] = 0 project['filename'] = None project_is_new = True if 'projectname' not in forms or \ len(forms['projectname']) == 0: project['projectname'] = "Unnamed Project" else: project['projectname'] = forms['projectname'].strip() if 'description' in forms: project['description'] = forms['description'].strip() else: project['description'] = '' if 'version' in forms: project['version'] = forms['version'].strip() else: project['version'] ='' # if there's no proj file yet, create en empty one if not project['filename']: version = project['version'] pname = project['projectname'] if len(version): filename = '%s-%s' % (pname, version) else: filename = '%s' % pname filename = clean_filename(filename) unique = '%s.proj' % filename i = 1 while os.path.exists(os.path.join(self.get_project_dir(), \ unique)): unique = '%s_%s.proj' % (filename, str(i)) i = i+1 with open(os.path.join(self.get_project_dir(), unique), 'w') as out: out.write('') out.close() project['filename'] = unique if project_is_new: pdb.new(project) else: for key, value in project.iteritems(): pdb.set(project_id, key, value) pdb.modified(project_id) self.redirect(self.request.uri)
def post(self): # The project file is uploaded once to extract the metadata. # It is then deleted and the metadata is used to populate another # import dialog, giving the user an opportunity to edit the # info before importing or cancel the import. if not 'projectname' in self.request.arguments: # First upload sourcefile = self.request.files['projectfile'][0] if sourcefile: filename = sourcefile['filename'] if len(filename) > 0: unique = _get_unique_name(self.get_project_dir(), parse_archive_name(filename)) tdir = mkdtemp(prefix=unique) buff = StringIO.StringIO(sourcefile['body']) archive = tarfile.open(fileobj=buff, mode='r:gz') archive.extractall(path=tdir) proj = Project(tdir) project_info = proj.get_info() try: shutil.rmtree(tdir, onerror=onerror) except: pass self.render('projdb/import-metadata-fields.html', projectname=parse_archive_name(unique), description=project_info['description'], version=project_info['version']) else: # second upload forms = {} for field in ['projectname', 'description', 'version']: if field in self.request.arguments.keys(): forms[field] = self.request.arguments[field][0] sourcefile = self.request.files['projectfile'][0] if sourcefile: filename = sourcefile['filename'] if len(filename) > 0: unique = _get_unique_name(self.get_project_dir(), parse_archive_name(filename)) pdb = Projects() project = {} project['id'] = pdb.predict_next_rowid() project['active'] = 1 project['projectname'] = forms['projectname'].strip() project['description'] = forms['description'].strip() project['version'] = forms['version'].strip() project['projpath'] = unique os.mkdir(unique) buff = StringIO.StringIO(sourcefile['body']) archive = tarfile.open(fileobj=buff, mode='r:gz') archive.extractall(path=unique) vcslist = find_vcs() if vcslist: vcs = vcslist[0](unique) else: vcs = DumbRepo(unique) vcs.init_repo() # Update project settings. proj = Project(project['projpath']) dummy = proj.get_info() # Just to get required keys. info = {} for key in dummy: info[key] = project[key] proj.set_info(info) pdb.new(project) self.redirect("/workspace/project?projpath=" + quote_plus(project['projpath'])) self.redirect("/")
def post(self, project_id): forms = {} for field in ['projectname', 'description', 'version']: if field in self.request.arguments.keys(): forms[field] = self.request.arguments[field][0] pdb = Projects() # Existing project. if int(project_id) != pdb.predict_next_rowid(): project = pdb.get(project_id) project_is_new = False # New project else: project = {} project['active'] = 0 project['filename'] = None project_is_new = True if 'projectname' not in forms or \ len(forms['projectname']) == 0: project['projectname'] = "Unnamed Project" else: project['projectname'] = forms['projectname'].strip() if 'description' in forms: project['description'] = forms['description'].strip() else: project['description'] = '' if 'version' in forms: project['version'] = forms['version'].strip() else: project['version'] = '' # if there's no proj file yet, create en empty one if not project['filename']: version = project['version'] pname = project['projectname'] if len(version): filename = '%s-%s' % (pname, version) else: filename = '%s' % pname filename = clean_filename(filename) unique = '%s.proj' % filename i = 1 while os.path.exists(os.path.join(self.get_project_dir(), \ unique)): unique = '%s_%s.proj' % (filename, str(i)) i = i+1 with open(os.path.join(self.get_project_dir(), unique), 'w') as out: out.write('') out.close() project['filename'] = unique print 'created file:', pname, unique if project_is_new: pdb.new(project) else: for key, value in project.iteritems(): pdb.set(project_id, key, value) pdb.modified(project_id) self.redirect(self.request.uri)