From a84ff494138945997a2ef7cbf9cd53c00cb955e1 Mon Sep 17 00:00:00 2001 From: Damien De Paoli Date: Sun, 9 Apr 2023 13:10:28 +1000 Subject: [PATCH] added BUG-120, somehow losing pref info. No prints are working in PROD, so changed a lot of printf( in the F/E to SetFELog with error and persistent/cant_close set across many files. Also used opportunity to remove a few unnecessary debugs --- BUGs | 20 +++++++++++++++++++- files.py | 4 ++-- main.py | 6 ++---- person.py | 7 +------ settings.py | 5 +++-- states.py | 21 +++++++++++++-------- 6 files changed, 40 insertions(+), 23 deletions(-) diff --git a/BUGs b/BUGs index 97c5778..5b55018 100644 --- a/BUGs +++ b/BUGs @@ -1,4 +1,4 @@ -### Next: 120 +### Next: 121 BUG-100: I managed to get 2 photos matching mich in the NOT_WORKING photo (probably dif refimgs but same p.tag?) = /photos/2012/20120414-damien/IMG_8467.JPG BUG-106: cant add trudy /pat? as refimgs via FaceDBox @@ -10,3 +10,21 @@ BUG-119: "Uncaught (in promise) Error: A listener indicated an asynchronous response by returning true, but the message channel closed before a response was received" investigate this (possible I'm calling check_for_jobs and maybe not doing the async right?) + +BUG-120: on tablet: +[2023-04-09 12:21:21,214] ERROR in app: Exception on /view/16978 [GET] +Traceback (most recent call last): + File "/usr/local/lib/python3.10/dist-packages/flask/app.py", line 2525, in wsgi_app + response = self.full_dispatch_request() + File "/usr/local/lib/python3.10/dist-packages/flask/app.py", line 1822, in full_dispatch_request + rv = self.handle_user_exception(e) + File "/usr/local/lib/python3.10/dist-packages/flask/app.py", line 1820, in full_dispatch_request + rv = self.dispatch_request() + File "/usr/local/lib/python3.10/dist-packages/flask/app.py", line 1796, in dispatch_request + return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args) + File "/code/files.py", line 655, in view + OPT=States( request ) + File "/code/states.py", line 92, in __init__ + self.url = pref.orig_url +AttributeError: 'NoneType' object has no attribute 'orig_url' + diff --git a/files.py b/files.py index 7e60955..4875ddb 100644 --- a/files.py +++ b/files.py @@ -588,7 +588,7 @@ def view_list(): # this occurs when we went from the last image on a page (with how_many on # it) and it just happened to also be the last in the DB... if not entries: - print("DDP: DONT think this can happen anymore") + SetFELog( message="DDP: DONT think this can happen anymore", log_level="error", job=None, persistent=True, cant_close=True ) # undo the skip by how_many and getentries again OPT.offset -= int(OPT.how_many) @@ -676,7 +676,7 @@ def view(id): eids=eids.rstrip(",") # jic, sometimes we trip this, and rather than show broken pages / destroy if id not in eids: - print( f"ERROR: viewing an id, but its not in eids OPT={OPT}, id={id}, eids={eids}") + SetFELog( message=f"ERROR: viewing an id, but its not in eids OPT={OPT}, id={id}, eids={eids}", log_level="error", persistent=True, cant_close=True) msg="Sorry, viewing data is confused, cannot view this image now" if os.environ['ENV'] == "production": msg += "Clearing out all states. This means browser back buttons will not work, please start a new tab and try again" diff --git a/main.py b/main.py index 1ae3865..c28e3c6 100644 --- a/main.py +++ b/main.py @@ -23,7 +23,6 @@ from flask_ldap3_login.forms import LDAPLoginForm ####################################### Flask App globals ####################################### hostname = socket.gethostname() -print( "Running on: {}".format( hostname) ) app = Flask(__name__) @@ -38,8 +37,6 @@ try: except Exception: app.config['SECRET_KEY'] = b'my_insecure_PA_token_with_random_2134876adsfjhlkasdf87' -print(app.config['SECRET_KEY']) - # ldap config vars: (the last one is required, or python ldap freaks out) app.config['LDAP_HOST'] = 'mara.ddp.net' app.config['LDAP_BASE_DN'] = 'dc=depaoli,dc=id,dc=au' @@ -67,6 +64,7 @@ from files import Entry from person import Person from settings import Settings from user import PAUser +from job import SetFELog ####################################### GLOBALS ####################################### # allow jinja2 to call these python functions directly @@ -122,7 +120,7 @@ def login(): # the re matches on any special LDAP chars, we dont want someone # ldap-injecting our username, so send them back to the login page instead if request.method == 'POST' and re.search( r'[()\\*&!]', request.form['username']): - print( f"WARNING: Detected special LDAP chars in username: {request.form['username']}") + SetFELog( message=f"ERROR: Detected special LDAP chars in username: {request.form['username']}", log_level="error", persistent=True, cant_close=True ) return redirect(url_for('login')) if form.validate_on_submit(): # Successfully logged in, We can now access the saved user object via form.user. diff --git a/person.py b/person.py index a9a0f3e..63f1618 100644 --- a/person.py +++ b/person.py @@ -94,12 +94,11 @@ def AddRefimgToPerson( filename, person ): except Exception as e: # can fail "silently" here, if the face_locn worked, great, its only # a tmp file in /tmp - if not, the next if will send a msg to the front-end - print( f"Failed to delete tmp file for refimg addition: {e}" ) + SetFELog( message=f"Failed to delete tmp file for refimg addition: {e}", log_level="danger", persistent=True, cant_close=True ) if not face_locn: SetFELog( f"Failed to find face in Refimg:", "danger" ) raise Exception("Could not find face in uploaded reference image" ) - return refimg.face_top = face_locn[0] refimg.face_right = face_locn[1] refimg.face_bottom = face_locn[2] @@ -344,7 +343,6 @@ def add_force_match_override(): # dont do status update here, the F/E is in the middle of a dbox, just send metadata through to the B/E NewJob( "metadata", num_files=0, wait_for=None, jex=jex, desc="create metadata for adding forced match" ) - print( f"Placing an override match with face_id {face_id}, for person: {p.tag}" ) # this will reply to the Ajax / POST, and cause the page to re-draw with new face override to person_tag return make_response( jsonify( person_tag=p.tag ) ) @@ -357,7 +355,6 @@ def remove_force_match_override(): face_id = request.form['face_id'] person_tag = request.form['person_tag'] file_eid = request.form['file_eid'] - print( f"Remove override force match of face_id={face_id} to person_tag={person_tag}" ) FaceForceMatchOverride.query.filter( FaceForceMatchOverride.face_id==face_id ).delete() db.session.commit() @@ -383,7 +380,6 @@ def remove_force_match_override(): def remove_no_match_override(): face_id = request.form['face_id'] type_id = request.form['type_id'] - print( f"Remove override of no match (type_id={type_id}) for face_id={face_id}" ) FaceNoMatchOverride.query.filter( FaceNoMatchOverride.face_id==face_id, FaceNoMatchOverride.type_id==type_id ).delete() db.session.commit() @@ -426,6 +422,5 @@ def add_no_match_override(): # dont do status update here, the F/E is in the middle of a dbox, just send metadata through to the B/E NewJob( "metadata", num_files=0, wait_for=None, jex=jex, desc="create metadata for adding forced non-match" ) - print( f"Placing an override of NO Match for face_id {face_id}" ) # this will reply to the Ajax / POST, and cause the page to re-draw with new face override to person_tag return make_response( jsonify( type=t.name ) ) diff --git a/settings.py b/settings.py index fa114e5..d28b18c 100644 --- a/settings.py +++ b/settings.py @@ -5,6 +5,7 @@ from sqlalchemy import Sequence from sqlalchemy.exc import SQLAlchemyError from flask_login import login_required, current_user from main import db, app, ma +from job import SetFELog # pylint: disable=no-member @@ -136,7 +137,7 @@ def settings(): def SettingsRBPath(): settings = Settings.query.first() if settings == None: - print("Cannot create file data with no settings / recycle bin path is missing") + SetFELog( message="Cannot create file data with no settings / recycle bin path is missing", log_level="error", persistent=True, cant_close=False) return # path setting is an absolute path, just use it, otherwise prepend base_path first if settings.recycle_bin_path[0] == '/': @@ -153,7 +154,7 @@ def SettingsSPath(): paths=[] settings = Settings.query.first() if settings == None: - print("Cannot create file data with no settings / storage path is missing") + SetFELog( message="Cannot create file data with no settings / storage path is missing", log_level="error", persistent=True, cant_close=False) return if settings.storage_path[0] == '/': path=settings.storage_path diff --git a/states.py b/states.py index cf0d898..99fa320 100644 --- a/states.py +++ b/states.py @@ -4,6 +4,7 @@ from main import db, app, ma from shared import PA from user import PAUser from datetime import datetime +from job import SetFELog import pytz import re @@ -88,8 +89,10 @@ class States(PA): st='' pref=PA_UserState.query.filter(PA_UserState.pa_user_dn==current_user.dn,PA_UserState.path_type==self.path_type,PA_UserState.view_eid==self.view_eid,PA_UserState.orig_search_term==st).first() if not pref: - print( f"pref not found dn={current_user.dn}, st={st}, s={self}????" ) - self.url = pref.orig_url + SetFELog( message=f"ERROR: pref not found - DONT CLOSE THIS!!! dn={current_user.dn}, st={st}, s={self}????" , log_level="error", persistent=True, cant_close=True ) + redirect("/") + else: + self.url = pref.orig_url if 'files_ip' in self.url or 'file_list_ip' in self.url: if self.path_type == "View": @@ -123,8 +126,9 @@ class States(PA): self.path_type="View" self.orig_url=self.url elif 'change_file_opts' not in self.url: - print( f"ERROR: DDP messed up, failed to match URL {self.url} for settings this will fail, redirecting to home" ) - print( f"referrer={request.referrer}" ) + SetFELog( message=f"ERROR: DDP messed up, failed to match URL {self.url} for settings this will fail, redirecting to home" , log_level="error", persistent=True, cant_close=True ) + SetFELog( message=f"referrer={request.referrer}" , log_level="error", + persistent=True, cant_close=True ) return if self.path_type == 'View': @@ -132,8 +136,9 @@ class States(PA): # should find original path or search for this view (if not a search, search_term='') orig_pref=PA_UserState.query.filter(PA_UserState.pa_user_dn==current_user.dn,PA_UserState.path_type==self.orig_ptype,PA_UserState.orig_search_term==self.orig_search_term).first() if not orig_pref: - print( f"ERROR: DDP messed up 2, failed to find orig_pref for a view pt={self.path_type} for search={self.orig_search_term}" ) - print( f"referrer={request.referrer}" ) + SetFELog( message=f"ERROR: DDP messed up 2, failed to find orig_pref for a view pt={self.path_type} for search={self.orig_search_term}" , log_level="error", persistent=True, cant_close=True ) + SetFELog( message=f"referrer={request.referrer}" , log_level="error", + persistent=True, cant_close=True ) return elif self.path_type == 'Search': pref=PA_UserState.query.filter(PA_UserState.pa_user_dn==current_user.dn,PA_UserState.path_type==self.path_type,PA_UserState.orig_search_term==self.orig_search_term).first() @@ -250,8 +255,8 @@ class States(PA): self.offset += int(self.how_many) else: # should be impossible now, but leave jic - print( f"WARNING: next image requested, but would go past end of list? - ignore this" ) - print( f"DDP - offset={self.offset} + how_many={self.how_many} > num_entries={self.num_entries}" ) + SetFELog( message=f"WARNING: next image requested, but would go past end of list? - ignore this" , log_level="warning", persistent=True, cant_close=True ) + SetFELog( message=f"DDP - offset={self.offset} + how_many={self.how_many} > num_entries={self.num_entries}" , log_level="error", persistent=True, cant_close=True ) if 'current' in request.form: self.current = int(request.form['current'])