github.com/swiftstack/proxyfs@v0.0.0-20201223034610-5434d919416e/bin/autodoc (about)

     1  #!/usr/bin/env python
     2  # Copyright (c) 2015 SwiftStack, Inc.
     3  #
     4  # Licensed under the Apache License, Version 2.0 (the "License");
     5  # you may not use this file except in compliance with the License.
     6  # You may obtain a copy of the License at
     7  #
     8  #    http://www.apache.org/licenses/LICENSE-2.0
     9  #
    10  # Unless required by applicable law or agreed to in writing, software
    11  # distributed under the License is distributed on an "AS IS" BASIS,
    12  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
    13  # implied.
    14  # See the License for the specific language governing permissions and
    15  # limitations under the License.
    16  
    17  import argparse
    18  import os
    19  import Queue
    20  import sys
    21  import threading
    22  
    23  PROJECTS = {
    24      'swift': {
    25          'root': '/vagrant/swift/doc/',
    26          'dir': ['../swift', 'saio'],
    27          'container': 'doc',
    28      },
    29      'swiftclient': {
    30          'root': '/vagrant/python-swiftclient/doc/',
    31          'dir': [],
    32          'container': 'swiftclient',
    33      }
    34  }
    35  
    36  parser = argparse.ArgumentParser()
    37  parser.add_argument('-r', '--root', default=None,
    38                      help="the root of the doc tree")
    39  parser.add_argument('--dir', action='append', default=[],
    40                      help="extra dirs to append, if relative path, "
    41                      "it's relative to the root")
    42  parser.add_argument('--container', default=None,
    43                      help="the swift container into which the "
    44                      "compiled html will be uploaded")
    45  parser.add_argument('project', nargs='?', default='swift',
    46                      choices=PROJECTS.keys(),
    47                      help="use defaults for pre-configured projects")
    48  
    49  
    50  def iter_path_mtime(source_dir):
    51      for root, dirs, files in os.walk(source_dir):
    52          for filename in files:
    53              if filename.rsplit('.', 1)[-1] not in ('rst', 'py'):
    54                  continue
    55              full_path = os.path.join(root, filename)
    56              current_mtime = os.path.getmtime(full_path)
    57              yield full_path, current_mtime
    58  
    59  
    60  def watch_changed_files(q, *source_dirs):
    61      last_changed_time = {}
    62      while True:
    63          full_pass_has_changes = False
    64          for source_dir in source_dirs:
    65              for path, mtime in iter_path_mtime(source_dir):
    66                  if (path in last_changed_time and
    67                          last_changed_time[path] < mtime):
    68                      yield path
    69                      full_pass_has_changes = True
    70                      last_changed_time = {}
    71                  last_changed_time[path] = mtime
    72          if not full_pass_has_changes:
    73              # sleep for three seconds (or till user hits enter...)
    74              try:
    75                  q.get(timeout=1.0)
    76              except Queue.Empty:
    77                  pass
    78              else:
    79                  yield 'User says path...'
    80  
    81  
    82  def main():
    83      options = parser.parse_args()
    84      if options.root:
    85          root = options.root
    86          montior_paths = options.dir
    87          default_container = 'doc'
    88      else:
    89          root = PROJECTS[options.project]['root']
    90          montior_paths = PROJECTS[options.project]['dir'] + options.dir
    91          default_container = PROJECTS[options.project]['container']
    92  
    93      container = options.container or default_container
    94      source_dir = os.path.join(root, 'source')
    95      build_dir = os.path.join(root, 'build/html')
    96      extra_dirs = [os.path.join(root, path) for path in montior_paths]
    97  
    98      # intial build
    99      rv = os.system('sphinx-build -b html %s %s' % (source_dir, build_dir))
   100      if rv != 0:
   101          # bail on build fail
   102          return rv
   103      os.chdir(build_dir)
   104      os.system('swift post %s -r .r:*' % container)
   105      print 'uploading...'
   106      os.system('swift upload --changed %s . > /dev/null' % container)
   107      print 'done...'
   108      os.system('swift stat -v %s index.html | grep URL' % container)
   109      # we're gunna let the user hit enter to rebuild immediately
   110      q = Queue.Queue()
   111  
   112      def get_input():
   113          while True:
   114              q.put(raw_input())
   115      continue_thread = threading.Thread(target=get_input)
   116      continue_thread.daemon = True
   117      continue_thread.start()
   118      for filename in watch_changed_files(q, source_dir, *extra_dirs):
   119          print '%s has CHANGED!' % filename
   120          print 'rebuilding...'
   121          os.system('sphinx-build -q -b html %s %s' % (source_dir, build_dir))
   122          print 'uploading...'
   123          os.system('swift upload --changed %s . > /dev/null' % container)
   124          print 'done...'
   125          os.system('swift stat -v %s index.html | grep URL' % container)
   126  
   127  
   128  if __name__ == "__main__":
   129      try:
   130          sys.exit(main())
   131      except KeyboardInterrupt:
   132          print 'quit.'