55
66from time import sleep
77from shutil import rmtree
8- from subprocess import run , Popen
8+ from subprocess import run , call , Popen , PIPE
99
10- import psutil
10+ import errno
11+ import time
12+ import unicodedata
1113
1214from tf .core .helpers import console
1315
2830 ),
2931)
3032
33+ URL = "https://annotation.github.io/text-fabric/"
3134AN_BASE = os .path .expanduser ("~/github/annotation" )
3235TUT_BASE = f"{ AN_BASE } /tutorials"
3336TF_BASE = f"{ AN_BASE } /text-fabric"
3639PACKAGE = "text-fabric"
3740SCRIPT = "/Library/Frameworks/Python.framework/Versions/3.7/bin/text-fabric"
3841
42+ SRC = "site"
43+ REMOTE = "origin"
44+ BRANCH = "gh-pages"
45+
3946currentVersion = None
4047newVersion = None
4148
5966--help
6067help : print help and exit
6168
62- adocs : serve apidocs locally
63- bdocs : build apidocs
6469docs : serve docs locally
70+ pdocs : build docs
71+ sdocs : ship docs
6572clean : clean local develop build
6673l : local develop build
6774i : local non-develop build
@@ -93,9 +100,9 @@ def readArgs():
93100 if arg not in {
94101 "a" ,
95102 "t" ,
96- "adocs" ,
97- "bdocs" ,
98103 "docs" ,
104+ "pdocs" ,
105+ "sdocs" ,
99106 "clean" ,
100107 "l" ,
101108 "lp" ,
@@ -226,28 +233,181 @@ def commitTut(msg):
226233 os .chdir (f"{ TF_BASE } " )
227234
228235
229- def shipDocs ():
230- codestats ()
231- apidocs ()
232- run (["mkdocs" , "gh-deploy" ])
233-
234-
235- def serveApidocs ():
236- # proc = Popen(["pdoc3", "--http", ":", "tf"])
237- proc = Popen (
238- [
239- "pdoc3" ,
240- "--force" ,
241- "--html" ,
242- "--output-dir" ,
243- "docs" ,
244- "--template-dir" ,
245- "docs/templates" ,
246- "--http" ,
247- ":" ,
248- "tf" ,
249- ]
250- )
236+ if sys .version_info [0 ] == 3 :
237+
238+ def enc (text ):
239+ if isinstance (text , bytes ):
240+ return text
241+ return text .encode ()
242+
243+ def dec (text ):
244+ if isinstance (text , bytes ):
245+ return text .decode ("utf-8" )
246+ return text
247+
248+ def write (pipe , data ):
249+ try :
250+ pipe .stdin .write (data )
251+ except OSError as e :
252+ if e .errno != errno .EPIPE :
253+ raise
254+
255+
256+ else :
257+
258+ def enc (text ):
259+ if isinstance (text , unicode ): # noqa: F821
260+ return text .encode ("utf-8" )
261+ return text
262+
263+ def dec (text ):
264+ if isinstance (text , unicode ): # noqa: F821
265+ return text
266+ return text .decode ("utf-8" )
267+
268+ def write (pipe , data ):
269+ pipe .stdin .write (data )
270+
271+
272+ # COPIED FROM MKDOCS AND MODIFIED
273+
274+
275+ def normalize_path (path ):
276+ # Fix unicode pathnames on OS X
277+ # See: https://stackoverflow.com/a/5582439/44289
278+ if sys .platform == "darwin" :
279+ return unicodedata .normalize ("NFKC" , dec (path ))
280+ return path
281+
282+
283+ def try_rebase (remote , branch ):
284+ cmd = ["git" , "rev-list" , "--max-count=1" , "{}/{}" .format (remote , branch )]
285+ p = Popen (cmd , stdin = PIPE , stdout = PIPE , stderr = PIPE )
286+ (rev , _ ) = p .communicate ()
287+ if p .wait () != 0 :
288+ return True
289+ cmd = ["git" , "update-ref" , "refs/heads/%s" % branch , dec (rev .strip ())]
290+ if call (cmd ) != 0 :
291+ return False
292+ return True
293+
294+
295+ def get_config (key ):
296+ p = Popen (["git" , "config" , key ], stdin = PIPE , stdout = PIPE )
297+ (value , _ ) = p .communicate ()
298+ return value .decode ("utf-8" ).strip ()
299+
300+
301+ def get_prev_commit (branch ):
302+ cmd = ["git" , "rev-list" , "--max-count=1" , branch , "--" ]
303+ p = Popen (cmd , stdin = PIPE , stdout = PIPE , stderr = PIPE )
304+ (rev , _ ) = p .communicate ()
305+ if p .wait () != 0 :
306+ return None
307+ return rev .decode ("utf-8" ).strip ()
308+
309+
310+ def mk_when (timestamp = None ):
311+ if timestamp is None :
312+ timestamp = int (time .time ())
313+ currtz = "%+05d" % (- 1 * time .timezone / 36 ) # / 3600 * 100
314+ return "{} {}" .format (timestamp , currtz )
315+
316+
317+ def start_commit (pipe , branch , message ):
318+ uname = dec (get_config ("user.name" ))
319+ email = dec (get_config ("user.email" ))
320+ write (pipe , enc ("commit refs/heads/%s\n " % branch ))
321+ write (pipe , enc ("committer {} <{}> {}\n " .format (uname , email , mk_when ())))
322+ write (pipe , enc ("data %d\n %s\n " % (len (message ), message )))
323+ head = get_prev_commit (branch )
324+ if head :
325+ write (pipe , enc ("from %s\n " % head ))
326+ write (pipe , enc ("deleteall\n " ))
327+
328+
329+ def add_file (pipe , srcpath , tgtpath ):
330+ with open (srcpath , "rb" ) as handle :
331+ if os .access (srcpath , os .X_OK ):
332+ write (pipe , enc ("M 100755 inline %s\n " % tgtpath ))
333+ else :
334+ write (pipe , enc ("M 100644 inline %s\n " % tgtpath ))
335+ data = handle .read ()
336+ write (pipe , enc ("data %d\n " % len (data )))
337+ write (pipe , enc (data ))
338+ write (pipe , enc ("\n " ))
339+
340+
341+ def add_nojekyll (pipe ):
342+ write (pipe , enc ("M 100644 inline .nojekyll\n " ))
343+ write (pipe , enc ("data 0\n " ))
344+ write (pipe , enc ("\n " ))
345+
346+
347+ def gitpath (fname ):
348+ norm = os .path .normpath (fname )
349+ return "/" .join (norm .split (os .path .sep ))
350+
351+
352+ def ghp_import ():
353+ if not try_rebase (REMOTE , BRANCH ):
354+ print ("Failed to rebase %s branch." , BRANCH )
355+
356+ cmd = ["git" , "fast-import" , "--date-format=raw" , "--quiet" ]
357+ kwargs = {"stdin" : PIPE }
358+ if sys .version_info >= (3 , 2 , 0 ):
359+ kwargs ["universal_newlines" ] = False
360+ pipe = Popen (cmd , ** kwargs )
361+ start_commit (pipe , BRANCH , "docs update" )
362+ for path , _ , fnames in os .walk (SRC ):
363+ for fn in fnames :
364+ fpath = os .path .join (path , fn )
365+ fpath = normalize_path (fpath )
366+ gpath = gitpath (os .path .relpath (fpath , start = SRC ))
367+ add_file (pipe , fpath , gpath )
368+ add_nojekyll (pipe )
369+ write (pipe , enc ("\n " ))
370+ pipe .stdin .close ()
371+ if pipe .wait () != 0 :
372+ sys .stdout .write (enc ("Failed to process commit.\n " ))
373+
374+ cmd = ["git" , "push" , REMOTE , BRANCH ]
375+ proc = Popen (cmd , stdout = PIPE , stderr = PIPE )
376+ (out , err ) = proc .communicate ()
377+ result = proc .wait () == 0
378+
379+ return result , dec (err )
380+
381+
382+ def gh_deploy ():
383+ (result , error ) = ghp_import ()
384+ if not result :
385+ print ("Failed to deploy to GitHub with error: \n %s" , error )
386+ raise SystemExit (1 )
387+ else :
388+ print ("Your documentation should shortly be available at: " + URL )
389+
390+
391+ # END COPIED FROM MKDOCS AND MODIFIED
392+
393+
394+ PDOC3 = [
395+ "pdoc3" ,
396+ "--force" ,
397+ "--html" ,
398+ "--output-dir" ,
399+ "site" ,
400+ "--template-dir" ,
401+ "docs/templates" ,
402+ ]
403+ PDOC3STR = " " .join (PDOC3 )
404+
405+
406+ def pdoc3serve ():
407+ """Build the docs into site and serve them.
408+ """
409+
410+ proc = Popen ([* PDOC3 , "--http" , ":" , "tf" ])
251411 sleep (1 )
252412 run ("open http://localhost:8080/tf" , shell = True )
253413 try :
@@ -257,52 +417,13 @@ def serveApidocs():
257417 proc .terminate ()
258418
259419
260- def serveDocs ():
261- codestats ()
262- apidocs ()
263- killProcesses ()
264- proc = Popen (["mkdocs" , "serve" ])
265- sleep (3 )
266- run ("open http://127.0.0.1:8000" , shell = True )
267- try :
268- proc .wait ()
269- except KeyboardInterrupt :
270- pass
271- proc .terminate ()
272-
420+ def pdoc3 ():
421+ """Build the docs into site.
422+ """
273423
274- def killProcesses ():
275- myself = os .getpid ()
276- for proc in psutil .process_iter (attrs = ["pid" , "name" ]):
277- pid = proc .info ["pid" ]
278- if pid == myself :
279- continue
280- if filterProcess (proc ):
281- try :
282- proc .terminate ()
283- console (f"mkdocs [{ pid } ] terminated" )
284- except psutil .NoSuchProcess :
285- console (f"mkdocs [{ pid } ] already terminated" )
286-
287-
288- def filterProcess (proc ):
289- procName = proc .info ["name" ]
290- commandName = "" if procName is None else procName .lower ()
291- found = False
292- if commandName .endswith ("python" ):
293- parts = proc .cmdline ()
294- if len (parts ) >= 3 :
295- if parts [1 ].endswith ("mkdocs" ) and parts [2 ] == "serve" :
296- found = True
297- if parts [1 ] == "build.py" and parts [2 ] == "docs" :
298- found = True
299- return found
300-
301-
302- def apidocs ():
303424 cmdLines = [
304425 "rm -rf site" ,
305- "pdoc3 --force --html --output-dir site --template-dir docs/templates tf" ,
426+ f" { PDOC3STR } tf" ,
306427 "mv site/tf/* site" ,
307428 "rmdir site/tf" ,
308429 "cp -r docs/images site" ,
@@ -313,35 +434,12 @@ def apidocs():
313434 run (cmdLine , shell = True )
314435
315436
316- def codestats ():
317- xd = (
318- ".pytest_cache,__pycache__,node_modules,.tmp,.git,_temp,"
319- ".ipynb_checkpoints,images,fonts,favicons,compiled"
320- )
321- xdtf = xd + ",applib,convert,compose,core,search,server,writing"
322- xdtest = xd + ",tf"
323- rfFmt = "docs/Code/Stats{}.md"
324- cmdLine = (
325- "cloc"
326- " --no-autogen"
327- " --exclude_dir={}"
328- " --exclude-list-file={}"
329- f" --report-file={ rfFmt } "
330- " --md"
331- " {}"
332- )
333- nex = "cloc_exclude.lst"
334- run (cmdLine .format (xd , nex , "" , ". ../app-*/code" ), shell = True )
335- run (cmdLine .format (xdtf , nex , "Toplevel" , "tf" ), shell = True )
336- run (cmdLine .format (xd , nex , "Applib" , "tf/applib" ), shell = True )
337- run (cmdLine .format (xd , nex , "Apps" , "../app-*/code" ), shell = True )
338- run (cmdLine .format (xd , nex , "Compose" , "tf/compose" ), shell = True )
339- run (cmdLine .format (xd , nex , "Convert" , "tf/convert" ), shell = True )
340- run (cmdLine .format (xd , nex , "Core" , "tf/core" ), shell = True )
341- run (cmdLine .format (xd , nex , "Search" , "tf/search" ), shell = True )
342- run (cmdLine .format (xd , nex , "Server" , "tf/server" ), shell = True )
343- run (cmdLine .format (xd , nex , "Writing" , "tf/writing" ), shell = True )
344- run (cmdLine .format (xdtest , nex , "Test" , "test/generic" ), shell = True )
437+ def shipDocs ():
438+ """Build the docs into site and ship them.
439+ """
440+
441+ pdoc3 ()
442+ gh_deploy ()
345443
346444
347445def tfbrowse (dataset , remaining ):
@@ -390,12 +488,12 @@ def main():
390488 tfbrowse (msg , remaining )
391489 elif task == "t" :
392490 tftest (msg , remaining )
393- elif task == "adocs" :
394- serveApidocs ()
395- elif task == "bdocs" :
396- apidocs ()
397491 elif task == "docs" :
398- serveDocs ()
492+ pdoc3serve ()
493+ elif task == "pdocs" :
494+ pdoc3 ()
495+ elif task == "sdocs" :
496+ shipDocs ()
399497 elif task == "clean" :
400498 clean ()
401499 elif task == "l" :
0 commit comments