import re from pathlib import Path import django.forms as forms from django.http import HttpResponseRedirect from django.shortcuts import redirect, render import troggle.settings as settings #from troggle.core.models.caves import Entrance, Cave from troggle.core.utils import ( COOKIE_MAX_AGE, WriteAndCommitError, current_expo, get_cookie, git_string, write_and_commit, ) from troggle.core.views.caves import get_cave_from_slug """Forms to handle renaming files and editing contents when a cave is 'katastered', ie.e moves from an informal number, such as 1623-2024-BL-10 to 1623-999 """ def get_loser_dir(cave): """ Copes with capitalisation mismatch between declared loser diretory and actual """ loser_name = f"{str(cave.unofficial_number)}" parent = settings.SURVEX_DATA / f"caves-{str(cave.areacode)}" for dn in [loser_name, loser_name.lower(), loser_name.upper()]: if ( parent / dn).is_dir(): return parent / dn, Path(f"caves-{str(cave.areacode)}") / dn return None, None def kataster(request, slug): """Create the page which analyses how to rename a cave and all the files from the unofficial_number identifier, e.g. 1623-2023-mg-03 to the kataster number e.g. 1623-999 """ def do_file_finding(knum): global cavefilename, cave_data, entrance_data, loser_name, loser_data mvscript = f"cd {settings.CAVEDESCRIPTIONS }\n" cavefilename = str(cave) + ".html" target= f"{cave.areacode}-{str(knum)}" cave_data = Path( "cave_data", cavefilename ) if not (settings.CAVEDESCRIPTIONS / cavefilename).is_file: # settings.EXPOWEB / cave_data cave_data = "does not exist" mvscript += f"mv {cavefilename} {target}.html\n" ent_dir = settings.ENTRANCEDESCRIPTIONS # settings.EXPOWEB / "entrance_data" mvscript += f"\ncd {settings.ENTRANCEDESCRIPTIONS }\n" entrance_data = [] for ent in ent_dir.iterdir(): if str(ent.name).startswith(str(cave)): print(ent.name) entrance_data.append("entrance_data/"+ent.name) mvscript += f"mv {ent.name} {ent.name.replace(str(cave.unofficial_number),str(knum))}\n" loser_data = [] loser_dir, loser_name = get_loser_dir(cave) if (loser_dir).is_dir(): print(loser_dir) for svx in loser_dir.iterdir(): print(svx) loser_data.append(Path(loser_dir , svx).name) return mvscript def script_loser(knum): global cavefilename, cave_data, entrance_data, loser_name, loser_data loser_dir, loser_name = get_loser_dir(cave) #/home/philip/expo/loser/caves-1623/2024-jc-01 , caves-1623/2024-jc-01 target = loser_name.parent / str(knum) survex_name = str(loser_name.name) l_script = f"\ncd {settings.SURVEX_DATA}\n" l_script += f'sed -i "/^*include/s/{survex_name}/{knum}/g" {loser_name.parent}/caves.svx\n' l_script += f'sed -i "/^*equate/s/{survex_name}/{knum}/g" {loser_name}/{survex_name}.svx\n' l_script += f'sed -i "/^*begin/s/{survex_name}/{knum}/" {loser_name}/{survex_name}.svx\n' l_script += f'sed -i "/^*end/s/{survex_name}/{knum}/" {loser_name}/{survex_name}.svx\n' l_script +=f"# These 'sed' edits will not do everything in all cases, but they do the basics\n\n" l_script +=f"mv {loser_name} {target}\n" l_script +=f"cd {target}\n" for filename in loser_data: l_script +=f"mv {filename} {filename.replace(survex_name,str(knum))}\n" l_script +=f"# But note that git ignores .log and .3d files\n" return l_script knum = 9999 if cave := get_cave_from_slug(slug.lower()): pass elif cave := get_cave_from_slug(slug.upper()): pass else: return HttpResponseRedirect("/caves") entrances = [] for e in cave.entrances(): # horrid CaveAndEntrance indirection we need to refactor out in due course if e.entrance.best_station(): entrances.append(e.entrance) _ = do_file_finding(knum) alias = f'(\\"{cave.slug()}\\", \\"{cave.areacode}-{knum}\\"),' aliasfile = settings.CAVEDESCRIPTIONS / "cavealiases.txt" try: # this is a python generator idiom. # see https://realpython.com/introduction-to-python-generators/ # THIS IS VERY SILLY. We have this in the databse fom when this file was parsed. Don't read it again ! # However we will need to parse the href= and src= strings in the cave description text, notes etc. with open(settings.CAVEDESCRIPTIONS / cavefilename, 'r') as f: for line in f: if match := re.search(r'(.*?)', line): entrance = match.group(1) print(entrance) except PermissionError as e: msg=f"CANNOT save this file.\nPERMISSIONS incorrectly set on server for this file {filepath}. Ask a nerd to fix this: {e}" print(msg) raise except Exception as e: msg=f"CANNOT write this file {filepath}. Ask a nerd to fix this: {e}" print(msg) # Restart script with POST data script = "# Conversion script - VERY INCOMPLETE AS YET\n# When doing it by hand, it is less error-prone to do the file re-namings last,\n" script += "# but in a script it does not matter so much so long as everything is consistent and tested.\n" script += "# Except that reversing changes using git does not always restore directories exactly\n# (because of .gitignore).\n\n" script += "# Be careful with the directory names, they might not be the same on your PC as on the server\n\n" warning ="" if request.method == "POST": # If the form has been submitted... form = KatasterForm(request.POST) # A form bound to the POST data if form.is_valid(): clean = form.cleaned_data knum = clean['kataster_number'] print(f" # kataster_number {clean['kataster_number']}") if test := get_cave_from_slug(f"{cave.areacode}-{knum}"): warning = "

DANGER DANGER You will overwrite an existing katastered cave !!!
" warning += "resetting proposed new kataster number to 666.

" knum = 666 else: # GET and fall-through if POST is not valid form = KatasterForm() script += do_file_finding(knum) script += script_loser(knum) script += f'\necho "{alias}" >> {aliasfile}' script_rows = str(min(35,3+script.count('\n'))) return render( request, "cave_kataster.html", { "form": form, "warning": warning, "cave": cave, "entrances": entrances, "cave_data": cave_data, "entrance_data": entrance_data, "loser_name": loser_name, "loser_data": loser_data, "knum": knum, "script": script, "rows": script_rows, }, ) class KatasterForm(forms.Form): # areacode = forms.CharField(label='Full name', max_length=4, widget=forms.TextInput(attrs={'tabindex': 1, 'placeholder': '1623'})) # official_name = forms.CharField(label='CUCC name', max_length=160,widget=forms.TextInput(attrs={'tabindex': 2, 'placeholder': '2012-ns-07'})) kataster_number= forms.IntegerField(label="New kataster no.", widget=forms.TextInput(attrs={'tabindex': 1, 'size':1, 'placeholder': '9999'})) """ areacode = models.CharField(max_length=4, blank=True, null=True) # could use models.IntegerChoices entrances = models.ManyToManyField("Entrance", through="CaveAndEntrance") filename = models.CharField(max_length=200) # if a cave is 'pending' this is not set. Otherwise it is. kataster_code = models.CharField(max_length=20, blank=True, null=True) kataster_number = models.CharField(max_length=10, blank=True, null=True) kataster_status = models.TextField(blank=True, null=True) official_name = models.CharField(max_length=160) survex_file = models.CharField(max_length=100, blank=True, null=True) # should be a foreign key? unofficial_number = models.CharField(max_length=60, blank=True, null=True) url = models.CharField(max_length=300, blank=True, null=True, unique = True) SURVEX_DATA = REPOS_ROOT_PATH / "loser" EXPOWEB = REPOS_ROOT_PATH / "expoweb" CAVEDESCRIPTIONS = EXPOWEB / "cave_data" ENTRANCEDESCRIPTIONS = EXPOWEB / "entrance_data" """