Loading .readthedocs.yml +18 −0 Original line number Diff line number Diff line # .readthedocs.yml # Read the Docs configuration file # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details # Required version: 2 # Build documentation in the docs/ directory with Sphinx sphinx: configuration: docs/src/conf.py # Build documentation with MkDocs #mkdocs: # configuration: mkdocs.yml # Optionally build your docs in additional formats such as PDF and ePub # formats: all conda: file: docs/src/environment.yml docs/src/conf.py +1 −271 Original line number Diff line number Diff line Loading @@ -19,16 +19,7 @@ import sys sys.path.append(os.path.abspath('../../csp-lmc-common/')) sys.path.append(os.path.abspath('../../csp-lmc-mid/')) sys.path.append(os.path.abspath('./')) # Import tango try: import tango except ImportError: from mock_tango_extension import tango from tango import Release print("Building documentation for PyTango {0}".format(Release.version_long)) print("Using PyTango from: {0}".format(os.path.dirname(tango.__file__))) #import skabase autodoc_mock_imports = ['PyTango','run', 'DeviceMeta', 'command', 'future', 'future.utils', 'logging', 'logging.handlers', 'ska', Loading Loading @@ -226,264 +217,3 @@ intersphinx_mapping = {'https://docs.python.org/': None} # If true, `todo` and `todoList` produce output, else they produce nothing. todo_include_todos = True def copy_spaces(origin): r = '' for x in range(len(origin)): if origin[x] in (' ', '\t'): r += origin[x] else: return r return r def type_to_link(tipus): if tipus[:9] == 'sequence<' and tipus[-1:] == '>': return 'sequence<' + type_to_link(tipus[9:-1]) + '>' #elif tipus in dir(PyTango): else: return ':class:`' + tipus + "`" #else: # return tipus def type_to_pytango_link(tipus): if tipus[:9] == 'sequence<' and tipus[-1:] == '>': return 'sequence<' + type_to_link(tipus[9:-1]) + '>' elif tipus in dir(tango): return ':class:`' + tipus + "`" else: return tipus def possible_type_to_link(text): if len(text) and text[0] == '(' and text[-1] == ')': return '(' + type_to_link(text[1:-1]) +')' return text def parse_typed_line(line): spacesSplit = line.strip().split(' ') first = spacesSplit[0].strip() return possible_type_to_link(first) + ' ' + ' '.join(spacesSplit[1:]) def parse_parameters(line): spaces = copy_spaces(line) miniLine = line.strip() if miniLine[:2] != '- ': return line spl = miniLine[2:].split(':', 1) assert(len(spl) == 2) return spaces + ':' + spl[0].strip() + ': ' + parse_typed_line(spl[1]) def parse_bullet_with_type(line): spaces = copy_spaces(line) miniLine = line.strip() if miniLine[:2] not in ['- ', '* ']: return line spl = miniLine.split(':', 1) if len(spl) != 2: return line return spaces + spl[0] + ': ' + parse_typed_line(spl[1]) def parse_throws(line): words = re.split('(\W+)', line) assert(line == ''.join(words)) return ''.join(map(type_to_pytango_link, words)) # http://codedump.tumblr.com/post/94712647/handling-python-docstring-indentation def docstring_to_lines(docstring): if not docstring: return [] lines = docstring.expandtabs().splitlines() # Determine minimum indentation (first line doesn't count): indent = sys.maxint for line in lines[1:]: stripped = line.lstrip() if stripped: indent = min(indent, len(line) - len(stripped)) # Remove indentation (first line is special): trimmed = [lines[0].strip()] if indent < sys.maxint: for line in lines[1:]: trimmed.append(line[indent:].rstrip()) # Strip off trailing and leading blank lines: while trimmed and not trimmed[-1]: trimmed.pop() while trimmed and not trimmed[0]: trimmed.pop(0) return trimmed def search_ONLY_signature(name, text): lines = docstring_to_lines(text) # There should be ONE signature and must be the FIRST text # Signature is the ONLY starting at position 0 signatureLine = None for ln in range(len(lines)): line = lines[ln] if len(line.strip()) and line[0] != ' ': parentesis = line.split('(', 1) fname = parentesis[0].strip() if len(parentesis)==2 and fname == name.rsplit('.',1)[1]: if signatureLine is not None: # More than one signature! return None signatureLine = ln else: return None # There's a text as FIRST text that's NOT the signature! if signatureLine is None: return None return lines[signatureLine] def split_signature(text): if text is None: return None # split "fname(params)", "returntype" ops = text.split('->') if len(ops) != 2: return None # get rid of "fname" params = ops[0].strip() ret_type = ops[1].strip() p = params.find('(') if p < 0: return None params = params[p:] return params, ret_type _with_only_one_signature_methods = {} def __reformat_lines(app, what, name, obj, options, lines): global _with_only_one_signature_methods if what != 'method': for ln in range(len(lines)): lines[ln] = parse_bullet_with_type(lines[ln]) return toinsert = [] parsingParameters = False parsingThrows = False toinsert.append((0, "")) for ln in range(len(lines)): line = lines[ln] if len(line) and line[0] != ' ': if name in _with_only_one_signature_methods: # This method has one and only one signature. So it will # be displayed by sphinx, there's no need for us to fake # it here... lines[ln] = "" else: parentesis = line.split('(', 1) fname = parentesis[0].strip() if len(parentesis)==2 and fname == name.rsplit('.',1)[1]: sg = split_signature(line) if sg is not None: # Main lines are like small titles (**bold**): lines[ln] = '**' + fname +'** *' + sg[0] + '* **->** ' + type_to_link(sg[1]) # Add an ENTER after the title, to make a different # paragraph. So if I have 2 signatures, there's no problem # with it... toinsert.append((ln+1, "")) ## Main lines are like small titles (**bold**): #lines[ln]='**' + line.strip() + '**' ## Add an ENTER after the title, to make a different ## paragraph. So if I have 2 signatures, there's no problem ## with it... #toinsert.append((ln+1, "")) # Mark the "New in this version" lines... if line.strip()[:14] == "New in PyTango": lines[ln] = copy_spaces(lines[ln]) + "*" + line.strip() + "*" parsingParameters = False parsingThrows = False # Look for special control_words # To replace the actual syntax: "Return : something" # with the one understood by reStructuredText ":Return: something" spl = line.strip().split(':', 1) control_word = spl[0].strip() if ((len(spl) != 2) or (control_word not in ["Parameters", "Return", "Throws", "Example", "See Also" ]) ): if parsingParameters: lines[ln] = parse_parameters(line) elif parsingThrows: lines[ln] = parse_throws(line) continue parsingParameters = False parsingThrows = False spaces = copy_spaces(line) # The Example control word is even more special. I will put # the contents from the following line into a code tag (::) if control_word == 'Example': lines[ln] = spaces + ":" + control_word + ": " + spl[1] toinsert.append((ln+1, "")) toinsert.append((ln+1, spaces + ' ::')) toinsert.append((ln+1, "")) elif control_word == 'Parameters': lines[ln] = spaces + ":Parameters:" + parse_parameters(spl[1]) parsingParameters = True elif control_word == 'Return': lines[ln] = spaces + ":Return: " + parse_typed_line(spl[1]) elif control_word == "Throws": lines[ln] = spaces + ":Throws:" + parse_throws(spl[1]) parsingThrows = True else: lines[ln] = spaces + ":" + control_word + ": " + spl[1] for x in range(len(toinsert)-1, -1, -1): pos, txt = toinsert[x] lines.insert(pos, txt) def __process_signature(app, what, name, obj, options, signature, return_annotation): global _with_only_one_signature_methods if what != 'method': return sg = split_signature(search_ONLY_signature(name, obj.__doc__)) if sg is not None: _with_only_one_signature_methods[name] = True return sg return (signature, return_annotation) def setup(app): # sphinx will call these methods when he finds an object to document. # I want to edit the docstring to adapt its format to something more # beautiful. # I also want to edit the signature because boost methods have no # signature. I will read the signature from the docstring. # The order sphinx will call it is __process_signature, __reformat_lines. # And it is important because I keep some information between the two # processes # Problem is __process_signature works great with python methods... # but is not even called for methods defined by boost. So, as it is, # is useless now. #app.connect('autodoc-process-signature', __process_signature) app.connect('autodoc-process-docstring', __reformat_lines) docs/src/environment.yml +1 −0 Original line number Diff line number Diff line Loading @@ -8,3 +8,4 @@ dependencies: - pillow - sphinx - sphinx_rtd_theme - pytango No newline at end of file Loading
.readthedocs.yml +18 −0 Original line number Diff line number Diff line # .readthedocs.yml # Read the Docs configuration file # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details # Required version: 2 # Build documentation in the docs/ directory with Sphinx sphinx: configuration: docs/src/conf.py # Build documentation with MkDocs #mkdocs: # configuration: mkdocs.yml # Optionally build your docs in additional formats such as PDF and ePub # formats: all conda: file: docs/src/environment.yml
docs/src/conf.py +1 −271 Original line number Diff line number Diff line Loading @@ -19,16 +19,7 @@ import sys sys.path.append(os.path.abspath('../../csp-lmc-common/')) sys.path.append(os.path.abspath('../../csp-lmc-mid/')) sys.path.append(os.path.abspath('./')) # Import tango try: import tango except ImportError: from mock_tango_extension import tango from tango import Release print("Building documentation for PyTango {0}".format(Release.version_long)) print("Using PyTango from: {0}".format(os.path.dirname(tango.__file__))) #import skabase autodoc_mock_imports = ['PyTango','run', 'DeviceMeta', 'command', 'future', 'future.utils', 'logging', 'logging.handlers', 'ska', Loading Loading @@ -226,264 +217,3 @@ intersphinx_mapping = {'https://docs.python.org/': None} # If true, `todo` and `todoList` produce output, else they produce nothing. todo_include_todos = True def copy_spaces(origin): r = '' for x in range(len(origin)): if origin[x] in (' ', '\t'): r += origin[x] else: return r return r def type_to_link(tipus): if tipus[:9] == 'sequence<' and tipus[-1:] == '>': return 'sequence<' + type_to_link(tipus[9:-1]) + '>' #elif tipus in dir(PyTango): else: return ':class:`' + tipus + "`" #else: # return tipus def type_to_pytango_link(tipus): if tipus[:9] == 'sequence<' and tipus[-1:] == '>': return 'sequence<' + type_to_link(tipus[9:-1]) + '>' elif tipus in dir(tango): return ':class:`' + tipus + "`" else: return tipus def possible_type_to_link(text): if len(text) and text[0] == '(' and text[-1] == ')': return '(' + type_to_link(text[1:-1]) +')' return text def parse_typed_line(line): spacesSplit = line.strip().split(' ') first = spacesSplit[0].strip() return possible_type_to_link(first) + ' ' + ' '.join(spacesSplit[1:]) def parse_parameters(line): spaces = copy_spaces(line) miniLine = line.strip() if miniLine[:2] != '- ': return line spl = miniLine[2:].split(':', 1) assert(len(spl) == 2) return spaces + ':' + spl[0].strip() + ': ' + parse_typed_line(spl[1]) def parse_bullet_with_type(line): spaces = copy_spaces(line) miniLine = line.strip() if miniLine[:2] not in ['- ', '* ']: return line spl = miniLine.split(':', 1) if len(spl) != 2: return line return spaces + spl[0] + ': ' + parse_typed_line(spl[1]) def parse_throws(line): words = re.split('(\W+)', line) assert(line == ''.join(words)) return ''.join(map(type_to_pytango_link, words)) # http://codedump.tumblr.com/post/94712647/handling-python-docstring-indentation def docstring_to_lines(docstring): if not docstring: return [] lines = docstring.expandtabs().splitlines() # Determine minimum indentation (first line doesn't count): indent = sys.maxint for line in lines[1:]: stripped = line.lstrip() if stripped: indent = min(indent, len(line) - len(stripped)) # Remove indentation (first line is special): trimmed = [lines[0].strip()] if indent < sys.maxint: for line in lines[1:]: trimmed.append(line[indent:].rstrip()) # Strip off trailing and leading blank lines: while trimmed and not trimmed[-1]: trimmed.pop() while trimmed and not trimmed[0]: trimmed.pop(0) return trimmed def search_ONLY_signature(name, text): lines = docstring_to_lines(text) # There should be ONE signature and must be the FIRST text # Signature is the ONLY starting at position 0 signatureLine = None for ln in range(len(lines)): line = lines[ln] if len(line.strip()) and line[0] != ' ': parentesis = line.split('(', 1) fname = parentesis[0].strip() if len(parentesis)==2 and fname == name.rsplit('.',1)[1]: if signatureLine is not None: # More than one signature! return None signatureLine = ln else: return None # There's a text as FIRST text that's NOT the signature! if signatureLine is None: return None return lines[signatureLine] def split_signature(text): if text is None: return None # split "fname(params)", "returntype" ops = text.split('->') if len(ops) != 2: return None # get rid of "fname" params = ops[0].strip() ret_type = ops[1].strip() p = params.find('(') if p < 0: return None params = params[p:] return params, ret_type _with_only_one_signature_methods = {} def __reformat_lines(app, what, name, obj, options, lines): global _with_only_one_signature_methods if what != 'method': for ln in range(len(lines)): lines[ln] = parse_bullet_with_type(lines[ln]) return toinsert = [] parsingParameters = False parsingThrows = False toinsert.append((0, "")) for ln in range(len(lines)): line = lines[ln] if len(line) and line[0] != ' ': if name in _with_only_one_signature_methods: # This method has one and only one signature. So it will # be displayed by sphinx, there's no need for us to fake # it here... lines[ln] = "" else: parentesis = line.split('(', 1) fname = parentesis[0].strip() if len(parentesis)==2 and fname == name.rsplit('.',1)[1]: sg = split_signature(line) if sg is not None: # Main lines are like small titles (**bold**): lines[ln] = '**' + fname +'** *' + sg[0] + '* **->** ' + type_to_link(sg[1]) # Add an ENTER after the title, to make a different # paragraph. So if I have 2 signatures, there's no problem # with it... toinsert.append((ln+1, "")) ## Main lines are like small titles (**bold**): #lines[ln]='**' + line.strip() + '**' ## Add an ENTER after the title, to make a different ## paragraph. So if I have 2 signatures, there's no problem ## with it... #toinsert.append((ln+1, "")) # Mark the "New in this version" lines... if line.strip()[:14] == "New in PyTango": lines[ln] = copy_spaces(lines[ln]) + "*" + line.strip() + "*" parsingParameters = False parsingThrows = False # Look for special control_words # To replace the actual syntax: "Return : something" # with the one understood by reStructuredText ":Return: something" spl = line.strip().split(':', 1) control_word = spl[0].strip() if ((len(spl) != 2) or (control_word not in ["Parameters", "Return", "Throws", "Example", "See Also" ]) ): if parsingParameters: lines[ln] = parse_parameters(line) elif parsingThrows: lines[ln] = parse_throws(line) continue parsingParameters = False parsingThrows = False spaces = copy_spaces(line) # The Example control word is even more special. I will put # the contents from the following line into a code tag (::) if control_word == 'Example': lines[ln] = spaces + ":" + control_word + ": " + spl[1] toinsert.append((ln+1, "")) toinsert.append((ln+1, spaces + ' ::')) toinsert.append((ln+1, "")) elif control_word == 'Parameters': lines[ln] = spaces + ":Parameters:" + parse_parameters(spl[1]) parsingParameters = True elif control_word == 'Return': lines[ln] = spaces + ":Return: " + parse_typed_line(spl[1]) elif control_word == "Throws": lines[ln] = spaces + ":Throws:" + parse_throws(spl[1]) parsingThrows = True else: lines[ln] = spaces + ":" + control_word + ": " + spl[1] for x in range(len(toinsert)-1, -1, -1): pos, txt = toinsert[x] lines.insert(pos, txt) def __process_signature(app, what, name, obj, options, signature, return_annotation): global _with_only_one_signature_methods if what != 'method': return sg = split_signature(search_ONLY_signature(name, obj.__doc__)) if sg is not None: _with_only_one_signature_methods[name] = True return sg return (signature, return_annotation) def setup(app): # sphinx will call these methods when he finds an object to document. # I want to edit the docstring to adapt its format to something more # beautiful. # I also want to edit the signature because boost methods have no # signature. I will read the signature from the docstring. # The order sphinx will call it is __process_signature, __reformat_lines. # And it is important because I keep some information between the two # processes # Problem is __process_signature works great with python methods... # but is not even called for methods defined by boost. So, as it is, # is useless now. #app.connect('autodoc-process-signature', __process_signature) app.connect('autodoc-process-docstring', __reformat_lines)
docs/src/environment.yml +1 −0 Original line number Diff line number Diff line Loading @@ -8,3 +8,4 @@ dependencies: - pillow - sphinx - sphinx_rtd_theme - pytango No newline at end of file