import re import os import datetime import difflib from django import forms from django.http import HttpResponseRedirect, HttpResponse from django.shortcuts import render_to_response, render #from django.core.context_processors import csrf from django.template.context_processors import csrf from django.http import HttpResponse, Http404 import troggle.settings as settings import parsers.survex from troggle.core.models import Expedition, Person, PersonExpedition from troggle.core.models_survex import SurvexBlock, SurvexPersonRole, SurvexFile, SurvexDirectory, SurvexTitle from troggle.core.models_caves import Cave, PersonTrip, LogbookEntry from troggle.parsers.people import GetPersonExpeditionNameLookup survextemplatefile = """; *** DO NOT SAVE THIS FILE WITHOUT RENAMING IT !! *** ;[Stuff in square brackets is example text to be replaced with real data, ; removing the square brackets] *begin [surveyname] ; stations linked into other surveys (or likely to) *export [1 8 12 34] ; Cave: ; Area in cave/QM: *title "" *date [2040.07.04] *team Insts [Fred Foo] *team Notes [Brenda Bar] *team Pics [Brenda Bar] *team Tape [Albert Anyone] *instrument [SAP #+Laser Tape/DistoX/Compass # ; Clino #] ; Calibration: [Where, readings] *ref 2040#00 ; the #number is on the clear pocket containing the original notes ; if using a tape: *calibrate tape +0.0 ; +ve if tape was too short, -ve if too long ; Centreline data *data normal from to length bearing gradient ignoreall [ 1 2 5.57 034.5 -12.8 ] ;----------- ;recorded station details (leave commented out) ;(NP=Nail Polish, LHW/RHW=Left/Right Hand Wall) ;Station Left Right Up Down Description ;[Red] nail varnish markings [;1 0.8 0 5.3 1.6 ; NP on boulder. pt 23 on foo survey ] [;2 0.3 1.2 6 1.2 ; NP '2' LHW ] [;3 1.3 0 3.4 0.2 ; Rock on floor - not refindable ] ;LRUDs arranged into passage tubes ;new *data command for each 'passage', ;repeat stations and adjust numbers as needed *data passage station left right up down ;[ 1 0.8 0 5.3 1.6 ] ;[ 2 0.3 1.2 6 1.2 ] *data passage station left right up down ;[ 1 1.3 1.5 5.3 1.6 ] ;[ 3 2.4 0 3.4 0.2 ] ;----------- ;Question Mark List ;(leave commented-out) ; The nearest-station is the name of the survey and station which are nearest to ; the QM. The resolution-station is either '-' to indicate that the QM hasn't ; been checked; or the name of the survey and station which push that QM. If a ; QM doesn't go anywhere, set the resolution-station to be the same as the ; nearest-station. Include any relevant details of how to find or push the QM in ; the textual description. ;Serial number grade(A/B/C/X) nearest-station resolution-station description ;[ QM1 A surveyname.3 - description of QM ] ;[ QM2 B surveyname.5 - description of QM ] ;------------ ;Cave description ;(leave commented-out) ;freeform text describing this section of the cave *end [surveyname] """ class SvxForm(forms.Form): dirname = forms.CharField(widget=forms.TextInput(attrs={"readonly":True})) filename = forms.CharField(widget=forms.TextInput(attrs={"readonly":True})) datetime = forms.DateTimeField(widget=forms.TextInput(attrs={"readonly":True})) outputtype = forms.CharField(widget=forms.TextInput(attrs={"readonly":True})) code = forms.CharField(widget=forms.Textarea(attrs={"cols":150, "rows":18})) def GetDiscCode(self): fname = settings.SURVEX_DATA + self.data['filename'] + ".svx" if not os.path.isfile(fname): return survextemplatefile fin = open(fname, "rt",encoding='utf8',newline='') svxtext = fin.read() fin.close() return svxtext def DiffCode(self, rcode): code = self.GetDiscCode() difftext = difflib.unified_diff(code.splitlines(), rcode.splitlines()) difflist = [ diffline.strip() for diffline in difftext if not re.match(r"\s*$", diffline) ] return difflist def SaveCode(self, rcode): fname = settings.SURVEX_DATA + self.data['filename'] + ".svx" if not os.path.isfile(fname): if re.search(r"\[|\]", rcode): return "Error: remove all []s from the text. They are only template guidance." mbeginend = re.search(r"(?s)\*begin\s+(\w+).*?\*end\s+(\w+)", rcode) if not mbeginend: return "Error: no begin/end block here" if mbeginend.group(1) != mbeginend.group(2): return "Error: mismatching begin/end labels" fout = open(fname, "wt", encoding='utf8',newline='\n') # javascript seems to insert CRLF on WSL1. res = fout.write(rcode.replace("\r","")) fout.close() return "SAVED ." def Process(self): print("....\n\n\n....Processing\n\n\n") cwd = os.getcwd() os.chdir(os.path.split(settings.SURVEX_DATA + self.data['filename'])[0]) os.system(settings.CAVERN + " --log " + settings.SURVEX_DATA + self.data['filename'] + ".svx") os.chdir(cwd) fin = open(settings.SURVEX_DATA + self.data['filename'] + ".log", "rt",encoding='utf8') log = fin.read() fin.close() log = re.sub("(?s).*?(Survey contains)", "\\1", log) return log def svx(request, survex_file): # get the basic data from the file given in the URL dirname = os.path.split(survex_file)[0] dirname += "/" nowtime = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') outputtype = "normal" form = SvxForm({'filename':survex_file, 'dirname':dirname, 'datetime':nowtime, 'outputtype':outputtype}) # if the form has been returned difflist = [ ] logmessage = "" message = "" if request.method == 'POST': # If the form has been submitted... rform = SvxForm(request.POST) # if rform.is_valid(): # All validation rules pass (how do we check it against the filename and users?) rcode = rform.cleaned_data['code'] outputtype = rform.cleaned_data['outputtype'] difflist = form.DiffCode(rcode) #print "ssss", rform.data if "revert" in rform.data: pass if "process" in rform.data: if not difflist: message = "OUTPUT FROM PROCESSING" logmessage = form.Process() print(logmessage) else: message = "SAVE FILE FIRST" form.data['code'] = rcode if "save" in rform.data: if request.user.is_authenticated(): #print("sssavvving") message = form.SaveCode(rcode) else: message = "You do not have authority to save this file" if message != "SAVED": form.data['code'] = rcode if "diff" in rform.data: form.data['code'] = rcode #process(survex_file) if 'code' not in form.data: form.data['code'] = form.GetDiscCode() if not difflist: difflist.append("none") if message: difflist.insert(0, message) #print [ form.data['code'] ] svxincludes = re.findall(r'\*include\s+(\S+)(?i)', form.data['code'] or "") vmap = {'settings': settings, 'has_3d': os.path.isfile(settings.SURVEX_DATA + survex_file + ".3d"), 'title': survex_file, 'svxincludes': svxincludes, 'difflist': difflist, 'logmessage':logmessage, 'form':form} vmap.update(csrf(request)) if outputtype == "ajax": return render_to_response('svxfiledifflistonly.html', vmap) return render_to_response('svxfile.html', vmap) def svxraw(request, survex_file): svx = open(os.path.join(settings.SURVEX_DATA, survex_file+".svx"), "rt",encoding='utf8') return HttpResponse(svx, content_type="text") # The cavern running function def process(survex_file): cwd = os.getcwd() os.chdir(os.path.split(settings.SURVEX_DATA + survex_file)[0]) os.system(settings.CAVERN + " --log " + settings.SURVEX_DATA + survex_file + ".svx") os.chdir(cwd) def threed(request, survex_file): process(survex_file) try: threed = open(settings.SURVEX_DATA + survex_file + ".3d", "rt",encoding='utf8') return HttpResponse(threed, content_type="model/3d") except: log = open(settings.SURVEX_DATA + survex_file + ".log", "rt",encoding='utf8') return HttpResponse(log, content_type="text") def log(request, survex_file): process(survex_file) log = open(settings.SURVEX_DATA + survex_file + ".log", "rt",encoding='utf8') return HttpResponse(log, content_type="text") def err(request, survex_file): process(survex_file) err = open(settings.SURVEX_DATA + survex_file + ".err", "rt",encoding='utf8') return HttpResponse(err, content_type="text") def identifycavedircontents(gcavedir): # find the primary survex file in each cave directory name = os.path.split(gcavedir)[1] subdirs = [ ] subsvx = [ ] primesvx = None for f in os.listdir(gcavedir): if name == "204" and (f in ["skel.svx", "template.svx", "204withents.svx"]): pass elif name == "136" and (f in ["136-noents.svx"]): pass elif name == "115" and (f in ["115cufix.svx", "115fix.svx"]): pass elif os.path.isdir(os.path.join(gcavedir, f)): if f[0] != ".": subdirs.append(f) elif f[-4:] == ".svx": nf = f[:-4] if nf.lower() == name.lower() or nf[:3] == "all" or (name, nf) in [("resurvey2005", "145-2005"), ("cucc", "cu115")]: if primesvx: if nf[:3] == "all": assert primesvx[:3] != "all", (name, nf, primesvx, gcavedir, subsvx) primesvx = nf else: assert primesvx[:3] == "all", (name, nf, primesvx, gcavedir, subsvx) else: primesvx = nf else: subsvx.append(nf) else: pass #assert re.match(".*?(?:.3d|.log|.err|.txt|.tmp|.diff|.e?spec|~)$", f), (gcavedir, f) subsvx.sort() #assert primesvx, (gcavedir, subsvx) if primesvx: subsvx.insert(0, primesvx) return subdirs, subsvx # direct local non-database browsing through the svx file repositories # perhaps should use the database and have a reload button for it def survexcaveslist(request): cavesdir = os.path.join(settings.SURVEX_DATA, "caves-1623") #cavesdircontents = { } onefilecaves = [ ] multifilecaves = [ ] subdircaves = [ ] # first sort the file list fnumlist = sorted([ (-int(re.match(r"\d*", f).group(0) or "0"), f) for f in os.listdir(cavesdir) ]) print(fnumlist) # go through the list and identify the contents of each cave directory for num, cavedir in fnumlist: if cavedir in ["144", "40"]: continue gcavedir = os.path.join(cavesdir, cavedir) if os.path.isdir(gcavedir) and cavedir[0] != ".": subdirs, subsvx = identifycavedircontents(gcavedir) survdirobj = [ ] for lsubsvx in subsvx: survdirobj.append(("caves-1623/"+cavedir+"/"+lsubsvx, lsubsvx)) # caves with subdirectories if subdirs: subsurvdirs = [ ] for subdir in subdirs: dsubdirs, dsubsvx = identifycavedircontents(os.path.join(gcavedir, subdir)) assert not dsubdirs lsurvdirobj = [ ] for lsubsvx in dsubsvx: lsurvdirobj.append(("caves-1623/"+cavedir+"/"+subdir+"/"+lsubsvx, lsubsvx)) subsurvdirs.append((lsurvdirobj[0], lsurvdirobj[1:])) subdircaves.append((cavedir, (survdirobj[0], survdirobj[1:]), subsurvdirs)) # multifile caves elif len(survdirobj) > 1: multifilecaves.append((survdirobj[0], survdirobj[1:])) # single file caves else: #print("survdirobj = ") #print(survdirobj) onefilecaves.append(survdirobj[0]) return render_to_response('svxfilecavelist.html', {'settings': settings, "onefilecaves":onefilecaves, "multifilecaves":multifilecaves, "subdircaves":subdircaves }) # parsing all the survex files of a single cave and showing that it's consistent and can find all the files and people # doesn't use recursion. just writes it twice def survexcavesingle(request, survex_cave): breload = False cave = Cave.objects.get(kataster_number=survex_cave) if breload: parsers.survex.ReloadSurvexCave(survex_cave) return render_to_response('svxcavesingle.html', {'settings': settings, "cave":cave })