1
0
Fork 0

Reformat code with 'yapf', check format using 'tox'

Use configration based on Django coding style guidelines

Signed-off-by: Vasilis Tsiligiannis <acinonyx@openwrt.gr>
merge-requests/377/head
Vasilis Tsiligiannis 2019-04-27 12:04:49 +03:00
parent 2df9d69d9d
commit 140180b6b3
26 changed files with 321 additions and 261 deletions

2
.yapfignore 100644
View File

@ -0,0 +1,2 @@
db/_version.py
db/base/migrations

View File

@ -7,9 +7,7 @@ class Auth0(BaseOAuth2):
name = 'auth0'
SCOPE_SEPARATOR = ' '
ACCESS_TOKEN_METHOD = 'POST'
EXTRA_DATA = [
('email', 'email')
]
EXTRA_DATA = [('email', 'email')]
def authorization_url(self):
"""Return the authorization endpoint."""
@ -29,7 +27,9 @@ class Auth0(BaseOAuth2):
resp = requests.get(url, headers=headers)
userinfo = resp.json()
return {'username': userinfo['nickname'],
'email': userinfo['email'],
# 'first_name': userinfo['name'],
'user_id': userinfo['sub']}
return {
'username': userinfo['nickname'],
'email': userinfo['email'],
# 'first_name': userinfo['name'],
'user_id': userinfo['sub']
}

View File

@ -2,7 +2,6 @@ from __future__ import absolute_import
from .celery import app as celery_app # noqa
__all__ = ['celery_app']
from ._version import get_versions

View File

@ -6,9 +6,7 @@ from db.base.models import Transmitter, DemodData, Satellite
class TransmitterViewFilter(FilterSet):
alive = filters.BooleanFilter(field_name='status',
label='Alive',
method='filter_status')
alive = filters.BooleanFilter(field_name='status', label='Alive', method='filter_status')
def filter_status(self, queryset, name, value):
if value:
@ -23,9 +21,7 @@ class TransmitterViewFilter(FilterSet):
class SatelliteViewFilter(FilterSet):
''' filter on decayed field '''
in_orbit = filters.BooleanFilter(field_name='decayed',
label='In orbit',
lookup_expr='isnull')
in_orbit = filters.BooleanFilter(field_name='decayed', label='In orbit', lookup_expr='isnull')
class Meta:
model = Satellite
@ -33,8 +29,9 @@ class SatelliteViewFilter(FilterSet):
class TelemetryViewFilter(FilterSet):
satellite = django_filters.NumberFilter(field_name='satellite__norad_cat_id',
lookup_expr='exact')
satellite = django_filters.NumberFilter(
field_name='satellite__norad_cat_id', lookup_expr='exact'
)
class Meta:
model = DemodData

View File

@ -24,9 +24,11 @@ class TransmitterSerializer(serializers.ModelSerializer):
class Meta:
model = Transmitter
fields = ('uuid', 'description', 'alive', 'type', 'uplink_low', 'uplink_high',
'uplink_drift', 'downlink_low', 'downlink_high', 'downlink_drift', 'mode_id',
'mode', 'invert', 'baud', 'norad_cat_id', 'status', 'updated', 'citation')
fields = (
'uuid', 'description', 'alive', 'type', 'uplink_low', 'uplink_high', 'uplink_drift',
'downlink_low', 'downlink_high', 'downlink_drift', 'mode_id', 'mode', 'invert', 'baud',
'norad_cat_id', 'status', 'updated', 'citation'
)
# Keeping alive field for compatibility issues
def get_alive(self, obj):
@ -57,8 +59,10 @@ class TelemetrySerializer(serializers.ModelSerializer):
class Meta:
model = DemodData
fields = ('norad_cat_id', 'transmitter', 'app_source', 'schema',
'decoded', 'frame', 'observer', 'timestamp')
fields = (
'norad_cat_id', 'transmitter', 'app_source', 'schema', 'decoded', 'frame', 'observer',
'timestamp'
)
def get_norad_cat_id(self, obj):
return obj.satellite.norad_cat_id
@ -85,5 +89,4 @@ class TelemetrySerializer(serializers.ModelSerializer):
class SidsSerializer(serializers.ModelSerializer):
class Meta:
model = DemodData
fields = ('satellite', 'payload_frame', 'station', 'lat', 'lng',
'timestamp', 'app_source')
fields = ('satellite', 'payload_frame', 'station', 'lat', 'lng', 'timestamp', 'app_source')

View File

@ -22,8 +22,7 @@ class ModeViewApiTest(TestCase):
self.assertEqual(response.status_code, status.HTTP_200_OK)
def test_retrieve(self):
response = self.client.get('/api/modes/{0}/'.format(self.mode.id),
format='json')
response = self.client.get('/api/modes/{0}/'.format(self.mode.id), format='json')
self.assertContains(response, self.mode.name)
@ -43,8 +42,9 @@ class SatelliteViewApiTest(TestCase):
self.assertEqual(response.status_code, status.HTTP_200_OK)
def test_retrieve(self):
response = self.client.get('/api/satellites/{0}/'.format(self.satellite.norad_cat_id),
format='json')
response = self.client.get(
'/api/satellites/{0}/'.format(self.satellite.norad_cat_id), format='json'
)
self.assertContains(response, self.satellite.name)
@ -65,8 +65,9 @@ class TransmitterViewApiTest(TestCase):
self.assertEqual(response.status_code, status.HTTP_200_OK)
def test_retrieve(self):
response = self.client.get('/api/transmitters/{0}/'.format(self.transmitter.uuid),
format='json')
response = self.client.get(
'/api/transmitters/{0}/'.format(self.transmitter.uuid), format='json'
)
self.assertContains(response, self.transmitter.description)

View File

@ -2,7 +2,6 @@ from rest_framework import routers
from db.api import views
router = routers.DefaultRouter()
router.register(r'modes', views.ModeView)

View File

@ -29,8 +29,8 @@ class TransmitterView(viewsets.ReadOnlyModelViewSet):
lookup_field = 'uuid'
class TelemetryView(mixins.ListModelMixin, mixins.RetrieveModelMixin,
mixins.CreateModelMixin, viewsets.GenericViewSet):
class TelemetryView(mixins.ListModelMixin, mixins.RetrieveModelMixin, mixins.CreateModelMixin,
viewsets.GenericViewSet):
queryset = DemodData.objects.all()
serializer_class = serializers.TelemetrySerializer
filter_class = filters.TelemetryViewFilter

View File

@ -8,17 +8,17 @@ from django.urls import reverse
from django.http import HttpResponseRedirect
from django.shortcuts import redirect
from db.base.models import (Mode, Satellite, TransmitterEntry, TransmitterSuggestion,
Transmitter, DemodData, Telemetry)
from db.base.models import (
Mode, Satellite, TransmitterEntry, TransmitterSuggestion, Transmitter, DemodData, Telemetry
)
from db.base.tasks import check_celery, reset_decoded_data, decode_all_data
logger = logging.getLogger('db')
@admin.register(Mode)
class ModeAdmin(admin.ModelAdmin):
list_display = ('name',)
list_display = ('name', )
@admin.register(Satellite)
@ -31,10 +31,12 @@ class SatelliteAdmin(admin.ModelAdmin):
urls = super(SatelliteAdmin, self).get_urls()
my_urls = [
url(r'^check_celery/$', self.check_celery, name='check_celery'),
url(r'^reset_data/(?P<norad>[0-9]+)/$', self.reset_data,
name='reset_data'),
url(r'^decode_all_data/(?P<norad>[0-9]+)/$', self.decode_all_data,
name='decode_all_data'),
url(r'^reset_data/(?P<norad>[0-9]+)/$', self.reset_data, name='reset_data'),
url(
r'^decode_all_data/(?P<norad>[0-9]+)/$',
self.decode_all_data,
name='decode_all_data'
),
]
return my_urls + urls
@ -72,25 +74,41 @@ class SatelliteAdmin(admin.ModelAdmin):
@admin.register(TransmitterEntry)
class TransmitterEntryAdmin(admin.ModelAdmin):
list_display = ('uuid', 'description', 'satellite', 'type', 'mode', 'baud', 'downlink_low',
'downlink_high', 'downlink_drift', 'uplink_low', 'uplink_high', 'uplink_drift',
'reviewed', 'approved', 'status', 'created', 'citation', 'user')
list_display = (
'uuid', 'description', 'satellite', 'type', 'mode', 'baud', 'downlink_low',
'downlink_high', 'downlink_drift', 'uplink_low', 'uplink_high', 'uplink_drift', 'reviewed',
'approved', 'status', 'created', 'citation', 'user'
)
search_fields = ('satellite__id', 'uuid', 'satellite__name', 'satellite__norad_cat_id')
list_filter = ('reviewed', 'approved', 'type', 'status', 'mode', 'baud',)
list_filter = (
'reviewed',
'approved',
'type',
'status',
'mode',
'baud',
)
readonly_fields = ('uuid', 'satellite')
@admin.register(TransmitterSuggestion)
class TransmitterSuggestionAdmin(admin.ModelAdmin):
list_display = ('uuid', 'description', 'satellite', 'type', 'mode', 'baud', 'downlink_low',
'downlink_high', 'downlink_drift', 'uplink_low', 'uplink_high', 'uplink_drift',
'status', 'created', 'citation', 'user')
list_display = (
'uuid', 'description', 'satellite', 'type', 'mode', 'baud', 'downlink_low',
'downlink_high', 'downlink_drift', 'uplink_low', 'uplink_high', 'uplink_drift', 'status',
'created', 'citation', 'user'
)
search_fields = ('satellite__id', 'uuid', 'satellite__name', 'satellite__norad_cat_id')
list_filter = ('type', 'mode', 'baud',)
readonly_fields = ('uuid', 'description', 'status', 'type', 'uplink_low', 'uplink_high',
'uplink_drift', 'downlink_low', 'downlink_high', 'downlink_drift', 'mode',
'invert', 'baud', 'satellite', 'reviewed', 'approved', 'created',
'citation', 'user')
list_filter = (
'type',
'mode',
'baud',
)
readonly_fields = (
'uuid', 'description', 'status', 'type', 'uplink_low', 'uplink_high', 'uplink_drift',
'downlink_low', 'downlink_high', 'downlink_drift', 'mode', 'invert', 'baud', 'satellite',
'reviewed', 'approved', 'created', 'citation', 'user'
)
actions = ['approve_suggestion', 'reject_suggestion']
def get_actions(self, request):
@ -115,6 +133,7 @@ class TransmitterSuggestionAdmin(admin.ModelAdmin):
self.message_user(request, "Transmitter suggestion was successfully approved")
else:
self.message_user(request, "Transmitter suggestions were successfully approved")
approve_suggestion.short_description = 'Approve selected transmitter suggestions'
def reject_suggestion(self, request, queryset):
@ -132,16 +151,24 @@ class TransmitterSuggestionAdmin(admin.ModelAdmin):
self.message_user(request, "Transmitter suggestion was successfully rejected")
else:
self.message_user(request, "Transmitter suggestions were successfully rejected")
reject_suggestion.short_description = 'Reject selected transmitter suggestions'
@admin.register(Transmitter)
class TransmitterAdmin(admin.ModelAdmin):
list_display = ('uuid', 'description', 'satellite', 'type', 'mode', 'baud', 'downlink_low',
'downlink_high', 'downlink_drift', 'uplink_low', 'uplink_high', 'uplink_drift',
'status', 'created', 'citation', 'user')
list_display = (
'uuid', 'description', 'satellite', 'type', 'mode', 'baud', 'downlink_low',
'downlink_high', 'downlink_drift', 'uplink_low', 'uplink_high', 'uplink_drift', 'status',
'created', 'citation', 'user'
)
search_fields = ('satellite__id', 'uuid', 'satellite__name', 'satellite__norad_cat_id')
list_filter = ('type', 'status', 'mode', 'baud',)
list_filter = (
'type',
'status',
'mode',
'baud',
)
readonly_fields = ('uuid', 'satellite')

View File

@ -2,7 +2,6 @@ from rest_framework.authtoken.models import Token
from django.core.cache import cache
UPPER = 'ABCDEFGHIJKLMNOPQRSTUVWX'
LOWER = 'abcdefghijklmnopqrstuvwx'
@ -28,8 +27,10 @@ def gridsquare(lat, lng):
grid_lat_subsq = LOWER[int(adj_lat_remainder / 2.5)]
grid_lon_subsq = LOWER[int(adj_lon_remainder / 5)]
qth = '{}'.format(grid_lon_sq + grid_lat_sq + grid_lon_field +
grid_lat_field + grid_lon_subsq + grid_lat_subsq)
qth = '{}'.format(
grid_lon_sq + grid_lat_sq + grid_lon_field + grid_lat_field + grid_lon_subsq +
grid_lat_subsq
)
return qth
@ -63,5 +64,7 @@ def cache_for(time):
result = fn(*args, **kwargs)
cache.set(key, result, time)
return result
return wrapper
return decorator

View File

@ -8,9 +8,7 @@ class Command(BaseCommand):
def add_arguments(self, parser):
# Positional arguments
parser.add_argument('satellite_identifiers',
nargs='+',
metavar='<Satellite Identifier>')
parser.add_argument('satellite_identifiers', nargs='+', metavar='<Satellite Identifier>')
def handle(self, *args, **options):
for item in options['satellite_identifiers']:
@ -29,8 +27,9 @@ class Command(BaseCommand):
frame = fp.read()
try:
payload_decoded = decoder.decode_payload(frame, obj.timestamp,
obj.data_id)
payload_decoded = decoder.decode_payload(
frame, obj.timestamp, obj.data_id
)
except ValueError:
obj.payload_decoded = ''
obj.payload_telemetry = None

View File

@ -8,9 +8,7 @@ class Command(BaseCommand):
def add_arguments(self, parser):
# Positional arguments
parser.add_argument('norad_ids',
nargs='+',
metavar='<norad id>')
parser.add_argument('norad_ids', nargs='+', metavar='<norad id>')
def handle(self, *args, **options):
for norad_id in options['norad_ids']:

View File

@ -34,7 +34,8 @@ class Command(BaseCommand):
continue
try:
transmitter = TransmitterEntry.objects.get(
uuid=obj['transmitter'], created=obj['transmitter_created'])
uuid=obj['transmitter'], created=obj['transmitter_created']
)
except TransmitterEntry.DoesNotExist:
transmitter = None
@ -42,12 +43,20 @@ class Command(BaseCommand):
for demoddata in obj['demoddata']:
payload_url = demoddata['payload_demod']
timestamp = datetime.strptime(payload_url.split('/')[-1].split('_')[0],
'%Y%m%dT%H%M%SZ').replace(tzinfo=timezone('UTC'))
timestamp = datetime.strptime(
payload_url.split('/')[-1].split('_')[0], '%Y%m%dT%H%M%SZ'
).replace(tzinfo=timezone('UTC'))
frame = str(requests.get(payload_url).json())
payload_frame = ContentFile(frame, name='network')
DemodData.objects.create(satellite=satellite, transmitter=transmitter,
data_id=data_id, payload_frame=payload_frame,
timestamp=timestamp, source='network',
station=station, lat=lat, lng=lng)
DemodData.objects.create(
satellite=satellite,
transmitter=transmitter,
data_id=data_id,
payload_frame=payload_frame,
timestamp=timestamp,
source='network',
station=station,
lat=lat,
lng=lng
)

View File

@ -8,9 +8,7 @@ class Command(BaseCommand):
def add_arguments(self, parser):
# Positional arguments
parser.add_argument('norad_ids',
nargs='+',
metavar='<norad id>')
parser.add_argument('norad_ids', nargs='+', metavar='<norad id>')
def handle(self, *args, **options):
for norad_id in options['norad_ids']:

View File

@ -61,13 +61,13 @@ class Satellite(models.Model):
name = models.CharField(max_length=45)
names = models.TextField(blank=True)
description = models.TextField(blank=True)
image = models.ImageField(upload_to='satellites', blank=True,
help_text='Ideally: 250x250')
image = models.ImageField(upload_to='satellites', blank=True, help_text='Ideally: 250x250')
tle1 = models.CharField(max_length=200, blank=True)
tle2 = models.CharField(max_length=200, blank=True)
tle_source = models.CharField(max_length=300, blank=True)
status = models.CharField(choices=zip(SATELLITE_STATUS, SATELLITE_STATUS),
max_length=10, default='alive')
status = models.CharField(
choices=zip(SATELLITE_STATUS, SATELLITE_STATUS), max_length=10, default='alive'
)
decayed = models.DateTimeField(null=True, blank=True)
class Meta:
@ -109,23 +109,26 @@ class TransmitterEntry(models.Model):
"""Model for satellite transmitters."""
uuid = ShortUUIDField(db_index=True)
description = models.TextField()
status = models.CharField(choices=zip(TRANSMITTER_STATUS, TRANSMITTER_STATUS),
max_length=8, default='active')
type = models.CharField(choices=zip(TRANSMITTER_TYPE, TRANSMITTER_TYPE),
max_length=11, default='Transmitter')
status = models.CharField(
choices=zip(TRANSMITTER_STATUS, TRANSMITTER_STATUS), max_length=8, default='active'
)
type = models.CharField(
choices=zip(TRANSMITTER_TYPE, TRANSMITTER_TYPE), max_length=11, default='Transmitter'
)
uplink_low = models.BigIntegerField(blank=True, null=True)
uplink_high = models.BigIntegerField(blank=True, null=True)
uplink_drift = models.IntegerField(blank=True, null=True)
downlink_low = models.BigIntegerField(blank=True, null=True)
downlink_high = models.BigIntegerField(blank=True, null=True)
downlink_drift = models.IntegerField(blank=True, null=True)
mode = models.ForeignKey(Mode, blank=True, null=True, on_delete=models.SET_NULL,
related_name='transmitter_entries')
mode = models.ForeignKey(
Mode, blank=True, null=True, on_delete=models.SET_NULL, related_name='transmitter_entries'
)
invert = models.BooleanField(default=False)
baud = models.FloatField(validators=[MinValueValidator(0)], blank=True, null=True)
satellite = models.ForeignKey(Satellite, null=True,
related_name='transmitter_entries',
on_delete=models.SET_NULL)
satellite = models.ForeignKey(
Satellite, null=True, related_name='transmitter_entries', on_delete=models.SET_NULL
)
reviewed = models.BooleanField(default=False)
approved = models.BooleanField(default=False)
created = models.DateTimeField(default=now)
@ -154,18 +157,17 @@ class TransmitterSuggestion(TransmitterEntry):
class Meta:
proxy = True
permissions = (('approve', 'Can approve/reject transmitter suggestions'),)
permissions = (('approve', 'Can approve/reject transmitter suggestions'), )
class TransmitterManager(models.Manager):
def get_queryset(self):
subquery = TransmitterEntry.objects.filter(
reviewed=True, approved=True
).filter(
uuid=OuterRef('uuid')
).order_by('-created')
).filter(uuid=OuterRef('uuid')).order_by('-created')
return super(TransmitterManager, self).get_queryset().filter(
reviewed=True, approved=True).filter(created=Subquery(subquery.values('created')[:1]))
reviewed=True, approved=True
).filter(created=Subquery(subquery.values('created')[:1]))
class Transmitter(TransmitterEntry):
@ -177,9 +179,9 @@ class Transmitter(TransmitterEntry):
class Telemetry(models.Model):
"""Model for satellite telemtry decoders."""
satellite = models.ForeignKey(Satellite, null=True,
related_name='telemetries',
on_delete=models.SET_NULL)
satellite = models.ForeignKey(
Satellite, null=True, related_name='telemetries', on_delete=models.SET_NULL
)
name = models.CharField(max_length=45)
schema = models.TextField(blank=True)
decoder = models.CharField(max_length=20, blank=True)
@ -194,24 +196,27 @@ class Telemetry(models.Model):
class DemodData(models.Model):
"""Model for satellite for observation data."""
satellite = models.ForeignKey(Satellite, null=True,
related_name='telemetry_data',
on_delete=models.SET_NULL)
transmitter = models.ForeignKey(TransmitterEntry, null=True, blank=True,
on_delete=models.SET_NULL)
app_source = models.CharField(choices=zip(DATA_SOURCES, DATA_SOURCES),
max_length=7, default='sids')
satellite = models.ForeignKey(
Satellite, null=True, related_name='telemetry_data', on_delete=models.SET_NULL
)
transmitter = models.ForeignKey(
TransmitterEntry, null=True, blank=True, on_delete=models.SET_NULL
)
app_source = models.CharField(
choices=zip(DATA_SOURCES, DATA_SOURCES), max_length=7, default='sids'
)
data_id = models.PositiveIntegerField(blank=True, null=True)
payload_frame = models.FileField(upload_to=_name_payload_frame, blank=True, null=True)
payload_decoded = models.TextField(blank=True)
payload_telemetry = models.ForeignKey(Telemetry, null=True, blank=True,
on_delete=models.SET_NULL)
payload_telemetry = models.ForeignKey(
Telemetry, null=True, blank=True, on_delete=models.SET_NULL
)
station = models.CharField(max_length=45, default='Unknown')
observer = models.CharField(max_length=60, blank=True)
lat = models.FloatField(validators=[MaxValueValidator(90), MinValueValidator(-90)],
default=0)
lng = models.FloatField(validators=[MaxValueValidator(180), MinValueValidator(-180)],
default=0)
lat = models.FloatField(validators=[MaxValueValidator(90), MinValueValidator(-90)], default=0)
lng = models.FloatField(
validators=[MaxValueValidator(180), MinValueValidator(-180)], default=0
)
is_decoded = models.BooleanField(default=False, db_index=True)
timestamp = models.DateTimeField(null=True)
@ -233,9 +238,7 @@ class DemodData(models.Model):
return fp.read()
except IOError as err:
logger.error(
err,
exc_info=True,
extra={
err, exc_info=True, extra={
'payload frame path': self.payload_frame.path,
}
)

View File

@ -98,9 +98,7 @@ def update_all_tle():
satellite.tle2 = tle[2]
satellite.save()
print('Updated TLE for {}: {} from {}'.format(norad_id,
satellite.name,
source))
print('Updated TLE for {}: {} from {}'.format(norad_id, satellite.name, source))
for norad_id in sorted(missing_norad_ids):
satellite = satellites.get(norad_cat_id=norad_id)
@ -123,8 +121,7 @@ def export_frames(norad, email, uid, period=None):
q = now - timedelta(days=30)
suffix = 'month'
q = make_aware(q)
frames = DemodData.objects.filter(satellite__norad_cat_id=norad,
timestamp__gte=q)
frames = DemodData.objects.filter(satellite__norad_cat_id=norad, timestamp__gte=q)
else:
frames = DemodData.objects.filter(satellite__norad_cat_id=norad)
suffix = 'all'
@ -142,8 +139,7 @@ def export_frames(norad, email, uid, period=None):
subject = '[satnogs] Your request for exported frames is ready!'
template = 'emails/exported_frames.txt'
data = {
'url': '{0}{1}download/{2}'.format(site.domain,
settings.MEDIA_URL, filename),
'url': '{0}{1}download/{2}'.format(site.domain, settings.MEDIA_URL, filename),
'norad': norad
}
message = render_to_string(template, {'data': data})
@ -169,11 +165,15 @@ def reset_decoded_data(norad):
frame.is_decoded = False
frame.save()
if settings.USE_INFLUX:
client = InfluxDBClient(settings.INFLUX_HOST, settings.INFLUX_PORT,
settings.INFLUX_USER, settings.INFLUX_PASS,
settings.INFLUX_DB, ssl=settings.INFLUX_SSL)
client.query('DROP MEASUREMENT "{0}"'
.format(norad))
client = InfluxDBClient(
settings.INFLUX_HOST,
settings.INFLUX_PORT,
settings.INFLUX_USER,
settings.INFLUX_PASS,
settings.INFLUX_DB,
ssl=settings.INFLUX_SSL
)
client.query('DROP MEASUREMENT "{0}"'.format(norad))
# decode data for a satellite, and a given time frame (if provided). If not

View File

@ -8,9 +8,9 @@ from django.contrib.auth.models import User
from django.test import TestCase
from django.utils.timezone import now
from db.base.models import (DATA_SOURCES, Mode, Satellite, Transmitter, TransmitterSuggestion,
Telemetry, DemodData)
from db.base.models import (
DATA_SOURCES, Mode, Satellite, Transmitter, TransmitterSuggestion, Telemetry, DemodData
)
DATA_SOURCE_IDS = [c[0] for c in DATA_SOURCES]
@ -26,8 +26,9 @@ def generate_payload():
def generate_payload_name():
filename = datetime.strftime(fuzzy.FuzzyDateTime(now() - timedelta(days=10), now()).fuzz(),
'%Y%m%dT%H%M%SZ')
filename = datetime.strftime(
fuzzy.FuzzyDateTime(now() - timedelta(days=10), now()).fuzz(), '%Y%m%dT%H%M%SZ'
)
return filename
@ -139,6 +140,7 @@ class HomeViewTest(TestCase):
"""
Simple test to make sure the home page is working
"""
def test_home_page(self):
response = self.client.get('/')
self.assertContains(response, 'SatNOGS DB is, and will always be, an open database.')
@ -165,6 +167,7 @@ class AboutViewTest(TestCase):
"""
Test to make sure the about page is working
"""
def test_about_page(self):
response = self.client.get('/about/')
self.assertContains(response, 'SatNOGS DB is an effort to create an hollistic')
@ -175,6 +178,7 @@ class FaqViewTest(TestCase):
"""
Test to make sure the faq page is working
"""
def test_faq_page(self):
response = self.client.get('/faq/')
self.assertContains(response, 'How do I suggest a new transmitter?')

View File

@ -2,19 +2,26 @@ from django.conf.urls import url
from db.base import views
base_urlpatterns = ([
url(r'^$', views.home, name='home'),
url(r'^about/$', views.about, name='about'),
url(r'^faq/$', views.faq, name='faq'),
url(r'^satellite/(?P<norad>[0-9]+)/$', views.satellite, name='satellite'),
url(r'^frames/(?P<norad>[0-9]+)/$', views.request_export,
name='request_export_all'),
url(r'^frames/(?P<norad>[0-9]+)/(?P<period>[0-9]+)/$', views.request_export,
name='request_export'),
url(r'^transmitter_suggestion/$', views.transmitter_suggestion, name='transmitter_suggestion'),
url(r'^statistics/$', views.statistics, name='statistics'),
url(r'^stats/$', views.stats, name='stats'),
url(r'^users/edit/$', views.users_edit, name='users_edit'),
url(r'^robots\.txt$', views.robots, name='robots'),
])
base_urlpatterns = (
[
url(r'^$', views.home, name='home'),
url(r'^about/$', views.about, name='about'),
url(r'^faq/$', views.faq, name='faq'),
url(r'^satellite/(?P<norad>[0-9]+)/$', views.satellite, name='satellite'),
url(r'^frames/(?P<norad>[0-9]+)/$', views.request_export, name='request_export_all'),
url(
r'^frames/(?P<norad>[0-9]+)/(?P<period>[0-9]+)/$',
views.request_export,
name='request_export'
),
url(
r'^transmitter_suggestion/$',
views.transmitter_suggestion,
name='transmitter_suggestion'
),
url(r'^statistics/$', views.statistics, name='statistics'),
url(r'^stats/$', views.stats, name='stats'),
url(r'^users/edit/$', views.users_edit, name='users_edit'),
url(r'^robots\.txt$', views.robots, name='robots'),
]
)

View File

@ -25,9 +25,9 @@ def calculate_statistics():
alive_transmitters = transmitters.filter(status='active').count()
if alive_transmitters > 0 and total_transmitters > 0:
try:
alive_transmitters_percentage = '{0}%'.format(round((float(alive_transmitters) /
float(total_transmitters)) *
100, 2))
alive_transmitters_percentage = '{0}%'.format(
round((float(alive_transmitters) / float(total_transmitters)) * 100, 2)
)
except ZeroDivisionError as error:
logger.error(error, exc_info=True)
alive_transmitters_percentage = '0%'
@ -56,56 +56,63 @@ def calculate_statistics():
band_data.append(filtered)
# 30.000.000 ~ 300.000.000 - VHF
filtered = transmitters.filter(downlink_low__gte=30000000,
downlink_low__lt=300000000).count()
filtered = transmitters.filter(downlink_low__gte=30000000, downlink_low__lt=300000000).count()
band_label.append('VHF')
band_data.append(filtered)
# 300.000.000 ~ 1.000.000.000 - UHF
filtered = transmitters.filter(downlink_low__gte=300000000,
downlink_low__lt=1000000000).count()
filtered = transmitters.filter(
downlink_low__gte=300000000, downlink_low__lt=1000000000
).count()
band_label.append('UHF')
band_data.append(filtered)
# 1G ~ 2G - L
filtered = transmitters.filter(downlink_low__gte=1000000000,
downlink_low__lt=2000000000).count()
filtered = transmitters.filter(
downlink_low__gte=1000000000, downlink_low__lt=2000000000
).count()
band_label.append('L')
band_data.append(filtered)
# 2G ~ 4G - S
filtered = transmitters.filter(downlink_low__gte=2000000000,
downlink_low__lt=4000000000).count()
filtered = transmitters.filter(
downlink_low__gte=2000000000, downlink_low__lt=4000000000
).count()
band_label.append('S')
band_data.append(filtered)
# 4G ~ 8G - C
filtered = transmitters.filter(downlink_low__gte=4000000000,
downlink_low__lt=8000000000).count()
filtered = transmitters.filter(
downlink_low__gte=4000000000, downlink_low__lt=8000000000
).count()
band_label.append('C')
band_data.append(filtered)
# 8G ~ 12G - X
filtered = transmitters.filter(downlink_low__gte=8000000000,
downlink_low__lt=12000000000).count()
filtered = transmitters.filter(
downlink_low__gte=8000000000, downlink_low__lt=12000000000
).count()
band_label.append('X')
band_data.append(filtered)
# 12G ~ 18G - Ku
filtered = transmitters.filter(downlink_low__gte=12000000000,
downlink_low__lt=18000000000).count()
filtered = transmitters.filter(
downlink_low__gte=12000000000, downlink_low__lt=18000000000
).count()
band_label.append('Ku')
band_data.append(filtered)
# 18G ~ 27G - K
filtered = transmitters.filter(downlink_low__gte=18000000000,
downlink_low__lt=27000000000).count()
filtered = transmitters.filter(
downlink_low__gte=18000000000, downlink_low__lt=27000000000
).count()
band_label.append('K')
band_data.append(filtered)
# 27G ~ 40G - Ka
filtered = transmitters.filter(downlink_low__gte=27000000000,
downlink_low__lt=40000000000).count()
filtered = transmitters.filter(
downlink_low__gte=27000000000, downlink_low__lt=40000000000
).count()
band_label.append('Ka')
band_data.append(filtered)
@ -147,9 +154,14 @@ def create_point(fields, satellite, telemetry, demoddata):
def write_influx(json_obj):
"""Take a json object and send to influxdb."""
client = InfluxDBClient(settings.INFLUX_HOST, settings.INFLUX_PORT,
settings.INFLUX_USER, settings.INFLUX_PASS,
settings.INFLUX_DB, ssl=settings.INFLUX_SSL)
client = InfluxDBClient(
settings.INFLUX_HOST,
settings.INFLUX_PORT,
settings.INFLUX_USER,
settings.INFLUX_PASS,
settings.INFLUX_DB,
ssl=settings.INFLUX_SSL
)
client.write_points(json_obj)
@ -174,8 +186,7 @@ def decode_data(norad, period=None):
# iterate over Telemetry decoders
for tlmdecoder in telemetry_decoders:
try:
decoder_class = getattr(decoder,
tlmdecoder.decoder.capitalize())
decoder_class = getattr(decoder, tlmdecoder.decoder.capitalize())
except AttributeError:
continue
try:
@ -189,8 +200,9 @@ def decode_data(norad, period=None):
if settings.USE_INFLUX:
try:
frame = decoder_class.from_bytes(bindata)
json_obj = create_point(decoder.get_fields(frame), sat,
tlmdecoder, obj)
json_obj = create_point(
decoder.get_fields(frame), sat, tlmdecoder, obj
)
write_influx(json_obj)
obj.payload_decoded = 'influxdb'
obj.is_decoded = True
@ -209,8 +221,9 @@ def decode_data(norad, period=None):
obj.save()
continue
else:
json_obj = create_point(decoder.get_fields(frame), sat,
tlmdecoder, obj)
json_obj = create_point(
decoder.get_fields(frame), sat, tlmdecoder, obj
)
obj.payload_decoded = json_obj
obj.is_decoded = True
obj.save()

View File

@ -20,7 +20,6 @@ from db.base.tasks import export_frames
from db.base.utils import cache_statistics
from _mysql_exceptions import OperationalError
logger = logging.getLogger('db')
@ -36,10 +35,14 @@ def home(request):
statistics = cache.get('stats_transmitters')
except OperationalError:
pass
return render(request, 'base/home.html', {'satellites': satellites,
'statistics': statistics,
'contributors': contributors,
'transmitter_suggestions': transmitter_suggestions})
return render(
request, 'base/home.html', {
'satellites': satellites,
'statistics': statistics,
'contributors': contributors,
'transmitter_suggestions': transmitter_suggestions
}
)
def custom_404(request):
@ -54,8 +57,7 @@ def custom_500(request):
def robots(request):
data = render(request, 'robots.txt', {'environment': settings.ENVIRONMENT})
response = HttpResponse(data,
content_type='text/plain; charset=utf-8')
response = HttpResponse(data, content_type='text/plain; charset=utf-8')
return response
@ -83,23 +85,28 @@ def satellite(request, norad):
except Exception:
latest_frame = ''
return render(request, 'base/satellite.html',
{'satellite': satellite,
'transmitter_suggestions': transmitter_suggestions,
'modes': modes,
'types': types,
'statuses': statuses,
'latest_frame': latest_frame,
'sats_cache': sats_cache,
'mapbox_token': settings.MAPBOX_TOKEN})
return render(
request, 'base/satellite.html', {
'satellite': satellite,
'transmitter_suggestions': transmitter_suggestions,
'modes': modes,
'types': types,
'statuses': statuses,
'latest_frame': latest_frame,
'sats_cache': sats_cache,
'mapbox_token': settings.MAPBOX_TOKEN
}
)
@login_required
def request_export(request, norad, period=None):
"""View to request frames export download."""
export_frames.delay(norad, request.user.email, request.user.pk, period)
messages.success(request, ('Your download request was received. '
'You will get an email when it\'s ready'))
messages.success(
request, ('Your download request was received. '
'You will get an email when it\'s ready')
)
return redirect(reverse('satellite', kwargs={'norad': norad}))
@ -121,8 +128,9 @@ def transmitter_suggestion(request):
# Notify admins
admins = User.objects.filter(is_superuser=True)
site = get_current_site(request)
subject = '[{0}] A new suggestion for {1} was submitted'.format(site.name,
transmitter.satellite.name)
subject = '[{0}] A new suggestion for {1} was submitted'.format(
site.name, transmitter.satellite.name
)
template = 'emails/new_transmitter_suggestion.txt'
saturl = '{0}{1}'.format(
site.domain,
@ -139,13 +147,13 @@ def transmitter_suggestion(request):
try:
user.email_user(subject, message, from_email=settings.DEFAULT_FROM_EMAIL)
except Exception:
logger.error(
'Could not send email to user',
exc_info=True
)
logger.error('Could not send email to user', exc_info=True)
messages.success(request, ('Your transmitter suggestion was stored successfully. '
'Thanks for contibuting!'))
messages.success(
request,
('Your transmitter suggestion was stored successfully. '
'Thanks for contibuting!')
)
return redirect(reverse('satellite', kwargs={'norad': transmitter.satellite.norad_cat_id}))
else:
logger.error(
@ -179,8 +187,7 @@ def stats(request):
cache_statistics()
except OperationalError:
pass
return render(request, 'base/stats.html', {'satellites': satellites,
'observers': observers})
return render(request, 'base/stats.html', {'satellites': satellites, 'observers': observers})
def statistics(request):

View File

@ -22,11 +22,10 @@ app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)
def setup_periodic_tasks(sender, **kwargs):
from db.base.tasks import update_all_tle, background_cache_statistics, decode_recent_data
sender.add_periodic_task(RUN_DAILY, update_all_tle.s(),
name='update-all-tle')
sender.add_periodic_task(RUN_DAILY, update_all_tle.s(), name='update-all-tle')
sender.add_periodic_task(RUN_HOURLY, background_cache_statistics.s(),
name='background-cache-statistics')
sender.add_periodic_task(
RUN_HOURLY, background_cache_statistics.s(), name='background-cache-statistics'
)
sender.add_periodic_task(RUN_EVERY_15, decode_recent_data.s(),
name='decode-recent-data')
sender.add_periodic_task(RUN_EVERY_15, decode_recent_data.s(), name='decode-recent-data')

View File

@ -4,7 +4,6 @@ from unipath import Path
import sentry_sdk
from sentry_sdk.integrations.django import DjangoIntegration
ROOT = Path(__file__).parent
ENVIRONMENT = config('ENVIRONMENT', default='dev')
@ -39,8 +38,8 @@ LOCAL_APPS = (
)
if AUTH0:
THIRD_PARTY_APPS += ('social_django',)
LOCAL_APPS += ('auth0login',)
THIRD_PARTY_APPS += ('social_django', )
LOCAL_APPS += ('auth0login', )
INSTALLED_APPS = DJANGO_APPS + THIRD_PARTY_APPS + LOCAL_APPS
@ -67,22 +66,19 @@ EMAIL_USE_TLS = config('EMAIL_USE_TLS', default=False, cast=bool)
EMAIL_HOST_USER = config('EMAIL_HOST_USER', default='')
EMAIL_HOST_PASSWORD = config('EMAIL_HOST_PASSWORD', default='')
DEFAULT_FROM_EMAIL = config('DEFAULT_FROM_EMAIL', default='noreply@satnogs.org')
ADMINS = [
('SatNOGS Admins', DEFAULT_FROM_EMAIL)
]
ADMINS = [('SatNOGS Admins', DEFAULT_FROM_EMAIL)]
MANAGERS = ADMINS
SERVER_EMAIL = DEFAULT_FROM_EMAIL
# Cache
CACHES = {
'default': {
'BACKEND': config('CACHE_BACKEND',
default='django.core.cache.backends.locmem.LocMemCache'),
'BACKEND':
config('CACHE_BACKEND', default='django.core.cache.backends.locmem.LocMemCache'),
'LOCATION': config('CACHE_LOCATION', default='unique-location'),
'OPTIONS': {
'MAX_ENTRIES': 5000,
'CLIENT_CLASS': config('CACHE_CLIENT_CLASS',
default=''),
'CLIENT_CLASS': config('CACHE_CLIENT_CLASS', default=''),
},
'KEY_PREFIX': 'db-{0}'.format(ENVIRONMENT),
}
@ -113,21 +109,19 @@ TEMPLATES = [
'django.template.context_processors.tz',
'django.contrib.messages.context_processors.messages',
'django.template.context_processors.request',
'db.base.context_processors.analytics',
'db.base.context_processors.stage_notice',
'db.base.context_processors.auth_block',
'db.base.context_processors.logout_block',
'db.base.context_processors.version',
'db.base.context_processors.decoders_version'
'db.base.context_processors.analytics', 'db.base.context_processors.stage_notice',
'db.base.context_processors.auth_block', 'db.base.context_processors.logout_block',
'db.base.context_processors.version', 'db.base.context_processors.decoders_version'
],
'loaders': [
('django.template.loaders.cached.Loader', [
'django.template.loaders.filesystem.Loader',
'django.template.loaders.app_directories.Loader',
]),
(
'django.template.loaders.cached.Loader', [
'django.template.loaders.filesystem.Loader',
'django.template.loaders.app_directories.Loader',
]
),
],
},
},
]
@ -150,8 +144,7 @@ COMPRESS_ENABLED = config('COMPRESS_ENABLED', default=False, cast=bool)
COMPRESS_OFFLINE = config('COMPRESS_OFFLINE', default=False, cast=bool)
COMPRESS_CACHE_BACKEND = config('COMPRESS_CACHE_BACKEND', default='default')
COMPRESS_CSS_FILTERS = [
'compressor.filters.css_default.CssAbsoluteFilter',
'compressor.filters.cssmin.rCSSMinFilter'
'compressor.filters.css_default.CssAbsoluteFilter', 'compressor.filters.cssmin.rCSSMinFilter'
]
# App conf
@ -159,11 +152,9 @@ ROOT_URLCONF = 'db.urls'
WSGI_APPLICATION = 'db.wsgi.application'
# Auth
AUTHENTICATION_BACKENDS = (
'django.contrib.auth.backends.ModelBackend',
)
AUTHENTICATION_BACKENDS = ('django.contrib.auth.backends.ModelBackend', )
if AUTH0:
AUTHENTICATION_BACKENDS += ('auth0login.auth0backend.Auth0',)
AUTHENTICATION_BACKENDS += ('auth0login.auth0backend.Auth0', )
ACCOUNT_AUTHENTICATION_METHOD = 'username'
ACCOUNT_EMAIL_REQUIRED = True
@ -220,10 +211,7 @@ LOGGING = {
# Sentry
SENTRY_ENABLED = config('SENTRY_ENABLED', default=False, cast=bool)
if SENTRY_ENABLED:
sentry_sdk.init(
dsn=config('SENTRY_DSN', default=''),
integrations=[DjangoIntegration()]
)
sentry_sdk.init(dsn=config('SENTRY_DSN', default=''), integrations=[DjangoIntegration()])
# Celery
CELERY_ENABLE_UTC = USE_TZ
@ -245,15 +233,10 @@ REDIS_CONNECT_RETRY = True
# API
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly',
),
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.TokenAuthentication',
),
'DEFAULT_FILTER_BACKENDS': (
'django_filters.rest_framework.DjangoFilterBackend',
)
'DEFAULT_PERMISSION_CLASSES':
('rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly', ),
'DEFAULT_AUTHENTICATION_CLASSES': ('rest_framework.authentication.TokenAuthentication', ),
'DEFAULT_FILTER_BACKENDS': ('django_filters.rest_framework.DjangoFilterBackend', )
}
# Security
@ -276,9 +259,7 @@ CSP_IMG_SRC = (
'data:',
'blob:',
)
CSP_CHILD_SRC = (
'blob:',
)
CSP_CHILD_SRC = ('blob:', )
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
SECURE_CONTENT_TYPE_NOSNIFF = True
SECURE_BROWSER_XSS_FILTER = True
@ -306,7 +287,7 @@ INFLUX_DB = config('INFLUX_DB', default='db')
INFLUX_SSL = config('INFLUX_SSL', default=False, cast=bool)
if AUTH0:
SOCIAL_AUTH_TRAILING_SLASH = False # Remove end slash from routes
SOCIAL_AUTH_TRAILING_SLASH = False # Remove end slash from routes
SOCIAL_AUTH_AUTH0_DOMAIN = config('SOCIAL_AUTH_AUTH0_DOMAIN', default='YOUR_AUTH0_DOMAIN')
SOCIAL_AUTH_AUTH0_KEY = config('SOCIAL_AUTH_AUTH0_KEY', default='YOUR_CLIENT_ID')
SOCIAL_AUTH_AUTH0_SECRET = config('SOCIAL_AUTH_AUTH0_SECRET', default='YOUR_CLIENT_SECRET')

View File

@ -27,12 +27,9 @@ urlpatterns = [
# Auth0
if settings.AUTH0:
urlpatterns += [
url(r'^', include('auth0login.urls'))
]
urlpatterns += [url(r'^', include('auth0login.urls'))]
if settings.DEBUG:
urlpatterns += [
url(r'^media/(?P<path>.*)$', serve,
{'document_root': settings.MEDIA_ROOT}),
url(r'^media/(?P<path>.*)$', serve, {'document_root': settings.MEDIA_ROOT}),
]

View File

@ -2,7 +2,6 @@
import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'db.settings')
application = get_wsgi_application()

View File

@ -83,6 +83,11 @@ max-line-length = 99
ignore = F403,W504
exclude = db/_version.py,versioneer.py,*/migrations,docs
[yapf]
column_limit = 99
split_before_first_argument = True
dedent_closing_brackets = True
[tool:pytest]
addopts = -v --cov --cov-report=term-missing
python_files = tests.py

10
tox.ini
View File

@ -1,6 +1,7 @@
[tox]
envlist =
flake8
yapf
pytest
py27
py36
@ -14,6 +15,15 @@ commands = flake8 \
db \
auth0login
[testenv:yapf]
deps =
yapf
skip_install = True
commands = yapf -d -r \
setup.py \
db \
auth0login
[testenv:deps]
install_command = python -m pip install --no-deps {opts} {packages}
recreate = True