Skip to content

Commit

Permalink
Merge a2d2bc0 into 42a5977
Browse files Browse the repository at this point in the history
  • Loading branch information
jwhitlock committed Aug 27, 2014
2 parents 42a5977 + a2d2bc0 commit b8c53d7
Show file tree
Hide file tree
Showing 15 changed files with 4,591 additions and 3 deletions.
3 changes: 2 additions & 1 deletion MANIFEST.in
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ recursive-exclude * __pycache__ *.py[co]

recursive-include tests *
recursive-include bpz *.py *.keep
recursive-include bpz/templates *.jinja2
recursive-include bpz/fixtures *.json
recursive-include bpz/static *.css *.js *.map *.eot *.svg *.ttf *.woff
recursive-include bpz/templates *.jinja2
recursive-include bpzaroundme *.py
recursive-include docs *.rst conf.py Makefile make.bat .keep
17 changes: 17 additions & 0 deletions bpz/admin.py
Original file line number Diff line number Diff line change
@@ -1 +1,18 @@
'''Django admin configuration for bpz'''

from django.contrib.gis import admin
from .models import Case, HomeOwnersAssociation

geo_admin = admin.OSMGeoAdmin


class HomeOwnersAssociationAdmin(geo_admin):
pass


class CaseAdmin(geo_admin):
pass


admin.site.register(Case, CaseAdmin)
admin.site.register(HomeOwnersAssociation, HomeOwnersAssociationAdmin)
4,107 changes: 4,107 additions & 0 deletions bpz/fixtures/bpz-2014-08-24.json

Large diffs are not rendered by default.

Empty file added bpz/management/__init__.py
Empty file.
Empty file.
88 changes: 88 additions & 0 deletions bpz/management/commands/load_boa_cases.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
from datetime import datetime
from json import loads
from time import mktime

from django.core.management.base import BaseCommand, CommandError
from django.contrib.gis.gdal import DataSource
from django.contrib.gis.geos import GEOSGeometry
from parsedatetime import Calendar

from bpz.models import Case

'''Import Board of Adjustment cases data
TODO: Refactor into utility function with other load_* commands
'''


class Command(BaseCommand):
args = '<boa-cases.json>'
help = 'Imports Board of Adjustment cases GeoJSON'

def handle(self, *args, **options):
if len(args) != 1:
raise CommandError('Must pass exactly one json file to import')

same, new, updated = 0, 0, 0 # Object counts
calendar = Calendar() # date parser

# Load data
datasource = DataSource(args[0], encoding='iso-8859-1')
layer = datasource[0]
for feature in layer:
# Gather and transform attributes
attr = {
'object_id': feature['OBJECTID'].value,
'case_id': loads('"%s"' % feature['Case_'].value),
'status': feature['Status'].value,
'location': loads('"%s"' % feature['Location'].value),
'link': loads('"%s"' % feature['Link'].value),
}

raw_date = loads('"%s"' % feature['Date_'].value)
timestamp = mktime(calendar.parseDateText(raw_date))
attr['hearing_date'] = datetime.fromtimestamp(timestamp).date()

attr['geom'] = GEOSGeometry(feature.geom.wkt)

# Is there a case with this object ID?
case_query = Case.objects.filter(
object_id=attr['object_id'], domain=Case.DOMAIN_BOA)
if case_query.exists():
case = case_query.get()

# Did the data change?
different = []
for name, new_value in attr.items():
existing = getattr(case, name)
if existing != new_value:
different.append((name, existing, new_value))
if different:
updated += 1
diff_message = ', '.join(
["%s:'%s' -> '%s'" % x for x in different])
msg = 'Updated case "%s" (%s)' % (
attr['case_id'], diff_message)
self.stdout.write(msg)
else:
same += 1
self.stdout.write(
'No change to case "%s"' % attr['case_id'])
else:
# Create new Case
case = Case(
object_id=attr['object_id'], domain=Case.DOMAIN_BOA,
case_type="Board of Adjustment")
self.stdout.write('New case "%s"' % attr['case_id'])
new += 1
different = True

if different:
# Save changes
for name, value in attr.items():
setattr(case, name, value)
case.save()

self.stdout.write(
'Imported %d BOA cases (%d new, %d changed, %d unchanged)' % (
new + updated + same, new, updated, same))
101 changes: 101 additions & 0 deletions bpz/management/commands/load_home_owners_associations.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
from json import loads

from django.core.management.base import BaseCommand, CommandError
from django.contrib.gis.gdal import DataSource, OGRException

from bpz.models import HomeOwnersAssociation

'''Import Home Owners Association data
TODO: Refactor into utility function with other load_* commands
'''


class Command(BaseCommand):
args = '<home-owners-associatons.json>'
help = 'Imports Home Owners Association GeoJSON'

def handle(self, *args, **options):
if len(args) != 1:
raise CommandError('Must pass exactly one json file to import')

same, new, updated, skipped = 0, 0, 0, 0 # Object counts

# Load data
datasource = DataSource(args[0], encoding='iso-8859-1')
layer = datasource[0]
for feature in layer:
# Gather and transform attributes
attr = {
'object_id': feature['OBJECTID'].value,
'name': loads('"%s"' % feature['Name'].value),
}

raw_hoa_name = feature['HOA_Name'].value
if '\r\n' in raw_hoa_name:
self.stderr.write('Invalid HOA_Name %s' % repr(raw_hoa_name))
raw_hoa_name = raw_hoa_name.split('\r\n', 1)[0]
attr['hoa_name'] = loads('"%s"' % raw_hoa_name)

if not (attr['name'] or attr['hoa_name']):
self.stderr.write('Unnamed HOA')
skipped += 1
continue

try:
geom = feature.geom
except OGRException:
self.stderr.write(
'No or invalid geometry for %s' % attr['name'])
skipped += 1
continue
attr['geom'] = geom.wkt

# Is there a matching HOA?
if attr['object_id']:
hoa_query = HomeOwnersAssociation.objects.filter(
object_id=attr['object_id'])
else:
self.stderr.write(
'Useless object_id %d for %s' %
(attr['object_id'], attr['name']))
assert attr['name']
hoa_query = HomeOwnersAssociation.objects.filter(
name=attr['name'])
if hoa_query.exists():
hoa = hoa_query.get()

# Did the data change?
different = []
for name, new_value in attr.items():
existing = getattr(hoa, name)
if existing != new_value:
different.append((name, existing, new_value))
if different:
updated += 1
diff_message = ', '.join(
["%s:'%s' -> '%s'" % x for x in different])
msg = 'Updated HOA "%s" (%s)' % (
attr['name'], diff_message)
self.stdout.write(msg)
else:
same += 1
self.stdout.write(
'No change to HOA "%s"' % attr['name'])
else:
# Create new HOA
hoa = HomeOwnersAssociation()
self.stdout.write('New HOA "%s"' % attr['name'])
new += 1
different = True

if different:
# Save changes
for name, value in attr.items():
setattr(hoa, name, value)
hoa.save()

self.stdout.write(
'Imported %d Home Owner Associations (%d new, %d changed,'
' %d unchanged, %d skipped)' %
(new + updated + same, new, updated, same, skipped))
98 changes: 98 additions & 0 deletions bpz/management/commands/load_tmapc_cases.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
from datetime import datetime
from json import loads
from time import mktime

from django.core.management.base import BaseCommand, CommandError
from django.contrib.gis.gdal import DataSource
from django.contrib.gis.geos import GEOSGeometry
from parsedatetime import Calendar

from bpz.models import Case

'''Import Tulsa Metropolitan Area Planning Commission case data
TODO: Refactor into utility function with other load_* commands
'''


class Command(BaseCommand):
args = '<tmapc-cases.json>'
help = 'Imports Tulsa Metropolitan Area Planning Commission case GeoJSON'

def handle(self, *args, **options):
if len(args) != 1:
raise CommandError('Must pass exactly one json file to import')

same, new, updated = 0, 0, 0 # Object counts
calendar = Calendar() # date parser

# Load data
datasource = DataSource(args[0], encoding='iso-8859-1')
layer = datasource[0]
for feature in layer:
# Gather and transform attributes
attr = {
'object_id': feature['OBJECTID'].value,
'case_id': loads('"%s"' % feature['Case_'].value),
'status': feature['Status'].value,
'link': loads('"%s"' % feature['Link'].value),
}

raw_location = feature['Location'].value
if '\r\n' in raw_location:
self.stderr.write('Invalid Location %s' % repr(raw_location))
raw_location = raw_location.split('\r\n', 1)[0]
attr['location'] = loads('"%s"' % raw_location)

raw_type = feature['Type'].value
if '\r\n' in raw_type:
self.stderr.write('Invalid Type %s' % repr(raw_type))
raw_type = raw_type.split('\r\n', 1)[0]
attr['case_type'] = loads('"%s"' % raw_type)

raw_date = loads('"%s"' % feature['Date_'].value)
timestamp = mktime(calendar.parseDateText(raw_date))
attr['hearing_date'] = datetime.fromtimestamp(timestamp).date()

attr['geom'] = GEOSGeometry(feature.geom.wkt)

# Is there a case with this object ID?
case_query = Case.objects.filter(
object_id=attr['object_id'], domain=Case.DOMAIN_TMAPC)
if case_query.exists():
case = case_query.get()

# Did the data change?
different = []
for name, new_value in attr.items():
existing = getattr(case, name)
if existing != new_value:
different.append((name, existing, new_value))
if different:
updated += 1
diff_message = ', '.join(
["%s:'%s' -> '%s'" % x for x in different])
msg = 'Updated case "%s" (%s)' % (
attr['case_id'], diff_message)
self.stdout.write(msg)
else:
same += 1
self.stdout.write(
'No change to case "%s"' % attr['case_id'])
else:
# Create new Case
case = Case(
object_id=attr['object_id'], domain=Case.DOMAIN_TMAPC)
self.stdout.write('New case "%s"' % attr['case_id'])
new += 1
different = True

if different:
# Save changes
for name, value in attr.items():
setattr(case, name, value)
case.save()

self.stdout.write(
'Imported %d BOA cases (%d new, %d changed, %d unchanged)' % (
new + updated + same, new, updated, same))
70 changes: 70 additions & 0 deletions bpz/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# -*- coding: utf-8 -*-
# flake8: noqa
from south.utils import datetime_utils as datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models


class Migration(SchemaMigration):

def forwards(self, orm):
# Adding model 'Case'
db.create_table(u'bpz_case', (
(u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('object_id', self.gf('django.db.models.fields.IntegerField')()),
('case_id', self.gf('django.db.models.fields.CharField')(max_length=30)),
('domain', self.gf('django.db.models.fields.CharField')(max_length=10)),
('status', self.gf('django.db.models.fields.CharField')(max_length=10)),
('location', self.gf('django.db.models.fields.CharField')(max_length=50)),
('link', self.gf('django.db.models.fields.URLField')(max_length=200)),
('hearing_date', self.gf('django.db.models.fields.DateField')()),
('case_type', self.gf('django.db.models.fields.CharField')(max_length=30)),
('geom', self.gf('django.contrib.gis.db.models.fields.GeometryField')()),
))
db.send_create_signal(u'bpz', ['Case'])

# Adding model 'HomeOwnersAssociation'
db.create_table(u'bpz_homeownersassociation', (
(u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('object_id', self.gf('django.db.models.fields.IntegerField')(null=True, blank=True)),
('name', self.gf('django.db.models.fields.CharField')(max_length=50)),
('hoa_name', self.gf('django.db.models.fields.CharField')(max_length=50)),
('geom', self.gf('django.contrib.gis.db.models.fields.GeometryField')()),
))
db.send_create_signal(u'bpz', ['HomeOwnersAssociation'])


def backwards(self, orm):
# Deleting model 'Case'
db.delete_table(u'bpz_case')

# Deleting model 'HomeOwnersAssociation'
db.delete_table(u'bpz_homeownersassociation')


models = {
u'bpz.case': {
'Meta': {'object_name': 'Case'},
'case_id': ('django.db.models.fields.CharField', [], {'max_length': '30'}),
'case_type': ('django.db.models.fields.CharField', [], {'max_length': '30'}),
'domain': ('django.db.models.fields.CharField', [], {'max_length': '10'}),
'geom': ('django.contrib.gis.db.models.fields.GeometryField', [], {}),
'hearing_date': ('django.db.models.fields.DateField', [], {}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'link': ('django.db.models.fields.URLField', [], {'max_length': '200'}),
'location': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
'object_id': ('django.db.models.fields.IntegerField', [], {}),
'status': ('django.db.models.fields.CharField', [], {'max_length': '10'})
},
u'bpz.homeownersassociation': {
'Meta': {'object_name': 'HomeOwnersAssociation'},
'geom': ('django.contrib.gis.db.models.fields.GeometryField', [], {}),
'hoa_name': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
'object_id': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'})
}
}

complete_apps = ['bpz']
Empty file added bpz/migrations/__init__.py
Empty file.

0 comments on commit b8c53d7

Please sign in to comment.