Skip to content

Commit

Permalink
feat: switch from copier to cookiecutter
Browse files Browse the repository at this point in the history
  • Loading branch information
smotornyuk committed Nov 19, 2024
1 parent 98b28d7 commit 0da6d0f
Show file tree
Hide file tree
Showing 153 changed files with 395 additions and 537 deletions.
2 changes: 1 addition & 1 deletion MANIFEST.in
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ include LICENSE
include requirements.txt
recursive-include ckanext/toolbelt *.html *.json *.js *.less *.css *.mo *.yml *.yaml *.toml *.sh *.ini
recursive-include ckanext/toolbelt/migration *.ini *.py *.mako
recursive-include ckanext/toolbelt/cli/copier *
recursive-include ckanext/toolbelt/cli/cookiecutter *
recursive-exclude * *.pyc
9 changes: 9 additions & 0 deletions ckanext/toolbelt/cli/cookiecutter/extended/cookiecutter.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"project": "Project's name",
"description": "",
"author": "",
"author_email": "",
"github_user_name": "",
"project_shortname": "{{ cookiecutter.project[8:].lower().replace('-','_') }}",
"plugin_class_name": "{{ cookiecutter.project_shortname.title().replace('_','') }}Plugin"
}
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,4 @@ jobs:
ckan -c test.ini db upgrade
- name: Run tests
run: pytest --ckan-ini=test.ini --cov=ckanext.{{ project_shortname }} --disable-warnings ckanext
run: pytest --ckan-ini=test.ini --cov=ckanext.{{ cookiecutter.project_shortname }} --disable-warnings ckanext
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ sdist/
*.egg-info/
.installed.cfg
*.egg
{{_copier_conf.answers_file}}

# PyInstaller
# Usually these files are written by a python script from a template
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
include README.md
include LICENSE
include requirements.txt
recursive-include ckanext/{{ cookiecutter.project_shortname }} *.html *.json *.js *.less *.css *.mo *.yml *.yaml *.cfg *.toml
recursive-include ckanext/{{ cookiecutter.project_shortname }}/migration *.ini *.py *.mako
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ _version = master
prepare: ## download CDM rules
curl -O https://raw.githubusercontent.com/DataShades/ckan-deps-installer/$(_version)/deps.mk

vendor-dir = ckanext/{{ project_shortname }}/assets/vendor
vendor-dir = ckanext/{{ cookiecutter.project_shortname }}/assets/vendor

vendor: ## Copy vendor libraries from node_modules/ to assets directory
cp node_modules/tom-select/dist/js/tom-select.{base,complete}.min.js $(vendor-dir)
Expand All @@ -139,12 +139,12 @@ vendor: ## Copy vendor libraries from node_modules/ to assets directory
cp node_modules/izitoast/dist/js/iziToast.js $(vendor-dir)
cp node_modules/slick-carousel/slick/slick.{js,css} $(vendor-dir)
cp node_modules/slick-carousel/slick/slick-theme.css $(vendor-dir)
cp node_modules/slick-carousel/slick/ajax-loader.gif ckanext/{{ project_shortname }}/public
cp node_modules/slick-carousel/slick/fonts ckanext/{{ project_shortname }}/public/slick-fonts -r
cp node_modules/daterangepicker/daterangepicker.{js,css} ckanext/{{ project_shortname }}/assets/vendor
cp node_modules/daterangepicker/moment.min.js ckanext/{{ project_shortname }}/assets/vendor
cp node_modules/overlayscrollbars/styles/overlayscrollbars.css ckanext/{{ project_shortname }}/assets/vendor
cp node_modules/overlayscrollbars/browser/overlayscrollbars.browser.es6.js ckanext/{{ project_shortname }}/assets/vendor/overlayscrollbars.js
cp node_modules/slick-carousel/slick/ajax-loader.gif ckanext/{{ cookiecutter.project_shortname }}/public
cp node_modules/slick-carousel/slick/fonts ckanext/{{ cookiecutter.project_shortname }}/public/slick-fonts -r
cp node_modules/daterangepicker/daterangepicker.{js,css} ckanext/{{ cookiecutter.project_shortname }}/assets/vendor
cp node_modules/daterangepicker/moment.min.js ckanext/{{ cookiecutter.project_shortname }}/assets/vendor
cp node_modules/overlayscrollbars/styles/overlayscrollbars.css ckanext/{{ cookiecutter.project_shortname }}/assets/vendor
cp node_modules/overlayscrollbars/browser/overlayscrollbars.browser.es6.js ckanext/{{ cookiecutter.project_shortname }}/assets/vendor/overlayscrollbars.js

typecheck: ## Run typechecker
npx pyright --pythonpath="$$(which python)"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[![Tests](https://github.com/{{ github_user_name }}/{{ project }}/workflows/tests.yml/badge.svg)](https://github.com/{{ github_user_name }}/{{ project }}/actions/workflows/test.yml)
[![Tests](https://github.com/{{ cookiecutter.github_user_name }}/{{ cookiecutter.project }}/workflows/tests.yml/badge.svg)](https://github.com/{{ cookiecutter.github_user_name }}/{{ cookiecutter.project }}/actions/workflows/test.yml)

# {{ project }}
# {{ cookiecutter.project }}

Extended template of CKAN extension.

Expand Down Expand Up @@ -111,7 +111,7 @@ registered by extension.
## Code
Code of the extension resides inside `ckanext/{{project_shortname}}`.
Code of the extension resides inside `ckanext/{{ cookiecutter.project_shortname }}`.
### `plugin.py`
Expand Down Expand Up @@ -147,17 +147,17 @@ There are 7 blankets in CKAN:
| Blanket | Effect |
|---------------------|-----------------------------------------------------------------------------------------------------|
| actions | Register all public functions from `ckanext.{{ project_shortname }}.logic.action` as actions |
| auth_functions | Register all public functions from `ckanext.{{ project_shortname }}.logic.auth` as auth functions |
| blueprints | Register all blueprints from `ckanext.{{ project_shortname }}.views` as blueprints |
| cli | Register all public members(`__all__`) from `ckanext.{{ project_shortname }}.cli` as commands |
| config_declarations | Register all declarations from `ckanext/{{ project_shortname }}/config_declaration.yaml` |
| helpers | Register all public functions from `ckanext.{{ project_shortname }}.helpers` as helpers |
| validators | Register all public functions from `ckanext.{{ project_shortname }}.logic.validators` as validators |
| actions | Register all public functions from `ckanext.{{ cookiecutter.project_shortname }}.logic.action` as actions |
| auth_functions | Register all public functions from `ckanext.{{ cookiecutter.project_shortname }}.logic.auth` as auth functions |
| blueprints | Register all blueprints from `ckanext.{{ cookiecutter.project_shortname }}.views` as blueprints |
| cli | Register all public members(`__all__`) from `ckanext.{{ cookiecutter.project_shortname }}.cli` as commands |
| config_declarations | Register all declarations from `ckanext/{{ cookiecutter.project_shortname }}/config_declaration.yaml` |
| helpers | Register all public functions from `ckanext.{{ cookiecutter.project_shortname }}.helpers` as helpers |
| validators | Register all public functions from `ckanext.{{ cookiecutter.project_shortname }}.logic.validators` as validators |
Because of blankets, you don't need to import views, CLI commands or actions
into plugin. You don't even have to register `get_actions`-like function. Any
function defined inside `ckanext.{{ project_shortname }}.logic.action` will be
function defined inside `ckanext.{{ cookiecutter.project_shortname }}.logic.action` will be
registered as an action with the same name, if it's not prefixed with
underscore. Imported functions are not registered as actions: you have to
create function inside the `action` module to export it automatically.
Expand All @@ -168,7 +168,7 @@ blanket:

```python
@tk.blanket.actions(get_actions)
class {{ plugin_class_name }}(p.SingletonPlugin):
class {{ cookiecutter.plugin_class_name }}(p.SingletonPlugin):
...
```

Expand All @@ -186,7 +186,7 @@ Other interfaces usually are quite complex. The recommended way of implementing
these interfaces(and custom interfaces from extensions, like IFiles) includes
extra steps.
First, create a module inside `ckanext.{{ project_shortname }}.implementations`
First, create a module inside `ckanext.{{ cookiecutter.project_shortname }}.implementations`
using snake-case version of the interface name. For example,
`IPackageController` turns into `package_controller.py`, `IAdminPanel` turns
into `admin_panel.py`.
Expand All @@ -203,7 +203,7 @@ class PackageController(SingletonPlugin):
...
```
Re-export implementation from `ckanext/{{ project_shortname }}/implementations/__init__.py`
Re-export implementation from `ckanext/{{ cookiecutter.project_shortname }}/implementations/__init__.py`
```python
from .package_controller import PackageController
Expand All @@ -218,7 +218,7 @@ And finally add this implementation as a parent class to your main plugin:
```python
from . import implementations
class {{ plugin_class_name }}(
class {{ cookiecutter.plugin_class_name }}(
implementations.PackageController,
p.SingletonPlugin,
):
Expand All @@ -234,7 +234,7 @@ readable.
Define all commands here. It's recommended to create a single `click` group
that maches the name of the plugin and add this group to `__all__` attribute of
the module. As result, only this group will be available as `ckan {{
project_shortname }}` CLI command.
cookiecutter.project_shortname }}` CLI command.
All commands should be registered under this group or its subgroups.
Expand Down Expand Up @@ -270,7 +270,7 @@ Instead of accessing untyped options inside `tk.config`, it's recommended to
define typed accessors inside this module. It improves a number of aspects:
* config options can be accessed by shorter name: `option()` instead of
`tk.config["ckanext.{{ project_shortname }}.option.name"]`.
`tk.config["ckanext.{{ cookiecutter.project_shortname }}.option.name"]`.
* accessor has specific type, while `tk.config[KEY]` is always `Any`
* any additional processing of options value can be hidden inside the accessor
* you can safely change the name of the config option
Expand Down Expand Up @@ -316,15 +316,15 @@ also be stored inside assets folder.
Assets cannot be accessed directly. You have to define [named
asset](https://docs.ckan.org/en/2.10/contributing/frontend/assets.html) inside
`assets/webassets.yml` and include this named asset into template using `{{
'{%' }} asset "{{ project_shortname }}/ASSET_NAME" {{ '%}' }}` tag.
'{%' }} asset "{{ cookiecutter.project_shortname }}/ASSET_NAME" {{ '%}' }}` tag.

### `templates/`

This is the base folder for Jinja2 templates. Templates that override existing
pages must replicate structure of CKAN's `templates` folder. If you are going
to create a completely new page, prefer storing templates for it inside
separate subfolder with the name matching the plugin name. For example,
template for the blog page may be stored as `templates/{{ project_shortname
template for the blog page may be stored as `templates/{{ cookiecutter.project_shortname
}}/blog/index.html`.
### `logic/action.py`
Expand Down Expand Up @@ -366,7 +366,7 @@ All public members defined in this module are registered as validators by
Folder for all your models. Define every model in a separate file. Don't forget
to generate migrations for the model using `ckan generate migration -p {{
project_shortname }} -m "Migration message"` CLI command.
cookiecutter.project_shortname }} -m "Migration message"` CLI command.

### `schemas/`

Expand All @@ -379,7 +379,7 @@ configurations are stored here. Apart from `project.ini` with the project level
configuration, you can also keep `licenses.json`, `resource_formats.json`,
`who.ini`, SAML2 credentials, GoogleCloud credentials, etc. You can even store
metadata schemas here, but historically they are kept together with the code,
so we suggest leaving them inside `ckanext/{{ project_shortname }}/schemas`.
so we suggest leaving them inside `ckanext/{{ cookiecutter.project_shortname }}/schemas`.

### `project.ini`

Expand Down Expand Up @@ -1070,12 +1070,12 @@ Ruff configuration is managed by `[tool.ruff.*]` sections of `pyproject.toml`.
Majority of tests for the extension is written using `pytest`.
`ckanext/{{ project_shortname }}/tests` contains examples of tests for standard
`ckanext/{{ cookiecutter.project_shortname }}/tests` contains examples of tests for standard
operations. Every `test_*.py` file contains tests. Every `conftest.py` file
defines fixtures that are available for modules on the same level and child
modules.
`ckanext/{{ project_shortname }}/tests/benchmarks` contains benchmarks. They
`ckanext/{{ cookiecutter.project_shortname }}/tests/benchmarks` contains benchmarks. They
are written in the same way as normal tests, but we are using them to measure
code performance. By default, all benchmarks are excluded from selection when
pytest in running. You need to run benchmarks explicitely using `-m benchmark`
Expand All @@ -1096,10 +1096,10 @@ If possible, try achieving 100% test coverage. To measure current coverage, use
```sh
## print coverage to terminal
pytest --cov=ckanext.{{ project_shortname }}
pytest --cov=ckanext.{{ cookiecutter.project_shortname }}
## generate HTML report at htmlcov/index.html
pytest --cov=ckanext.{{ project_shortname }} --cov-report html
pytest --cov=ckanext.{{ cookiecutter.project_shortname }} --cov-report html
```
#### Run tests
Expand All @@ -1110,10 +1110,10 @@ Run all tests
pytest
```
Run tests from `ckanext/{{ project_shortname }}/tests/test_plugin.py`
Run tests from `ckanext/{{ cookiecutter.project_shortname }}/tests/test_plugin.py`
```sh
pytest ckanext/{{ project_shortname }}/tests/test_plugin.py
pytest ckanext/{{ cookiecutter.project_shortname }}/tests/test_plugin.py
```
Run only tests that failed during previous test session
Expand All @@ -1129,7 +1129,7 @@ pytest -x
```
Run only tests that contain `hello` and `world` in their full path. Full path
contains filepath, class and test name: `ckanext/{{ project_shortname
contains filepath, class and test name: `ckanext/{{ cookiecutter.project_shortname
}}/tests/test_smth.py:TestSmth:test_smth`
```sh
Expand All @@ -1139,7 +1139,7 @@ pytest -k "hello and world"
#### Produce coverage report
```sh
pytest --cov=ckanext.{{ project_shortname }}
pytest --cov=ckanext.{{ cookiecutter.project_shortname }}
```
#### Run benchmarks
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* Daterangepicker adapter.
* https://www.daterangepicker.com/
*/
ckan.module("{{ project_shortname }}-datepicker", function ($) {
ckan.module("{{ cookiecutter.project_shortname }}-datepicker", function ($) {
return {
options: {},

Expand All @@ -11,12 +11,12 @@ ckan.module("{{ project_shortname }}-datepicker", function ($) {
if (typeof $.fn.daterangepicker === "undefined") {
// reporting the source of the problem is always a good idea.
console.error(
"[{{ project_shortname }}-datepicker] daterangepicker library is not loaded",
"[{{ cookiecutter.project_shortname }}-datepicker] daterangepicker library is not loaded",
);
return;
}

const options = this.sandbox["{{ project_shortname }}"].nestedOptions(
const options = this.sandbox["{{ cookiecutter.project_shortname }}"].nestedOptions(
this.options,
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* iziModal adapter.
* https://izimodal.marcelodolza.com
*/
ckan.module("{{ project_shortname }}-izi-modal", function ($) {
ckan.module("{{ cookiecutter.project_shortname }}-izi-modal", function ($) {
return {
options: {},

Expand All @@ -11,7 +11,7 @@ ckan.module("{{ project_shortname }}-izi-modal", function ($) {
if (typeof $.fn.iziModal === "undefined") {
// reporting the source of the problem is always a good idea.
console.error(
"[{{ project_shortname }}-izi-modal] iziModal library is not loaded",
"[{{ cookiecutter.project_shortname }}-izi-modal] iziModal library is not loaded",
);
return;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* iziToast adapter.
* https://izitoast.marcelodolza.com
*/
ckan.module("{{ project_shortname }}-izi-toast", function ($) {
ckan.module("{{ cookiecutter.project_shortname }}-izi-toast", function ($) {
return {
options: {},

Expand All @@ -11,7 +11,7 @@ ckan.module("{{ project_shortname }}-izi-toast", function ($) {
if (typeof iziToast === "undefined") {
// reporting the source of the problem is always a good idea.
console.error(
"[{{ project_shortname }}-izi-toast] iziToast library is not loaded",
"[{{ cookiecutter.project_shortname }}-izi-toast] iziToast library is not loaded",
);
return;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* OverlayScrollbars adapter.
* https://kingsora.github.io/OverlayScrollbars/
*/
ckan.module("{{ project_shortname }}-scrollbar", function ($) {
ckan.module("{{ cookiecutter.project_shortname }}-scrollbar", function ($) {
return {
options: {},

Expand All @@ -11,12 +11,12 @@ ckan.module("{{ project_shortname }}-scrollbar", function ($) {
if (typeof OverlayScrollbarsGlobal === "undefined") {
// reporting the source of the problem is always a good idea.
console.error(
"[{{ project_shortname }}-scrollbar] OverlayScrollbars library is not loaded",
"[{{ cookiecutter.project_shortname }}-scrollbar] OverlayScrollbars library is not loaded",
);
return;
}

const options = this.sandbox["{{ project_shortname }}"].nestedOptions(
const options = this.sandbox["{{ cookiecutter.project_shortname }}"].nestedOptions(
this.options,
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* Slick adapter.
* https://kenwheeler.github.io/slick/
*/
ckan.module("{{ project_shortname }}-slick", function ($) {
ckan.module("{{ cookiecutter.project_shortname }}-slick", function ($) {
return {
options: {},

Expand All @@ -11,7 +11,7 @@ ckan.module("{{ project_shortname }}-slick", function ($) {
if (typeof $.fn.slick === "undefined") {
// reporting the source of the problem is always a good idea.
console.error(
"[{{ project_shortname }}-slick] slick library is not loaded",
"[{{ cookiecutter.project_shortname }}-slick] slick library is not loaded",
);
return;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* SortableJS adapter.
* https://sortablejs.github.io/Sortable/
*/
ckan.module("{{ project_shortname }}-sortable", function () {
ckan.module("{{ cookiecutter.project_shortname }}-sortable", function () {
return {
options: {},

Expand All @@ -11,7 +11,7 @@ ckan.module("{{ project_shortname }}-sortable", function () {
if (typeof Sortable === "undefined") {
// reporting the source of the problem is always a good idea.
console.error(
"[{{ project_shortname }}-sortable] SortableJS library is not loaded",
"[{{ cookiecutter.project_shortname }}-sortable] SortableJS library is not loaded",
);
return;
}
Expand Down
Loading

0 comments on commit 0da6d0f

Please sign in to comment.