diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 3bdba91..5fb5a8b 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -9,7 +9,7 @@ jobs: name: Unit tests strategy: matrix: - python-version: ['3.10'] + python-version: ['3.10', '3.12'] os: [macos-latest, ubuntu-latest, windows-latest] runs-on: ${{ matrix.os }} @@ -37,7 +37,7 @@ jobs: - name: set up Python uses: actions/setup-python@v2 with: - python-version: 3.7 + python-version: '3.12' - name: set up node # we need node for for semantic release uses: actions/setup-node@v4 with: @@ -71,7 +71,7 @@ jobs: - name: set up Python uses: actions/setup-python@v2 with: - python-version: 3.7 + python-version: '3.12' - name: install dependencies run: | pip install -U . diff --git a/README.md b/README.md index 9e7296c..cfd4915 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,9 @@ Provides methods for translating ladybug-geometry objects to VTK PolyData. ## Installation + +To install the library use: + ```console pip install ladybug-vtk ``` diff --git a/dev-requirements.txt b/dev-requirements.txt index 6b46c19..14bb4b6 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -1,13 +1,10 @@ -pytest==6.2.4 -Sphinx==5.3.0 -docutils==0.17 +pytest==8.3.2 +Sphinx==8.0.2 sphinx-bootstrap-theme==0.8.1 sphinxcontrib-fulltoc==1.2.0 -sphinxcontrib-websupport==1.2.4 -sphinx-click==4.4.0 -twine==3.4.1 -wheel==0.38.1 -setuptools==65.5.1 -importlib-metadata==4.8.0 -jinja2==3.0.3 -markupsafe==2.0.1 +sphinxcontrib-websupport==2.0.0 +sphinx-click==6.0.0 +twine==5.1.1 +wheel==0.44.0 +setuptools==75.1.0 +importlib-metadata==8.5.0 diff --git a/docs/_static/custom.css b/docs/_static/custom.css index 5e15300..8929223 100644 --- a/docs/_static/custom.css +++ b/docs/_static/custom.css @@ -5,44 +5,61 @@ * Sphinx stylesheet -- Bootstrap theme. */ +/* Overwrite colors */ +div.navbar-inverse { + background-color: #EB2227; + border-color: #EB2227; +} +a { + color: #EB2227; +} +a:visited { + color: #Bf0408; +} +code { + color: #Bf0408; +} +div.bs-sidenav a { + color: #333333; +} -/* The code below is based on the bootstrap website sidebar */ +/* Prevent top nav from blocking docs */ +div.navbar-fixed-top { + position: absolute; +} +/* Indent the side nav when in mobile mode */ +@media screen and (min-width: 0px) { + div.bs-sidenav ul { + margin-bottom: 0; + padding-left: 5px; + list-style: none; + } +} -/* Show and affix the side nav when space allows it */ +/* Widen and de-indent the side nav when space is restricted */ @media screen and (min-width: 992px) { .bs-sidenav .nav > .active > ul { display: block; } div.bs-sidenav ul { margin-bottom: 0; - padding-left: 5px; + padding-left: 0px; list-style: none; } - div.bs-sidenav a { - color: #333333; - } - /* Widen the fixed sidenav */ - .bs-sidenav.affix, - .bs-sidenav.affix-bottom { - width: 292px; - } - .bs-sidenav.affix { - position: fixed; /* Undo the static from mobile first approach */ - } - .bs-sidenav.affix-bottom { - position: absolute; /* Undo the static from mobile first approach */ - } - .bs-sidenav.affix-bottom .bs-sidenav, - .bs-sidenav.affix .bs-sidenav { - margin-top: 0; - margin-bottom: 0; + .bs-sidenav { + width: 300px; } } + +/* Slightly indent the side nav when space allows it */ @media screen and (min-width: 1200px) { - /* Widen the fixed sidenav again */ - .bs-sidenav.affix-bottom, - .bs-sidenav.affix { - width: 360px; + div.bs-sidenav ul { + margin-bottom: 0; + padding-left: 5px; + list-style: none; + } + .bs-sidenav { + width: 370px; } } diff --git a/docs/conf.py b/docs/conf.py index ed3cc6e..a9ad209 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -2,7 +2,7 @@ # # Configuration file for the Sphinx documentation builder. # -# This file only contains a selection of the most common options. For a +# This file does only contain a selection of the most common options. For a # full list see the documentation: # http://www.sphinx-doc.org/en/master/config @@ -12,18 +12,20 @@ # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. # -import sphinx_bootstrap_theme +from datetime import datetime import os -import sys import re -import datetime -now = datetime.datetime.now() +import sys + +# The theme to use for HTML and HTML Help pages +import sphinx_bootstrap_theme + sys.path.insert(0, os.path.abspath('../')) # -- Project information ----------------------------------------------------- -project = 'ladybug-vtk' -copyright = '{}, Ladybug Tools'.format(str(now.year)) +project = 'ladybug vtk' +copyright = '{}, Ladybug Tools'.format(datetime.today().year) author = 'Ladybug Tools' # The full version, including alpha/beta/rc tags @@ -72,7 +74,7 @@ # # This is also used if you do content translation via gettext catalogs. # Usually you set "language" from the command line for these cases. -language = None +language = 'en' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. @@ -82,13 +84,11 @@ # The name of the Pygments (syntax highlighting) style to use. pygments_style = None +# hide the class names in the nav bar +toc_object_entries_show_parents = 'hide' # -- Options for HTML output ------------------------------------------------- -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. -# - # html_theme = 'alabaster' html_theme = 'bootstrap' html_theme_path = sphinx_bootstrap_theme.get_html_theme_path() @@ -112,6 +112,7 @@ # Bootstrap theme custom file paths (relative to this file) # Layout.html path (already added above, include if different) # templates_path = ['_templates'] +# Stylesheet path # on_rtd is whether we are on readthedocs.org # on_rtd = os.environ.get('READTHEDOCS', None) == 'True' @@ -124,7 +125,8 @@ # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -# html_static_path = ['_static'] +html_static_path = ['_static'] +html_css_files = ['custom.css'] # Custom sidebar templates, must be a dictionary that maps document names # to template names. @@ -142,7 +144,7 @@ # -- Options for HTMLHelp output --------------------------------------------- # Output file base name for HTML help builder. -htmlhelp_basename = 'ladybuggeodoc' +htmlhelp_basename = 'lbvtkdoc' # -- Options for LaTeX output ------------------------------------------------ @@ -169,7 +171,7 @@ # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ - (master_doc, 'ladybug-vtk.tex', 'ladybug-vtk Documentation', + (master_doc, 'ladybug vtk.tex', 'ladybug vtk Documentation', 'Ladybug Tools', 'manual'), ] @@ -179,7 +181,7 @@ # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ - (master_doc, 'ladybug-vtk', 'ladybug-vtk Documentation', + (master_doc, 'ladybug vtk', 'ladybug vtk Documentation', [author], 1) ] @@ -190,8 +192,8 @@ # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ - (master_doc, 'ladybug-vtk', 'ladybug-vtk Documentation', - author, 'ladybug-vtk', 'One line description of project.', + (master_doc, 'ladybug vtk', 'ladybug vtk Documentation', + author, 'ladybug vtk', 'One line description of project.', 'Miscellaneous'), ] @@ -228,7 +230,6 @@ autodoc_member_order = 'groupwise' - # -- CLI documentation ------------------------------------------------------- """Improves the CLI documentation section. @@ -240,7 +241,7 @@ """ # Activate this CLI documentation process. custom_cli_docs = True -# Override existing reSt files found in docs\cli folder. +# Override existing reSt files found in docs//cli folder. cli_overwrite = False # Repository/library hash table. @@ -363,12 +364,10 @@ def get_cli_data(project_folder): print("[CLI data]: Cannot find library path") return None - cli_path = lib_path - if not os.path.isfile(os.path.join(lib_path, "cli.py")): - cli_path = os.path.join(lib_path, 'cli') - if not os.path.isdir(cli_path): - print("[CLI data]: No CLI library found") - return None + cli_path = os.path.join(lib_path, 'cli') + if not os.path.isdir(cli_path): + print("[CLI data]: No CLI library found") + return None # Get CLI module names and their corresponding group names as a dictionary. ht_mod_group = get_cli_groups(cli_path) @@ -392,11 +391,8 @@ def get_cli_groups(cli_path): A dictionary with module file names and the corresponding group names found. """ - if os.path.split(cli_path)[1] == 'cli': - module_names = [os.path.splitext(file)[0] for file in os.listdir(cli_path) - if os.path.splitext(file)[1] == ".py"] - else: - module_names = ['cli'] + module_names = [os.path.splitext(file)[0] for file in os.listdir(cli_path) + if os.path.splitext(file)[1] == ".py"] # Look for group function names inside their CLI module. Assume (1) group # and (1) function per module. Assumme possible multiple groups and @@ -411,18 +407,19 @@ def get_cli_groups(cli_path): fnd = re.findall(r'^@click\.group\(.*\n(@click.*\n){0,2}def\s(\w*)\s*\(\):\n', text, flags=re.MULTILINE) # Add multiple commands found in each group inside '__init__.py' - if name == "__init__" or name == "cli": + if name == "__init__": init_text = text for result in fnd: - options, cli_comm = result + tr, cli_comm = result comm_exp = r'^@' + cli_comm + r'.command\(\'([\w-]+)' im = re.findall(comm_exp, text, flags=re.MULTILINE) - if im or 'version_option' in options: + if im: # add sub-group key with list of commands to the # 'main' group dict. key - if name not in ht_groups: - ht_groups[name] = {} - ht_groups[name][cli_comm] = list(im) + if 'main' not in ht_groups: + ht_groups['main'] = {} + ht_groups['main'][cli_comm] = list(im) + else: # Store module function name and initial command name in hash table. if fnd: @@ -438,7 +435,7 @@ def get_cli_groups(cli_path): cli_func, tr, cli_comm = group for file in ht_groups: # 'main' groups are excluded, assumes not used in CLI. - if file not in ["__init__", "cli"] and ht_groups[file][0] == cli_func: + if file != 'main' and ht_groups[file][0] == cli_func: ht_groups[file][1] = cli_comm return ht_groups @@ -466,37 +463,32 @@ def write_cli_files(ht_cli_data, lib_name, tool_name, doc_folder): # Write sphinx-click directive with options for each CLI group. for file in group_filenames: - if file != "__init__" and file != "cli": + cli_content = ["{}\n".format(file), + "{}\n".format("=" * len(file))] + if file != "main": # one command(with all its subcommands) per cli module. - cli_content = ["{}\n".format(file), - "{}\n".format("=" * len(file)), - "\n", - ".. click:: {}.cli.{}:{}\n".format( - lib_name, file, ht_cli_data[file][0]), - " :prog: {} {}\n".format( - tool_name, ht_cli_data[file][1]), - " :show-nested:\n"] - group_file = file + cli_content += ["\n", + ".. click:: {}.cli.{}:{}\n".format( + lib_name, file, ht_cli_data[file][0]), + " :prog: {} {}\n".format( + tool_name, ht_cli_data[file][1]), + " :show-nested:\n"] else: - # multiple commands in the 'main' group (explicitly named to + # multiple commands in the 'main' group (implicitly named to # avoid commands from other modules to be included). Also specify - # commands as root commands. - main_file = 'cli' if file == "cli" else 'cli.__init__' - cli_content = ["main\n", - "====\n"] + # commands as a root command. for group in ht_cli_data[file].keys(): cli_content += ["\n", - ".. click:: {}.{}:{}\n". - format(lib_name, main_file, group), + ".. click:: {}.cli.{}:{}\n". + format(lib_name, "__init__", group), " :prog: {}\n".format(tool_name), " :show-nested:\n", " :commands: " + " ,". join(ht_cli_data[file][group]) + "\n" ] - group_file = 'main' # Create CLI group reST file. - with open(os.path.join(doc_folder, group_file + ".rst"), 'w') as group_file: + with open(os.path.join(doc_folder, file + ".rst"), 'w') as group_file: group_file.writelines(cli_content) return 1 @@ -533,12 +525,10 @@ def update_cli_index(index_path, group_filenames): "\n" ] - # replace root filenames with 'main' and place at top of list - main_file = list(set(group_filenames).intersection(["__init__", "cli"]))[0] - if main_file: - group_filenames.remove(main_file) - group_filenames.insert(0, 'main') # Add sub-command groups to content. + if "main" in group_filenames: + group_filenames.remove('main') + group_filenames.insert(0, 'main') for file in group_filenames: cli_content.append(" {}\n".format(file)) @@ -575,7 +565,7 @@ def update_doc_index(proj_folder, lib_name): return 1 print("[CLI doc\\index]: Updating index.rst file...") - # Add CLI Docs section + # Add CLi Docs section cli_text = "\n" + \ "CLI Docs\n" + \ "========\n" + \ @@ -591,15 +581,15 @@ def update_doc_index(proj_folder, lib_name): "\n" # Find insert location, add text and save - lib_exp = r'^' + lib_name + r' *\n=+\n|^\.\. toctree:: *\n' + lib_exp = r'^' + lib_name + ' *\n=+\n' m = re.search(lib_exp, text, flags=re.MULTILINE) if m: text_updated = text[:m.start()-1] + cli_text + text[m.start():] with open(os.path.join(proj_folder, "index.rst"), 'w') as index_file: text = index_file.write(text_updated) else: - print( - "[CLI doc\\index]: index.rst update not possible - content format cannot be recognized.") + print("[CLI doc\\index]: index.rst update not possible - content \ + format cannot be recognized.") return -1 return 1 @@ -610,13 +600,3 @@ def update_doc_index(proj_folder, lib_name): create_cli_files() # ----------------------------------------------------------------------------- - - -def setup(app): - """Run custom code with access to the Sphinx application object - Args: - app: the Sphinx application object - """ - - # Add bootstrap theme custom stylesheet - app.add_css_file("custom.css")