def get(self): if self.logged_in: try: user = self.current_user attacks = user.get_attacks() ndb.delete_multi([attack.key for attack in attacks]) self.response.out.write( simplejson.dumps({'message': "All attacks cleared."})) except Exception as e: trace = traceback.format_exc() logging.error(e.message) logging.error(trace) self.response.set_status(500) self.response.out.write( simplejson.dumps({ 'message': "Clear attacks failed. Sorry! We're looking at it." })) else: self.redirect('/')
def post(self): if self.logged_in: try: if len(self.request.params.multi.dicts) > 1 and 'file' in self.request.params.multi.dicts[1]: file_info = self.request.POST['file'] file_content = file_info.file.read() if file_info.filename.endswith('.json'): events = json_to_events(file_content) if file_info.filename.endswith('.xlsx'): events = excel_to_events(file_content) if file_info.filename.endswith('.xls'): events = excel_to_events(file_content) if file_info.filename.endswith('.csv'): events = csv_to_events(file_content) if file_info.filename.endswith('.ics'): events = ics_to_events(file_content) new_attacks = [] for event in events: new_attack = attack.Attack(parent=self.current_user.key) new_attack.start_time = event['Start'].replace(tzinfo=None) new_attack.duration = event['Duration'] new_attack.comment = event['Comment'] new_attack.start_text = create_start_text(event['Start']) new_attack.duration_text = create_duration_text(event['Duration']) new_attacks.append(new_attack) ndb.put_multi(new_attacks) self.response.out.write(simplejson.dumps({'message': str(len(new_attacks)) + ' attacks uploaded.'})) support_email("List uploaded", str(len(new_attacks)) + " attacks uploaded.") except Exception as e: trace = traceback.format_exc() logging.error(e.message) logging.error(trace) self.response.set_status(500) self.response.out.write(simplejson.dumps({'message': "Upload failed.<br/>Sorry! We're looking at it."})) support_email("Upload failed", "Couldn't upload: " + file_info.filename) else: self.response.out.write(simplejson.dumps({'message': 'Please login before uploading attacks.'}))
def get(self): if self.logged_in: user = self.current_user; attacks = user.get_attacks_as_dict() if len(attacks) > 0: self.response.out.write(simplejson.dumps(generate_statistics_from_events(attacks))) else: self.response.out.write(simplejson.dumps({})) else: self.response.out.write(simplejson.dumps({}))
def get(self): if self.logged_in: user = self.current_user attacks = user.get_attacks_as_dict() if len(attacks) > 0: self.response.out.write( simplejson.dumps(generate_statistics_from_events(attacks))) else: self.response.out.write(simplejson.dumps({})) else: self.response.out.write(simplejson.dumps({}))
def query(self): body = self.request.body query = json.loads(body)['query'] if query == 'count': count = '%s' % self.api.model.query().count(100) self.response.headers['Content-Type'] = 'text/plain' self.response.out.write(count) return self.response.headers['Content-Type'] = 'application/json' def values(): for value in query['values']: if isinstance(value, dict): kind = value['kind'] id = int(value['value']) value = ndb.Key(kind, id) yield value items = self.api.model\ .gql(query['string'], *[i for i in values()])#\ #.fetch(1000) def get_items_json(): for item in items: try: self.api.__is_readable__(self, item) except HTTPError as e: pass else: yield self.api.item_to_JSON(item) json_data = {} json_data[self.api.plural_name] = [ i for i in get_items_json() ] self.response.out.write(json.dumps(json_data))
def delete(self, id): self.response.headers['Content-Type'] = 'application/json' item = self.api.model.get_by_id(int(id)) try: self.api.__is_removable__(self, item) # user should delete dependencies themselves # del children # ndb.delete_multi( # ndb.Query( # ancestor=item.key # ).iter( # keys_only = True # ) # ) item.key.delete() except HTTPError as e: self.response.out.write(e.message) self.response.set_status(e.status) except Exception as e: status = getattr(e, 'status', 500) self.response.out.write(e.message) self.response.set_status(status) else: json_data = {} json_data[self.api.name] = self.api.item_to_JSON(item) self.response.out.write(json.dumps(json_data))
def call(self, payload, url='https://svcs.%spaypal.com/AdaptivePayments/Pay'): url = self.get_url(url) headers = { 'X-PAYPAL-SECURITY-USERID' : user, 'X-PAYPAL-SECURITY-PASSWORD' : password, 'X-PAYPAL-SECURITY-SIGNATURE' : signature, 'X-PAYPAL-APPLICATION-ID': app_id, 'X-PAYPAL-REQUEST-DATA-FORMAT' : 'JSON', 'X-PAYPAL-RESPONSE-DATA-FORMAT' : 'JSON', 'Content-Type': 'application/json' } ctx = ndb.get_context() res = ctx.urlfetch( url, headers=headers, payload=json.dumps(payload), method=urlfetch.POST ).get_result() if res.status_code != 200: raise RequestError(res.content) data = json.loads(res.content) envelope = data['responseEnvelope'] ack = envelope.get('ack') or envelope.get('ACK') if ack != 'Success': raise AckError(res.content) return data
def query(self): body = self.request.body query = json.loads(body)['query'] if query == 'count': count = '%s' % self.api.model.query().count(100) self.response.headers['Content-Type'] = 'text/plain' self.response.out.write(count) return self.response.headers['Content-Type'] = 'application/json' def values(): for value in query['values']: if isinstance(value, dict): kind = value['kind'] id = int(value['value']) value = ndb.Key(kind, id) yield value items = self.api.model\ .gql(query['string'], *[i for i in values()])#\ #.fetch(1000) def get_items_json(): for item in items: try: self.api.__is_readable__(self, item) except HTTPError as e: pass else: yield self.api.item_to_JSON(item) json_data = {} json_data[self.api.plural_name] = [i for i in get_items_json()] self.response.out.write(json.dumps(json_data))
def get(self): config = Configuration.get_instance() matches = re.match( r"/(?P<hash>[0-9a-z]+)", self.request.path) if matches: file_hash = matches.group("hash") current_conversion = get_conversion_from_hash(file_hash) if current_conversion: path = os.path.join(os.path.join(os.path.dirname(__file__), 'html'), '../templates/main.html') colors = current_conversion.get_palette() self.response.out.write(template.render(path, {'show_file': True, 'key': current_conversion.hash, 'filename': current_conversion.filename, 'palette': simplejson.dumps( {'filename': current_conversion.filename, 'colors': colors}), 'web_debug': config.web_debug})) return path = os.path.join(os.path.join(os.path.dirname(__file__), 'html'), '../templates/error.html') self.response.out.write(template.render(path, {'status': '404', 'message': "We don't have what you're looking for."})) self.response.status = 404
def get(self): query_str = "SELECT * FROM FeedItem ORDER BY date DESC LIMIT 10" feed_items = db.GqlQuery(query_str).fetch(10) self.response.headers['Content-Type'] = "application/json" feed_items_serialized = [] for item in feed_items: feed_items_serialized.append(to_dict(item)); self.response.out.write(simplejson.dumps(feed_items_serialized))
def get(self): query_str = "SELECT * FROM FeedItem ORDER BY date DESC LIMIT 10" feed_items = db.GqlQuery(query_str).fetch(10) self.response.headers['Content-Type'] = "application/json" feed_items_serialized = [] for item in feed_items: feed_items_serialized.append(to_dict(item)) self.response.out.write(simplejson.dumps(feed_items_serialized))
def get(self): logging.info('Starting to fetch statistics') today = datetime.combine(date.today(), time()) yesterday = today - timedelta(days=1) month_ago = today - timedelta(days=30) three_months_ago = datetime.now() + timedelta(days=-91) query = Download.query(Download.created_date > three_months_ago) logging.info('Built query') query_options = {'batch_size': 1000} all_downloads = query.fetch(**query_options) logging.info('Called fetch(**query_options) on query') # all_downloads = [] month_items = [download for download in all_downloads if download.created_date > month_ago] yesterday_items = [download for download in month_items if yesterday < download.created_date < today] today_items = [download for download in month_items if download.created_date > today] logging.info('Sorted results into buckets') today_values = extract_data(today_items) today_values['title'] = "Today" yesterday_values = extract_data(yesterday_items) yesterday_values['title'] = "Yesterday" month_values = extract_data(month_items) month_values['title'] = "Last 30 days" logging.info('Extracted today, yesterday and month') all_values = extract_data(all_downloads) all_values['title'] = "Last 3 months" logging.info('Extracted all') trend_labels, trend_uploads, trend_downloads = extract_trend_data(month_items) trend_data = {'labels': trend_labels, 'uploads': trend_uploads, 'downloads': trend_downloads} days_data = [today_values, yesterday_values, month_values, all_values] response = {'days': days_data, 'trend': trend_data} self.response.out.write(simplejson.dumps(response))
def log( event_json, sourcetype='syslog', host=None, source=None ): """ posts to input_url Args: event_json{dict} - event payload sourcetype{str} - sourcetype, defaults to syslog host{str} - log host origin host source{str} - log origin api Returns: {str} - post response """ if not project_id: raise Exception('project_id is required') if not access_token: raise Exception('access_token is required') params = { 'project': project_id, 'sourcetype': sourcetype } if host: params['host'] = host if source: params['source'] = source url = input_url + urllib.urlencode(params) payload = json.dumps(event_json) authorization = 'Basic ' + base64.b64encode(':'+access_token) headers = {'Authorization': authorization} # rpc = urlfetch.create_rpc() # urlfetch.make_fetch_call( # rpc, # url, # payload=payload, # headers=headers, # method=urlfetch.POST # ) # rpc.get_result() return urlfetch.fetch( url, payload=payload, headers=headers, method=urlfetch.POST )
def get(self): map = [] map.append(DataId.map) map.append(Field.map) map.append(FieldAndString.map) map.append(Range.map) map.append(Recent.map) self.response.out.write(simplejson.dumps(map)) return
def get_first_ten_events(self): if self.first_ten_events: return json.loads(str(self.first_ten_events)) else: events = self.get_events() first_ten = events[:10] self.first_ten_events = simplejson.dumps(first_ten) self.put() return first_ten
def get(self): if self.logged_in: try: user = self.current_user; attacks = user.get_attacks() ndb.delete_multi([attack.key for attack in attacks]) self.response.out.write(simplejson.dumps({'message': "All attacks cleared."})) except Exception as e: trace = traceback.format_exc() logging.error(e.message) logging.error(trace) self.response.set_status(500) self.response.out.write(simplejson.dumps({'message': "Clear attacks failed. Sorry! We're looking at it."})) else: self.redirect('/')
def get(self): config = Configuration.get_instance() example_palette = [{"name": "Sugar Hearts You", "hex": "#fe4365", "safeName": "sugar-hearts-you"}, {"name": "Party Confetti", "hex": "#fc9d9a", "safeName": "party-confetti"}, {"name": "Sugar Champagne", "hex": "#f9cdad", "safeName": "sugar-champagne"}, {"name": "Bursts Of Euphoria", "hex": "#c8c8a9", "safeName": "bursts-of-euphoria"}, {"name": "Happy Balloons", "hex": "#83af9b", "safeName": "happy-balloons"}] path = os.path.join(os.path.join(os.path.dirname(__file__), 'html'), '../templates/main.html') self.response.out.write(template.render(path, {'show_file': False, 'web_debug': config.web_debug, 'palette': simplejson.dumps({'filename': 'Example from <a href="http://www.colourlovers.com/palettes/most-loved/all-time/meta">ColourLovers.com</a>', 'colors': example_palette})}))
def _request(self, method, path, data={}): path = path.rstrip('/') + '/' if method == 'POST': authorization = 'Basic ' + base64.b64encode(self.auth_id+':'+self.auth_token) headers = { 'Authorization': authorization, 'Content-Type': 'application/json' } headers.update(self.headers) url = self._api + path payload = json.dumps(data) res = urlfetch.fetch( url, payload=payload, headers=headers, method=urlfetch.POST ) # elif method == 'GET': # r = requests.get(self._api + path, headers=self.headers, # auth=(self.auth_id, self.auth_token), # params=data) # elif method == 'DELETE': # r = requests.delete(self._api + path, headers=self.headers, # auth=(self.auth_id, self.auth_token), # params=data) # elif method == 'PUT': # headers = {'content-type': 'application/json'} # headers.update(self.headers) # r = requests.put(self._api + path, headers=headers, # auth=(self.auth_id, self.auth_token), # data=json.dumps(data)) content = res.content if content: try: response = json.loads(content) except ValueError: response = content else: response = content return (res.status_code, response)
def get(self): self.response.headers['Content-Type'] = 'application/json' def get_items_json(): items = self.api.model.query().fetch(100) for item in items: try: self.api.__is_readable__(self, item) except HTTPError as e: pass else: yield self.api.item_to_JSON(item) json_data = {} json_data[self.api.plural_name] = [ i for i in get_items_json() ] self.response.out.write(json.dumps(json_data))
def get(self, id): self.response.headers['Content-Type'] = 'application/json' item = self.api.model.get_by_id(int(id)) try: self.api.__is_readable__(self, item) except HTTPError as e: self.response.out.write(e.message) self.response.set_status(e.status) except Exception as e: status = getattr(e, 'status', 500) self.response.out.write(e.message) self.response.set_status(status) else: json_data = {} json_data[self.api.name] = self.api.item_to_JSON(item) self.response.out.write(json.dumps(json_data))
def send(self): if len(self) != 0: logger.info('SENDING') res = {} for message in self: logger.info(message) event = message['event'] res.setdefault(event, []) del message['event'] res[event].append(message) events = [{'event': k, 'messages': v} for k, v in res.iteritems()] content = {'events': events} json_content = json.dumps(content) self.view.response.headers['Content-Type'] = 'application/json' self.view.response.out.write(json_content) return
def get(self): self.response.headers['Content-Type'] = 'application/json' def get_items_json(): items = self.api.model.query().fetch(100) for item in items: try: self.api.__is_readable__(self, item) except HTTPError as e: pass else: yield self.api.item_to_JSON(item) json_data = {} json_data[self.api.plural_name] = [i for i in get_items_json()] self.response.out.write(json.dumps(json_data))
def create(self): self.response.headers['Content-Type'] = 'application/json' item = self.api.model() self.api.update_item(self, item) try: self.api.__is_creatable__(self, item) item.put() except HTTPError as e: self.response.out.write(e.message) self.response.set_status(e.status) except Exception as e: status = getattr(e, 'status', 500) self.response.out.write(e.message) self.response.set_status(status) else: json_data = {} json_data[self.api.name] = self.api.item_to_JSON(item) self.response.out.write(json.dumps(json_data))
def send(self): if len(self) != 0: logger.info('SENDING') res = {} for message in self: logger.info(message) event = message['event'] res.setdefault(event, []) del message['event'] res[event].append(message) events = [{'event': k, 'messages': v} for k, v in res.iteritems()] content = { 'events': events } json_content = json.dumps(content) self.view.response.headers['Content-Type'] = 'application/json' self.view.response.out.write(json_content) return
def show_main(self, user): response = {} attacks = user.get_attacks_as_dict() response['data'] = simplejson.dumps(generate_statistics_from_events(attacks)) response['web_debug'] = Configuration.get_instance().web_debug response['share_report'] = user.share_report_key response['share_report_and_list'] = user.share_report_and_list_key response['logout_url'] = self.get_logout() response['show_logout'] = True response['show_add'] = True response['show_options'] = True response['show_list'] = True response['user'] = user path = os.path.join(os.path.join(os.path.dirname(__file__), 'html'), '../../templates/main.html') self.response.out.write(template.render(path, response))
def get(self): events = self.get_example_attacks() response = generate_statistics_from_events(events) response['web_debug'] = Configuration.get_instance().web_debug response['show_logout'] = False response['share_report'] = "example_report" response['share_report_and_list'] = "example_report_and_list" response['show_add'] = True response['show_options'] = True response['show_list'] = True response['example'] = True response['user'] = {'name': 'Example User', 'provider_name': 'Google+'} response['data'] = simplejson.dumps(response) path = os.path.join(os.path.join(os.path.dirname(__file__), 'html'), '../../templates/main.html') self.response.out.write(template.render(path, response))
def show_main(self, user): response = {} attacks = user.get_attacks_as_dict() response['data'] = simplejson.dumps( generate_statistics_from_events(attacks)) response['web_debug'] = Configuration.get_instance().web_debug response['share_report'] = user.share_report_key response['share_report_and_list'] = user.share_report_and_list_key response['logout_url'] = self.get_logout() response['show_logout'] = True response['show_add'] = True response['show_options'] = True response['show_list'] = True response['user'] = user path = os.path.join(os.path.join(os.path.dirname(__file__), 'html'), '../../templates/main.html') self.response.out.write(template.render(path, response))
def post(self): if self.logged_in: try: if len(self.request.params.multi.dicts ) > 1 and 'file' in self.request.params.multi.dicts[1]: file_info = self.request.POST['file'] file_content = file_info.file.read() if file_info.filename.endswith('.json'): events = json_to_events(file_content) if file_info.filename.endswith('.xlsx'): events = excel_to_events(file_content) if file_info.filename.endswith('.xls'): events = excel_to_events(file_content) if file_info.filename.endswith('.csv'): events = csv_to_events(file_content) if file_info.filename.endswith('.ics'): events = ics_to_events(file_content) new_attacks = [] for event in events: new_attack = attack.Attack( parent=self.current_user.key) new_attack.start_time = event['Start'].replace( tzinfo=None) new_attack.duration = event['Duration'] new_attack.comment = event['Comment'] new_attack.start_text = create_start_text( event['Start']) new_attack.duration_text = create_duration_text( event['Duration']) new_attacks.append(new_attack) ndb.put_multi(new_attacks) self.response.out.write( simplejson.dumps({ 'message': str(len(new_attacks)) + ' attacks uploaded.' })) support_email("List uploaded", str(len(new_attacks)) + " attacks uploaded.") except Exception as e: trace = traceback.format_exc() logging.error(e.message) logging.error(trace) self.response.set_status(500) self.response.out.write( simplejson.dumps({ 'message': "Upload failed.<br/>Sorry! We're looking at it." })) support_email("Upload failed", "Couldn't upload: " + file_info.filename) else: self.response.out.write( simplejson.dumps( {'message': 'Please login before uploading attacks.'}))
def post(self): if len(self.request.params.multi.dicts) > 1 and 'file' in self.request.params.multi.dicts[1]: file_info = self.request.POST['file'] head, tail = ntpath.split(file_info.filename) full_filename = tail or ntpath.basename(head) file_content = file_info.file.read() file_size = len(file_content) file_hash = hashlib.md5(file_content).hexdigest() try: current_conversion = self.get_conversion_from_hash(file_hash) start_time = time.time() if not current_conversion: # noinspection PyBroadException try: cal = icalendar.Calendar.from_ical(file_content) except Exception, e: cal = None logging.warn('Could not convert "' + full_filename + '".') logging.warn('Storing failed conversion "' + full_filename + '" with hash ' + file_hash + '.') logging.warn(e.message) self.save_file(file_hash, file_content) if cal: current_conversion = conversion.Conversion() events = process_calendar(cal) current_conversion.hash = file_hash current_conversion.full_filename = full_filename current_conversion.filename = drop_extension_from_filename(full_filename) current_conversion.file_size = file_size current_conversion.event_count = len(events) current_conversion.first_ten_events = simplejson.dumps(events[:10]) current_conversion.blob_key = self.save_file(file_hash, file_content) current_conversion.put() first_ten_events = current_conversion.get_first_ten_events() first_ten_events = format_events_for_html(first_ten_events) response = {'message': "Calendar created.", 'paid': not current_conversion.paid_date is None, 'filename': current_conversion.filename, 'full_filename': current_conversion.full_filename, 'event_count': current_conversion.event_count, 'todo_count': current_conversion.todo_count, 'key': current_conversion.hash, 'events': first_ten_events} logging.info('Uploaded "' + current_conversion.full_filename + '" with ' + str(current_conversion.event_count) + ' events.') log_upload(current_conversion, time.time() - start_time) else: # Not a valid iCalendar response = {'message': "That's not a valid iCalendar file.", 'filename': None, 'paid': False, 'key': None} self.response.status = 500 else: filename = drop_extension_from_filename(full_filename) if current_conversion.full_filename != full_filename or current_conversion.filename != filename: current_conversion.full_filename = full_filename current_conversion.filename = filename current_conversion.put() first_ten_events = format_events_for_html(current_conversion.get_first_ten_events()) response = {'message': "Exisiting calendar.", 'paid': not current_conversion.paid_date is None, 'filename': current_conversion.filename, 'full_filename': current_conversion.full_filename, 'event_count': current_conversion.event_count, 'todo_count': current_conversion.todo_count, 'key': current_conversion.hash, 'events': first_ten_events} log_upload(current_conversion, time.time() - start_time)
def __init__(self, status=422, message=''): self.status = status if isinstance(message, dict): message = json.dumps(message) self.message = message
def get(self): matches = re.match(r"/shared/(?P<key>[0-9a-z_]+)/.*", self.request.path) if matches: shared_link = matches.group("key") response = {} attacks = None if len(shared_link) == 7: # Report with List acc = User.get_account_from_share_link_report_and_list( shared_link) response['show_list'] = True attacks = acc.get_attacks_as_dict() if len(shared_link) == 8: # Report only acc = User.get_account_from_share_link_report_only(shared_link) response['show_list'] = False attacks = acc.get_attacks_as_dict() if shared_link == "example_report": response['show_list'] = False attacks = Example.get_example_attacks() if shared_link == "example_report_and_list": response['show_list'] = True attacks = Example.get_example_attacks() if attacks is not None: if len(attacks) > 0: response['data'] = simplejson.dumps( generate_statistics_from_events(attacks)) else: response['data'] = {} response['show_logout'] = False response['show_add'] = False response['show_options'] = False response['shared'] = True response['web_debug'] = Configuration.get_instance().web_debug path = os.path.join( os.path.join(os.path.dirname(__file__), 'html'), '../../templates/main.html') self.response.out.write(template.render(path, response)) else: template_values = { 'status': '404 - Not found', 'title': 'What a headache!', 'message': "Sorry, we couldn't find what you're looking for." } self.response.status = 404 path = os.path.join( os.path.join(os.path.dirname(__file__), 'html'), '../../templates/error.html') self.response.out.write(template.render(path, template_values)) else: template_values = { 'status': '404 - Not found', 'title': 'What a headache!', 'message': "Sorry, we couldn't find what you're looking for." } self.response.status = 404 path = os.path.join( os.path.join(os.path.dirname(__file__), 'html'), '../../templates/error.html') self.response.out.write(template.render(path, template_values))
'palette': {'filename': current_conversion.filename, 'colors': colors}} log_upload(current_conversion, time.time() - start_time) except Exception, e: trace = traceback.format_exc() logging.error('Exception while tyring to upload.') logging.error(e.message) logging.error(trace) email_message = e.message + '\r\n\r\n' + trace support_email('Upload Failed', email_message) response = {'message': "Something bad happened, we're looking at it."} self.response.status = 500 else: response = {'message': "Something bad happened, we're looking at it."} logging.error(self.request.params.multi) if len(self.request.params.multi) > 0: support_email('Upload Failed', str(self.request.params.multi)) self.response.status = 500 self.response.out.write(simplejson.dumps(response))
def get(self): matches = re.match( r"/shared/(?P<key>[0-9a-z_]+)/.*", self.request.path) if matches: shared_link = matches.group("key") response = {} attacks = None if len(shared_link) == 7: # Report with List acc = User.get_account_from_share_link_report_and_list(shared_link) response['show_list'] = True attacks = acc.get_attacks_as_dict() if len(shared_link) == 8: # Report only acc = User.get_account_from_share_link_report_only(shared_link) response['show_list'] = False attacks = acc.get_attacks_as_dict() if shared_link == "example_report": response['show_list'] = False attacks = Example.get_example_attacks() if shared_link == "example_report_and_list": response['show_list'] = True attacks = Example.get_example_attacks() if attacks is not None: if len(attacks) > 0: response['data'] = simplejson.dumps(generate_statistics_from_events(attacks)) else: response['data'] = {} response['show_logout'] = False response['show_add'] = False response['show_options'] = False response['shared'] = True response['web_debug'] = Configuration.get_instance().web_debug path = os.path.join(os.path.join(os.path.dirname(__file__), 'html'), '../../templates/main.html') self.response.out.write(template.render(path, response)) else: template_values = {'status': '404 - Not found', 'title': 'What a headache!', 'message': "Sorry, we couldn't find what you're looking for."} self.response.status = 404 path = os.path.join(os.path.join(os.path.dirname(__file__), 'html'), '../../templates/error.html') self.response.out.write(template.render(path, template_values)) else: template_values = {'status': '404 - Not found', 'title': 'What a headache!', 'message': "Sorry, we couldn't find what you're looking for."} self.response.status = 404 path = os.path.join(os.path.join(os.path.dirname(__file__), 'html'), '../../templates/error.html') self.response.out.write(template.render(path, template_values))