Commit aa46c532 authored by Bruce Flynn's avatar Bruce Flynn

Beta implementation working.

parent 76444713
This diff is collapsed.
import logging
import math
from datetime import timedelta
import numpy as np
......@@ -10,8 +9,8 @@ from sqlalchemy import (
)
from metobs.data.calc import wind_vector_degrees
from amrc_aws import rdr
from amrc_aws import rdr
LOG = logging.getLogger(__name__)
......@@ -31,42 +30,30 @@ def insert_frames(frames):
Insert data from frames as a batch, i.e., if one insert fails all frames
fail.
"""
sensor_map = fetch_sensor_map()
result = engine.execute('select id, name from stations')
stations = {r[1]: r[0] for r in result}
order = ('air_temp', 'vtempdiff', 'rh', 'pressure',
'_wind_vector_north', '_wind_vector_east')
inserts = []
for frame in frames:
aid = frame['_argosid']
site = frame['_site']
stamp = frame['_stamp']
varnames = sorted([f for f in frame.keys()
if not f.startswith('_') or f.startswith('_wind')])
for varname in varnames:
value = frame[varname]
if rdr.is_nan(value):
LOG.isEnabledFor(0) and LOG.log(9, 'NaN %s=%s', varname, value)
continue # don't insert NaNs
sensor_id = sensor_map.get((varname, site))
if sensor_id:
inserts.append(dict(
sid=sensor_id,
stamp=stamp,
aid=aid,
value=value
))
query = sql.text("""
INSERT INTO data (sensor_id, stamp, aid, values)
VALUES (:sid, :stamp, :aid, :value)
""")
result = engine.execute(query, inserts)
return result.rowcount
def fetch_sensor_map():
rows = engine.execute(sql.text('SELECT name, site, id FROM sensors'))
return {(r[0], r[1]): r[2] for r in rows}
def get_slice(stations, sensors, start, end, avg=300):
station_id = stations.get(site)
dat = {n: frame.get(n, rdr.NAN) for n in order}
nans = len([x for x in dat.values() if x != x])
# skip inserts if data is all NaNs
if nans == len(order):
continue
dat.update({'stamp': stamp, 'station_id': station_id})
inserts.append(dat)
engine.execute(sql.text('''
insert into data (stamp, station_id, air_temp, vtempdiff, rh, pressure, _wind_vector_north, _wind_vector_east)
values (%s, %s, %s, %s, %s, %s, %s, %s)
'''), inserts)
def get_slice(stations, symbols, start, end, avg=300):
select = sql.text("""
SELECT
series.stamp, air_temp, vtempdiff, rh, pressure,
......@@ -77,7 +64,7 @@ def get_slice(stations, sensors, start, end, avg=300):
LEFT JOIN stations ON name IN :stations
) AS series
LEFT JOIN (
SELECT s.name as station, d.* FROM data2 d, stations s
SELECT s.name as station, d.* FROM data d, stations s
WHERE d.station_id = s.id
AND stamp >= :start AND stamp <= :end
AND s.name IN :stations
......@@ -107,5 +94,18 @@ def get_slice(stations, sensors, start, end, avg=300):
# return only the columns for the requested sensors
all_sensors = ['air_temp', 'vtempdiff', 'rh', 'pressure', 'wind_dir', 'wind_spd']
colidxs = [0] + [all_sensors.index(s) + 1 for s in sensors]
colidxs = [0] + [all_sensors.index(s) + 1 for s in symbols]
return dat[:,colidxs]
def get_stations():
results = engine.execute(sql.text("""
SELECT name, min(stamp), max(stamp)
FROM stations, data
WHERE stations.id = data.station_id
GROUP BY name
ORDER BY min(stamp)
"""))
return [dict(r) for r in results]
CREATE TABLE data (
stamp timestamp without time zone NOT NULL,
station_id integer NOT NULL,
air_temp real,
vtempdiff real,
rh real,
pressure real,
_wind_vector_north real,
_wind_vector_east real,
PRIMARY KEY (stamp, station_id)
);
CREATE INDEX ON data (stamp, station_id);
CREATE TABLE stations (
id SERIAL PRIMARY KEY,
name text,
region text
);
CREATE INDEX ON stations (name);
CREATE TABLE locations (
station_id integer,
stamp timestamp,
latitude real,
longitude real,
altitude real,
PRIMARY KEY (station_id, stamp)
);
from datetime import datetime
def unixtime(dt):
return (dt - datetime(1970, 1, 1)).total_seconds()
......@@ -16,33 +16,9 @@ args = parser.parse_args()
NAN = float('nan')
def insert_frames(frames, cur):
inserts = []
for frame in frames:
aid = frame['_argosid']
site = frame['_site']
stamp = frame['_stamp']
varnames = sorted([f for f in frame.keys()
if not f.startswith('_') or f.startswith('_wind')])
for varname in varnames:
value = frame[varname]
if rdr.is_nan(value):
continue # don't insert NaNs
sensor_id = sensor_map.get((varname, site))
if sensor_id:
inserts.append((sensor_id, stamp, aid, value))
if '_wind_vector_north' in frame and '_wind_vector_east' in frame:
frame['wind_dir_north'] = frame.pop('_wind_dir_north')
frame['wind_dir_east'] = frame.pop('_wind_dir_east')
cur.executemany('insert into data (sensor_id, stamp, aid, value) values (%s, %s, %s, %s)', inserts)
def insert_frames2(frames, cur):
cur.execute('select id, name from sites')
cur.execute('select id, name from stations')
stations = {r[1]: r[0] for r in cur.fetchall()}
order = ('air_temp', 'vtempdiff', 'rh', 'pressure',
'_wind_vector_north', '_wind_vector_east')
......@@ -58,26 +34,13 @@ def insert_frames2(frames, cur):
inserts.append([stamp, station_id] + dat)
cur.executemany('''
insert into data2 (stamp, station_id, air_temp, vtempdiff, rh, pressure, _wind_vector_north, _wind_vector_east)
insert into data (stamp, station_id, air_temp, vtempdiff, rh, pressure, _wind_vector_north, _wind_vector_east)
values (%s, %s, %s, %s, %s, %s, %s, %s)
''', inserts)
def fetch_sensor_map(cur):
cur.execute('select name, site, id from sensors')
return {(r[0], r[1]): r[2] for r in cur.fetchall()}
def fetch_site_names(cur):
cur.execute('select name from sites')
return [r[0] for r in cur.fetchall()]
logging.basicConfig(level=logging.DEBUG, format='[%(asctime)s %(levelname)s] %(message)s')
conn = connect(database='amrc_aws')
sensor_map = fetch_sensor_map(conn.cursor())
site_names = fetch_site_names(conn.cursor())
def error_callback(*args):
......
CREATE table sites (
id serial PRIMARY KEY,
name text,
region text
);
CREATE INDEX ON sites(name);
CREATE table sensors (
id serial primary key,
site text,
name text
);
CREATE INDEX ON sensors (id, site);
CREATE table data (
sensor_id int,
stamp timestamp,
value real,
aid int,
PRIMARY KEY (sensor_id, stamp)
);
CREATE INDEX ON data (sensor_id, stamp);
-- CREATE MATERIALIZED VIEW data_30m AS
-- WITH
-- series AS (SELECT generate_series('1985-01-01', now(), '00:30:00'::interval) AS stamp),
-- data_avg AS (
-- SELECT data.sensor_id,
-- avg(data.value) AS value,
-- count(*) AS count,
-- to_timestamp((date_part('epoch', data.stamp)::int - date_part('epoch', data.stamp)::int % 1800)) AS bucket
-- FROM data
-- WHERE data.stamp >= '1985-01-01' AND data.stamp <= now()
-- GROUP BY bucket, data.sensor_id
-- )
-- SELECT d.sensor_id,
-- s.stamp,
-- d.value,
-- d.count
-- FROM series s
-- LEFT JOIN data_avg d ON s.stamp = d.bucket,
-- sensors
-- WHERE sensors.id = d.sensor_id;
-- CREATE MATERIALIZED VIEW data_3h AS
-- WITH
-- series AS (SELECT generate_series('1985-01-01', now(), '3 hours'::interval) AS stamp),
-- data_avg AS (
-- SELECT data.sensor_id,
-- avg(data.value) AS value,
-- count(*) AS count,
-- to_timestamp((date_part('epoch', data.stamp)::int - date_part('epoch', data.stamp)::int % 10800)) AS bucket
-- FROM data
-- WHERE data.stamp >= '1985-01-01' AND data.stamp <= now()
-- GROUP BY bucket, data.sensor_id
-- )
-- SELECT d.sensor_id,
-- s.stamp,
-- d.value,
-- d.count
-- FROM series s
-- LEFT JOIN data_avg d ON s.stamp = d.bucket,
-- sensors
-- WHERE sensors.id = d.sensor_id;
-- CREATE MATERIALIZED VIEW data_6h AS
-- WITH
-- series AS (SELECT generate_series('1985-01-01', now(), '6 hours'::interval) AS stamp),
-- data_avg AS (
-- SELECT data.sensor_id,
-- avg(data.value) AS value,
-- count(*) AS count,
-- to_timestamp((date_part('epoch', data.stamp)::int - date_part('epoch', data.stamp)::int % 21600)) AS bucket
-- FROM data
-- WHERE data.stamp >= '1985-01-01' AND data.stamp <= now()
-- GROUP BY bucket, data.sensor_id
-- )
-- SELECT d.sensor_id,
-- s.stamp,
-- d.value,
-- d.count
-- FROM series s
-- LEFT JOIN data_avg d ON s.stamp = d.bucket,
-- sensors
-- WHERE sensors.id = d.sensor_id;
-- SELECT stamp, array_agg(var || ':' || avg) as foo
-- FROM (
-- SELECT generate_series('1986-05-01', '1986-06-01', '1800 seconds'::interval) as stamp) AS s
-- LEFT JOIN (
-- SELECT
-- site||'.'||name as var,
-- avg(value),
-- to_timestamp(extract('epoch' from stamp)::int - extract('epoch' from stamp)::int % 1800) AS bucket
-- FROM data JOIN sensors ON data.sensor_id = sensors.id
-- WHERE
-- sensor_id IN (33)
-- AND stamp >= '1986-05-01'
-- AND stamp <= '1986-06-01'
-- GROUP BY bucket, var
-- ORDER BY var) AS d
-- ON s.stamp = d.bucket
-- GROUP BY stamp
-- ORDER BY stamp;
......@@ -17,6 +17,6 @@ def main(global_config, **settings):
config.add_static_view('static', 'static', cache_max_age=3600)
config.add_route('data_form_csv', '/data.csv')
config.add_route('data_form_netcdf', '/data.nc')
config.add_route('sites', '/sites.json')
config.add_route('stations', '/stations.json')
config.scan()
return config.make_wsgi_app()
......@@ -8,15 +8,19 @@ def csv_response(stations, sensors, rows):
def yielder():
yield '# AMRC AWS\n'
yield '# Fields: stamp,{}\n'.format(','.join(fields))
# rows should always be a multiple of the number of stations
for sidx in range(0, len(rows), len(stations)):
stamp = rows[sidx][0]
# Rows should always be a multiple of the number of stations. Therefore,
# stamp_idx will always point to the first station row for a given
# timestamp.
for stamp_idx in range(0, len(rows), len(stations)):
stamp = rows[stamp_idx][0]
vals = []
for ridx in range(len(stations)):
for val in rows[sidx][1:]:
# station_idx will be the index into this timestamp for each station
for station_idx in range(len(stations)):
for val in rows[stamp_idx + station_idx][1:]:
if val is None or val != val:
vals.append('')
else:
vals.append('{:.2f}'.format(float(val)))
# product the row for a timestamp
yield '{:%Y-%m-%dT%H:%M:%SZ},{}\n'.format(stamp, ','.join(vals))
return yielder()
......@@ -3,23 +3,11 @@
var app = angular.module('amrcAws', ['ui.bootstrap']);
app.factory('ArgosIds', function($http) {
app.factory('Stations', function($http) {
function getForSite(siteCode) {
}
return {
getForSite: getForSite,
};
});
app.factory('Sites', function($http) {
// return sites sorted by name
// return stations sorted by name
function get() {
return $http.get('/sites.json', {cache: true}).then(function(response) {
return $http.get('stations.json', {cache: true}).then(function(response) {
return response.data.sort(function(a, b) {
if (a.name < b.name) return -1;
if (a.name === b.name) return 0;
......@@ -33,6 +21,7 @@ app.factory('Sites', function($http) {
};
});
app.filter('objectKey', function() {
return function(input, key) {
if (!input) return input;
......@@ -46,18 +35,34 @@ app.filter('objectKey', function() {
}
});
app.directive('dateInput', function() {
return {
requires: ['ngModel'],
scope: {
}
}
app.controller('App', function ($scope, Sites) {
});
$scope.selectedArgosIds = {};
app.controller('App', function ($scope, Stations) {
$scope.form = {
start: {
opened: false,
value: null
},
end: {
opened: false,
value: null
},
stations: [],
symbols: []
}
Sites.get().then(function (sites) {
$scope.sites = sites;
$.each(sites, function (idx, site) {
$.each(site.aids, function (idx, id) {
$scope.selectedArgosIds[id] = false;
});
});
Stations.get().then(function (stations) {
$scope.stations = stations;
});
});
......@@ -40,14 +40,43 @@
<form class="form-horizontal">
<h4 class="col-sm-12">Select Date Range</h4>
<div class="form-group">
<label class="col-sm-2 control-label">Start</label>
<div class="col-sm-4">
<p class="input-group">
<input type="text" class="form-control"
uib-datepicker-popup
ng-model="form.start.value"
ng-required="true" />
<span class="input-group-btn">
<button type="button" class="btn btn-default" ng-click="><i class="glyphicon glyphicon-calendar"></i></button>
</span>
</p>
</div>
<label class="col-sm-2 control-label">End</label>
<div class="col-sm-4">
<p class="input-group">
<input type="text" class="form-control"
uib-datepicker-popup
ng-model="form.end"
ng-required="true" />
<span class="input-group-btn">
<button type="button" class="btn btn-default"><i class="glyphicon glyphicon-calendar"></i></button>
</span>
</p>
</div>
</div>
<h4 class="col-sm-12">Select ARGOS IDs</h4>
<div class="form-group">
<label class="col-sm-2 control-label">Station</label>
<div class="col-sm-10">
<select name="site" class="form-control"
ng-model="selectedSite"
ng-options="site.name for site in sites"></select>
ng-model="selectedStation"
ng-options="station.name for station in stations"></select>
</div>
</div>
......@@ -55,33 +84,16 @@
<label class="col-sm-2 control-label">Argos IDs</label>
<div class="col-sm-10">
<div class="btn-group">
<labe$ class="btn btn-primary" ng-repeat="aid in selectedSite.aids" ng-model="selectedArgosIds[aid]" btn-checkbox>{{aid}}</label>
<label class="btn btn-primary" ng-repeat="aid in selectedSite.aids" ng-model="selectedArgosIds[aid]" btn-checkbox>{{aid}}</label>
</div>
</div>
</div>
<h4 class="col-sm-12">Select Sensors</h4>
<div class="form-group">
<label for="inputPassword3" class="col-sm-2 control-label">Password</label>
<div class="col-sm-10">
<input type="password" class="form-control" id="inputPassword3" placeholder="Password">
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<div class="checkbox">
<label>
<input type="checkbox"> Remember me
</label>
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-default">Sign in</button>
<button type="submit" class="btn btn-default">Search</button>
</div>
</div>
......
[{"min_available": 441856800.0, "name": "Siple Station"}, {"min_available": 441856800.0, "name": "Windless Bight"}, {"min_available": 441856800.0, "name": "Ferrell"}, {"min_available": 441856800.0, "name": "Manning"}, {"min_available": 441856800.0, "name": "Marble Point"}, {"min_available": 441856800.0, "name": "Whitlock"}, {"min_available": 441856800.0, "name": "Meeley"}, {"min_available": 441856800.0, "name": "Byrd"}, {"min_available": 441857400.0, "name": "D-57"}, {"min_available": 442138800.0, "name": "Marilyn"}, {"min_available": 442188600.0, "name": "Fogle"}, {"min_available": 442212600.0, "name": "Manuela"}, {"min_available": 442720200.0, "name": "D-47"}, {"min_available": 442732200.0, "name": "Martha I"}, {"min_available": 443007000.0, "name": "D-10"}, {"min_available": 443062200.0, "name": "Laurie"}, {"min_available": 443839800.0, "name": "Tiffany"}, {"min_available": 443851200.0, "name": "Dome C"}, {"min_available": 465276600.0, "name": "D-80"}, {"min_available": 474881400.0, "name": "Schwerdtfeger"}, {"min_available": 474881400.0, "name": "Gill"}, {"min_available": 498797400.0, "name": "Larsen Ice Shelf"}, {"min_available": 505613400.0, "name": "Bowers"}, {"min_available": 505629600.0, "name": "Allison"}, {"min_available": 506989200.0, "name": "Elaine"}, {"min_available": 507345000.0, "name": "Patrick"}, {"min_available": 507430200.0, "name": "Clean Air"}, {"min_available": 507430800.0, "name": "Lettau"}, {"min_available": 507577800.0, "name": "Butler Island"}, {"min_available": 508018800.0, "name": "Dolleman Island"}, {"min_available": 510388800.0, "name": "Uranus Glacier"}, {"min_available": 539224800.0, "name": "Buckle Island"}, {"min_available": 539236800.0, "name": "Jimmy"}, {"min_available": 540120000.0, "name": "Martha II"}, {"min_available": 568081200.0, "name": "Shristi"}, {"min_available": 568083600.0, "name": "Scott Island"}, {"min_available": 568095000.0, "name": "Sushila"}, {"min_available": 568518600.0, "name": "Sandra"}, {"min_available": 569362800.0, "name": "Lynn"}, {"min_available": 583808400.0, "name": "Rothera"}, {"min_available": 599184600.0, "name": "Pat"}, {"min_available": 601290000.0, "name": "Pegasus"}, {"min_available": 602123400.0, "name": "Cape Adams"}, {"min_available": 613498200.0, "name": "Kenton"}, {"min_available": 624499800.0, "name": "Racer Rock"}, {"min_available": 627729000.0, "name": "Mt. Erebus"}, {"min_available": 632388000.0, "name": "Port Martin"}, {"min_available": 632697000.0, "name": "Pegasus North"}, {"min_available": 632890200.0, "name": "Cape Denison"}, {"min_available": 638108400.0, "name": "Halley Bay"}, {"min_available": 662781000.0, "name": "Young Island"}, {"min_available": 663751800.0, "name": "Pegasus South"}, {"min_available": 664257000.0, "name": "Minna Bluff"}, {"min_available": 664532400.0, "name": "Linda"}, {"min_available": 664990200.0, "name": "Ago Site"}, {"min_available": 694717800.0, "name": "Bonaparte Point"}, {"min_available": 694908000.0, "name": "Mount Howe"}, {"min_available": 696283800.0, "name": "Willie Field"}, {"min_available": 696989400.0, "name": "Mount Siple"}, {"min_available": 725262000.0, "name": "Penguin Point"}, {"min_available": 725601600.0, "name": "Possession Island"}, {"min_available": 725933400.0, "name": "Ago-A81"}, {"min_available": 727413000.0, "name": "Kelly"}, {"min_available": 728093400.0, "name": "Henry"}, {"min_available": 728098800.0, "name": "Lindsay"}, {"min_available": 728104200.0, "name": "Nico"}, {"min_available": 758991000.0, "name": "Recovery Glacier"}, {"min_available": 761933400.0, "name": "Ski-Hi"}, {"min_available": 786148800.0, "name": "J.C."}, {"min_available": 786154800.0, "name": "Erin"}, {"min_available": 786160800.0, "name": "Theresa"}, {"min_available": 786174600.0, "name": "Harry"}, {"min_available": 786180000.0, "name": "Doug"}, {"min_available": 786246600.0, "name": "Brianna"}, {"min_available": 787170600.0, "name": "Santa Claus Island"}, {"min_available": 788511000.0, "name": "Sutton"}, {"min_available": 788685000.0, "name": "Cape Webb"}, {"min_available": 791728200.0, "name": "Relay Station"}, {"min_available": 791734800.0, "name": "Dome Fuji"}, {"min_available": 817849200.0, "name": "Limbert"}, {"min_available": 818669400.0, "name": "Dome C II"}, {"min_available": 820875000.0, "name": "AGO-A84"}, {"min_available": 824402400.0, "name": "Elizabeth"}, {"min_available": 853652400.0, "name": "Swithinbank"}, {"min_available": 853889400.0, "name": "Siple Dome"}, {"min_available": 855145200.0, "name": "Dome F"}, {"min_available": 912559200.0, "name": "White Out"}, {"min_available": 912560400.0, "name": "White Island"}, {"min_available": 916165200.0, "name": "Herbie Alley"}, {"min_available": 916165800.0, "name": "Cape Spencer"}, {"min_available": 917568600.0, "name": "Cape Bird"}, {"min_available": 918499200.0, "name": "Sky-Blu"}, {"min_available": 948329400.0, "name": "Noel"}, {"min_available": 949452600.0, "name": "Laurie II"}, {"min_available": 971016000.0, "name": "Mizuho"}, {"min_available": 981073800.0, "name": "Odell Glacier"}, {"min_available": 990546600.0, "name": "Kirkwood Island"}, {"min_available": 990576600.0, "name": "Dismal Island"}, {"min_available": 1003933800.0, "name": "Madison"}, {"min_available": 1075860600.0, "name": "Emilia"}, {"min_available": 1075927800.0, "name": "Vito"}, {"min_available": 1106712000.0, "name": "Mary"}, {"min_available": 1107068400.0, "name": "Eric"}, {"min_available": 1107394200.0, "name": "Carolyn"}, {"min_available": 1136985600.0, "name": "Fossil Bluff"}, {"min_available": 1137211800.0, "name": "Kominko-Slade"}, {"min_available": 1143936600.0, "name": "Peter I"}, {"min_available": 1161376200.0, "name": "Mulock"}, {"min_available": 1162426200.0, "name": "Mullock"}, {"min_available": 1165861200.0, "name": "D-57 (in Dumont)"}, {"min_available": 1165864800.0, "name": "Dumont D'Urville"}, {"min_available": 1168731000.0, "name": "Lorne"}, {"min_available": 1193962200.0, "name": "Mt. Fleming"}, {"min_available": 1194677400.0, "name": "JASE2007"}, {"min_available": 1195270200.0, "name": "PANDA-South"}, {"min_available": 1196904000.0, "name": "E-66"}, {"min_available": 1200609000.0, "name": "Baldrick"}, {"min_available": 1226563200.0, "name": "Margaret"}, {"min_available": 1230855000.0, "name": "D-85"}, {"min_available": 1233627600.0, "name": "Sabrina"}, {"min_available": 1238786400.0, "name": "Hugo Island"}, {"min_available": 1294888200.0, "name": "Evans Knoll"}, {"min_available": 1294972800.0, "name": "Marlene"}, {"min_available": 1294980000.0, "name": "Tom"}, {"min_available": 1295046000.0, "name": "Janet"}, {"min_available": 1295058000.0, "name": "Bear Peninsula"}, {"min_available": 1295484000.0, "name": "Thurston Island"}, {"min_available": 1296796200.0, "name": "Alexander (TT!)"}, {"min_available": 1297326600.0, "name": "Ferrell II"}, {"min_available": 1321836000.0, "name": "Cape Hallett"}, {"min_available": 1325571600.0, "name": "AGO-4"}, {"min_available": 1417572600.0, "name": "Emma"}]
......@@ -9,7 +9,7 @@ from pyramid.response import Response, FileIter
from pyramid.httpexceptions import HTTPNotFound, HTTPBadRequest
from app.csv import csv_response
from amrc_aws import sites, nc
from amrc_aws import sites, nc, util
# valid station names
station_names = sorted(set(sites._dirty_names.values()))
......@@ -108,5 +108,12 @@ def data_netcdf_view(request):
return response
def sites_view(request):
return request.registry.settings['db'].get_sites()
@view_config(route_name='stations', renderer='json')
def stations_view(request):
db = request.registry.settings['db']
return [
{'name':r['name'],
'min_available': util.unixtime(r['min']),
'min_available': util.unixtime(r['min'])}
for r in db.get_stations()
]
File added
###
# app configuration
# http://docs.pylonsproject.org/projects/pyramid/en/1.5-branch/narr/environment.html
###
[app:main]
use = egg:app
pyramid.reload_templates = true
pyramid.debug_authorization = false
pyramid.debug_notfound = false
pyramid.debug_routematch = false
pyramid.default_locale_name = en
pyramid.includes =
pyramid_debugtoolbar
# By default, the toolbar only appears for clients from IP addresses
# '127.0.0.1' and '::1'.
# debugtoolbar.hosts = 127.0.0.1 ::1
debugtoolbar.hosts = 0.0.0.0/0
dburl = postgresql://@/amrc_aws
###
# wsgi server configuration
###
[server:main]
use = egg:waitress#main
host = 0.0.0.0
port = 5001
###
# logging configuration
# http://docs.pylonsproject.org/projects/pyramid/en/1.5-branch/narr/logging.html
###
[loggers]
keys = root, app
[handlers]
keys = console
[formatters]
keys = generic
[logger_root]
level = INFO
handlers = console
[logger_app]
level = DEBUG
handlers =
qualname = app
[handler_console]
class = StreamHandler
args = (sys.stderr,)
level = NOTSET
formatter = generic
[formatter_generic]
format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment