2019-04-14 17:50:56 -07:00
# iterate source tree
# create directors in target tree
# for each item:
# run processor(s) on item, each processor could be in a chain or a branch
# Processors also provide filename munging
# output target based on processor output
import argparse
import logging
import os
2019-04-17 19:19:09 -07:00
import shutil
2019-04-14 17:50:56 -07:00
import sys
import time
from typing import Dict , List , cast
2021-04-28 23:09:35 -07:00
from .metadata import MetaTree
2019-04-14 17:50:56 -07:00
from .processchain import ProcessorChains
2019-04-17 19:19:09 -07:00
from .processors.processors import PassthroughException
2019-05-23 17:51:21 -07:00
from .pygments import pygments_get_css , pygments_markup_contents_html
2021-04-28 23:09:35 -07:00
from .template_tools import ( date_iso8601 , file_content , file_list ,
file_list_hier , file_metadata , file_name ,
file_raw , time_iso8601 )
2019-04-14 17:50:56 -07:00
logger = logging . getLogger ()
def setup_logging ( verbose : bool = False ) -> None :
pass
def get_args ( args : List [ str ]) -> argparse . Namespace :
parser = argparse . ArgumentParser ( "Compile a Pixywerk directory into an output directory." )
parser . add_argument ( "root" , help = "The root of the pixywerk directory to process." )
parser . add_argument ( "output" , help = "The output directory to export post-compiled files to." )
parser . add_argument (
"-c" , "--clean" , help = "Remove the target tree before proceeding (by renaming to .bak)." , action = "store_true"
)
parser . add_argument ( "-s" , "--safe" , help = "Abort if the target directory already exists." , action = "store_true" )
parser . add_argument ( "-t" , "--template" , help = "The template directory (default: root/templates)" , default = None )
parser . add_argument ( "-d" , "--dry-run" , help = "Perform a dry-run." , action = "store_true" )
parser . add_argument ( "-v" , "--verbose" , help = "Output verbosely." , action = "store_true" )
parser . add_argument ( "--processors" , help = "Specify a path to a processor configuration file." , default = None )
2019-05-26 19:39:11 -07:00
# parser.add_argument("--prescript", help="Specify one or more prescripts to run (in order specified) with context of the compile.", default=[], action="append")
# parser.add_argument("--postscript", help="Specify one or more postsscripts to run (in order specified) with context of the compile.", default=[], action="append")
2019-04-14 17:50:56 -07:00
result = parser . parse_args ( args )
# validate arguments
if not os . path . isdir ( result . root ):
raise FileNotFoundError ( "can't find root folder {} " . format ( result . root ))
if not result . template :
result . template = os . path . join ( result . root , "templates" )
result . excludes = [ result . template ]
return result
def main () -> int :
try :
args = get_args ( sys . argv [ 1 :])
except FileNotFoundError as ex :
print ( "error finding arguments: {} " . format ( ex ))
return 1
setup_logging ( args . verbose )
if os . path . exists ( args . output ) and args . clean :
bak = " {} .bak- {} " . format ( args . output , int ( time . time ()))
print ( "cleaning target {} -> {} " . format ( args . output , bak ))
os . rename ( args . output , bak )
process_chains = ProcessorChains ( args . processors )
default_metadata = {
"templates" : args . template ,
"template" : "default.jinja2" ,
"dir-template" : "default-dir.jinja2" ,
"filters" : {},
"build-time" : time . time (),
"uuid-oid-root" : "pixywerk" ,
2019-04-17 19:19:09 -07:00
"summary" : "" ,
"description" : "" ,
"author" : "" ,
2019-05-23 17:51:21 -07:00
"author_email" : "" ,
2019-04-14 17:50:56 -07:00
}
meta_tree = MetaTree ( args . root , default_metadata )
file_list_cache = cast ( Dict , {})
file_cont_cache = cast ( Dict , {})
file_name_cache = cast ( Dict , {})
2019-05-23 17:51:21 -07:00
file_raw_cache = cast ( Dict , {})
2021-04-28 23:09:35 -07:00
flist = file_list ( args . root , file_list_cache )
2019-04-14 17:50:56 -07:00
default_metadata [ "globals" ] = {
2021-04-28 23:09:35 -07:00
"get_file_list" : flist ,
"get_hier" : file_list_hier ( args . root , flist ),
2019-04-14 17:50:56 -07:00
"get_file_name" : file_name ( args . root , meta_tree , process_chains , file_name_cache ),
"get_file_content" : file_content ( args . root , meta_tree , process_chains , file_cont_cache ),
2019-05-23 17:51:21 -07:00
"get_raw" : file_raw ( args . root , file_raw_cache ),
2019-04-14 17:50:56 -07:00
"get_file_metadata" : file_metadata ( meta_tree ),
"get_time_iso8601" : time_iso8601 ( "UTC" ),
2019-05-26 19:39:11 -07:00
"get_date_iso8601" : date_iso8601 ( "UTC" ),
2019-05-23 17:51:21 -07:00
"pygments_get_css" : pygments_get_css ,
"pygments_markup_contents_html" : pygments_markup_contents_html ,
2019-04-14 17:50:56 -07:00
}
for root , _ , files in os . walk ( args . root ):
workroot = os . path . relpath ( root , args . root )
if workroot == "." :
workroot = ""
target_dir = os . path . join ( args . output , workroot )
print ( "mkdir -> {} " . format ( target_dir ))
if not args . dry_run :
try :
os . mkdir ( target_dir )
except FileExistsError :
if args . safe :
print ( "error, target directory exists, aborting" )
return 1
for f in files :
# fixme global generic filters
if f . endswith ( ".meta" ) or f . endswith ( "~" ):
continue
metadata = meta_tree . get_metadata ( os . path . join ( workroot , f ))
chain = process_chains . get_chain_for_filename ( os . path . join ( root , f ), ctx = metadata )
print ( "process {} -> {} " . format ( os . path . join ( root , f ), os . path . join ( target_dir , chain . output_filename )))
if not args . dry_run :
2019-04-17 19:19:09 -07:00
try :
with open ( os . path . join ( target_dir , chain . output_filename ), "w" ) as outfile :
for line in chain . output :
outfile . write ( line )
except PassthroughException :
shutil . copyfile ( os . path . join ( root , f ), os . path . join ( target_dir , chain . output_filename ))
2019-04-14 17:50:56 -07:00
return 0
if __name__ == "__main__" :
sys . exit ( main ())