diff --git a/.bumpversion.cfg b/.bumpversion.cfg new file mode 100644 index 0000000..d552d54 --- /dev/null +++ b/.bumpversion.cfg @@ -0,0 +1,17 @@ +[bumpversion] +current_version = 0.1.0 +message = Bump version to {new_version} +commit = True +tag = True + +[bumpversion:file:setup.py] +search = version="{current_version}" +replace = version="{new_version}" + +[bumpversion:file:docsource/conf.py] +search = release = "{current_version}" +replace = release = "{new_version}" + +[bumpversion:file:src/compas_fab_pychoreo/__init__.py] +search = __version__ = "{current_version}" +replace = __version__ = "{new_version}" diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..014a4f0 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,25 @@ +# http://editorconfig.org + +root = true + +[*] +end_of_line = lf +trim_trailing_whitespace = true +insert_final_newline = true +indent_style = space +indent_size = 4 +charset = utf-8 + +[*.bat] +indent_style = tab +end_of_line = crlf + +[*.{md,diff,patch}] +trim_trailing_whitespace = false + +[Makefile] +indent_style = tab +indent_size = 4 + +[LICENSE] +insert_final_newline = false diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..fe4fb0c --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,29 @@ +--- +name: Bug report +about: Create a report to help us improve + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Steps to reproduce the behavior: +1. Context [e.g. ST3, Rhino, Blender, ...] +2. Sample script +3. Sample data +4. See error + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**Desktop (please complete the following information):** + - OS: [e.g. iOS] + - Python version [e.g. 2.7] + - Python package manager [e.g. macports, pip, conda] + +**Additional context** +Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..66047bf --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,22 @@ +--- +name: Feature request +about: Suggest an idea for this project + +--- +# Feature Request + +As a [role], I want [something] so that [benefit]. + +## Details + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ad64a34 --- /dev/null +++ b/.gitignore @@ -0,0 +1,116 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +env/ +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +*.egg-info/ +.installed.cfg +*.egg + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +.hypothesis/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# pyenv +.python-version + +# celery beat schedule file +celerybeat-schedule + +# SageMath parsed files +*.sage.py + +# dotenv +.env + +# virtualenv +.venv +venv/ +ENV/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ + +# ============================================================================== +# compas_fab_pychoreo +# ============================================================================== + +*.3dmbak +*.rhl +*.rui_bak + +temp/** +!temp/PLACEHOLDER + +.DS_Store + +.vscode diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..ac31a4e --- /dev/null +++ b/.travis.yml @@ -0,0 +1,15 @@ +language: python + +python: +- "2.7" +- "3.6" + +before_install: +- pip install --upgrade pip +- pip install Cython --install-option="--no-cython-compile" + +install: +- pip install --process-dependency-links --no-cache-dir -r requirements-dev.txt + +script: +- invoke test diff --git a/AUTHORS.md b/AUTHORS.md new file mode 100644 index 0000000..0ca9600 --- /dev/null +++ b/AUTHORS.md @@ -0,0 +1 @@ +# Authors diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..e69de29 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..1a68a76 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,57 @@ +# Contributing + +Contributions are welcome and very much appreciated! + +## Code contributions + +We accept code contributions through pull requests. +In short, this is how that works. + +1. Fork [the repository](https://github.com//compas_fab_pychoreo) and clone the fork. +2. Create a virtual environment using your tool of choice (e.g. `virtualenv`, `conda`, etc). +3. Install development dependencies: + + ```bash + pip install -r requirements-dev.txt + ``` + +4. Make sure all tests pass: + + ```bash + invoke test + ``` + +5. Start making your changes to the **master** branch (or branch off of it). +6. Make sure all tests still pass: + + ```bash + invoke test + ``` + +7. Add yourself to the *Contributors* section of `AUTHORS.md`. +8. Commit your changes and push your branch to GitHub. +9. Create a [pull request](https://help.github.com/articles/about-pull-requests/) through the GitHub website. + +During development, use [pyinvoke](http://docs.pyinvoke.org/) tasks on the +command line to ease recurring operations: + +* `invoke clean`: Clean all generated artifacts. +* `invoke check`: Run various code and documentation style checks. +* `invoke docs`: Generate documentation. +* `invoke test`: Run all tests and checks in one swift command. +* `invoke`: Show available tasks. + +## Bug reports + +When [reporting a bug](https://github.com//compas_fab_pychoreo/issues) please include: + +* Operating system name and version. +* Any details about your local setup that might be helpful in troubleshooting. +* Detailed steps to reproduce the bug. + +## Feature requests + +When [proposing a new feature](https://github.com//compas_fab_pychoreo/issues) please include: + +* Explain in detail how it would work. +* Keep the scope as narrow as possible, to make it easier to implement. diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..beec838 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Yijiang Huang + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..07ce359 --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,23 @@ +graft src + +prune .github + +prune data +prune docs +prune docsource +prune examples +prune temp +prune tests + +include LICENSE +include README.md +include AUTHORS.md +include CHANGELOG.md +include requirements.txt + +exclude requirements-dev.txt +exclude pytest.ini .bumpversion.cfg .editorconfig +exclude tasks.py +exclude CONTRIBUTING.md + +global-exclude *.py[cod] __pycache__ *.dylib *.nb[ic] .DS_Store \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..69e373c --- /dev/null +++ b/README.md @@ -0,0 +1,6 @@ +# compas_fab_pychoreo + +![](https://img.shields.io/badge/compas-16.0.1-blue) +![](https://img.shields.io/badge/compas__fab-0.11.0-ff69b4) + +an experimental package containing research prototpyes to integrate more planning functionalities to compas_fab diff --git a/data/PLACEHOLDER b/data/PLACEHOLDER new file mode 100644 index 0000000..b7a5709 --- /dev/null +++ b/data/PLACEHOLDER @@ -0,0 +1 @@ +# container for sample data files diff --git a/docs/PLACEHOLDER b/docs/PLACEHOLDER new file mode 100644 index 0000000..5d9de59 --- /dev/null +++ b/docs/PLACEHOLDER @@ -0,0 +1 @@ +# container for compiled documentation diff --git a/docsource/.nojekyll b/docsource/.nojekyll new file mode 100644 index 0000000..e69de29 diff --git a/docsource/PLACEHOLDER b/docsource/PLACEHOLDER new file mode 100644 index 0000000..f9768c1 --- /dev/null +++ b/docsource/PLACEHOLDER @@ -0,0 +1 @@ +# container for the source files of the documentation diff --git a/docsource/_images/PLACEHOLDER b/docsource/_images/PLACEHOLDER new file mode 100644 index 0000000..48f73eb --- /dev/null +++ b/docsource/_images/PLACEHOLDER @@ -0,0 +1 @@ +# container for images to be included in the docs diff --git a/docsource/_static/PLACEHOLDER b/docsource/_static/PLACEHOLDER new file mode 100644 index 0000000..f611256 --- /dev/null +++ b/docsource/_static/PLACEHOLDER @@ -0,0 +1 @@ +# container for static files, e.g. logo, banner images, javascript, stylesheets, ... diff --git a/docsource/_templates/PLACEHOLDER b/docsource/_templates/PLACEHOLDER new file mode 100644 index 0000000..27c4a9e --- /dev/null +++ b/docsource/_templates/PLACEHOLDER @@ -0,0 +1 @@ +# template files for Sphinx diff --git a/docsource/_templates/autosummary/base.rst b/docsource/_templates/autosummary/base.rst new file mode 100644 index 0000000..d7b3b9e --- /dev/null +++ b/docsource/_templates/autosummary/base.rst @@ -0,0 +1,8 @@ +.. rst-class:: detail + +{{ objname }} +{{ underline }} + +.. currentmodule:: {{ module }} + +.. auto{{ objtype }}:: {{ objname }} diff --git a/docsource/_templates/autosummary/class.rst b/docsource/_templates/autosummary/class.rst new file mode 100644 index 0000000..6a7bc18 --- /dev/null +++ b/docsource/_templates/autosummary/class.rst @@ -0,0 +1,60 @@ +.. rst-class:: detail + +{{ objname }} +{{ underline }} + +.. currentmodule:: {{ module }} + +.. autoclass:: {{ objname }} + + {% block attributes %} + {% if attributes %} + + .. rubric:: Attributes + + .. autosummary:: + {% for item in attributes %} + {%- if item not in inherited_members %} + ~{{ name }}.{{ item }} + {%- endif %} + {%- endfor %} + + .. rubric:: Inherited Attributes + + .. autosummary:: + {% for item in attributes %} + {%- if item in inherited_members %} + ~{{ name }}.{{ item }} + {%- endif %} + {%- endfor %} + + {% endif %} + {% endblock %} + + {% block methods %} + {% if methods %} + + .. rubric:: Methods + + .. autosummary:: + :toctree: + + {% for item in methods %} + {%- if item not in inherited_members %} + ~{{ name }}.{{ item }} + {%- endif %} + {%- endfor %} + + .. rubric:: Inherited Methods + + .. autosummary:: + :toctree: + + {% for item in methods %} + {%- if item in inherited_members %} + ~{{ name }}.{{ item }} + {%- endif %} + {%- endfor %} + + {% endif %} + {% endblock %} diff --git a/docsource/_templates/autosummary/method.rst b/docsource/_templates/autosummary/method.rst new file mode 100644 index 0000000..d7b3b9e --- /dev/null +++ b/docsource/_templates/autosummary/method.rst @@ -0,0 +1,8 @@ +.. rst-class:: detail + +{{ objname }} +{{ underline }} + +.. currentmodule:: {{ module }} + +.. auto{{ objtype }}:: {{ objname }} diff --git a/docsource/_templates/autosummary/module.rst b/docsource/_templates/autosummary/module.rst new file mode 100644 index 0000000..6ca6bbf --- /dev/null +++ b/docsource/_templates/autosummary/module.rst @@ -0,0 +1,39 @@ +.. rst-class:: detail + +{{ fullname }} +{{ underline }} + +.. automodule:: {{ fullname }} + + {% block functions %} + {% if functions %} + .. rubric:: Functions + + .. autosummary:: + {% for item in functions %} + {{ item }} + {%- endfor %} + {% endif %} + {% endblock %} + + {% block classes %} + {% if classes %} + .. rubric:: Classes + + .. autosummary:: + {% for item in classes %} + {{ item }} + {%- endfor %} + {% endif %} + {% endblock %} + + {% block exceptions %} + {% if exceptions %} + .. rubric:: Exceptions + + .. autosummary:: + {% for item in exceptions %} + {{ item }} + {%- endfor %} + {% endif %} + {% endblock %} diff --git a/docsource/api.rst b/docsource/api.rst new file mode 100644 index 0000000..de28444 --- /dev/null +++ b/docsource/api.rst @@ -0,0 +1,8 @@ +******************************************************************************** +API Reference +******************************************************************************** + +.. toctree:: + :maxdepth: 1 + + api/compas_fab_pychoreo diff --git a/docsource/api/compas_fab_pychoreo.rst b/docsource/api/compas_fab_pychoreo.rst new file mode 100644 index 0000000..5f6a517 --- /dev/null +++ b/docsource/api/compas_fab_pychoreo.rst @@ -0,0 +1,2 @@ + +.. automodule:: compas_fab_pychoreo diff --git a/docsource/conf.py b/docsource/conf.py new file mode 100644 index 0000000..6be298b --- /dev/null +++ b/docsource/conf.py @@ -0,0 +1,114 @@ +# -*- coding: utf-8 -*- + +# If your documentation needs a minimal Sphinx version, state it here. +# +# needs_sphinx = "1.0" + +import sys +import os + +import sphinx_compas_theme + + +# -- General configuration ------------------------------------------------ + +project = "compas_fab_pychoreo" +copyright = "Yijiang Huang" +author = "Yijiang Huang" +release = "0.1.0" +version = ".".join(release.split(".")[0:2]) + +master_doc = "index" +source_suffix = [".rst", ] +templates_path = ["_templates", ] +exclude_patterns = [] + +pygments_style = "sphinx" +show_authors = True +add_module_names = True +language = None + + +# -- Extension configuration ------------------------------------------------ + +extensions = [ + "sphinx.ext.autodoc", + "sphinx.ext.autosummary", + "sphinx.ext.doctest", + "sphinx.ext.intersphinx", + "sphinx.ext.mathjax", + "sphinx.ext.napoleon", + "matplotlib.sphinxext.plot_directive", +] + +# autodoc options + +autodoc_default_flags = [ + "undoc-members", + "show-inheritance", +] + +autodoc_member_order = "alphabetical" + +autoclass_content = "class" + +# autosummary options + +autosummary_generate = True + +# napoleon options + +napoleon_google_docstring = True +napoleon_numpy_docstring = True +napoleon_include_init_with_doc = False +napoleon_include_private_with_doc = False +napoleon_include_special_with_doc = True +napoleon_use_admonition_for_examples = False +napoleon_use_admonition_for_notes = False +napoleon_use_admonition_for_references = False +napoleon_use_ivar = False +napoleon_use_param = False +napoleon_use_rtype = False + +# plot options + +# plot_include_source +# plot_pre_code +# plot_basedir +# plot_formats +# plot_rcparams +# plot_apply_rcparams +# plot_working_directory +# plot_template + +plot_html_show_source_link = False +plot_html_show_formats = False + +# intersphinx options + +intersphinx_mapping = { + "python": ("https://docs.python.org/", None), + "compas": ("https://compas-dev.github.io/main", "https://compas-dev.github.io/main/objects.inv"), +} + + +# -- Options for HTML output ---------------------------------------------- + +html_theme = "compaspkg" +html_theme_path = sphinx_compas_theme.get_html_theme_path() + +html_theme_options = { + "package_name" : "compas_fab_pychoreo", + "package_title" : project, + "package_version" : release, +} + +html_context = {} +html_static_path = [] +html_extra_path = [".nojekyll"] +html_last_updated_fmt = "" +html_copy_source = False +html_show_sourcelink = False +html_add_permalinks = "" +html_experimental_html5_writer = True +html_compact_lists = True diff --git a/docsource/examples.rst b/docsource/examples.rst new file mode 100644 index 0000000..49e8715 --- /dev/null +++ b/docsource/examples.rst @@ -0,0 +1,10 @@ +******************************************************************************** +Examples +******************************************************************************** + +.. toctree:: + :maxdepth: 1 + :titlesonly: + :glob: + + examples/* diff --git a/docsource/gettingstarted.rst b/docsource/gettingstarted.rst new file mode 100644 index 0000000..ea1d20b --- /dev/null +++ b/docsource/gettingstarted.rst @@ -0,0 +1,3 @@ +******************************************************************************** +Getting Started +******************************************************************************** diff --git a/docsource/index.rst b/docsource/index.rst new file mode 100644 index 0000000..2297ff6 --- /dev/null +++ b/docsource/index.rst @@ -0,0 +1,13 @@ +******************************************************************************** +compas_fab_pychoreo +******************************************************************************** + +.. toctree:: + :maxdepth: 3 + :titlesonly: + + intro + gettingstarted + examples + api + license diff --git a/docsource/intro.rst b/docsource/intro.rst new file mode 100644 index 0000000..600075b --- /dev/null +++ b/docsource/intro.rst @@ -0,0 +1,3 @@ +******************************************************************************** +Introduction +******************************************************************************** diff --git a/docsource/license.rst b/docsource/license.rst new file mode 100644 index 0000000..e6a80ce --- /dev/null +++ b/docsource/license.rst @@ -0,0 +1,5 @@ +******************************************************************************** +License +******************************************************************************** + +.. literalinclude:: ../LICENSE diff --git a/examples/PLACEHOLDER b/examples/PLACEHOLDER new file mode 100644 index 0000000..e69de29 diff --git a/pytest.ini b/pytest.ini new file mode 100644 index 0000000..ba2d137 --- /dev/null +++ b/pytest.ini @@ -0,0 +1,3 @@ +[pytest] +testpaths = tests +doctest_optionflags= NORMALIZE_WHITESPACE IGNORE_EXCEPTION_DETAIL ALLOW_UNICODE ALLOW_BYTES diff --git a/requirements-dev.txt b/requirements-dev.txt new file mode 100644 index 0000000..90899ba --- /dev/null +++ b/requirements-dev.txt @@ -0,0 +1,18 @@ +autopep8 +attrs >=17.4 +bumpversion >=0.5 +check-manifest >=0.36 +doc8 +flake8 +invoke >=0.14 +ipykernel +ipython >=5.8 +isort +m2r +nbsphinx +pydocstyle +pytest >=3.2 +sphinx_compas_theme >=0.4 +sphinx >=1.6 +twine +-e . diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..09225f5 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,3 @@ + +COMPAS>=0.16.1 + diff --git a/scripts/PLACEHOLDER b/scripts/PLACEHOLDER new file mode 100644 index 0000000..e69de29 diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..95b125e --- /dev/null +++ b/setup.cfg @@ -0,0 +1,20 @@ +[bdist_wheel] +universal = 1 + +[tool:pytest] +testpaths = tests + +norecursedirs = + migrations + +python_files = + test_*.py + *_test.py + tests.py + +addopts = + -ra + --strict + --doctest-modules + --doctest-glob=\*.rst + --tb=short diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..ea63c33 --- /dev/null +++ b/setup.py @@ -0,0 +1,71 @@ +#!/usr/bin/env python +# -*- encoding: utf-8 -*- +# flake8: noqa +from __future__ import absolute_import +from __future__ import print_function + +import io +from os import path + +from setuptools import setup +from setuptools.command.develop import develop +from setuptools.command.install import install + + +here = path.abspath(path.dirname(__file__)) + + +def read(*names, **kwargs): + return io.open( + path.join(here, *names), + encoding=kwargs.get("encoding", "utf8") + ).read() + + +long_description = read("README.md") +requirements = read("requirements.txt").split("\n") +optional_requirements = {} + +setup( + name="compas_fab_pychoreo", + version="0.1.0", + description="an experimental package containing research prototpyes to integrate more planning functionalities to compas_fab", + long_description=long_description, + long_description_content_type="text/markdown", + url="", + author="Yijiang Huang", + author_email="yijiangh@mit.edu", + license="MIT license", + classifiers=[ + "Development Status :: 4 - Beta", + "Intended Audience :: Developers", + "Topic :: Scientific/Engineering", + "License :: OSI Approved :: MIT License", + "Operating System :: Unix", + "Operating System :: POSIX", + "Operating System :: Microsoft :: Windows", + "Programming Language :: Python", + "Programming Language :: Python :: 2.7", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.4", + "Programming Language :: Python :: 3.5", + "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: Implementation :: CPython", + ], + keywords=[], + project_urls={}, + packages=["compas_fab_pychoreo"], + package_dir={"": "src"}, + package_data={}, + data_files=[], + include_package_data=True, + zip_safe=False, + install_requires=requirements, + python_requires=">=2.7", + extras_require=optional_requirements, + entry_points={ + "console_scripts": [], + }, + ext_modules=[], +) diff --git a/src/compas_fab_pychoreo/__init__.py b/src/compas_fab_pychoreo/__init__.py new file mode 100644 index 0000000..744ce87 --- /dev/null +++ b/src/compas_fab_pychoreo/__init__.py @@ -0,0 +1,56 @@ +""" +******************************************************************************** +compas_fab_pychoreo +******************************************************************************** + +.. currentmodule:: compas_fab_pychoreo + + +.. toctree:: + :maxdepth: 1 + + +""" + +from __future__ import print_function + +import os +import sys + + +__author__ = ["Yijiang Huang"] +__copyright__ = "Yijiang Huang" +__license__ = "MIT License" +__email__ = "yijiangh@mit.edu" +__version__ = "0.1.0" + + +HERE = os.path.dirname(__file__) + +HOME = os.path.abspath(os.path.join(HERE, "../../")) +DATA = os.path.abspath(os.path.join(HOME, "data")) +DOCS = os.path.abspath(os.path.join(HOME, "docs")) +TEMP = os.path.abspath(os.path.join(HOME, "temp")) + +# Check if package is installed from git +# If that's the case, try to append the current head's hash to __version__ +try: + git_head_file = compas._os.absjoin(HOME, '.git', 'HEAD') + + if os.path.exists(git_head_file): + # git head file contains one line that looks like this: + # ref: refs/heads/master + with open(git_head_file, 'r') as git_head: + _, ref_path = git_head.read().strip().split(' ') + ref_path = ref_path.split('/') + + git_head_refs_file = compas._os.absjoin(HOME, '.git', *ref_path) + + if os.path.exists(git_head_refs_file): + with open(git_head_refs_file, 'r') as git_head_ref: + git_commit = git_head_ref.read().strip() + __version__ += '-' + git_commit[:8] +except Exception: + pass + +__all__ = ["HOME", "DATA", "DOCS", "TEMP"] diff --git a/tasks.py b/tasks.py new file mode 100644 index 0000000..767260f --- /dev/null +++ b/tasks.py @@ -0,0 +1,213 @@ +# -*- coding: utf-8 -*- +from __future__ import print_function + +import contextlib +import glob +import os +import sys +from shutil import rmtree + +from invoke import Exit +from invoke import task + +try: + input = raw_input +except NameError: + pass + + +BASE_FOLDER = os.path.dirname(__file__) + + +class Log(object): + def __init__(self, out=sys.stdout, err=sys.stderr): + self.out = out + self.err = err + + def flush(self): + self.out.flush() + self.err.flush() + + def write(self, message): + self.flush() + self.out.write(message + '\n') + self.out.flush() + + def info(self, message): + self.write('[INFO] %s' % message) + + def warn(self, message): + self.write('[WARN] %s' % message) + + +log = Log() + + +def confirm(question): + while True: + response = input(question).lower().strip() + + if not response or response in ('n', 'no'): + return False + + if response in ('y', 'yes'): + return True + + print('Focus, kid! It is either (y)es or (n)o', file=sys.stderr) + + +@task(default=True) +def help(ctx): + """Lists available tasks and usage.""" + ctx.run('invoke --list') + log.write('Use "invoke -h " to get detailed help for a task.') + + +@task(help={ + 'docs': 'True to clean up generated documentation, otherwise False', + 'bytecode': 'True to clean up compiled python files, otherwise False.', + 'builds': 'True to clean up build/packaging artifacts, otherwise False.'}) +def clean(ctx, docs=True, bytecode=True, builds=True): + """Cleans the local copy from compiled artifacts.""" + + with chdir(BASE_FOLDER): + if builds: + ctx.run('python setup.py clean') + + if bytecode: + for root, dirs, files in os.walk(BASE_FOLDER): + for f in files: + if f.endswith('.pyc'): + os.remove(os.path.join(root, f)) + if '.git' in dirs: + dirs.remove('.git') + + folders = [] + + if docs: + folders.append('docs/api/generated') + + folders.append('dist/') + + if bytecode: + for t in ('src', 'tests'): + folders.extend(glob.glob('{}/**/__pycache__'.format(t), recursive=True)) + + if builds: + folders.append('build/') + folders.append('src/compas_fab_pychoreo.egg-info/') + + for folder in folders: + rmtree(os.path.join(BASE_FOLDER, folder), ignore_errors=True) + + +@task(help={ + 'rebuild': 'True to clean all previously built docs before starting, otherwise False.', + 'doctest': 'True to run doctests, otherwise False.', + 'check_links': 'True to check all web links in docs for validity, otherwise False.'}) +def docs(ctx, doctest=False, rebuild=True, check_links=False): + """Builds package's HTML documentation.""" + + if rebuild: + clean(ctx) + + with chdir(BASE_FOLDER): + if doctest: + ctx.run('sphinx-build -E -b doctest docsource docs') + + ctx.run('sphinx-build -E -b html docsource docs') + + if check_links: + ctx.run('sphinx-build -E -b linkcheck docsource docs') + + +@task() +def check(ctx): + """Check the consistency of documentation, coding style and a few other things.""" + + with chdir(BASE_FOLDER): + log.write('Checking MANIFEST.in...') + ctx.run('check-manifest --ignore-bad-ideas=test.so,fd.so,smoothing.so,drx_c.so') + + log.write('Checking metadata...') + ctx.run('python setup.py check --strict --metadata') + + log.write('Running flake8 python linter...') + ctx.run('flake8 --count --statistics src tests') + + # log.write('Checking python imports...') + # ctx.run('isort --check-only --diff --recursive src tests setup.py') + + +@task(help={ + 'checks': 'True to run all checks before testing, otherwise False.'}) +def test(ctx, checks=False, doctest=False): + """Run all tests.""" + if checks: + check(ctx) + + with chdir(BASE_FOLDER): + cmd = ['pytest'] + if doctest: + cmd.append('--doctest-modules') + + ctx.run(' '.join(cmd)) + + +@task +def prepare_changelog(ctx): + """Prepare changelog for next release.""" + UNRELEASED_CHANGELOG_TEMPLATE = '## Unreleased\n\n### Added\n\n### Changed\n\n### Removed\n\n\n## ' + + with chdir(BASE_FOLDER): + # Preparing changelog for next release + with open('CHANGELOG.md', 'r+') as changelog: + content = changelog.read() + changelog.seek(0) + changelog.write(content.replace( + '## ', UNRELEASED_CHANGELOG_TEMPLATE, 1)) + + ctx.run('git add CHANGELOG.md && git commit -m "Prepare changelog for next release"') + + + +@task(help={ + 'release_type': 'Type of release follows semver rules. Must be one of: major, minor, patch.'}) +def release(ctx, release_type): + """Releases the project in one swift command!""" + if release_type not in ('patch', 'minor', 'major'): + raise Exit('The release type parameter is invalid.\nMust be one of: major, minor, patch') + + # Run checks + ctx.run('invoke check test') + + # Bump version and git tag it + ctx.run('bumpversion %s --verbose' % release_type) + + # Build project + ctx.run('python setup.py clean --all sdist bdist_wheel') + + # Upload to pypi + if confirm('You are about to upload the release to pypi.org. Are you sure? [y/N]'): + files = ['dist/*.whl', 'dist/*.gz', 'dist/*.zip'] + dist_files = ' '.join([pattern for f in files for pattern in glob.glob(f)]) + + if len(dist_files): + ctx.run('twine upload --skip-existing %s' % dist_files) + + prepare_changelog(ctx) + else: + raise Exit('No files found to release') + else: + raise Exit('Aborted release') + + +@contextlib.contextmanager +def chdir(dirname=None): + current_dir = os.getcwd() + try: + if dirname is not None: + os.chdir(dirname) + yield + finally: + os.chdir(current_dir) diff --git a/temp/PLACEHOLDER b/temp/PLACEHOLDER new file mode 100644 index 0000000..0a0022e --- /dev/null +++ b/temp/PLACEHOLDER @@ -0,0 +1,2 @@ +# container for temorary files +# these will be ignored by the version control system diff --git a/tests/PLACEHOLDER b/tests/PLACEHOLDER new file mode 100644 index 0000000..68ae651 --- /dev/null +++ b/tests/PLACEHOLDER @@ -0,0 +1 @@ +# container for unit tests