Compare commits

...

5 Commits

9 changed files with 101 additions and 36 deletions

23
.github/workflows/ci.yaml vendored Normal file
View File

@ -0,0 +1,23 @@
name: CI
on:
push:
branches:
- master
jobs:
test-and-check:
name: Tests and checks
uses: daniil-berg/reusable-workflows/.github/workflows/python-test.yaml@v0.0.1
with:
versions: '["3.9", "3.10", "3.11"]'
cache: pip
cache-dependency-path: pyproject.toml
unittest-command: 'scripts/test.sh'
coverage-command: 'scripts/cov.sh'
unittest-requirements: "-e '.[dev]'"
typecheck-command: 'scripts/typecheck.sh'
typecheck-requirements: '-U mypy'
typecheck-all-versions: true
lint-command: 'scripts/lint.sh'
lint-requirements: '-Ur requirements/dev.txt'

View File

@ -20,7 +20,7 @@ keywords = [
] ]
license = { text = "Apache Software License Version 2.0" } license = { text = "Apache Software License Version 2.0" }
classifiers = [ classifiers = [
"Development Status :: 4 - Beta", "Development Status :: 5 - Production/Stable",
"Programming Language :: Python :: 3 :: Only", "Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.10",
@ -52,14 +52,14 @@ dev = [
] ]
[project.urls] [project.urls]
repository = "https://github.com/daniil-berg/marshmallow-generic" "Repository" = "https://github.com/daniil-berg/marshmallow-generic"
bug_tracker = "https://github.com/daniil-berg/marshmallow-generic/issues" "Issue Tracker" = "https://github.com/daniil-berg/marshmallow-generic/issues"
documentation = "http://daniil-berg.github.io/marshmallow-generic" "Documentation" = "http://daniil-berg.github.io/marshmallow-generic"
[tool.setuptools.dynamic] [tool.setuptools.dynamic]
dependencies = { file = "requirements/common.txt" } dependencies = { file = "requirements/common.txt" }
readme = { file = ["README.md"] } readme = { file = ["README.md"], content-type = "text/markdown" }
version = {attr = "marshmallow_generic.__version__"} version = { attr = "marshmallow_generic.__version__" }
######################### #########################
# Static type checking: # # Static type checking: #

12
scripts/ci.sh Executable file
View File

@ -0,0 +1,12 @@
#!/usr/bin/env bash
# Runs full CI pipeline (test, typecheck, lint).
typeset scripts_dir="$(dirname $(realpath $0))"
source "${scripts_dir}/util.sh"
"${scripts_dir}/test.sh"
"${scripts_dir}/typecheck.sh"
"${scripts_dir}/lint.sh"
echo -e "${background_black}${bold_green}✅ 🎉 All checks passed!${color_reset}"

10
scripts/cov.sh Executable file
View File

@ -0,0 +1,10 @@
#!/usr/bin/env bash
# Runs unit tests.
# If successful, prints only the coverage percentage.
# If an error occurs, prints the entire unit tests progress output.
source "$(dirname $(realpath $0))/util.sh"
coverage erase
run_and_capture coverage run
coverage report | awk '$1 == "TOTAL" {print $NF; exit}'

View File

@ -1,18 +1,17 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# Runs type checker and linters. # Runs various linters.
# Ensure that we return to the current working directory source "$(dirname $(realpath $0))/util.sh"
# and exit the script immediately in case of an error:
trap "cd $(realpath ${PWD}); exit 1" ERR
# Change into project root directory:
cd "$(dirname $(dirname $(realpath $0)))"
echo 'Performing type checks...'
mypy
echo
echo 'Linting source and test files...' echo 'Linting source and test files...'
echo ' isort - consistent imports'
isort src/ tests/ --check-only isort src/ tests/ --check-only
echo ' ruff - extensive linting'
ruff src/ tests/ ruff src/ tests/
black src/ tests/ --check
echo -e 'No issues found.' echo ' black - consistent style'
run_and_capture black src/ tests/ --check
echo -e "${bold_green}No issues found${color_reset}\n"

View File

@ -1,17 +1,12 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# Runs unit tests and prints only coverage percentage, if successful. # Runs unit tests and reports coverage percentage.
# If an error occurs, prints the entire unit tests progress output.
# Ensure that we return to the current working directory in case of an error: source "$(dirname $(realpath $0))/util.sh"
trap "cd $(realpath ${PWD})" ERR
# Change into project root directory:
cd "$(dirname $(dirname $(realpath $0)))"
coverage erase echo 'Running unit tests...'
# Capture the test progression in a variable: coverage run
typeset progress typeset percentage
progress=$(coverage run 2>&1) typeset color
# If tests failed or produced errors, write progress/messages to stderr and exit: percentage="$(coverage report | awk '$1 == "TOTAL" {print $NF; exit}')"
[[ $? -eq 0 ]] || { >&2 echo "${progress}"; exit 1; } [[ $percentage == "100%" ]] && color="${bold_green}" || color="${yellow}"
# Otherwise extract the total coverage percentage from the produced report and write it to stdout: echo -e "${color}${percentage} coverage${color_reset}\n"
coverage report | awk '$1 == "TOTAL" {print $NF; exit}'

8
scripts/typecheck.sh Executable file
View File

@ -0,0 +1,8 @@
#!/usr/bin/env bash
# Runs type checker.
source "$(dirname $(realpath $0))/util.sh"
echo 'Performing type checks...'
mypy
echo

20
scripts/util.sh Normal file
View File

@ -0,0 +1,20 @@
run_and_capture() {
# Captures stderr of any command passed to it
# and releases it only if the command exits with a non-zero code.
typeset output
output=$($@ 2>&1)
typeset exit_status=$?
[[ $exit_status == 0 ]] || >&2 echo "${output}"
return $exit_status
}
# Ensure that we return to the current working directory
# and exit the script immediately in case of an error:
trap "cd $(realpath ${PWD}); exit 1" ERR
# Change into project root directory:
cd "$(dirname $(dirname $(realpath $0)))"
typeset background_black='\033[40m'
typeset bold_green='\033[1;92m'
typeset yellow='\033[0;33m'
typeset color_reset='\033[0m'

View File

@ -13,7 +13,7 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License.""" limitations under the License."""
__version__ = "0.0.1" __version__ = "1.0.0"
__doc__ = """ __doc__ = """
Generic schema with full typing support and minimal boilerplate. Generic schema with full typing support and minimal boilerplate.
@ -42,10 +42,8 @@ __all__ = [
] ]
from marshmallow import fields from marshmallow import fields
from marshmallow.decorators import ( # `post_load` overloaded
from marshmallow.decorators import (
post_dump, post_dump,
# post_load, # overloaded
pre_dump, pre_dump,
pre_load, pre_load,
validates, validates,