Assignment QaQc

#-- Install pypdf2 using the command below
#-- pip install pypdf2
import sys, os, datetime, math, PyPDF2, clipboard

#-- Adjust Parameters as needed
#--
deadline = datetime.datetime( 2021, 2, 1, 20, 0, 0 ) # YY-MM-DD HH-MM-SS
students = 2 #per group

#-- Requirements
#--
pagesize = 10
filesize = 50 * 1024 * 1024 #bytes
imagedpi = 300
pagewdth = 420 #mm
pagehght = 297 #mm

#-- Usage: python checkpdf.py "1001234.pdf"
#--
if( len( sys.argv ) != 2 ):
    print( 'Assignment file is required' )
    sys.exit( 1 )
path = sys.argv[1]
name = os.path.basename( path )

if( not path.lower( ).endswith( '.pdf' ) ):
    print( 'PDF file is required' )
    sys.exit( 2 )

check = lambda state: "\033[92m[Pass]\033[0m" if state else "\033[91m[Fail]\033[0m"

#-- File Size/Date
#--
stat = os.stat( path )
date = datetime.datetime.fromtimestamp( stat.st_mtime )
size = stat.st_size
print( f"File Size: {size:,} bytes {check( size <= filesize )}" )
print( f"Last Mod Date: {date} {check( date <= deadline )}" )

#-- File Name
#--
pos = 0
ids = []
for student in range( students ):
    pos = name.find( "100", pos )
    if( pos >= 0 ):
        id = name[pos:pos+7]
        if( not id.isnumeric( ) ):
            id = "#" * 7
        ids.append( id )
        pos = pos + 7

for id in ids:
    print( f"Student Id Detected: {id} {check( id.isnumeric( ) )}" )
print( f"Student Ids in Filename: {check( len( ids ) == students )}" )

#-- File Contents
#--
img_count = 0
img_allow = 0
pages = []
with open( path, 'rb' ) as stream:
    pdf = PyPDF2.PdfFileReader( stream )
    print( "Pages:" )
    for index in range( pdf.getNumPages( ) ):
        #-- Page Size and Format
        #--
        page = pdf.getPage( index )
        bbox = page.mediaBox
        dx = int( float( bbox[2] ) * 3.0 / 8.5 )
        dy = int( float( bbox[3] ) * 3.0 / 8.5 )
        ok = ( abs( dx - pagewdth ) < 1 and abs( dy - pagehght ) < 1 )
        pages.append( 1 if ok else 0 )
        print( f"   Page: {index+1} -> Dimensions {dx} x {dy}mm {check( ok )}" )

        #-- Image Resolution
        #--
        images = { }
        if( not ( "/Resources" in page ) ):
            print( "Bogus PDF" )
            os._exit( 1 )
        resources  = page["/Resources"]
        if( not ( "/XObject" in resources ) ):
            continue
        objs = resources["/XObject"]
        for key in objs: #-- Collect Images
            obj = objs[key]
            if( obj["/Subtype"] == "/Image" ):
                images[key] = obj
                img_count += 1
        try: #-- Extract PDF Contents
            contents = page.getContents( )
            if( isinstance( contents, list ) ):
                collect = ""
                for content in contents:
                    collect += content.getObject( ).getData( ).decode( "utf-8", "ignore" )
                contents = collect
            else:
                contents = contents.getData( ).decode( "utf-8", "ignore" )
        except: #-- Failure
            print( page.getContents( ), sys.exc_info( ) )
            os._exit( -1 )
        for image in images: #-- Detect Image Layout
            brk = contents.find( f"{image} Do" )
            if( brk < 0 ): continue
            spn = contents.rfind( "\n", 0, brk - 1 )
            if( spn < 0 ): continue
            try:
                tokens = contents[spn:brk] #; print( layout )
                layout = tokens.replace( "cm", "" )
                matrix = [abs( float( x ) ) for x in layout.strip( ).split( )]
                sx = matrix[0]; dx = images[image]["/Width"]
                sy = matrix[3]; dy = images[image]["/Height"]
                if( sx == 0 or sy == 0 ): #-- Rotation?
                    sx = matrix[1]; sy = matrix[2]
                rx = ( dx * 25.4 ) / ( sx * 3.0 / 8.5 ) #-- Resolution
                ry = ( dy * 25.4 ) / ( sy * 3.0 / 8.5 )
                if( min( rx, ry ) > ( imagedpi - 5 ) ):
                    img_allow += 1
                print( f"        {image}: {dx} x {dy} px -> dpi: {rx:.0f} x {ry:.0f} {check( min( rx, ry ) > ( imagedpi - 5 ) )}" )
            except:
                print( tokens, sys.exc_info( ) )
                os._exit( -2 )
            #break
print( f"Pages Count: {len( pages )}, required {pagesize} {check( len( pages ) == pagesize )}" )
print( f"A3 Lanscape: {sum( pages )} of {len( pages )} {check( len( pages ) == sum( pages ) )}" )
print( f"Resolutions: {img_allow} of {img_count} {check( img_allow == img_count )}" )