import pywikibot
import re
from pywikibot import pagegenerators
import unicodedata

abort=False
lessSaves=0
regexbase = "({{[Nn]owrap\|)?([0-9\.\,]+)([½⅓⅔¼¾⅕⅖⅗⅘⅙⅚⅐⅛⅜⅝⅞⅑])?(\+)?(}})?([\s\.\,]|( ))*( )?"
regexlist = {
    "kmh":regexbase+"(kmh|km\/h)",
    "m":regexbase+"(m)",
    "ft":regexbase+"(feet|ft)",
    "in":regexbase+"(in)",
    "sqm":regexbase+"(sqm|m2|m<sup>2<\/sup>|m²|sq m)",
    "sqft":regexbase+"(sq. ft.|sq ft|{{nowrap\|sq ft}}|sqft|ft2|ft<sup>2<\/sup>|ft²)",
    "kg":regexbase+"(kg)",
    "lb":regexbase+"(lb|\[\[pound \(mass\)\|lb]])",
    "kw":regexbase+"(kw|kW|\[\[k[wW]]]|\[\[kilowatt\|k[wW]]])",
    "hp":regexbase+"(hp|\[\[horsepower\|hp]])",
    "shp":regexbase+"(shp|\[\[horsepower\|shp]]|\[\[Shaft horsepower\|shp]])",
    "kn":regexbase+"(kn|kN|\[\[kilonewton\|kN]])",
    "lbf":regexbase+"(lb<sub>f<\/sub>|\[\[lbf]]|\[\[pound-force\|lb<sub>f<\/sub>]]|lbf|\[\[pound-force\|lbf]]|lb|lbs)",
    "mph":regexbase+"(mph)",
    "kts":regexbase+"(\[\[knot \(unit\)\|kn]]|kts|kt|knots|\[\[knot \(unit\)\|knots]]|kn)",
    "mach":regexbase+"(mach|\[\[Mach speed\|Mach]])",
    "km":regexbase+"(km)",
    "miles":regexbase+"(\[\[statute mile\|mi]]|miles|mi)",
    "nmi":regexbase+"(nmi|\[\[[Nn]autical mile\|nmi]]|\[\[nautical mile\|nm]]|nm|\[\[nautical mile\|NM]]|NM)",
    "ms":regexbase+"(ms|m\/s)",
    "ftmin":regexbase+"(ftmin|ft\/min|fpm)",
    "kg/m2":regexbase+"(kg\/m²|kg\/m2|kg\/m<sup>2<\/sup>)",
    "lb/sqft":regexbase+"(lb\/\(sq ft\)|lb\/sqft|lb\/ft²|lb\/ft<sup>2<\/sup>)",  
    "mmin":regexbase+"(m\/min)"
}
redirectregex = "{{([Aa]ircraft[ _]+specifications|[Aa]ircraft[ _]+specification|[Aa]irtemp\-test|[Aa]irtemp)"

fractionvalues = {
    "½":0.5,
    "⅓":0.3,
    "⅔":0.7,
    "¼":0.3,
    "¾":0.8,
    "⅕":0.2,
    "⅖":0.4,
    "⅗":0.6,
    "⅘":0.8,
    "⅙":0.2,
    "⅚":0.8,
    "⅐":0.1,
    "⅛":0.1,
    "⅜":0.4,
    "⅝":0.6,
    "⅞":0.9,
    "⅑":0.1
}

extratextregex ="^(lb<sub>f<\/sub>|feet|fpm|\[\[statute mile\|mi]]|\s|\(|\)|({{[Nn]owrap\|)|(}})|\+|(&nbsp;)|\,|\.|m\/min|[½⅓⅔¼¾⅕⅖⅗⅘⅙⅚⅐⅛⅜⅝⅞⅑]|\s|\d|sqm|m2|m<sup>2<\/sup>|m²|sq m|m|ft|in|sq ft|{{nowrap\|sq ft}}|sqft|ft2|ft<sup>2<\/sup>|ft²|lb|\[\[pound \(mass\)\|lb]]|kg|k[wW]|\[\[k[Ww]]]|hp|\[\[horsepower\|hp]]|shp|\[\[horsepower\|shp]]|\[\[Shaft horsepower\|shp]]|kn|\[\[kilowatt\|k[Ww]]]|kN|\[\[kilonewton\|kN]]|\[\[lbf]]|\[\[pound-force\|lb<sub>f<\/sub>]]|lbf|\[\[pounds?-force\|lbf]]|lb|lbs|(kmh|km\/h)|mph|\[\[knot \(unit\)\|kn]]|kts|kt|knots|\[\[knot \(unit\)\|knots]]|kn|[Mm]ach|\[\[Mach speed\|Mach]]|km|lb\/\(sq ft\)|lb\/sqft|lb\/ft²|lb\/ft<sup>2<\/sup>|kg\/m²|kg\/m2|kg\/m<sup>2<\/sup>|ftmin|ft\/min|ms|m\/s|nmi|\[\[[nN]autical mile\|nmi]]|nm|\[\[nautical mile\|NM]]|NM|miles|mi)*$"

def extratext(main):
    if not re.search(extratextregex,x[1].get(main+" alt")+x[1].get(main+" main")):
        errorpage.text += "\n*Extra text at " 
        errorpage.text += page.full_url()
        errorpage.text += " " 
        errorpage.text += x[1].get(main+" main")
        errorpage.text += " "
        errorpage.text += x[1].get(main+" alt")
        global abort 
        abort = True
        return True
    else:
        return False
    
def unitparam(unit, main):
    global abort
    if ((x[1].get(main+" main") is not "") and (main+" main" in x[1].keys())) or ((x[1].get(main+" alt") is not "") and (main + " alt" in x[1].keys())):
        if extratext(main):
            return ""
        elif re.search(regexlist.get(unit),x[1].get(main+" main")):
            fraction = 0
            if re.search(regexlist.get(unit),x[1].get(main+" main")).group(3) is not None:
                fraction = fractionvalues[re.search(regexlist.get(unit),x[1].get(main+" main")).group(3)]
                return str(float(re.search(regexlist.get(unit),x[1].get(main+" main")).group(2).replace(",",""))+fraction)
            return str(re.search(regexlist.get(unit),x[1].get(main+" main")).group(2).replace(",",""))
        elif re.search(regexlist.get(unit),x[1].get(main+" alt")):
            fraction = 0
            if re.search(regexlist.get(unit),x[1].get(main+" alt")).group(3) is not None:
                fraction = fractionvalues[re.search(regexlist.get(unit),x[1].get(main+" alt")).group(3)]
                return str(float(re.search(regexlist.get(unit),x[1].get(main+" alt")).group(2).replace(",",""))+fraction)
            return re.search(regexlist.get(unit),x[1].get(main+" alt")).group(2).replace(",","")
        elif unit == "in" and (re.search(regexlist.get("ft"),x[1].get(main+" main")) or re.search(regexlist.get("ft"),x[1].get(main+" alt"))):
            return "0"
        elif unit == "mach" or unit == "shp" or unit == "hp" or unit == "nmi" or unit == "kts":
            return ""
        elif not re.search("\d",x[1].get(main+" main")) and not re.search("\d",x[1].get(main+" alt")):
            return ""
        elif re.search(regexlist.get("mmin"),x[1].get(main+" main")):
            return ""
        elif re.search(regexlist.get("mmin"),x[1].get(main+" alt")):
            return ""
        else:
            unidentifiedstring = x[1].get(main+" main")+x[1].get(main+" alt")
            unidentifiedstring=re.sub(regexbase+regexlist.get("kmh"),"",unidentifiedstring)
            unidentifiedstring=re.sub(regexbase+regexlist.get("kts"),"",unidentifiedstring)
            unidentifiedstring=re.sub(regexbase+regexlist.get("nmi"),"",unidentifiedstring)
            for i in regexlist:
                unidentifiedstring=re.sub(regexbase+i,"",unidentifiedstring)
            if not re.search("^[^a-zA-Z]*$",unidentifiedstring) and unidentifiedstring is not "":
                print("Unidentifiedstring:"+unidentifiedstring)
                errorpage.text += "\n*Unidentified unit at " 
                errorpage.text += page.full_url()
                errorpage.text += " " 
                errorpage.text += x[1].get(main+" main")
                errorpage.text += ", " 
                errorpage.text += x[1].get(main+" alt")
                errorpage.text += " Looking for:"
                errorpage.text += unit
                abort = True
            return ""
    else:
        return ""
    
def unitif(what, unit, main):
    if what:
        return unitparam(unit, main)
    else:
        return ""
    
def findtype(what,x):
    if x.get("plane or copter?") == "plane" and what == "plane":
        return True
    if x.get("plane or copter?") == "copter" and what == "copter":
        return True
    if not (x.get("plane or copter?") == "copter" or x.get("plane or copter?") == "plane"):
        errorpage.text += "*Unknown type at " 
        errorpage.text += page.full_url()
        global abort
        abort = True
    if (x.get("plane or copter?") == "copter" and what == "plane") or (x.get("plane or copter?") == "plane" and what == "copter"):
        return False
    
def findprimeunit(x):
    if re.search(regexlist["m"],x.get("length main")) and (re.search(regexlist["ft"],x.get("length alt")) or re.search(regexlist["in"],x.get("length alt"))):
        return "met"
    elif (re.search(regexlist["ft"],x.get("length main"))or re.search(regexlist["in"],x.get("length main"))) and re.search(regexlist["m"],x.get("length alt")):
        if re.search(regexlist["kts"],x.get("max speed main")):
            return "kts"
        else:
            return "imp"
    else:
        errorpage.text += "*Unknown prime unit at " 
        errorpage.text += page.full_url()
        global abort
        abort = True
        return ""
    
def get(x,index,note=False):
    if (x.get(index) is not "") and (index in x.keys()):
        if note:
            return "*" + x.get(index)
        return x.get(index)
    else: 
        return ""
    
def armaments():
    if(x[1].get("armament") is "") or ("armament" not in x[1].keys()):
        return("")
    elif (x[1].get("armament") is not "") and ("armament" in x[1].keys()):
        return """|armament = """ + get(x[1],"armament") + """<!-- add bulletted list here or if you want to use the following 
        specific parameters, remove this parameter--> """
    else:
        global abort
        abort = True
        errorpage.text += "*Armaments error at " 
        errorpage.text += page.full_url()
        return ""
    
def badparam():
    if ((x[1].get("number of propellers per engine") is not "") and ("number of propellers per engine" in x[1].keys()) or (x[1].get("more general powerplant") is not "") and ("more general powerplant" in x[1].keys())):
        global abort
        abort = True
        errorpage.text += "\n*Bad parameter at " 
        errorpage.text += page.full_url()
        
def payload():
    payloadtext = ""
    if (x[1].get("payload main") is not "" and "payload main" in x[1].keys()) and (x[1].get("payload alt") is not "" and "payload alt" in x[1].keys()):
        extratext("payload")
        payloadtext =  "\n**" + "'''Payload:''' " + get(x[1],"payload main") + " (" + get(x[1],"payload alt") + ")"
    elif (x[1].get("payload main") is "" or "payload main" not in x[1].keys()) and (x[1].get("payload alt") is "" or "payload alt" not in x[1].keys()):
        print("")
    else:
        global abort
        abort = True
        errorpage.text += "\n*Payload problem at " 
        errorpage.text += page.full_url()
        return payloadtext
    if(((x[1].get("payload more") is not "") and ("payload more" in x[1].keys()))):
        payloadtext = payloadtext + "\n" + get(x[1],"payload more")
    return payloadtext

def usefulload():
    payloadtext = ""
    if (x[1].get("useful load main") is not "" and "useful load main" in x[1].keys()) and (x[1].get("useful load alt") is not "" and "useful load alt" in x[1].keys()):
        extratext("useful load")
        payloadtext =  "\n**" + "'''Useful load:''' " + get(x[1],"useful load main") + " (" + get(x[1],"useful load alt") + ")"
        return payloadtext
    elif (x[1].get("useful load main") is "" or "useful load main" not in x[1].keys()) and (x[1].get("useful load alt") is "" or "useful load alt" not in x[1].keys()):
        return ""
    else:
        global abort
        abort = True
        errorpage.text += "\n*Useful load problem at " 
        errorpage.text += page.full_url()
        return ""
    
def powermass():
    powermasstext = ""
    if(((x[1].get("power/mass main") is not "") and ("power/mass main" in x[1].keys()))):
        powermasstext = powermasstext + get(x[1],"power/mass main")
        if(((x[1].get("power/mass alt") is not "") and ("power/mass alt" in x[1].keys()))):
            powermasstext = powermasstext + " (" + get(x[1],"power/mass alt")+ ")"
    return powermasstext

def getarmaments(x, index):
    if re.search("^\*\*",get(x,index)):
        errorpage.text += "\n*Indentation problem at " 
        errorpage.text += page.full_url()
        errorpage.text += " " 
        errorpage.text += get(x,index)
        global abort
        abort = True  
        return ""
    else:
        return get(x,index)
    
def subtemplatenum(x):
    templatenum=0
    for parameter in x.values():
        if re.search("[^{]*{{"*7,parameter):
            templatenum += 7
        elif re.search("[^{]*{{"*6,parameter):
            templatenum += 6
        elif re.search("[^{]*{{"*5,parameter):
            templatenum += 5
        elif re.search("[^{]*{{"*4,parameter):
            templatenum += 4
        elif re.search("[^{]*{{"*3,parameter):
            templatenum += 3
        elif re.search("[^{]*{{"*2,parameter):
            templatenum += 2
        elif re.search("[^{]*{{",parameter):
            templatenum += 1
    return templatenum

def rotnumber(copter):
    if copter:
        return "1"
    else:
        return ""

def getoriginal(x,get):
    unidentifiedstring = ""
    if (x.get(get) is not "") and (get in x.keys()):
        unidentifiedstring += x.get(get)
        unidentifiedstring = re.sub(regexbase+regexlist.get("kmh"),"",unidentifiedstring)
        for i in regexlist:
            unidentifiedstring = re.sub(regexbase+i,"",unidentifiedstring)
        if not re.search("^[^a-zA-Z]*$",unidentifiedstring) and unidentifiedstring is not "":
            return x.get(get)
    return ""

def morepower():
    string = ""
    if get(x[1],"power more") is not "":
        if not re.search("<ref>",get(x[1],"power more")):
            string += "&#32;"
            string += get(x[1],"power more")
        else:
            string += get(x[1],"power more")
    return string
def getnote(x,main,indent=False):
    if indent:
        return get(x,main, True)
    if((x.get(main+" main") is "") or (main+" main" not in x.keys())) and ((x.get(main+" alt") is "") or (main + " alt" not in x.keys())):
        return ""
    else:
        return get(x,"more "+main)
def draw(x):
    longtext = ("""{{Aircraft specs
|ref                        = <!-- reference --> """ + get(x,"ref") + """
|prime units?               = """ + primeunit + """
<!--General characteristics-->
|crew                   = """ + get(x,"crew") + """
|capacity               = """ + get(x,"capacity") + payload() + usefulload() + """
|length m               = """ + unitparam("m","length") + """
|length ft              = """ + unitparam("ft","length") + """
|length in              = """ + unitparam("in","length") + """
|span m                 = """ + unitif(plane,"m","span") + """
|span ft                = """ + unitif(plane,"ft","span") + """
|span in                = """ + unitif(plane,"in","span") + """
|height m               = """ + unitparam("m","height") + """
|height ft              = """ + unitparam("ft","height") + """
|height in              = """ + unitparam("in","height") + """
|wing area sqm          = """ + unitif(plane,"sqm","area") + """
|wing area sqft         = """ + unitif(plane,"sqft","area") + """
|aspect ratio           = """ + get(x,"aspect ratio") + """
|airfoil                = """ + get(x,"airfoil") + """
|empty weight kg        = """ + unitparam("kg","empty weight") + """
|empty weight lb        = """ + unitparam("lb","empty weight") + """
|gross weight kg        = """ + unitparam("kg","loaded weight") + """
|gross weight lb        = """ + unitparam("lb","loaded weight") + """
|max takeoff weight kg  = """ + unitparam("kg","max takeoff weight") + """
|max takeoff weight lb  = """ + unitparam("lb","max takeoff weight") + """
|max takeoff weight note= """ + get(x,"max takeoff weight more") + """
|more general           = """ + getnote(x,"more general", True) + """
<!--Powerplant-->
|eng1 number            = """ + get(x,"number of props") + get(x,"number of jets") + """
|eng1 name              = """ + get(x,"engine (prop)") + get(x,"engine (jet)") + """
|eng1 type              = """ + get(x,"type of prop") + get(x,"type of jet") + """
|eng1 kw                = <!-- prop engines --> """ + unitparam("kw","power") + """
|eng1 hp                = <!-- prop engines --> """ + unitparam("hp","power") + """
|eng1 shp               = <!-- prop engines --> """ + unitparam("shp","power") + """
|eng1 kn                = <!-- jet/rocket engines --> """ + unitparam("kn","thrust") + """
|eng1 lbf               = <!-- jet/rocket engines --> """ + unitparam("lbf","thrust") + """
|power original         = """ + getoriginal(x,"power original") + """
|thrust original        = """ + getoriginal(x,"thrust original") + """
|eng1 kn-ab             = """ + unitparam("kn","afterburning thrust") + """
|eng1 lbf-ab            = """ + unitparam("lbf","afterburning thrust") + """
|more power             = """ + morepower() + """
|prop name              = """ + get(x,"propellers") + """
|prop dia m             = <!-- propeller aircraft --> """ + unitparam("m","propeller diameter") + """
|prop dia ft            = <!-- propeller aircraft --> """ + unitparam("ft","propeller diameter") + """
|prop dia in            = <!-- propeller aircraft --> """ + unitparam("in","propeller diameter") + """
|rot dia m              = <!-- helicopters --> """ + unitif(copter,"m","span") + """
|rot dia ft             = <!-- helicopters --> """ + unitif(copter,"ft","span") + """
|rot dia in             = <!-- helicopters --> """ + unitif(copter,"in","span")  + """
|rot area sqm           = <!-- helicopters --> """ + unitif(copter,"sqm","area")  + """
|rot area sqft          = <!-- helicopters --> """ + unitif(copter,"sqft","area") + """
|rot number             = """ + rotnumber(copter) + """
<!--Performance-->
|max speed kmh          = """ + unitparam("kmh","max speed") + """
|max speed mph          = """ + unitparam("mph","max speed") + """
|max speed kts          = """ + unitparam("kts","max speed") + """
|max speed note         = """ + get(x,"max speed more") + """
|max speed mach         = """ + unitparam("mach","max speed") + """
|cruise speed kmh       = """ + unitparam("kmh","cruise speed") + """
|cruise speed mph       = """ + unitparam("mph","cruise speed") + """
|cruise speed kts       = """ + unitparam("kts","cruise speed") + """
|cruise speed note      = """ + get(x,"cruise speed more") + """
|stall speed kmh        = """ + unitparam("kmh","stall speed") + """
|stall speed mph        = """ + unitparam("mph","stall speed") + """
|stall speed kts        = """ + unitparam("kts","stall speed") + """
|stall speed note       = """ + get(x,"stall speed more") + """
|never exceed speed kmh = """ + unitparam("kmh","never exceed speed") + """
|never exceed speed mph = """ + unitparam("mph","never exceed speed") + """
|never exceed speed kts = """ + unitparam("kts","never exceed speed") + """
|range km               = """ + unitparam("km","range") + """
|range miles            = """ + unitparam("miles","range") + """
|range nmi              = """ + unitparam("nmi","range") + """
|range note             = """ + get(x,"range more") + """
|combat range km        = """ + unitparam("km","combat radius") + """
|combat range miles     = """ + unitparam("miles","combat radius") + """
|combat range nmi       = """ + unitparam("nmi","combat radius") + """
|combat range note      = """ + get(x,"combat radius more") + """
|ferry range km         = """ + unitparam("km","ferry range") + """
|ferry range miles      = """ + unitparam("miles","ferry range") + """
|ferry range nmi        = """ + unitparam("nmi","ferry range") + """
|ferry range note       = """ + get(x,"ferry range more") + """
|endurance              = <!-- if range unknown --> """ + get(x,"endurance") + """
|ceiling m              = """ + unitparam("m","ceiling") + """
|ceiling ft             = """ + unitparam("ft","ceiling") + """
|ceiling note           = """ + get(x,"ceiling more") + """
|climb rate ms          = """ + unitparam("ms","climb rate") + """
|climb rate ftmin       = """ + unitparam("ftmin","climb rate") + """
|climb rate note        = """ + get(x,"climb rate more") + """
|sink rate ms           = <!-- sailplanes --> """ + unitparam("ms","sink rate") + """
|sink rate ftmin        = <!-- sailplanes --> """ + unitparam("ftmin","sink rate") + """
|sink rate note         = """ + get(x,"sink rate more") + """
|wing loading kg/m2     = """ + unitif(plane,"kg/m2","loading") + """
|wing loading lb/sqft   = """ + unitif(plane,"lb/sqft","loading") + """
|disk loading kg/m2     = """ + unitif(copter,"kg/m2","loading") + """
|disk loading lb/sqft   = """ + unitif(copter,"lb/sqft","loading") + """
|power/mass             = """ + powermass() + """
|thrust/weight          = """ + get(x,"thrust/weight") + """
|more performance       = """ + get(x,"more performance") + """
<!--Armament-->
""" + armaments() + """
|guns                   = """ + getarmaments(x,"guns") + """
|bombs                  = """ + getarmaments(x,"bombs") + """
|rockets                = """ + getarmaments(x,"rockets") + """
|missiles               = """ + getarmaments(x,"missiles") + """
|hardpoints             = """ + getarmaments(x,"hardpoints")+ """
|hardpoint capacity     = """ + getarmaments(x,"hardpoint capacity") + """
|hardpoint rockets      = """ + getarmaments(x,"hardpoint rockets") + """
|hardpoint missiles     = """ + getarmaments(x,"hardpoint missiles") + """
|hardpoint bombs        = """ + getarmaments(x,"hardpoint bombs") + """
|hardpoint other        = """ + getarmaments(x,"hardpoint other") + """
|avionics               = """ + getarmaments(x,"avionics")+ """
}}""")
    return longtext

site = pywikibot.Site('en', 'wikipedia')
errorpage = pywikibot.Page(site, u"User:PearBOT/Aircraft specs problems")
linkpage = pywikibot.Page(site, u"User:PearBOT/linkpage")
for page in pywikibot.pagegenerators.LinkedPageGenerator(linkpage):
    text = page.text
    templates=pywikibot.textlib.extract_templates_and_params(text,remove_disabled_parts="yes",strip ="yes")
    templatenum = 0
    for x in templates:
        if x[0] == "Aircraft specifications" or x[0] =="Aircraft specification" or x[0] == "Airtemp-test" or x[0] == "Airtemp-test" or x[0] == "aircraft specifications" or x[0] =="aircraft specification" or x[0] == "airtemp-test" or x[0] == "airtemp-test":
            print(page.full_url())
            templatetext=""
            longtext=""
            plane = False
            copter = False
            copter=findtype("copter", x[1])
            plane=findtype("plane", x[1])
            primeunit=findprimeunit(x[1])
            badparam()
            finalregex = ""
            lessSaves += 1
            finalregex += "[^}]*}}"*(subtemplatenum(x[1])+1)
            templatetext=""
            templatetext=draw(x[1])
            templatenumregex = "[^{]*"+("{{[^{]*")*(templatenum-1)
            print(templatenumregex+"("+redirectregex+finalregex+")")
            #print(re.search(templatenumregex+"("+redirectregex+finalregex+")",page.text).group(2*templatenum+1))
            page.text = re.sub(re.escape(re.search(templatenumregex+"("+redirectregex+finalregex+")",page.text).group(1)),templatetext,page.text)
            templatenum += 1
        templatenum += 1
    if abort:
        abort = False
        errorpage.text += "\n*Page skipped at: " 
        errorpage.text += page.full_url()
        if lessSaves % 1 == 0:
            errorpage.save("Page skipped")
            print(errorpage.text)
    else:
        print("")
        #print(page.text)
        #page.save(u"Replaced deprecated Aircraft specifications template. Bot in trial, see [[Wikipedia:Bots/Requests_for_approval/PearBOT|BRFA]]", minor=False)
https://en.wikipedia.org/wiki/User%3APearBOT%2Ftest

[^{]*({{([Aa]ircraft[ _]+specifications|[Aa]ircraft[ _]+specification|[Aa]irtemp\-test|[Aa]irtemp)[^}]*}})
https://en.wikipedia.org/wiki/User%3APearBOT%2Ftest

[^{]*{{[^{]*({{([Aa]ircraft[ _]+specifications|[Aa]ircraft[ _]+specification|[Aa]irtemp\-test|[Aa]irtemp)[^}]*}})
https://en.wikipedia.org/wiki/User%3APearBOT%2Ftest

[^{]*{{[^{]*{{[^{]*{{[^{]*({{([Aa]ircraft[ _]+specifications|[Aa]ircraft[ _]+specification|[Aa]irtemp\-test|[Aa]irtemp)[^}]*}})
https://en.wikipedia.org/wiki/User%3APearBOT%2Ftest

[^{]*{{[^{]*{{[^{]*{{[^{]*{{[^{]*{{[^{]*({{([Aa]ircraft[ _]+specifications|[Aa]ircraft[ _]+specification|[Aa]irtemp\-test|[Aa]irtemp)[^}]*}})
https://en.wikipedia.org/wiki/User%3APearBOT%2Ftest

[^{]*{{[^{]*{{[^{]*{{[^{]*{{[^{]*{{[^{]*{{[^{]*{{[^{]*({{([Aa]ircraft[ _]+specifications|[Aa]ircraft[ _]+specification|[Aa]irtemp\-test|[Aa]irtemp)[^}]*}})
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-64-ffa4391b8b3f> in <module>
    426             print(templatenumregex+"("+redirectregex+finalregex+")")
    427             #print(re.search(templatenumregex+"("+redirectregex+finalregex+")",page.text).group(2*templatenum+1))
--> 428             page.text = re.sub(re.escape(re.search(templatenumregex+"("+redirectregex+finalregex+")",page.text).group(1)),templatetext,page.text)
    429             templatenum += 1
    430         templatenum += 1

AttributeError: 'NoneType' object has no attribute 'group'