From d1abaf6806d8d7710422b8cd079d9106f5326135 Mon Sep 17 00:00:00 2001 From: Huy Nguyen Date: Sat, 30 Mar 2024 00:53:24 +0700 Subject: [PATCH] Initial project setup --- .github/workflows/publish.yml | 39 ++++++++++++ .github/workflows/test.yml | 72 +++++++++++++++++++++ .gitignore | 25 ++++++++ .pre-commit-config.yaml | 39 ++++++++++++ .readthedocs.yaml | 15 +++++ CONTRIBUTING.md | 42 +++++++++++++ LICENSE | 28 +++++++++ README.md | 34 ++++++++++ docs/Makefile | 20 ++++++ docs/conf.py | 36 +++++++++++ docs/index.rst | 15 +++++ docs/make.bat | 35 +++++++++++ docs/requirements.txt | 2 + headless_cms/__init__.py | 3 + pyproject.toml | 114 ++++++++++++++++++++++++++++++++++ requirements-tests.txt | 6 ++ requirements.txt | 4 ++ scripts/lint.sh | 11 ++++ 18 files changed, 540 insertions(+) create mode 100644 .github/workflows/publish.yml create mode 100644 .github/workflows/test.yml create mode 100644 .gitignore create mode 100644 .pre-commit-config.yaml create mode 100644 .readthedocs.yaml create mode 100644 CONTRIBUTING.md create mode 100644 LICENSE create mode 100644 README.md create mode 100644 docs/Makefile create mode 100644 docs/conf.py create mode 100644 docs/index.rst create mode 100644 docs/make.bat create mode 100644 docs/requirements.txt create mode 100644 headless_cms/__init__.py create mode 100644 pyproject.toml create mode 100644 requirements-tests.txt create mode 100644 requirements.txt create mode 100755 scripts/lint.sh diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000..0fa731b --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,39 @@ +name: Publish + +on: + release: + types: + - created + +jobs: + publish: + runs-on: ubuntu-latest + steps: + - name: Dump GitHub context + env: + GITHUB_CONTEXT: ${{ toJson(github) }} + run: echo "$GITHUB_CONTEXT" + - uses: actions/checkout@v3 + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: "3.11" + cache-dependency-path: pyproject.toml + - uses: actions/cache@v3 + id: cache + with: + path: ${{ env.pythonLocation }} + key: ${{ runner.os }}-python-${{ env.pythonLocation }}-${{ hashFiles('pyproject.toml') }}-publish + - name: Install build dependencies + if: steps.cache.outputs.cache-hit != 'true' + run: pip install build + - name: Build distribution + run: python -m build + - name: Publish + uses: pypa/gh-action-pypi-publish@v1.8.6 + with: + password: ${{ secrets.PYPI_API_TOKEN }} + - name: Dump GitHub context + env: + GITHUB_CONTEXT: ${{ toJson(github) }} + run: echo "$GITHUB_CONTEXT" diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..42fd5f0 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,72 @@ +name: Test + +on: + push: + branches: + - main + pull_request: + types: + - opened + - synchronize + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - name: Dump GitHub context + env: + GITHUB_CONTEXT: ${{ toJson(github) }} + run: echo "$GITHUB_CONTEXT" + - uses: actions/checkout@v3 + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: "3.11" + - uses: actions/cache@v3 + id: cache + with: + path: ${{ env.pythonLocation }} + key: ${{ runner.os }}-python-${{ env.pythonLocation }}-django-headless-cms-${{ hashFiles('pyproject.toml', 'requirements-tests.txt') }}-lint + - name: Install Dependencies + if: steps.cache.outputs.cache-hit != 'true' + run: pip install -r requirements-tests.txt + - name: Lint + run: bash scripts/lint.sh + + test: + runs-on: ubuntu-latest + strategy: + matrix: + python-version: ["3.9", "3.10", "3.11"] + fail-fast: false + steps: + - name: Dump GitHub context + env: + GITHUB_CONTEXT: ${{ toJson(github) }} + run: echo "$GITHUB_CONTEXT" + - uses: actions/checkout@v3 + - uses: FedericoCarboni/setup-ffmpeg@v2 + id: setup-ffmpeg + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python-version }} + - uses: actions/cache@v3 + id: cache + with: + path: ${{ env.pythonLocation }} + key: ${{ runner.os }}-python-${{ env.pythonLocation }}-django-headless-cms-${{ hashFiles('pyproject.toml', 'requirements-tests.txt') }}-test + - name: Install Dependencies + if: steps.cache.outputs.cache-hit != 'true' + run: pip install -r requirements-tests.txt + - run: mkdir coverage + - name: Test + run: coverage run -m pytest tests + env: + COVERAGE_FILE: coverage/.coverage.${{ runner.os }}-py${{ matrix.python-version }} + CONTEXT: ${{ runner.os }}-py${{ matrix.python-version }} + - name: Store coverage files + uses: actions/upload-artifact@v3 + with: + name: coverage + path: coverage diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..af4585f --- /dev/null +++ b/.gitignore @@ -0,0 +1,25 @@ +# Byte-compiled / Optimized / DLL Files +*.pyc +*.pyo +*.pyd +__pycache__/ + +# Distribution / Packaging +.venv/ +venv/ +dist +docs/_build/ + + +# Unit Test & coverage +.pytest_cache/ +htmlcov +.coverage +coverage.xml + +# Ignore IDE, Editor Files +.idea/ +.vscode/ + +# macOS +.DS_Store diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..a8a7a6e --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,39 @@ +# See https://pre-commit.com for more information +# See https://pre-commit.com/hooks.html for more hooks +default_language_version: + python: python3.11 +repos: +- repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.5.0 + hooks: + - id: check-added-large-files + - id: check-toml + - id: check-yaml + args: + - --unsafe + - id: end-of-file-fixer + - id: trailing-whitespace +- repo: https://github.com/asottile/pyupgrade + rev: v3.15.2 + hooks: + - id: pyupgrade + args: + - --py3-plus + - --keep-runtime-typing +- repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.3.4 + hooks: + - id: ruff + args: + - --fix +- repo: https://github.com/psf/black-pre-commit-mirror + rev: 24.3.0 + hooks: + - id: black +- repo: https://github.com/pappasam/toml-sort + rev: v0.23.1 + hooks: + - id: toml-sort-fix +ci: + autofix_commit_msg: 🎨 [pre-commit.ci] Auto format from pre-commit.com hooks + autoupdate_commit_msg: ⬆ [pre-commit.ci] pre-commit autoupdate diff --git a/.readthedocs.yaml b/.readthedocs.yaml new file mode 100644 index 0000000..d561687 --- /dev/null +++ b/.readthedocs.yaml @@ -0,0 +1,15 @@ +version: 2 + +build: + os: ubuntu-22.04 + tools: + python: "3.11" + +sphinx: + configuration: docs/conf.py + +python: + install: + - requirements: docs/requirements.txt + - method: pip + path: . diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..5b6ab6c --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,42 @@ +# Contributing to django-headless-cms + +Contributions are welcome! Here are some pointers to help you install the library for development and validate your changes before submitting a pull request. + +## Install the library for development + +First create your own `venv` and activate it: + +```bash +pythin -m venv .venv +source .venv/bin/activate +``` + +Then we recommend installing the module in editable mode with the `dev` extra requirements: +```bash +pip install -e ".[dev]" -r requirements.txt +``` + +To check it worked, use: +```bash +$ which pip +``` +Result: +```console +some/directory/django-headless-cms/.venv/bin/pip +``` + +## Validate the changes before creating a pull request + +1. Make sure the existing tests are still passing (and consider adding new tests as well!): + +```bash +pytest tests/ +``` + +2. Reformat and validate the code with the following tools: + +```bash +bash scripts/lint.sh [--fix] +``` + +These steps are also run automatically in the CI when you open the pull request. diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..c2f9125 --- /dev/null +++ b/LICENSE @@ -0,0 +1,28 @@ +Copyright © 2024-present, Huy Nguyen . + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..a0bdfa1 --- /dev/null +++ b/README.md @@ -0,0 +1,34 @@ +# Django Headless CMS + +**Django Headless CMS** is your tool for effortless headless CMS creation. +Based on Django, it simplifies dashboard and API development, allowing +you to focus on content creation for any device. Enjoy the flexibility +of headless architecture and the efficiency of Django, reshaping your +CMS workflow. +## Requirements + +* Python 3.9 or greater. +* Django knowledge. + +## Installation + +The module can be installed from [PyPI](https://pypi.org/project/django-headless-cms/): + +```bash +pip install django-headless-cms +``` + +
+Other installation methods (click to expand) + +### Install the latest dev version from github (or replace `@master` with a [@release_version] + +```bash +pip install git+https://github.com/huynguyengl99/django-headless-cms@master +``` + +
+ +## Document +Please visit [Django headless CMS doc](https://django-headless-cms.readthedocs.io/) for +documentation. diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 0000000..d4bb2cb --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,20 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line, and also +# from the environment for the first two. +SPHINXOPTS ?= +SPHINXBUILD ?= sphinx-build +SOURCEDIR = . +BUILDDIR = _build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/docs/conf.py b/docs/conf.py new file mode 100644 index 0000000..f5d0502 --- /dev/null +++ b/docs/conf.py @@ -0,0 +1,36 @@ +# Configuration file for the Sphinx documentation builder. +# +# For the full list of built-in configuration values, see the documentation: +# https://www.sphinx-doc.org/en/master/usage/configuration.html + +# -- Project information ----------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information +import sys +from pathlib import Path + +project = "Django Headless CMS" +copyright = "2024, Huy Nguyen" +author = "Huy Nguyen" +release = "0.0.1" +sys.path.insert(0, str(Path(__file__).parent.parent)) + +# -- General configuration --------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration + +extensions = [ + "sphinx.ext.duration", + "sphinx.ext.doctest", + "sphinx.ext.autodoc", + "sphinx.ext.autosummary", + "sphinx.ext.intersphinx", + "sphinx.ext.napoleon", +] + +templates_path = ["_templates"] +exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] + + +# -- Options for HTML output ------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output +html_theme = "sphinx_rtd_theme" +html_static_path = ["_static"] diff --git a/docs/index.rst b/docs/index.rst new file mode 100644 index 0000000..8454e1d --- /dev/null +++ b/docs/index.rst @@ -0,0 +1,15 @@ +Welcome to Django Headless CMS documentation! +============================================= + +**Django Headless CMS** is your tool for effortless headless CMS creation. +Based on Django, it simplifies dashboard and API development, allowing +you to focus on content creation for any device. Enjoy the flexibility +of headless architecture and the efficiency of Django, reshaping your +CMS workflow. + +.. note:: + + This project is under active development. + +Contents +-------- diff --git a/docs/make.bat b/docs/make.bat new file mode 100644 index 0000000..32bb245 --- /dev/null +++ b/docs/make.bat @@ -0,0 +1,35 @@ +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=. +set BUILDDIR=_build + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.https://www.sphinx-doc.org/ + exit /b 1 +) + +if "%1" == "" goto help + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% + +:end +popd diff --git a/docs/requirements.txt b/docs/requirements.txt new file mode 100644 index 0000000..1533f5c --- /dev/null +++ b/docs/requirements.txt @@ -0,0 +1,2 @@ +Sphinx >=7.0.0,<8 +sphinx_rtd_theme diff --git a/headless_cms/__init__.py b/headless_cms/__init__.py new file mode 100644 index 0000000..2388547 --- /dev/null +++ b/headless_cms/__init__.py @@ -0,0 +1,3 @@ +"""A simple django-based headless CMS.""" + +__version__ = "0.0.1" diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..9a94119 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,114 @@ +[build-system] +build-backend = "hatchling.build" +requires = ["hatchling >= 1.13.0"] + +[project] +authors = [ + {email = "danghuy1999@gmail.com", name = "Huy Nguyen"} +] +classifiers = [ + "Environment :: Web Environment", + "Framework :: Django :: 4.0", + "Framework :: Django :: 4.1", + "Framework :: Django :: 4.2", + "Framework :: Django :: 5.0", + "Framework :: Django", + "Intended Audience :: Developers", + "Intended Audience :: Information Technology", + "License :: OSI Approved :: BSD License", + "Operating System :: OS Independent", + "Programming Language :: Python :: 3 :: Only", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.9", + "Topic :: Internet :: WWW/HTTP :: Dynamic Content", + "Topic :: Internet :: WWW/HTTP", + "Topic :: Software Development :: Libraries :: Application Frameworks", + "Topic :: Software Development :: Libraries", + "Topic :: Software Development" +] +dependencies = [ + "Django>=4", + "django-admin-interface", + "django-admin-sortable2", + "django-localized-fields", + "django-reversion", + "django-solo", + "djangorestframework>=3", + "martor" +] +description = "A simple django-based headless CMS." +dynamic = ["version"] +license = "MIT" +name = "django-headless-cms" +readme = "README.md" +requires-python = ">=3.9" + +[project.urls] +Documentation = "https://django-headless-cms.readthedocs.io/" +Homepage = "https://github.com/huynguyengl99/django-headless-cms" +Repository = "https://github.com/huynguyengl99/django-headless-cms" + +[tool.black] +exclude = ''' +/( + \.git + | \.pytest_cache + | \.vscode + | __pycache__ + | .venv + | build + | coverage +)/ +''' +line-length = 88 +preview = true + +[tool.coverage.run] +omit = [ + "tests/*" +] + +[tool.hatch.build] +exclude = [ + "/.*", + "/scripts", + "/tests" +] + +[tool.hatch.build.targets.wheel] +packages = ["headless_cms"] + +[tool.hatch.version] +path = "headless_cms/__init__.py" + +[tool.ruff] +src = ["headless_cms"] + +[tool.ruff.lint] +ignore = [ + "E501" # line too long, handled by black +] +select = [ + "B", # flake8-bugbear + "C", # flake8-comprehensions + "E", # pycodestyle errors + "ERA", # eradicate + "F", # pyflakes + "I", # isort + "N", # pep8-naming + "PL", # pylint + "Q", # flake8-quotes + "UP", # pyupgrade + "W" # pycodestyle warnings +] + +[tool.ruff.lint.per-file-ignores] +"tests/*" = ["PLR2004"] + +[tool.tomlsort] +all = true +in_place = true +spaces_before_inline_comment = 2 diff --git a/requirements-tests.txt b/requirements-tests.txt new file mode 100644 index 0000000..a81e4bd --- /dev/null +++ b/requirements-tests.txt @@ -0,0 +1,6 @@ +-e .[extra] +pytest +coverage[toml] +ruff +black +toml-sort diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..cb5b925 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,4 @@ +-e .[extra] +-r requirements-tests.txt +-r docs/requirements.txt +pre-commit >=3.4.0,<4.0.0 diff --git a/scripts/lint.sh b/scripts/lint.sh new file mode 100755 index 0000000..b2e5705 --- /dev/null +++ b/scripts/lint.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash + +if [ -d ".venv" ]; then + source .venv/bin/activate +fi + +if [ "$1" == "--fix" ]; then + ruff check . --fix && black ./headless_cms && toml-sort pyproject.toml +else + ruff check . && black ./headless_cms --check && toml-sort pyproject.toml --check +fi