Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,15 @@ All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](https://semver.org/)

## [Unreleased]

### Changed

- all: update dev-dependencies
- plugin: tailored for Corporate Memory v25.1.x (cmem-plugin-base >= v4.9.0+)
- plugin: example test code now uses integrated Context classes


## [7.1.0] 2025-02-10

### Changed
Expand Down
2 changes: 2 additions & 0 deletions src/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -147,3 +147,5 @@ co
artifacts
.DS_Store
.task
__metadata__.json

7 changes: 3 additions & 4 deletions src/.gitlab-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,17 +46,16 @@ pytest:
- task check:pytest
artifacts:
when: always
name: artifacts-and__metadata__
reports:
coverage_report:
coverage_format: cobertura
path: dist/coverage.xml
junit:
- dist/junit-pytest.xml
paths:
- dist/badge-coverage.svg
- dist/badge-tests.svg
- dist/coverage
- dist/coverage.xml
- __metadata__.json
- dist/*

safety:
stage: test
Expand Down
5 changes: 4 additions & 1 deletion src/README-public.md.jinja
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ cmemc admin workspace python install {{ package_name }}
```
{%- endif %}
{% if github_page -%}[![workflow]({{ github_page }}/actions/workflows/check.yml/badge.svg)]({{ github_page}}/actions){%- endif %} {% if pypi -%}[![pypi version](https://img.shields.io/pypi/v/{{ package_name }})](https://pypi.org/project/{{ package_name }}){%- endif %} {% if pypi -%}[![license](https://img.shields.io/pypi/l/{{ package_name }})](https://pypi.org/project/{{ package_name }}){%- endif %}
[![poetry][poetry-shield]][poetry-link] [![ruff][ruff-shield]][ruff-link] [![mypy][mypy-shield]][mypy-link] [![copier][copier-shield]][copier]
[![poetry][poetry-shield]][poetry-link] [![ruff][ruff-shield]][ruff-link] [![mypy][mypy-shield]][mypy-link] [![copier][copier-shield]][copier] [![{cimd metadata enabled}][cmid-metadata-enabled]][cimd]


{% if project_type == 'plugin' -%}[cmem-link]: https://documentation.eccenca.com
[cmem-shield]: https://img.shields.io/endpoint?url=https://dev.documentation.eccenca.com/badge.json{%- endif %}
Expand All @@ -23,4 +24,6 @@ cmemc admin workspace python install {{ package_name }}
[mypy-shield]: https://www.mypy-lang.org/static/mypy_badge.svg
[copier]: https://copier.readthedocs.io/
[copier-shield]: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/copier-org/copier/master/img/badge/badge-grayscale-inverted-border-purple.json
[cimd]: https://github.com/seebi/cimd
[cmid-metadata-enabled]: https://img.shields.io/badge/%7Bcimd%7D-metadata_enabled-gray?labelColor=orange

5 changes: 4 additions & 1 deletion src/README.md.jinja
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
{{ project_description }}

{% if project_type == 'plugin' -%}[![eccenca Corporate Memory][cmem-shield]][cmem-link] {%- endif %}{% if github_page -%}[![workflow]({{ github_page }}/actions/workflows/check.yml/badge.svg)]({{ github_page}}/actions){%- endif %} {% if pypi -%}[![pypi version](https://img.shields.io/pypi/v/{{ package_name }})](https://pypi.org/project/{{ package_name}}){%- endif %} {% if pypi -%}[![license](https://img.shields.io/pypi/l/{{ package_name }})](https://pypi.org/project/{{ package_name}}){%- endif %}
[![poetry][poetry-shield]][poetry-link] [![ruff][ruff-shield]][ruff-link] [![mypy][mypy-shield]][mypy-link] [![copier][copier-shield]][copier]
[![poetry][poetry-shield]][poetry-link] [![ruff][ruff-shield]][ruff-link] [![mypy][mypy-shield]][mypy-link] [![copier][copier-shield]][copier] [![{cimd metadata enabled}][cmid-metadata-enabled]][cimd]

## Development

Expand All @@ -21,3 +21,6 @@
[mypy-shield]: https://www.mypy-lang.org/static/mypy_badge.svg
[copier]: https://copier.readthedocs.io/
[copier-shield]: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/copier-org/copier/master/img/badge/badge-grayscale-inverted-border-purple.json
[cimd]: https://github.com/seebi/cimd
[cmid-metadata-enabled]: https://img.shields.io/badge/%7Bcimd%7D-metadata_enabled-gray?labelColor=orange

72 changes: 55 additions & 17 deletions src/Taskfile.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ tasks:
clean:
desc: Removes dist, *.pyc and some caches
cmds:
- rm -rf {{.DIST_DIR}} .mypy_cache .pytest_cache
- rm -rf {{.DIST_DIR}} .mypy_cache .pytest_cache __metadata__.json
- find . -name "*.pyc" -print0 | xargs -0 rm || echo ""

# }}}
Expand All @@ -120,29 +120,67 @@ tasks:
# --memray is not used on windows
- platforms: [windows]
cmd: >
poetry run pytest --junitxml={{.JUNIT_FILE}}
--cov-report term --cov-report xml:{{.COVERAGE_FILE}}
--cov-report html:{{.COVERAGE_DIR}} --cov={{.PACKAGE}}
--html={{.HTML_FILE}} --self-contained-html
poetry run pytest
--cov={{.PACKAGE}}
--junitxml={{.PYTEST_XML}}
--html={{.PYTEST_HTML}} --self-contained-html
--cov-report term
--cov-report xml:{{.COVERAGE_FILE}}
--cov-report html:{{.COVERAGE_DIR}}
| tee {{.PYTEST_LOG}}
- platforms: [darwin, linux]
cmd: >
poetry run pytest --memray --junitxml={{.JUNIT_FILE}}
--cov-report term --cov-report xml:{{.COVERAGE_FILE}}
--cov-report html:{{.COVERAGE_DIR}} --cov={{.PACKAGE}}
--html={{.HTML_FILE}} --self-contained-html
- cmd: >
poetry run genbadge coverage -l
-i {{.COVERAGE_FILE}} -o {{.BADGE_COVERAGE}}
- cmd: >
poetry run genbadge tests -l
-i {{.JUNIT_FILE}} -o {{.BADGE_TESTS}}
poetry run pytest
--cov={{.PACKAGE}}
--memray --most-allocations=1
--junitxml={{.PYTEST_XML}}
--html={{.PYTEST_HTML}} --self-contained-html
--cov-report term
--cov-report xml:{{.COVERAGE_FILE}}
--cov-report html:{{.COVERAGE_DIR}}
| tee {{.PYTEST_LOG}}
- >
poetry run genbadge coverage -l
-i {{.COVERAGE_FILE}} -o {{.BADGE_COVERAGE}}
- >
poetry run genbadge tests -l
-i {{.PYTEST_XML}} -o {{.BADGE_TESTS}}
- poetry run cimd extract coverage-xml {{.COVERAGE_FILE}}
- poetry run cimd extract junit-xml {{.PYTEST_XML}}
- poetry run cimd delete --field value 0
- |
if [[ "$CI_JOB_URL" != "" ]]; then
poetry run cimd extend gitlab-link coverage-xml-line-rate --artifact-path {{.COVERAGE_DIR}}/index.html
poetry run cimd extend gitlab-link "junit-xml.*" --artifact-path {{.PYTEST_HTML}}
fi
- platforms: [darwin, linux]
task: check:pytest:cimd
vars:
BADGE_COVERAGE: ./{{.DIST_DIR}}/badge-coverage.svg
BADGE_TESTS: ./{{.DIST_DIR}}/badge-tests.svg
COVERAGE_DIR: ./{{.DIST_DIR}}/coverage
COVERAGE_FILE: ./{{.DIST_DIR}}/coverage.xml
HTML_FILE: ./{{.DIST_DIR}}/pytest.html
JUNIT_FILE: ./{{.DIST_DIR}}/junit-pytest.xml
PYTEST_HTML: ./{{.DIST_DIR}}/pytest.html
PYTEST_XML: ./{{.DIST_DIR}}/junit-pytest.xml
PYTEST_LOG: ./{{.DIST_DIR}}/pytest.log

check:pytest:cimd:
desc: prepare cimd metadata for pytest stage
internal: true
cmds:
- >
poetry run cimd add memray-max-memory {{.MAX_MEMORY}}
--label "Max Memory"
--description "Highest total memory allocated in a single test"
--image "https://img.shields.io/badge/Max%20Memory-{{.MAX_MEMORY}}-yellow"
- |
if [[ "$CI_JOB_URL" != "" ]]; then
poetry run cimd extend gitlab-link "memray.*" --artifact-path {{.PYTEST_LOG}}
fi
vars:
PYTEST_LOG: ./{{.DIST_DIR}}/pytest.log
MAX_MEMORY:
sh: cat {{.PYTEST_LOG}} | grep "Total memory allocated" | cut -d ":" -f 2 | tr -d "[:blank:]"

check:mypy:
desc: Complain about typing errors
Expand Down
9 changes: 5 additions & 4 deletions src/pyproject.toml.jinja
Original file line number Diff line number Diff line change
Expand Up @@ -20,22 +20,23 @@ python = "^3.11"{%- else %}
python = ">=3.11, ^3"{%- endif %}

{% if project_type == 'plugin' -%}[tool.poetry.dependencies.cmem-plugin-base]
version = "^4.8.0"
version = "^4.9.0"
allow-prereleases = false

[tool.poetry.group.dev.dependencies.cmem-cmemc]
version = "^24.3.0"{%- endif %}

[tool.poetry.group.dev.dependencies]
cimd = "^0"
genbadge = {extras = ["coverage"], version = "^1.1.1"}
mypy = "^1.14.1"
pip = "^25.0"
mypy = "^1.15.0"
pip = "^25.0.1"
pytest = "^8.3.4"
pytest-cov = "^6.0.0"
pytest-dotenv = "^0.5.2"
pytest-html = "^4.1.1"
pytest-memray = { version = "^1.7.0", markers = "platform_system != 'Windows'" }
ruff = "^0.9.4"
ruff = "^0.9.7"
safety = "^1.10.3"

[build-system]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ Remove this and other example files after bootstrapping your project.
"""

import io
import os
from collections.abc import Generator
from typing import Any

import pytest
from cmem.cmempy.workspace.projects.datasets.dataset import make_new_dataset
Expand All @@ -12,40 +15,47 @@ from cmem.cmempy.workspace.projects.resources.resource import (
create_resource,
get_resource_response,
)
from cmem_plugin_base.testing import TestExecutionContext

from {{ package_dir }}.example_transform import Lifetime
from {{ package_dir }}.example_workflow import DollyPlugin
from tests.utils import TestExecutionContext, needs_cmem

PROJECT_NAME = "{{ package_dir }}_test_project"
DATASET_NAME = "sample_dataset"
RESOURCE_NAME = "sample_dataset.txt"
DATASET_TYPE = "text"
needs_cmem = pytest.mark.skipif(
os.environ.get("CMEM_BASE_URI", "") == "", reason="Needs CMEM configuration"
)


class BuildProject:
"""Build Project Fixture"""

project_name = "{{ package_dir }}_test_project"
dataset_name = "sample_dataset"
resource_name = "sample_dataset.txt"
dataset_type = "text"
dataset_content = "{{ package_dir }} plugin sample file."


@pytest.fixture
def di_environment() -> object:
def build_project() -> Generator[BuildProject, Any, None]:
"""Provide the DI build project incl. assets."""
make_new_project(PROJECT_NAME)
_ = BuildProject()
make_new_project(_.project_name)
make_new_dataset(
project_name=PROJECT_NAME,
dataset_name=DATASET_NAME,
dataset_type=DATASET_TYPE,
parameters={"file": RESOURCE_NAME},
project_name=_.project_name,
dataset_name=_.dataset_name,
dataset_type=_.dataset_type,
parameters={"file": _.resource_name},
autoconfigure=False,
)
with io.StringIO("{{ package_name }} plugin sample file.") as response_file:
with io.StringIO(_.dataset_content) as response_file:
create_resource(
project_name=PROJECT_NAME,
resource_name=RESOURCE_NAME,
project_name=_.project_name,
resource_name=_.resource_name,
file_resource=response_file,
replace=True,
)
yield {
"project": PROJECT_NAME,
"dataset": RESOURCE_NAME,
}
delete_project(PROJECT_NAME)
yield _
delete_project(_.project_name)


@needs_cmem
Expand Down Expand Up @@ -74,7 +84,7 @@ def test_transform_execution_with_inputs() -> None:


@needs_cmem
def test_integration_placeholder(di_environment: dict) -> None:
def test_integration_placeholder(build_project: BuildProject) -> None:
"""Placeholder to write integration testcase with cmem"""
with get_resource_response(di_environment["project"], di_environment["dataset"]) as response:
assert response.text != ""
with get_resource_response(build_project.project_name, build_project.resource_name) as response:
assert response.text == build_project.dataset_content

This file was deleted.