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
91 changes: 69 additions & 22 deletions copier.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -38,45 +38,92 @@ _templates_suffix: .jinja
_answers_file: .copier-answers.yml

# === copier user provided ===
module_short_name:
module_code_name:
type: str
help: Please enter your module's short name as used in snakemake (should be in `snake_case`). This will be folder name within which your module lives.
help: |
Please enter your module's name as used in code in `snake_case`. This will be used for GitHub and Snakemake access.
💡 Core modules should start with "module_" as a convention.
default: module_
validator: >-
{% if not (module_short_name | regex_search('^[a-z][a-z0-9_]*$')) %}
{% if not (module_code_name | regex_search('^[a-z][a-z0-9_]*$')) %}
"Only lowercase letters, digits and underscores are valid."
{% endif %}
module_long_name:
module_human_name:
type: str
help: Please enter your module's long name (e.g., PV capacity factors, Hydropower, Heat-pump profiles, etc).
help: |
Please enter your module's human readable name (e.g., PV capacity factors, Hydropower, Heat-pump profiles, etc).
💡 This name will be used in the Modelblocks website, citation files and README documentation.
module_description:
type: str
help: "Please provide a description of your module."
author_given_name:
type: str
help: "Please provide your given name (e.g., Ursula)."
author_family_name:
type: str
help: "Please provide your family name (e.g., Le Guin)."
author_email:
type: str
help: Please provide your email address.
help: |
Please provide a description of your module.
💡 These will be used as the README's introduction.
authors:
type: yaml
multiline: true
help: |
Please provide a list of module authors (i.e., the people that wrote the software).
💡 These will be listed in licensing files and referenced when citing the software.
💡 Each author needs a given_name, family_name, and email fields.
💡 Multiple authors are possible (separate them with '-').
default:
- given_name: Ursula
family_name: Le Guin
email: ursula.leguin@example.com
validator: >-
{% if not (author_email | regex_search('^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+[.][a-zA-Z0-9-.]+$')) %}
"Invalid email address."
{% if authors is not sequence or authors is string or authors | length == 0 %}
Please provide at least one author as a YAML list.
{% else %}
{% for author in authors %}
{% if author is not mapping %}
Author {{ loop.index }} must be a mapping with given_name, family_name, and email.
{% elif not author.given_name or not author.family_name or not author.email %}
Author {{ loop.index }} must include given_name, family_name, and email.
{% elif not (author.email | regex_search('^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+[.][a-zA-Z0-9-.]+$')) %}
Invalid email address for author {{ loop.index }}.
{% endif %}
{% endfor %}
{% endif %}
maintainers:
type: yaml
multiline: true
help: |
Please provide the module maintainers (i.e., the people currently responsible for the software).
💡 Similar to authors, each needs a given_name, family_name, and email.
💡 The same person can be both an author and a maintainer.
default:
- given_name: Juan
family_name: Rulfo
email: j.rulfo@example.com
validator: >-
{% if maintainers is not sequence or maintainers is string or maintainers | length == 0 %}
Please provide at least one maintainer as a YAML list.
{% else %}
{% for maintainer in maintainers %}
{% if maintainer is not mapping %}
Maintainer {{ loop.index }} must be a mapping with given_name, family_name, and email.
{% elif not maintainer.given_name or not maintainer.family_name or not maintainer.email %}
Maintainer {{ loop.index }} must include given_name, family_name, and email.
{% elif not (maintainer.email | regex_search('^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+[.][a-zA-Z0-9-.]+$')) %}
Invalid email address for maintainer {{ loop.index }}.
{% endif %}
{% endfor %}
{% endif %}
github_org:
type: str
help: >-
Please provide the name of the github account or organisation where
this module will be created (e.g., 'modelblocks-org' in 'github.com/modelblocks-org').
help: |
Please provide the name of the github account or organisation where this module will be created.
💡 For example: 'modelblocks-org' in 'github.com/modelblocks-org'.
default: "modelblocks-org"
validator: >-
{% if not (github_org | regex_search('^[a-zA-Z0-9][a-zA-Z0-9-]*$')) %}
"Only lowercase letters, digits, hyphens and underscores are valid."
{% endif %}
default: "modelblocks-org"
license:
type: str
help: "Please choose a license."
help: |
Please choose a license.
💡 Core modules must use Apache-2.0 as a standard.
choices:
- "Apache-2.0"
- "MIT"
2 changes: 1 addition & 1 deletion template/.all-contributorsrc.jinja
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"projectName": "{{module_short_name}}",
"projectName": "{{module_code_name}}",
"projectOwner": "{{github_org}}",
"repoType": "github",
"repoHost": "https://github.com",
Expand Down
6 changes: 4 additions & 2 deletions template/AUTHORS.jinja
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ This is the list of contributors for copyright purposes.

This does not necessarily list everyone who has contributed to this software's
code or documentation. For a full contributor list, see:
<https://github.com/{{github_org}}/{{module_short_name}}/graphs/contributors>
<https://github.com/{{github_org}}/{{module_code_name}}/blob/main/.all-contributorsrc>
<https://github.com/{{github_org}}/{{module_code_name}}/graphs/contributors>

{{author_given_name}} {{author_family_name}}, <{{author_email}}>
{% for author in authors %}{{ author.given_name }} {{ author.family_name }}, <{{ author.email }}>
{% endfor %}
10 changes: 6 additions & 4 deletions template/CITATION.cff.jinja
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@
# https://citation-file-format.github.io/
cff-version: 1.2.0
message: If you use this software or data produced by it, please cite it using the metadata from this file.
title: "Modelblocks - {{module_short_name}}: {{module_long_name}}"
repository: "https://github.com/{{github_org}}/{{module_short_name}}"
title: "Modelblocks - {{module_code_name}}: {{module_human_name}}"
repository: "https://github.com/{{github_org}}/{{module_code_name}}"
license: {{license}}
authors:
- given-names: {{author_given_name}}
family-names: {{author_family_name}}
{% for author in authors %} - given-names: {{ author.given_name | tojson }}
family-names: {{ author.family_name | tojson }}
email: {{ author.email | tojson }}
{% endfor %}
9 changes: 6 additions & 3 deletions template/README.md.jinja
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
# {{module_long_name}}
# {{module_human_name}}

{{module_description}}

<!-- Place an attractive image of module outputs here -->
<p align="center">
<img src="./figures/module.png" width="75%">
</p>


## About
Expand Down Expand Up @@ -39,8 +42,8 @@ We use [`pixi`](https://pixi.sh/) as our package manager for development.
Once installed, run the following to clone this repository and install all dependencies.

```shell
git clone git@github.com:{{github_org}}/{{module_short_name}}.git
cd {{module_short_name}}
git clone git@github.com:{{github_org}}/{{module_code_name}}.git
cd {{module_code_name}}
pixi install --all
```

Expand Down
Binary file added template/figures/module.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion template/pixi.toml.jinja
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[workspace]
name = "{{ module_short_name }}"
name = "{{ module_code_name }}"
authors = ["See AUTHORS file"]
description = "{{ module_description }}"
license = "{{ license }}"
Expand Down
2 changes: 1 addition & 1 deletion template/tests/integration/test_config.yaml.jinja
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{{module_short_name}}:
{{module_code_name}}:
dummy_text: >-
Configuration values (like this one) are also external to the module!
This gives users a lot of flexibility in how they apply your methodology to solve their particular needs.
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ rule create_external_input:
# `snakefile:` specifies the module. It can use file paths and special github(...) / gitlab(...) markers
# `config`: specifies the module configuration.
# `pathvars:` helps you re-wire where the module places files.
module {{module_short_name}}:
module {{module_code_name}}:
snakefile: "../../workflow/Snakefile"
config: config["{{module_short_name}}"]
config: config["{{module_code_name}}"]
pathvars:
# Redirect specific user resources (inputs)
user_message=rules.create_external_input.output.text_file,
Expand All @@ -36,7 +36,7 @@ module {{module_short_name}}:


# rename all module rules with a prefix, to avoid naming conflicts.
use rule * from {{module_short_name}} as {{module_short_name}}_*
use rule * from {{module_code_name}} as {{module_code_name}}_*

# Request something from the module
rule all:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@
same "printed page" as the copyright notice for easier
identification within third-party archives.

Copyright {{ '%Y' | strftime }} AUTHORS
Copyright [yyyy] [name of copyright owner]

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand Down
74 changes: 74 additions & 0 deletions tests/template_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,83 @@
from pathlib import Path

import pytest
import yaml
from copier import run_copy


class TestTemplateAuthors:
"""Build and check author metadata rendering."""

def test_multiple_authors_are_rendered(
self, tmp_path, template_path, simple_answers
):
"""Multiple author answers should render in metadata files."""
answers = deepcopy(simple_answers)
answers["authors"] = [
{
"given_name": "Ursula",
"family_name": "Le Guin",
"email": "ursula.leguin@example.com",
},
{
"given_name": "Stanislaw",
"family_name": "Lem",
"email": "s.lem@example.com",
},
]

run_copy(
src_path=str(template_path),
dst_path=str(tmp_path),
data=answers,
vcs_ref="HEAD",
)

copier_answers = yaml.safe_load((tmp_path / ".copier-answers.yml").read_text())
assert copier_answers["authors"] == answers["authors"]

authors = (tmp_path / "AUTHORS").read_text()
assert "Ursula Le Guin, <ursula.leguin@example.com>" in authors
assert "Stanislaw Lem, <s.lem@example.com>" in authors

citation = (tmp_path / "CITATION.cff").read_text()
assert 'given-names: "Ursula"' in citation
assert 'family-names: "Lem"' in citation
assert 'email: "s.lem@example.com"' in citation


class TestTemplateMaintainers:
"""Build and check maintainer answer rendering."""

def test_multiple_maintainers_are_stored(
self, tmp_path, template_path, simple_answers
):
"""Multiple maintainer answers should be stored for documentation."""
answers = deepcopy(simple_answers)
answers["maintainers"] = [
{
"given_name": "Juan",
"family_name": "Rulfo",
"email": "j.rulfo@example.com",
},
{
"given_name": "Toni",
"family_name": "Morrison",
"email": "toni.morrison@example.com",
},
]

run_copy(
src_path=str(template_path),
dst_path=str(tmp_path),
data=answers,
vcs_ref="HEAD",
)

copier_answers = yaml.safe_load((tmp_path / ".copier-answers.yml").read_text())
assert copier_answers["maintainers"] == answers["maintainers"]


class TestBuiltTemplate:
"""Build and check the resulting template."""

Expand Down
17 changes: 11 additions & 6 deletions tests/utils/simple_answers.yaml
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
module_short_name: test_module
module_long_name: Test module
module_code_name: test_module
module_human_name: Test module
module_description: A simple module to test the template
author_given_name: Tester
author_family_name: McTest
author_email: tester.mctest@example.com
authors:
- given_name: Tester
family_name: McTest
email: tester.mctest@example.com
maintainers:
- given_name: Maintain
family_name: McMaintainer
email: maintain.mcmaintainer@example.com
github_org: modelblocks-org
license:
license: "Apache-2.0"
Loading