diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 0000000..1763353 --- /dev/null +++ b/.devcontainer/Dockerfile @@ -0,0 +1,21 @@ +# See here for image contents: https://github.com/microsoft/vscode-dev-containers/tree/v0.202.3/containers/python-3/.devcontainer/base.Dockerfile + +# [Choice] Python version (use -bullseye variants on local arm64/Apple Silicon): 3, 3.9, 3.8, 3.7, 3.6, 3-bullseye, 3.9-bullseye, 3.8-bullseye, 3.7-bullseye, 3.6-bullseye, 3-buster, 3.9-buster, 3.8-buster, 3.7-buster, 3.6-buster +ARG VARIANT="3.9-bullseye" +FROM mcr.microsoft.com/vscode/devcontainers/python:0-${VARIANT} + +# [Choice] Node.js version: none, lts/*, 16, 14, 12, 10 +ARG NODE_VERSION="none" +RUN if [ "${NODE_VERSION}" != "none" ]; then su vscode -c "umask 0002 && . /usr/local/share/nvm/nvm.sh && nvm install ${NODE_VERSION} 2>&1"; fi + +# [Optional] If your pip requirements rarely change, uncomment this section to add them to the image. +# COPY requirements.txt /tmp/pip-tmp/ +# RUN pip3 --disable-pip-version-check --no-cache-dir install -r /tmp/pip-tmp/requirements.txt \ +# && rm -rf /tmp/pip-tmp + +# [Optional] Uncomment this section to install additional OS packages. +# RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ +# && apt-get -y install --no-install-recommends + +# [Optional] Uncomment this line to install global node packages. +# RUN su vscode -c "source /usr/local/share/nvm/nvm.sh && npm install -g " 2>&1 diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..0a7f8dd --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,47 @@ +// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at: +// https://github.com/microsoft/vscode-dev-containers/tree/v0.202.3/containers/python-3 +{ + "name": "Python 3", + "runArgs": [ + "--init" + ], + "build": { + "dockerfile": "Dockerfile", + "context": "..", + "args": { + // Update 'VARIANT' to pick a Python version: 3, 3.9, 3.8, 3.7, 3.6. + // Append -bullseye or -buster to pin to an OS version. + // Use -bullseye variants on local on arm64/Apple Silicon. + "VARIANT": "3.7", + // Options + "NODE_VERSION": "lts/*" + } + }, + // Set *default* container specific settings.json values on container create. + "settings": { + "python.pythonPath": "/usr/local/bin/python", + "python.languageServer": "Pylance", + "python.formatting.autopep8Path": "/usr/local/py-utils/bin/autopep8", + "python.formatting.blackPath": "/usr/local/py-utils/bin/black", + "python.formatting.yapfPath": "/usr/local/py-utils/bin/yapf", + "python.linting.banditPath": "/usr/local/py-utils/bin/bandit", + "python.linting.flake8Path": "/usr/local/py-utils/bin/flake8", + "python.linting.mypyPath": "/usr/local/py-utils/bin/mypy", + "python.linting.pycodestylePath": "/usr/local/py-utils/bin/pycodestyle", + "python.linting.pydocstylePath": "/usr/local/py-utils/bin/pydocstyle", + "python.linting.pylintPath": "/usr/local/py-utils/bin/pylint", + }, + // Add the IDs of extensions you want installed when the container is created. + "extensions": [ + "ms-python.python", + "ms-python.vscode-pylance" + ], + // Use 'forwardPorts' to make a list of ports inside the container available locally. + "forwardPorts": [ + 8888 + ], + // Use 'postCreateCommand' to run commands after the container is created. + "postCreateCommand": "pip3 install --user -r requirements_dev.txt; pip install -e .[runtime]; npm i pyright", + // Comment out connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root. + "remoteUser": "vscode" +} diff --git a/.editorconfig b/.editorconfig new file mode 100755 index 0000000..4d34dcc --- /dev/null +++ b/.editorconfig @@ -0,0 +1,11 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true + +[*.py] +indent_style = space +indent_size = 2 diff --git a/.github/workflows/e2etests.yml b/.github/workflows/e2etests.yml index 2b645e4..ba1fa87 100644 --- a/.github/workflows/e2etests.yml +++ b/.github/workflows/e2etests.yml @@ -15,4 +15,3 @@ jobs: JUPYTER_PORT: 8899 - name: Run e2e tests run: docker-compose -f docker/docker-build.yml exec -e PYTHONPATH="." -w /usr/local/src/picatrix -T picatrix /home/picatrix/picenv/bin/python /usr/local/src/picatrix/end_to_end_tests/tools/run_in_container.py - diff --git a/.github/workflows/unittest-pipenv.yml b/.github/workflows/pre-commit.yml similarity index 53% rename from .github/workflows/unittest-pipenv.yml rename to .github/workflows/pre-commit.yml index c492c6c..0f0801a 100644 --- a/.github/workflows/unittest-pipenv.yml +++ b/.github/workflows/pre-commit.yml @@ -1,11 +1,12 @@ -name: unittests +name: pre-commit -on: - pull_request: - types: [opened, synchronize, reopened] +on: [push, pull_request] +env: + LANG: "C.UTF-8" + LC_ALL: "C.UTF-8" jobs: - unittests: + pre-commit: runs-on: ubuntu-20.04 strategy: matrix: @@ -15,14 +16,14 @@ jobs: steps: - uses: actions/checkout@v2 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v1 + uses: actions/setup-python@v2 with: python-version: ${{ matrix.python-version }} - name: Install dependencies run: | - pip install pipenv - pipenv install -d - pipenv install -r test_requirements.txt - - name: Test with pytest + python setup.py install + pip install -r requirements_dev.txt + pip install pre-commit + - name: Run all pre-commit checks run: | - pipenv run pytest + pre-commit run --all-files diff --git a/.github/workflows/pylint.yml b/.github/workflows/pylint.yml deleted file mode 100644 index 534a19b..0000000 --- a/.github/workflows/pylint.yml +++ /dev/null @@ -1,30 +0,0 @@ -name: pylint - -on: - pull_request: - types: [opened, synchronize, reopened] - -jobs: - linter: - - runs-on: ubuntu-latest - strategy: - matrix: - os: [ubuntu-latest] - python-version: [3.7, 3.8] - - steps: - - uses: actions/checkout@v2 - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v1 - with: - python-version: ${{ matrix.python-version }} - - name: Install dependencies - run: | - pip install pipenv - pip install -r test_requirements.txt - pip install -r requirements.txt - pip install -e . - - name: Run pylint on picatrix and tests - run: | - pipenv run pylint --rcfile=.pylintrc setup.py picatrix end_to_end_tests diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2211b50 --- /dev/null +++ b/.gitignore @@ -0,0 +1,159 @@ + +# Created by https://www.toptal.com/developers/gitignore/api/python,jupyternotebooks +# Edit at https://www.toptal.com/developers/gitignore?templates=python,jupyternotebooks + +### JupyterNotebooks ### +# gitignore template for Jupyter Notebooks +# website: http://jupyter.org/ + +.ipynb_checkpoints +*/.ipynb_checkpoints/* + +# IPython +profile_default/ +ipython_config.py + +# Remove previous ipynb_checkpoints +# git rm -r .ipynb_checkpoints/ + +### Python ### +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +# lib/ # ignored as `lib` is a valid path in Picatrix +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +node_modules +package-lock.json + +# 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/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook + +# IPython + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# End of https://www.toptal.com/developers/gitignore/api/python,jupyternotebooks diff --git a/.isort.cfg b/.isort.cfg new file mode 100755 index 0000000..8cbb74f --- /dev/null +++ b/.isort.cfg @@ -0,0 +1,8 @@ +[isort] +multi_line_output = 3 +include_trailing_comma = True +force_grid_wrap = 0 +use_parentheses = True +ensure_newline_before_comments = True +line_length = 80 +known_third_party = IPython,dateutil,dfdatetime,ipyaggrid,mock,pandas,pytest,setuptools,timesketch_api_client,timesketch_import_client diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100755 index 0000000..adeb725 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,44 @@ +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.0.1 + hooks: + - id: check-yaml + - id: end-of-file-fixer + - id: trailing-whitespace + - repo: https://github.com/pre-commit/mirrors-yapf + rev: "v0.31.0" + hooks: + - id: yapf + args: ["--style=.style.yapf", "--parallel", "--in-place"] + - repo: https://github.com/asottile/seed-isort-config + rev: v2.2.0 + hooks: + - id: seed-isort-config + - repo: https://github.com/pycqa/isort + rev: 5.9.3 + hooks: + - id: isort + name: isort (python) + verbose: true + - repo: local + hooks: + - id: pylint + name: pylint + entry: pylint + args: [picatrix] + language: system + types: [python] + # To be enabled later when all code type checks + # - id: pyright + # name: pyright + # entry: pyright + # language: node + # types: [python] + # pass_filenames: false + # additional_dependencies: ["pyright@1.1.130"] + - id: pytest-check + name: pytest-check + entry: pytest + language: system + pass_filenames: false + always_run: true diff --git a/.pylintrc b/.pylintrc index e2d52ba..cf2c3d5 100644 --- a/.pylintrc +++ b/.pylintrc @@ -11,7 +11,7 @@ extension-pkg-whitelist= # Add files or directories to the blacklist. They should be base names, not # paths. -ignore=CVS +ignore=CVS,jupyter_notebook_config.py # Add files or directories matching the regex patterns to the blacklist. The # regex matches against base names, not paths. @@ -87,7 +87,11 @@ disable= too-many-statements, unsubscriptable-object, useless-object-inheritance, - useless-suppression + useless-suppression, + no-else-raise, + no-else-return, + useless-type-doc, + consider-using-f-string # Enable the message, report, category or checker with the given id(s). You can # either give multiple identifier separated by comma (,) or put this option @@ -282,7 +286,7 @@ inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$ # Naming hint for method names method-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ #method-name-hint=(test|[A-Z_])[a-zA-Z0-9_]*$ -method-naming-style=snake_case +method-naming-style=snake_case # Regular expression matching correct method names method-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ diff --git a/.style.yapf b/.style.yapf new file mode 100644 index 0000000..372a36c --- /dev/null +++ b/.style.yapf @@ -0,0 +1,11 @@ +# For documentation of these options see +# https://github.com/google/yapf/blob/HEAD/README.rst +# based on Fuchsia YAPF config: +# https://fuchsia.googlesource.com/fuchsia/+/refs/heads/main/.style.yapf +[style] +based_on_style = google +indent_dictionary_value = true +split_arguments_when_comma_terminated = true +split_before_first_argument = true +indent_width = 2 +column_limit = 80 diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..75271fa --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,26 @@ +{ + "editor.formatOnSave": true, + "python.analysis.typeCheckingMode": "strict", + "python.testing.pytestArgs": [ + "picatrix" + ], + "python.testing.unittestEnabled": false, + "python.testing.pytestEnabled": true, + "python.testing.unittestArgs": [ + "-v", + "-s", + "./picatrix", + "-p", + "*_test.py" + ], + "python.formatting.provider": "yapf", + "python.languageServer": "Pylance", + "python.linting.enabled": true, + "python.linting.pylintEnabled": true, + "[python]": { + "editor.codeActionsOnSave": { + "source.organizeImports": true + } + }, + "files.insertFinalNewline": true, +} diff --git a/docker/Dockerfile b/docker/Dockerfile index 77550c2..93b5058 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -17,19 +17,13 @@ RUN python3 -m venv $VIRTUAL_ENV && \ ENV PATH="$VIRTUAL_ENV/bin:$PATH" ENV JUPYTER_PORT=8899 -COPY --chown=1000:1000 docker/00-import.py /home/picatrix/.ipython/profile_default/startup/00-import.py +COPY --chown=1000:1000 docker/notebook_init.py /home/picatrix/.ipython/profile_default/startup/notebook_init.py COPY --chown=1000:1000 . /home/picatrix/code COPY --chown=1000:1000 docker/jupyter_notebook_config.py /home/picatrix/.jupyter/jupyter_notebook_config.py RUN pip install --upgrade pip setuptools wheel && \ - cd /home/picatrix/code && pip install -e . && \ - pip install --upgrade ipywidgets jupyter_contrib_nbextensions jupyter_http_over_ws && \ - pip install scikit-learn matplotlib && \ - jupyter serverextension enable --py jupyter_http_over_ws && \ - jupyter nbextension enable --py widgetsnbextension --sys-prefix && \ - jupyter contrib nbextension install --user && \ - jupyter nbextensions_configurator enable --user && \ - jupyter nbextension enable --py --user ipyaggrid + cd /home/picatrix/code && pip install -e .[runtime] && \ + bash prepare-picatrix-runtime.sh WORKDIR /usr/local/src/picadata/ EXPOSE 8899 diff --git a/docker/docker-build.yml b/docker/docker-build.yml index 4562ac8..0a5650b 100644 --- a/docker/docker-build.yml +++ b/docker/docker-build.yml @@ -10,4 +10,3 @@ services: volumes: - ../:/usr/local/src/picatrix/:ro - /tmp/:/usr/local/src/picadata/ - diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 7f6ba32..c5c30bd 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -8,4 +8,3 @@ services: volumes: - ../:/usr/local/src/picatrix/:ro - /tmp/:/usr/local/src/picadata/ - diff --git a/docker/jupyter_notebook_config.py b/docker/jupyter_notebook_config.py index 867ed62..eb2ac47 100644 --- a/docker/jupyter_notebook_config.py +++ b/docker/jupyter_notebook_config.py @@ -1,13 +1,13 @@ # Configuration file for jupyter-notebook. ## Use a regular expression for the Access-Control-Allow-Origin header -# +# # Requests from an origin matching the expression will get replies with: -# +# # Access-Control-Allow-Origin: origin -# +# # where `origin` is the origin of the request. -# +# # Ignored if allow_origin is set. c.NotebookApp.allow_origin_pat = 'https://colab.[a-z]+.google.com' diff --git a/docker/00-import.py b/docker/notebook_init.py similarity index 92% rename from docker/00-import.py rename to docker/notebook_init.py index 008905c..245b743 100644 --- a/docker/00-import.py +++ b/docker/notebook_init.py @@ -13,10 +13,6 @@ # limitations under the License. """This is an import file that runs on every startup of the Jupyter runtime.""" -import altair as alt -import pandas as pd -import numpy as np - from picatrix import notebook_init notebook_init.init() diff --git a/picatrix/dependencies.py b/picatrix/dependencies.py deleted file mode 100644 index 92009a5..0000000 --- a/picatrix/dependencies.py +++ /dev/null @@ -1,56 +0,0 @@ -# Copyright 2020 Google Inc. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -"""List of dependencies for picatrix.""" -import sys - - -DEPENDENCIES = [ - 'altair>=4.1.0', - 'click>=7.1.2', - 'dfdatetime>=20200824', - 'google-auth>=1.17.2', - 'google-auth-oauthlib>=0.4.1', - 'ipython>=5.5.0', - 'ipywidgets>=5.1.1', - 'jupyter>=1.0.0', - 'jupyter-http-over-ws>=0.0.8', - 'networkx>=2.5', - 'MarkupSafe>=1.1.1', - 'nest-asyncio>=1.4.1', - 'notebook>=5.3.0', - 'numpy>=1.19.0', - 'oauthlib==3.1.0', - 'pandas>=1.1.3', - 'python-dateutil>=2.8.1', - 'pytz>=2020.1', - 'PyYAML>=5.3.1', - 'requests>=2.23.0', - 'requests-oauthlib>=1.3.0', - 'timesketch-api-client>=20201130', - 'timesketch-import-client>=20200910', - 'vega>=3.4.0', - 'ipyaggrid>=0.2.1', - 'xlrd>=1.2.0', -] - - -# Conditional dependencies define a dependency and then a condition that -# should return a bool. This bool will then be used to determine whether -# to include the dependency or not. -CONDITIONAL_DEPENDENCIES = [ - ( - 'typing-extensions==3.7.4.3', - (sys.version_info.major == 3 and sys.version_info.minor < 8) - ), -] diff --git a/prepare-picatrix-runtime.sh b/prepare-picatrix-runtime.sh new file mode 100644 index 0000000..3e8a8ec --- /dev/null +++ b/prepare-picatrix-runtime.sh @@ -0,0 +1,17 @@ +#!/bin/bash +# Initialize Picatrix runtime with right set of Jupyter extensions. + +# Exit on error. Append "|| true" if you expect an error. +set -o errexit +# Exit on error inside any functions or subshells. +set -o errtrace +# Do not allow use of undefined vars. Use ${VAR:-} to use an undefined VAR +set -o nounset +# Catch the error in case mysqldump fails (but gzip succeeds) in `mysqldump |gzip` +set -o pipefail + +jupyter serverextension enable --py jupyter_http_over_ws +jupyter nbextension enable --py widgetsnbextension --sys-prefix +jupyter contrib nbextension install --user +jupyter nbextensions_configurator enable --user +jupyter nbextension enable --py --user ipyaggrid diff --git a/requirements.txt b/requirements.txt index 624a915..d1e871f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,27 +1,10 @@ -altair>=4.1.0 -click>=7.1.2 -dfdatetime>=20200824 -google-auth>=1.17.2 +dfdatetime>=20210509 google-auth-oauthlib>=0.4.1 +google-auth>=1.17.2 +ipyaggrid>=0.2.1 ipython>=5.5.0 -ipywidgets>=5.1.1 -jupyter>=1.0.0 -jupyter-http-over-ws>=0.0.8 -MarkupSafe>=1.1.1 -nest-asyncio>=1.4.1 -notebook>=5.3.0 -numpy>=1.19.0 -oauthlib==3.1.0 +numpy>=1.19.5 pandas>=1.1.3 -python-dateutil>=2.8.1 -pytz>=2020.1 -PyYAML>=5.3.1 -requests>=2.23.0 -requests-oauthlib>=1.3.0 -timesketch-api-client>=20210416 -timesketch-import-client>=20210402 -vega>=3.4.0 -xlrd>=1.2.0 -typing-extensions==3.7.4.3 -networkx>=2.5 -ipyaggrid>=0.2.1 +timesketch-api-client>=20201130 +timesketch-import-client>=20200910 +typing-extensions>=3.7.4.3 diff --git a/requirements_dev.txt b/requirements_dev.txt new file mode 100644 index 0000000..931cbb3 --- /dev/null +++ b/requirements_dev.txt @@ -0,0 +1,7 @@ +coverage~=5.0.2 +isort~=5.8.0 +mock~=2.0.0 +pre-commit~=2.15.0 +pylint~=2.6.0 +pytest~=6.2.5 +yapf~=0.31.0 diff --git a/requirements_runtime.txt b/requirements_runtime.txt new file mode 100644 index 0000000..cd3744b --- /dev/null +++ b/requirements_runtime.txt @@ -0,0 +1,11 @@ +altair>=4.1.0 +ipyaggrid>=0.2.1 +ipython>=5.5.0 +ipywidgets>=5.1.1 +jupyter-contrib-nbextensions>=0.5.1 +jupyter-http-over-ws>=0.0.8 +jupyter>=1.0.0 +matplotlib>=2.2.0 +numpy>=1.19.0 +pandas>=1.1.3 +scikit-learn>=1.0 diff --git a/setup.py b/setup.py index 7b9587b..c3d764d 100644 --- a/setup.py +++ b/setup.py @@ -15,45 +15,41 @@ """This is the setup file for the project.""" from __future__ import unicode_literals -from setuptools import find_packages -from setuptools import setup +from setuptools import find_packages, setup -from picatrix import dependencies from picatrix import version -def get_requirements(): - """Returns a list of requirements.""" - requires = dependencies.DEPENDENCIES - - for dependency, condition in dependencies.CONDITIONAL_DEPENDENCIES: - if condition: - requires.append(dependency) - return requires +def from_file(name): + """Read dependencies from requirements.txt file.""" + with open(name, "r", encoding="utf-8") as f: + return f.read().splitlines() long_description = ( - 'picatrix - a framework to assist security analysts using ' - 'Colab or Jupyter to perform forensic investigations.') + "picatrix - a framework to assist security analysts using " + "Colab or Jupyter to perform forensic investigations.") setup( - name='picatrix', + name="picatrix", version=version.get_version(), - description='Picatrix IPython Helpers', + description="Picatrix IPython Helpers", long_description=long_description, - license='Apache License, Version 2.0', - url='https://github.com/google/picatrix/', - maintainer='Picatrix development team', - maintainer_email='picatrix-developers@googlegroups.com', + license="Apache License, Version 2.0", + url="https://github.com/google/picatrix/", + maintainer="Picatrix development team", + maintainer_email="picatrix-developers@googlegroups.com", classifiers=[ - 'Development Status :: 4 - Beta', - 'Environment :: Console', - 'Operating System :: OS Independent', - 'Programming Language :: Python', + "Development Status :: 4 - Beta", + "Environment :: Console", + "Operating System :: OS Independent", + "Programming Language :: Python", ], packages=find_packages(), include_package_data=True, zip_safe=False, - install_requires=get_requirements(), - tests_require='test_requirements.txt', -) + install_requires=from_file("requirements.txt"), + tests_require=from_file("requirements_dev.txt"), + extras_require={ + "runtime": from_file("requirements_runtime.txt"), + }) diff --git a/test_requirements.txt b/test_requirements.txt deleted file mode 100644 index 02baca4..0000000 --- a/test_requirements.txt +++ /dev/null @@ -1,4 +0,0 @@ -pylint==2.6.0 -mock>=2.0.0 -coverage>=5.0.2 -pytest==6.1.2 diff --git a/tools/create_requirements.py b/tools/create_requirements.py deleted file mode 100644 index 68a5366..0000000 --- a/tools/create_requirements.py +++ /dev/null @@ -1,31 +0,0 @@ -# Copyright 2020 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -"""Used to generate a requirements.txt file.""" -from picatrix import dependencies - - -def get_requirements(): - """Returns a list of requirements.""" - requires = dependencies.DEPENDENCIES - - for dependency, condition in dependencies.CONDITIONAL_DEPENDENCIES: - if condition: - requires.append(dependency) - return requires - - -if __name__ == '__main__': - with open('requirements.txt', 'w') as fw: - for dependency in get_requirements(): - fw.write(f'{dependency}\n')