generate.py 9.44 KB
Newer Older
gijs's avatar
gijs committed
1
2
3
4
5
# -*- coding: utf-8 -*-

import os
import os.path
import shutil
gijs's avatar
gijs committed
6
import re
gijs's avatar
gijs committed
7

gijs's avatar
gijs committed
8
from math import inf
gijs's avatar
gijs committed
9
from generator.index import make_index
gijs's avatar
gijs committed
10

gijs's avatar
gijs committed
11
from generator.parse import parse_pads
gijs's avatar
gijs committed
12
from generator.models import collectionFor, resetCollections, contentTypes
gijs's avatar
gijs committed
13
from generator.utils import info, regroup, try_attributes, render_to_string, keyFilter
gijs's avatar
gijs committed
14

15
from django.core.management.base import BaseCommand
gijs's avatar
gijs committed
16
17
from django.core.management import call_command

alexandre's avatar
alexandre committed
18
from django.conf import settings
gijs's avatar
gijs committed
19

gijs's avatar
gijs committed
20
21
from generator.templatetags.generator_utils import link_iterator, link_target_iterator

22
23
24
FIELD_SINGLE = 'FIELD_SINGLE'
FIELD_ITERABLE = 'FIELD_ITERABLE'

gijs's avatar
gijs committed
25
26
27
28
29
30
FIELD_DATE_FORMAT = '%d-%m-%Y'
FIELD_DATETIME_FORMAT = '%d-%m-%Y %H:%M'
FIELD_TIME_FORMAT = '%H:%M'

import datetime

gijs's avatar
gijs committed
31
from generator.fields import Date, DateRange, Time, TimeRange
gijs's avatar
gijs committed
32

gijs's avatar
gijs committed
33
34
from generator.settings import DATE_OUTPUT_FORMAT

gijs's avatar
gijs committed
35
36
37
38
# List pads
# Go through them, record information
# Feed content to templates

gijs's avatar
gijs committed
39
def output (path, template, context):  
gijs's avatar
gijs committed
40
  with open(path, 'w', encoding='utf-8') as w:
gijs's avatar
gijs committed
41
    info('Writing {} -> {}'.format(template, path))
gijs's avatar
gijs committed
42
43
    w.write(render_to_string(template, context))

gijs's avatar
gijs committed
44

45
46
def generate_single_pages (models, template, outputdir, make_context):
  for model in models:
gijs's avatar
gijs committed
47
    output(os.path.join(outputdir, model.prefix, '{}.html'.format(keyFilter(model.key))), template, make_context(model))
gijs's avatar
gijs committed
48

49
50
def datesorter (obj):
  if hasattr(obj, 'date'):
gijs's avatar
gijs committed
51
    date = getattr(obj, 'date').value
52
53
54
55
56
57
58
59
60
61

    if isinstance(date, Date):
      return date.date
    elif isinstance(date, DateRange):
      return date.start.date
    
  return datetime.date(1,1,1)

def timesorter (obj):
  if hasattr(obj, 'time'):
gijs's avatar
gijs committed
62
    time = getattr(obj, 'time').value
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77

    if isinstance(time, Time):
      return time.time
    elif isinstance(time, TimeRange):
      return time.start
  
  return datetime.time(0,0)

def datetimesorter (obj):
  date = datesorter(obj)
  time = timesorter(obj)

  return datetime.datetime.combine(date, time)
  
def groupedProgrammeItems(event):
gijs's avatar
gijs committed
78
  # print(list(link_target_iterator(event.programmeItems)))
gijs's avatar
gijs committed
79
  programmeItems = sorted(event.programmeItems.targets, key=datetimesorter)
80
81
  return regroup(programmeItems, lambda e: datesorter(e).strftime(DATE_OUTPUT_FORMAT))

gijs's avatar
gijs committed
82
def generate ():
gijs's avatar
gijs committed
83
84
  # Clear existing collections
  resetCollections(contentTypes)
alexandre's avatar
alexandre committed
85
  basedir = os.path.join(settings.BASE_DIR, 'generator')
gijs's avatar
gijs committed
86
  staticdir = os.path.join(basedir, 'templates', 'static')
87
88
89
  backupdir = os.path.join(basedir, 'static', 'generated.old')
  finaldir = os.path.join(basedir, 'static', 'generated')
  outputdir = os.path.join(basedir, 'static', 'generated.new')
gijs's avatar
gijs committed
90

gijs's avatar
gijs committed
91
92
  if os.path.exists(outputdir):
    shutil.rmtree(outputdir)
gijs's avatar
gijs committed
93
  
gijs's avatar
gijs committed
94
  os.mkdir(outputdir)
gijs's avatar
gijs committed
95
96
97
98
99
  
  print('Copying static files')
  shutil.copytree(staticdir, os.path.join(outputdir, 'static'))

  print('Parsing pads')
gijs's avatar
gijs committed
100
  os.mkdir(os.path.join(outputdir, 'produsers'))
101
  os.mkdir(os.path.join(outputdir, 'activities'))
gijs's avatar
gijs committed
102
103
  os.mkdir(os.path.join(outputdir, 'pages'))
  os.mkdir(os.path.join(outputdir, 'tags'))
104
  os.mkdir(os.path.join(outputdir, 'notes'))
gijs's avatar
gijs committed
105
  os.mkdir(os.path.join(outputdir, 'questions'))
106
107
  # os.mkdir(os.path.join(outputdir, 'trajectories'))
  os.mkdir(os.path.join(outputdir, 'reflections'))
108
109
  os.mkdir(os.path.join(outputdir, 'api'))
  os.mkdir(os.path.join(outputdir, 'api', 'activities'))
gijs's avatar
gijs committed
110
  
gijs's avatar
gijs committed
111
  models = parse_pads()
gijs's avatar
gijs committed
112

gijs's avatar
gijs committed
113
114
  print('Read pads')
  print('Generating output')
gijs's avatar
gijs committed
115

gijs's avatar
gijs committed
116
117
118
119
120
  produsers = collectionFor('produser')
  events = collectionFor('event')
  pages = collectionFor('page')
  tags = collectionFor('tag')
  bibliography = collectionFor('bibliography')
121
122
  externalProjects = collectionFor('external-project')
  notes = collectionFor('notes')
gijs's avatar
gijs committed
123
  trajectories = collectionFor('trajectory')
gijs's avatar
gijs committed
124
  questions = collectionFor('question')
125
  reflections = collectionFor('reflection')
gijs's avatar
gijs committed
126

gijs's avatar
gijs committed
127
128
129
130
131
132
133
134
  def getProduserSortKey (produser):
    attr = try_attributes(produser, ['sortname', 'name', 'produser'])

    if attr and attr.value:
      return attr.value.lower()
    else:
      return None

gijs's avatar
gijs committed
135
136
137
138
139
140
  def getTrajectorySortKey (trajectory):
    if trajectory.produser.resolved:
      return getProduserSortKey(trajectory.produser.target)
    else:
      return ''

gijs's avatar
gijs committed
141
142
143
144
145
146
147
148
  def getLabelAsSortKey (model):
    label = getattr(model, model.labelField)

    if label and label.value:
      return label.value.lower()
    else:
      return ''

gijs's avatar
gijs committed
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
  def makeGroupSorter (order):
    def sorter (line):
      sortKey = line[0]
      return order.index(sortKey) if sortKey in order else inf

    return sorter

  def makeAttributeSorter(attributes):
    def sorter (model):
      return str(try_attributes(model, attributes)).lower()

    return sorter

  ## Produsers
  ## First 
  produser_role_sorting = ['artist', 'co-producer', 'other professional', 'team', 'partner']
  sorted_produsers = sorted(produsers.models, key=getProduserSortKey)
  grouped_produsers = sorted(regroup(sorted_produsers, 'role'), key=makeGroupSorter(produser_role_sorting))
167

gijs's avatar
gijs committed
168
169
170
171
172
173
174
  output(
    os.path.join(outputdir, 'produsers.html'), 
    'produsers.html', 
    { 
      'produsers': sorted(produsers.models, key=makeAttributeSorter(['sortname', 'name', 'produser', 'key'])), 
      'grouped_produsers': grouped_produsers })
  
gijs's avatar
gijs committed
175
  # output(os.path.join(outputdir, 'produsers.layout.html'), 'produsers.layout.html', { 'produsers': sorted(produsers.models, key=lambda r: str(r.key)), 'grouped_produsers': grouped_produsers  })
gijs's avatar
gijs committed
176
177
  
  ## Tags
gijs's avatar
gijs committed
178
179
  sorted_tags = sorted(tags.models, key=lambda m: re.subn(r'\W', '', str(m))[0].lower())
  grouped_tags = regroup(sorted_tags, key=lambda m: re.subn(r'\W', '', str(m))[0].lower()[0])
gijs's avatar
gijs committed
180
181
182
  output(
    os.path.join(outputdir, 'tags.html'), 
    'tags.html', 
gijs's avatar
gijs committed
183
    { 'tags': sorted_tags, 'grouped_tags': grouped_tags })
gijs's avatar
gijs committed
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
  
  ## Bibliography
  output(
    os.path.join(outputdir, 'bibliography.html'),
    'bibliography.html', 
    { 'bibliography': sorted(bibliography.models, key=getLabelAsSortKey) })
  
  ## External projects
  output(
    os.path.join(outputdir, 'external-projects.html'),
    'external-projects.html',
    { 'externalProjects': sorted(externalProjects.models, key=getLabelAsSortKey) })
  
  ## Trajectories
  trajectory_category_sorting = ['artisttrajectory', 'designertrajectory', 'reflection']
  sorted_trajectories = sorted(trajectories.models, key=getTrajectorySortKey)
  grouped_trajectories = sorted(regroup(sorted_trajectories, 'category'), key=makeGroupSorter(trajectory_category_sorting))
  output(
    os.path.join(outputdir, 'trajectories.html'),
    'trajectories.html', 
    {
      'trajectories': sorted_trajectories,
206
      'grouped_trajectories': grouped_trajectories,
gijs's avatar
Silly    
gijs committed
207
      'reflections': sorted(reflections.models, key=getLabelAsSortKey)
gijs's avatar
gijs committed
208
209
    })

210
211
212
  # for trajectory in trajectories.models:
  #   if trajectory.title.value:
  #     output(os.path.join(outputdir, trajectory.prefix, '{}.html'.format(keyFilter(trajectory.title))), 'trajectory.html', { 'trajectory': trajectory })
213

gijs's avatar
gijs committed
214
215
216
217
218
219
  ## Questions
  output(
    os.path.join(outputdir, 'questions.html'),
    'questions.html',
    { 'questions': questions.models }
  )
gijs's avatar
gijs committed
220

gijs's avatar
gijs committed
221
222
  # for produser in produsers.models:
  #   output(os.path.join(outputdir, produser.prefix, '{}.html'.format(produser.key)), 'produser.html', { 'produser': produser })
223

gijs's avatar
gijs committed
224
225
  # for event in events.models:
  #   output(os.path.join(outputdir, event.prefix, '{}.html'.format(event.key)), 'event.html', { 'event': event })
gijs's avatar
gijs committed
226

gijs's avatar
gijs committed
227

gijs's avatar
gijs committed
228
229
230
231
  generate_single_pages(produsers.models, 'produser.html', outputdir, lambda produser: { 'produser': produser })
  generate_single_pages(pages.models, 'page.html', outputdir, lambda page: { 'page': page })
  generate_single_pages(tags.models, 'tag.html', outputdir, lambda tag: { 'tag': tag })
  generate_single_pages(filter(lambda e: not hasattr(e, 'programmeItems') or not e.programmeItems, events.models), 'event.html', outputdir, lambda event: { 'event': event })
gijs's avatar
gijs committed
232
  generate_single_pages(filter(lambda e: hasattr(e, 'programmeItems') and e.programmeItems, events.models), 'event-with-programme-items.html', outputdir, lambda event: { 'event': event, 'groupedProgrammeItems': groupedProgrammeItems(event)})
233
  generate_single_pages(events.models, 'snippets/home_event_detail.html', os.path.join(outputdir, 'api'), lambda event: { 'event': event })
gijs's avatar
gijs committed
234
  generate_single_pages(notes.models, 'note.html', outputdir, lambda note: { 'note': note })
235
  generate_single_pages(reflections.models, 'reflection.html', outputdir, lambda reflection: { 'reflection': reflection })
gijs's avatar
gijs committed
236

237
238
  output(os.path.join(outputdir, 'activities.html'), 'activities.html', { 'events': sorted(events.models, key=datesorter, reverse=True) })
  
gijs's avatar
gijs committed
239
240
  output(os.path.join(outputdir, 'index.old.html'), 'index.html', { 'events': sorted(events.models, key=datesorter, reverse=True) })
  output(os.path.join(outputdir, 'index.html'), 'index.new.html', { 'events': sorted(events.models, key=datesorter, reverse=True) })
241
  
242
243
244
  with open(os.path.join(outputdir, 'debug.html'), 'w', encoding='utf-8') as w:
    w.write(make_index(models))

245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260

  info('Making backup of previous version, putting new version in place')

  if os.path.exists(outputdir):
    # Test whether there is an existing version of the site
    if os.path.exists(finaldir):
      # Removing old backup if it exists
      if os.path.exists(backupdir):
        shutil.rmtree(backupdir)
      
      # Put new backup in place
      shutil.move(finaldir, backupdir)
    
    # Put new version of the site in place
    shutil.move(outputdir, finaldir)

alexandre's avatar
alexandre committed
261
  if not settings.DEBUG:
gijs's avatar
gijs committed
262
263
    print('Collecting static')
    call_command('collectstatic', interactive=False)
gijs's avatar
gijs committed
264

gijs's avatar
gijs committed
265
  print('Done')
gijs's avatar
gijs committed
266

gijs's avatar
gijs committed
267
268
269
class Command(BaseCommand):
  args = ''
  help = 'Generate a static interpretation of the pads'
gijs's avatar
gijs committed
270

gijs's avatar
gijs committed
271
272
  def handle(self, *args, **options):
    generate()