diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..6be1e24 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,38 @@ +# Git +.git +.gitignore +.github + +# Docker +.dockerignore + +# IDE +.idea +.vscode + +# Byte-compiled / optimized / DLL files +__pycache__/ +**/__pycache__/ +*.pyc +*.pyo +*.pyd +.Python +*.py[cod] +*$py.class +.pytest_cache/ +..mypy_cache/ + +# poetry +.venv + +# C extensions +*.so + +# Virtual environment +.venv +venv + +.DS_Store +.AppleDouble +.LSOverride +._* diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..7f578f1 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,24 @@ +# Check http://editorconfig.org for more information +# This is the main config file for this project: +root = true + +[*] +charset = utf-8 +end_of_line = lf +insert_final_newline = true +indent_style = space +indent_size = 2 +trim_trailing_whitespace = true + +[*.{py, pyi}] +indent_style = space +indent_size = 4 + +[Makefile] +indent_style = tab + +[*.md] +trim_trailing_whitespace = false + +[*.{diff,patch}] +trim_trailing_whitespace = false diff --git a/.github/.stale.yml b/.github/.stale.yml new file mode 100644 index 0000000..dc90e5a --- /dev/null +++ b/.github/.stale.yml @@ -0,0 +1,17 @@ +# Number of days of inactivity before an issue becomes stale +daysUntilStale: 60 +# Number of days of inactivity before a stale issue is closed +daysUntilClose: 7 +# Issues with these labels will never be considered stale +exemptLabels: + - pinned + - security +# Label to use when marking an issue as stale +staleLabel: wontfix +# Comment to post when marking an issue as stale. Set to `false` to disable +markComment: > + This issue has been automatically marked as stale because it has not had + recent activity. It will be closed if no further activity occurs. Thank you + for your contributions. +# Comment to post when closing a stale issue. Set to `false` to disable +closeComment: false diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..bdd7677 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,42 @@ +--- +name: πŸ› Bug report +about: If something isn't working πŸ”§ +title: '' +labels: bug +assignees: +--- + +## πŸ› Bug Report + + + +## πŸ”¬ How To Reproduce + +Steps to reproduce the behavior: + +1. ... + +### Code sample + + + +### Environment + +* OS: [e.g. Linux / Windows / macOS] +* Python version, get it with: + +```bash +python --version +``` + +### Screenshots + + + +## πŸ“ˆ Expected behavior + + + +## πŸ“Ž Additional context + + diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..8f2da54 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,3 @@ +# Configuration: https://help.github.com/en/github/building-a-strong-community/configuring-issue-templates-for-your-repository + +blank_issues_enabled: false diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..c387120 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,23 @@ +--- +name: πŸš€ Feature request +about: Suggest an idea for this project πŸ– +title: '' +labels: enhancement +assignees: +--- + +## πŸš€ Feature Request + + + +## πŸ”ˆ Motivation + + + +## πŸ›° Alternatives + + + +## πŸ“Ž Additional context + + diff --git a/.github/ISSUE_TEMPLATE/question.md b/.github/ISSUE_TEMPLATE/question.md new file mode 100644 index 0000000..e58d70c --- /dev/null +++ b/.github/ISSUE_TEMPLATE/question.md @@ -0,0 +1,25 @@ +--- +name: ❓ Question +about: Ask a question about this project πŸŽ“ +title: '' +labels: question +assignees: +--- + +## Checklist + + + +- [ ] I've searched the project's [`issues`](https://github.com/chaoqing/PyCXpress/issues?q=is%3Aissue). + +## ❓ Question + + + +How can I [...]? + +Is it possible to [...]? + +## πŸ“Ž Additional context + + diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..34d0416 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,28 @@ +## Description + + + +## Related Issue + + + +## Type of Change + + + +- [ ] πŸ“š Examples / docs / tutorials / dependencies update +- [ ] πŸ”§ Bug fix (non-breaking change which fixes an issue) +- [ ] πŸ₯‚ Improvement (non-breaking change which improves an existing feature) +- [ ] πŸš€ New feature (non-breaking change which adds functionality) +- [ ] πŸ’₯ Breaking change (fix or feature that would cause existing functionality to change) +- [ ] πŸ” Security fix + +## Checklist + + + +- [ ] I've read the [`CODE_OF_CONDUCT.md`](https://github.com/chaoqing/PyCXpress/blob/master/CODE_OF_CONDUCT.md) document. +- [ ] I've read the [`CONTRIBUTING.md`](https://github.com/chaoqing/PyCXpress/blob/master/CONTRIBUTING.md) guide. +- [ ] I've updated the code style using `make codestyle`. +- [ ] I've written tests for all new methods and classes that I created. +- [ ] I've written the docstring in Google format for all the methods and classes that I used. diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..3decb07 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,25 @@ +# Configuration: https://dependabot.com/docs/config-file/ +# Docs: https://docs.github.com/en/github/administering-a-repository/keeping-your-dependencies-updated-automatically + +version: 2 + +updates: + - package-ecosystem: "pip" + directory: "/" + schedule: + interval: "monthly" + allow: + - dependency-type: "all" + commit-message: + prefix: ":arrow_up:" + open-pull-requests-limit: 5 + + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "monthly" + allow: + - dependency-type: "all" + commit-message: + prefix: ":arrow_up:" + open-pull-requests-limit: 5 \ No newline at end of file diff --git a/.github/release-drafter.yml b/.github/release-drafter.yml new file mode 100644 index 0000000..0ce0984 --- /dev/null +++ b/.github/release-drafter.yml @@ -0,0 +1,28 @@ +# Release drafter configuration https://github.com/release-drafter/release-drafter#configuration +# Emojis were chosen to match the https://gitmoji.carloscuesta.me/ + +name-template: "v$NEXT_PATCH_VERSION" +tag-template: "v$NEXT_PATCH_VERSION" + +categories: + - title: ":rocket: Features" + labels: [enhancement, feature] + - title: ":wrench: Fixes & Refactoring" + labels: [bug, refactoring, bugfix, fix] + - title: ":package: Build System & CI/CD" + labels: [build, ci, testing] + - title: ":boom: Breaking Changes" + labels: [breaking] + - title: ":pencil: Documentation" + labels: [documentation] + - title: ":arrow_up: Dependencies updates" + labels: [dependencies] + +template: | + ## What’s Changed + + $CHANGES + + ## :busts_in_silhouette: List of contributors + + $CONTRIBUTORS diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..7f8742f --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,42 @@ +name: build + +on: [push, pull_request] + +jobs: + build: + runs-on: ubuntu-latest + strategy: + matrix: + python-version: ["3.8", "3.9"] + + steps: + - uses: actions/checkout@v4 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v5.1.0 + with: + python-version: ${{ matrix.python-version }} + + - name: Install poetry + run: make poetry-download + + - name: Set up cache + uses: actions/cache@v4.0.2 + with: + path: .venv + key: venv-${{ matrix.python-version }}-${{ hashFiles('pyproject.toml') }}-${{ hashFiles('poetry.lock') }} + - name: Install dependencies + run: | + poetry config virtualenvs.in-project true + poetry install + + - name: Run style checks + run: | + make check-codestyle + + - name: Run tests + run: | + make test + + - name: Run safety checks + run: | + make check-safety diff --git a/.github/workflows/greetings.yml b/.github/workflows/greetings.yml new file mode 100644 index 0000000..a1f6e89 --- /dev/null +++ b/.github/workflows/greetings.yml @@ -0,0 +1,16 @@ +name: Greetings + +on: [pull_request, issues] + +jobs: + greeting: + runs-on: ubuntu-latest + steps: + - uses: actions/first-interaction@v1 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + pr-message: 'Hello @${{ github.actor }}, thank you for submitting a PR! We will respond as soon as possible.' + issue-message: | + Hello @${{ github.actor }}, thank you for your interest in our work! + + If this is a bug report, please provide screenshots and **minimum viable code to reproduce your issue**, otherwise we can not help you. diff --git a/.github/workflows/publish-to-pypi.yml b/.github/workflows/publish-to-pypi.yml new file mode 100644 index 0000000..84216a1 --- /dev/null +++ b/.github/workflows/publish-to-pypi.yml @@ -0,0 +1,52 @@ +name: Publish package + +on: + release: + types: [created] + +jobs: + release-build: + if: github.event_name == 'release' && github.event.action == 'created' + runs-on: ubuntu-latest + strategy: + matrix: + python-version: ["3.11"] + + steps: + - uses: actions/checkout@v4 + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v5.1.0 + with: + python-version: ${{ matrix.python-version }} + + - name: Install build + run: python3 -m pip install --upgrade build + + - name: Build release distributions + run: | + python3 -m build --outdir dist/ + + - name: Upload dists + uses: actions/upload-artifact@v4 + with: + name: release-dists + path: dist/ + + pypi-publish: + runs-on: ubuntu-latest + needs: + - release-build + permissions: + id-token: write + + steps: + - name: Retrieve release distributions + uses: actions/download-artifact@v4 + with: + name: release-dists + path: dist/ + + - name: Publish release distributions to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 + \ No newline at end of file diff --git a/.github/workflows/release-drafter.yml b/.github/workflows/release-drafter.yml new file mode 100644 index 0000000..7fb0ef1 --- /dev/null +++ b/.github/workflows/release-drafter.yml @@ -0,0 +1,16 @@ +name: Release Drafter + +on: + push: + # branches to consider in the event; optional, defaults to all + branches: + - master + +jobs: + update_release_draft: + runs-on: ubuntu-latest + steps: + # Drafts your next Release notes as Pull Requests are merged into "master" + - uses: release-drafter/release-drafter@v6.0.0 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.gitignore b/.gitignore index 259148f..0a2ef70 100644 --- a/.gitignore +++ b/.gitignore @@ -30,3 +30,7 @@ *.exe *.out *.app + +# Python +dist/ +__pycache__/ \ No newline at end of file diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..85d266f --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,36 @@ +default_language_version: + python: python3.8 + +default_stages: [commit, push] + +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v2.5.0 + hooks: + - id: check-yaml + - id: end-of-file-fixer + exclude: LICENSE + + - repo: local + hooks: + - id: pyupgrade + name: pyupgrade + entry: poetry run pyupgrade --py38-plus + types: [python] + language: system + + - repo: local + hooks: + - id: isort + name: isort + entry: poetry run isort --settings-path pyproject.toml + types: [python] + language: system + + - repo: local + hooks: + - id: black + name: black + entry: poetry run black --config pyproject.toml + types: [python] + language: system diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..716f26c --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,76 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, sex characteristics, gender identity and expression, +level of experience, education, socio-economic status, nationality, personal +appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or + advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project e-mail +address, posting via an official social media account, or acting as an appointed +representative at an online or offline event. Representation of a project may be +further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting the project team at chaoqingwang.nick@gmail.com. All +complaints will be reviewed and investigated and will result in a response that +is deemed necessary and appropriate to the circumstances. The project team is +obligated to maintain confidentiality with regard to the reporter of an incident. +Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, +available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html + +[homepage]: https://www.contributor-covenant.org + +For answers to common questions about this code of conduct, see +https://www.contributor-covenant.org/faq diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..16e880e --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,47 @@ +# How to contribute + +## Dependencies + +We use `poetry` to manage the [dependencies](https://github.com/python-poetry/poetry). +If you dont have `poetry`, you should install with `make poetry-download`. + +To install dependencies and prepare [`pre-commit`](https://pre-commit.com/) hooks you would need to run `install` command: + +```bash +make install +make pre-commit-install +``` + +To activate your `virtualenv` run `poetry shell`. + +## Codestyle + +After installation you may execute code formatting. + +```bash +make codestyle +``` + +### Checks + +Many checks are configured for this project. Command `make check-codestyle` will check black, isort and darglint. +The `make check-safety` command will look at the security of your code. + +Comand `make lint` applies all checks. + +### Before submitting + +Before submitting your code please do the following steps: + +1. Add any changes you want +1. Add tests for the new changes +1. Edit documentation if you have changed something significant +1. Run `make codestyle` to format your changes. +1. Run `make lint` to ensure that types, security and docstrings are okay. + +## Other help + +You can contribute by spreading a word about this library. +It would also be a huge contribution to write +a short article on how you are using this project. +You can also share your best practices with us. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..421882e --- /dev/null +++ b/Makefile @@ -0,0 +1,113 @@ +#* Variables +SHELL := /usr/bin/env bash +PYTHON := python +PYTHONPATH := `pwd` + +#* Docker variables +IMAGE := PyCXpress +VERSION := latest + +#* Poetry +.PHONY: poetry-download +poetry-download: + curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/install-poetry.py | $(PYTHON) - + +.PHONY: poetry-remove +poetry-remove: + curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/install-poetry.py | $(PYTHON) - --uninstall + +#* Installation +.PHONY: install +install: + poetry lock -n && poetry export --without-hashes > requirements.txt + poetry install -n + -poetry run mypy --install-types --non-interactive ./ + +.PHONY: pre-commit-install +pre-commit-install: + poetry run pre-commit install + +#* Formatters +.PHONY: codestyle +codestyle: + poetry run pyupgrade --exit-zero-even-if-changed --py38-plus **/*.py + poetry run isort --settings-path pyproject.toml ./ + poetry run black --config pyproject.toml ./ + +.PHONY: formatting +formatting: codestyle + +#* Linting +.PHONY: test +test: + PYTHONPATH=$(PYTHONPATH) poetry run pytest -c pyproject.toml --cov-report=html --cov=PyCXpress tests/ + poetry run coverage-badge -o assets/images/coverage.svg -f + +.PHONY: check-codestyle +check-codestyle: + poetry run isort --diff --check-only --settings-path pyproject.toml ./ + poetry run black --diff --check --config pyproject.toml ./ + poetry run darglint --verbosity 2 PyCXpress tests + +.PHONY: mypy +mypy: + poetry run mypy --config-file pyproject.toml ./ + +.PHONY: check-safety +check-safety: + poetry check + poetry run safety check --full-report + poetry run bandit -ll --recursive PyCXpress tests + +.PHONY: lint +lint: test check-codestyle mypy check-safety + +.PHONY: update-dev-deps +update-dev-deps: + poetry add -D bandit@latest darglint@latest "isort[colors]@latest" mypy@latest pre-commit@latest pydocstyle@latest pylint@latest pytest@latest pyupgrade@latest safety@latest coverage@latest coverage-badge@latest pytest-html@latest pytest-cov@latest + poetry add -D --allow-prereleases black@latest + +#* Docker +# Example: make docker-build VERSION=latest +# Example: make docker-build IMAGE=some_name VERSION=0.0.1 +.PHONY: docker-build +docker-build: + @echo Building docker $(IMAGE):$(VERSION) ... + docker build \ + -t $(IMAGE):$(VERSION) . \ + -f ./docker/Dockerfile --no-cache + +# Example: make docker-remove VERSION=latest +# Example: make docker-remove IMAGE=some_name VERSION=0.0.1 +.PHONY: docker-remove +docker-remove: + @echo Removing docker $(IMAGE):$(VERSION) ... + docker rmi -f $(IMAGE):$(VERSION) + +#* Cleaning +.PHONY: pycache-remove +pycache-remove: + find . | grep -E "(__pycache__|\.pyc|\.pyo$$)" | xargs rm -rf + +.PHONY: dsstore-remove +dsstore-remove: + find . | grep -E ".DS_Store" | xargs rm -rf + +.PHONY: mypycache-remove +mypycache-remove: + find . | grep -E ".mypy_cache" | xargs rm -rf + +.PHONY: ipynbcheckpoints-remove +ipynbcheckpoints-remove: + find . | grep -E ".ipynb_checkpoints" | xargs rm -rf + +.PHONY: pytestcache-remove +pytestcache-remove: + find . | grep -E ".pytest_cache" | xargs rm -rf + +.PHONY: build-remove +build-remove: + rm -rf build/ + +.PHONY: cleanup +cleanup: pycache-remove dsstore-remove mypycache-remove ipynbcheckpoints-remove pytestcache-remove diff --git a/README.md b/README.md index 67f13c6..a3ad560 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,37 @@ # PyCXpress + +
+ +[![Build status](https://github.com/chaoqing/PyCXpress/workflows/build/badge.svg?branch=master&event=push)](https://github.com/chaoqing/PyCXpress/actions?query=workflow%3Abuild) +[![Python Version](https://img.shields.io/pypi/pyversions/PyCXpress.svg)](https://pypi.org/project/PyCXpress/) +[![Dependencies Status](https://img.shields.io/badge/dependencies-up%20to%20date-brightgreen.svg)](https://github.com/chaoqing/PyCXpress/pulls?utf8=%E2%9C%93&q=is%3Apr%20author%3Aapp%2Fdependabot) + +[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black) +[![Security: bandit](https://img.shields.io/badge/security-bandit-green.svg)](https://github.com/PyCQA/bandit) +[![Pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit&logoColor=white)](https://github.com/chaoqing/PyCXpress/blob/master/.pre-commit-config.yaml) +[![Semantic Versions](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--versions-e10079.svg)](https://github.com/chaoqing/PyCXpress/releases) +[![License](https://img.shields.io/github/license/chaoqing/PyCXpress)](https://github.com/chaoqing/PyCXpress/blob/master/LICENSE) +![Coverage Report](assets/images/coverage.svg) + PyCXpress is a high-performance hybrid framework that seamlessly integrates Python and C++ to harness the flexibility of Python and the speed of C++ for efficient and expressive computation, particularly in the realm of deep learning and numerical computing. + +
+ +## πŸ›‘ License + +[![License](https://img.shields.io/github/license/chaoqing/PyCXpress)](https://github.com/chaoqing/PyCXpress/blob/master/LICENSE) + +This project is licensed under the terms of the `MIT` license. See [LICENSE](https://github.com/chaoqing/PyCXpress/blob/master/LICENSE) for more details. + +## πŸ“ƒ Citation + +```bibtex +@misc{PyCXpress, + author = {chaoqing}, + title = {PyCXpress is a high-performance hybrid framework that seamlessly integrates Python and C++ to harness the flexibility of Python and the speed of C++ for efficient and expressive computation, particularly in the realm of deep learning and numerical computing.}, + year = {2024}, + publisher = {GitHub}, + journal = {GitHub repository}, + howpublished = {\url{https://github.com/chaoqing/PyCXpress}} +} +``` \ No newline at end of file diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..99948a5 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,27 @@ +# Security + +## πŸ” Reporting Security Issues + +> Do not open issues that might have security implications! +> It is critical that security related issues are reported privately so we have time to address them before they become public knowledge. + +Vulnerabilities can be reported by emailing core members: + +- chaoqing [chaoqingwang.nick@gmail.com](mailto:chaoqingwang.nick@gmail.com) + +Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: + +- Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) +- Full paths of source file(s) related to the manifestation of the issue +- The location of the affected source code (tag/branch/commit or direct URL) +- Any special configuration required to reproduce the issue +- Environment (e.g. Linux / Windows / macOS) +- Step-by-step instructions to reproduce the issue +- Proof-of-concept or exploit code (if possible) +- Impact of the issue, including how an attacker might exploit the issue + +This information will help us triage your report more quickly. + +## Preferred Languages + +We prefer all communications to be in English. diff --git a/__init__.py b/__init__.py new file mode 100644 index 0000000..3dfe521 --- /dev/null +++ b/__init__.py @@ -0,0 +1,19 @@ +# type: ignore[attr-defined] +"""PyCXpress is a high-performance hybrid framework that seamlessly integrates Python and C++ to harness the flexibility of Python and the speed of C++ for efficient and expressive computation, particularly in the realm of deep learning and numerical computing.""" + +import sys + +if sys.version_info >= (3, 8): + from importlib import metadata as importlib_metadata +else: + import importlib_metadata + + +def get_version() -> str: + try: + return importlib_metadata.version(__name__) + except importlib_metadata.PackageNotFoundError: # pragma: no cover + return "unknown" + + +version: str = get_version() diff --git a/__main__.py b/__main__.py new file mode 100644 index 0000000..b05f939 --- /dev/null +++ b/__main__.py @@ -0,0 +1,66 @@ +# type: ignore[attr-defined] +from typing import Optional + +from enum import Enum +from random import choice + +import typer +from rich.console import Console + +from PyCXpress import version + + +class Color(str, Enum): + white = "white" + red = "red" + cyan = "cyan" + magenta = "magenta" + yellow = "yellow" + green = "green" + + +app = typer.Typer( + name="PyCXpress", + help="PyCXpress is a high-performance hybrid framework that seamlessly integrates Python and C++ to harness the flexibility of Python and the speed of C++ for efficient and expressive computation, particularly in the realm of deep learning and numerical computing.", + add_completion=False, +) +console = Console() + + +def version_callback(print_version: bool) -> None: + """Print the version of the package.""" + if print_version: + console.print(f"[yellow]PyCXpress[/] version: [bold blue]{version}[/]") + raise typer.Exit() + + +@app.command(name="") +def main( + name: str = typer.Option(..., help="Person to greet."), + color: Optional[Color] = typer.Option( + None, + "-c", + "--color", + "--colour", + case_sensitive=False, + help="Color for print. If not specified then choice will be random.", + ), + print_version: bool = typer.Option( + None, + "-v", + "--version", + callback=version_callback, + is_eager=True, + help="Prints the version of the PyCXpress package.", + ), +) -> None: + """Print a greeting with a giving name.""" + if color is None: + color = choice(list(Color)) + + greeting: str = 'hello' + console.print(f"[bold {color}]{greeting}[/]") + + +if __name__ == "__main__": + app() diff --git a/assets/images/coverage.svg b/assets/images/coverage.svg new file mode 100644 index 0000000..0644a48 --- /dev/null +++ b/assets/images/coverage.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + coverage + coverage + 26% + 26% + + diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..bb83878 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,146 @@ +# Poetry pyproject.toml: https://python-poetry.org/docs/pyproject/ +[build-system] +requires = ["poetry_core>=1.0.0"] +build-backend = "poetry.core.masonry.api" + +[tool.poetry] +name = "PyCXpress" +version = "0.0.1" +description = "PyCXpress is a high-performance hybrid framework that seamlessly integrates Python and C++ to harness the flexibility of Python and the speed of C++ for efficient and expressive computation, particularly in the realm of deep learning and numerical computing." +readme = "README.md" +authors = ["chaoqing "] +license = "MIT" +repository = "https://github.com/chaoqing/PyCXpress" +homepage = "https://github.com/chaoqing/PyCXpress" + +# Keywords description https://python-poetry.org/docs/pyproject/#keywords +keywords = [] #! Update me + +# Pypi classifiers: https://pypi.org/classifiers/ +classifiers = [ #! Update me + "Development Status :: 3 - Alpha", + "Intended Audience :: Developers", + "Operating System :: OS Independent", + "Topic :: Software Development :: Libraries :: Python Modules", + "License :: OSI Approved :: MIT License", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", +] + +[tool.poetry.scripts] +# Entry points for the package https://python-poetry.org/docs/pyproject/#scripts +"PyCXpress" = "PyCXpress.__main__:app" + +[tool.poetry.dependencies] +python = "^3.8" + +typer = {extras = ["all"], version = "^0.12.3"} +rich = "^13.7.1" + +[tool.poetry.dev-dependencies] +bandit = "^1.7.1" +black = {version = "^24.4", allow-prereleases = true} +darglint = "^1.8.1" +isort = {extras = ["colors"], version = "^5.10.1"} +mypy = "^1.0" +mypy-extensions = "^0.4.3" +pre-commit = "^3.5.0" +pydocstyle = "^6.1.1" +pylint = "^3.1.0" +pytest = "^8.1.1" +pyupgrade = "^3.8.0" +safety = "^3.1.0" +coverage = "^7.4.4" +coverage-badge = "^1.1.0" +pytest-html = "^3.1.1" +pytest-cov = "^5.0.0" + +[tool.black] +# https://github.com/psf/black +target-version = ["py38"] +line-length = 88 +color = true + +exclude = ''' +/( + \.git + | \.hg + | \.mypy_cache + | \.tox + | \.venv + | _build + | buck-out + | build + | dist + | env + | venv +)/ +''' + +[tool.isort] +# https://github.com/timothycrosley/isort/ +py_version = 38 +line_length = 88 + +known_typing = ["typing", "types", "typing_extensions", "mypy", "mypy_extensions"] +sections = ["FUTURE", "TYPING", "STDLIB", "THIRDPARTY", "FIRSTPARTY", "LOCALFOLDER"] +include_trailing_comma = true +profile = "black" +multi_line_output = 3 +indent = 4 +color_output = true + +[tool.mypy] +# https://mypy.readthedocs.io/en/latest/config_file.html#using-a-pyproject-toml-file +python_version = 3.8 +pretty = true +show_traceback = true +color_output = true + +allow_redefinition = false +check_untyped_defs = true +disallow_any_generics = true +disallow_incomplete_defs = true +ignore_missing_imports = true +implicit_reexport = false +no_implicit_optional = true +show_column_numbers = true +show_error_codes = true +show_error_context = true +strict_equality = true +strict_optional = true +warn_no_return = true +warn_redundant_casts = true +warn_return_any = true +warn_unreachable = true +warn_unused_configs = true +warn_unused_ignores = true + + +[tool.pytest.ini_options] +# https://docs.pytest.org/en/6.2.x/customize.html#pyproject-toml +# Directories that are not visited by pytest collector: +norecursedirs =["hooks", "*.egg", ".eggs", "dist", "build", "docs", ".tox", ".git", "__pycache__"] +doctest_optionflags = ["NUMBER", "NORMALIZE_WHITESPACE", "IGNORE_EXCEPTION_DETAIL"] + +# Extra options: +addopts = [ + "--strict-markers", + "--tb=short", + "--doctest-modules", + "--doctest-continue-on-failure", +] + +[tool.coverage.run] +source = ["tests"] + +[coverage.paths] +source = "PyCXpress" + +[coverage.run] +branch = true + +[coverage.report] +fail_under = 50 +show_missing = true \ No newline at end of file diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..3c46a08 --- /dev/null +++ b/setup.cfg @@ -0,0 +1,4 @@ +[darglint] +# https://github.com/terrencepreilly/darglint +strictness = long +docstring_style = google