https://github.com/annotation/text-fabric
Raw File
Tip revision: e251b1556be35387659f4535f9a71a439677a73b authored by Dirk Roorda on 09 July 2018, 08:23:00 UTC
better help display
Tip revision: e251b15
build.py
import sys
import os
import re

from time import sleep
from shutil import rmtree
from subprocess import run, Popen

import psutil

HELP = '''
python3 build.py command

command:

-h
--help
help  : print help and exit

docs  : serve docs locally
clean : clean local develop build
l     : local develop build
g     : push to github, code and docs
r     : build for shipping, leave version as is
r1    : build for shiping, version becomes r1+1.0.0
r2    : build for shiping, version becomes r1.r2+1.0
r3    : build for shiping, version becomes r1.r2.r3+1

For g and the r-commands you need to pass a commit message as well.
'''

DIST = 'dist'

VERSION_CONFIG = dict(
    setup=dict(
        file='setup.py',
        re=re.compile(
            r'''version\s*=\s*['"]([^'"]*)['"]'''
        ),
        mask="version='{}'",
    ),
    fabric=dict(
        file='tf/fabric.py',
        re=re.compile(
            r'''VERSION\s*=\s*['"]([^'"]*)['"]'''
        ),
        mask="VERSION = '{}'",
    ),
)

PACKAGE = 'text-fabric'
SCRIPT = '/Library/Frameworks/Python.framework/Versions/3.7/bin/text-fabric'

currentVersion = None
newVersion = None


def readArgs():
  args = sys.argv[1:]
  if not len(args) or args[0] in {'-h', '--help', 'help'}:
    print(HELP)
    return (False, None)
  arg = args[0]
  if arg not in {'docs', 'clean', 'l', 'g', 'r', 'r1', 'r2', 'r3'}:
    print(HELP)
    return (False, None)
  if arg in {'g', 'r', 'r1', 'r2', 'r3'}:
    if len(args) < 2:
      print('Provide a commit message')
      return (False, None)
    return (arg, args[1])
  return (arg, None)


def incVersion(version, task):
  comps = [int(c) for c in version.split('.')]
  (major, minor, update) = comps
  if task == 'r1':
    major += 1
    minor = 0
    update = 0
  elif task == 'r2':
    minor += 1
    update = 0
  elif task == 'r3':
    update += 1
  return '.'.join(str(c) for c in (major, minor, update))


def replaceVersion(task, mask):
  def subVersion(match):
    global currentVersion
    global newVersion
    currentVersion = match.group(1)
    newVersion = incVersion(currentVersion, task)
    return mask.format(newVersion)
  return subVersion


def adjustVersion(task):
    for (key, c) in VERSION_CONFIG.items():
      print(f'Adjusting version in {c["file"]}')
      with open(c['file']) as fh:
        text = fh.read()
      text = c['re'].sub(
          replaceVersion(task, c['mask']),
          text,
      )
      if key == 'setup':
        print(text[586:607])
      if key == 'fabric':
        print(text[516:534])
      with open(c['file'], 'w') as fh:
        fh.write(text)
    if currentVersion == newVersion:
      print(f'Rebuilding version {newVersion}')
    else:
      print(f'Replacing version {currentVersion} by {newVersion}')


def makeDist():
    distFile = "{}-{}".format(PACKAGE, newVersion)
    distFileCompressed = f'{distFile}.tar.gz'
    distPath = f'{DIST}/{distFileCompressed}'
    rmtree(DIST)
    os.makedirs(DIST, exist_ok=True)
    run(['python3', 'setup.py', 'sdist'])
    run(['twine', 'upload', distPath])


def commit(task, msg):
  run(['git', 'add', '--all', '.'])
  run(['git', 'commit', '-m', msg])
  run(['git', 'push', 'origin', 'master'])
  if task in {'r1', 'r2', 'r3'}:
    tagVersion = f'v{newVersion}'
    commitMessage = f'Release {newVersion}: {msg}'
    run(['git', 'tag', '-a', tagVersion, '-m', commitMessage])
    run(['git', 'push', 'origin', '--tags'])


def shipDocs():
  codestats()
  run(['mkdocs', 'gh-deploy'])


def serveDocs():
  codestats()
  killProcesses()
  proc = Popen(['mkdocs', 'serve'])
  sleep(3)
  run('open http://127.0.0.1:8000', shell=True)
  try:
    proc.wait()
  except KeyboardInterrupt:
    pass
  proc.terminate()


def killProcesses():
  myself = os.getpid()
  for proc in psutil.process_iter(attrs=['pid', 'name']):
    pid = proc.info['pid']
    if pid == myself:
      continue
    if filterProcess(proc):
      try:
        proc.terminate()
        print(f'mkdocs [{pid}] terminated')
      except psutil.NoSuchProcess:
        print(f'mkdocs [{pid}] already terminated')


def filterProcess(proc):
  procName = proc.info['name']
  commandName = '' if procName is None else procName.lower()
  found = False
  if commandName.endswith('python'):
    parts = proc.cmdline()
    if len(parts) >= 3:
      if parts[1].endswith('mkdocs') and parts[2] == 'serve':
        found = True
      if parts[1] == 'build.py' and parts[2] == 'docs':
        found = True
  return found


def codestats():
  xd = (
      '__pycache__,node_modules,.tmp,.git,_temp,'
      '.ipynb_checkpoints,images,fonts,favicons,compiled'
  )
  xdtf = xd + ',search,server,extra'
  rfFmt = 'docs/Code/Stats{}.md'
  cmdLine = (
      'cloc'
      ' --no-autogen'
      ' --exclude_dir={}'
      f' --exclude-list-file=cloc_exclude.lst'
      f' --report-file={rfFmt}'
      ' --md'
      ' {}'
  )
  run(cmdLine.format(xd, '', '.'), shell=True)
  run(cmdLine.format(xdtf, 'Base', 'tf'), shell=True)
  run(cmdLine.format(xd, 'Search', 'tf/search'), shell=True)
  run(cmdLine.format(xd, 'Server', 'tf/server'), shell=True)
  run(cmdLine.format(xd, 'Apps', 'tf/extra'), shell=True)


def main():
  (task, msg) = readArgs()
  if not task:
    return
  elif task == 'docs':
    serveDocs()
  elif task == 'clean':
    run(['python3', 'setup.py', 'develop', '-u'])
    os.unlink(SCRIPT)
  elif task == 'l':
    run(['python3', 'setup.py', 'develop'])
  elif task == 'g':
    shipDocs()
    commit(task, msg)
  elif task in {'r', 'r1', 'r2', 'r3'}:
    adjustVersion(task)
    shipDocs()
    makeDist()
    commit(task, msg)


main()
back to top