Skip to content

Commit

Permalink
Feature: plugins downloader (#168)
Browse files Browse the repository at this point in the history
This PR add logic to download plugins which are referenced within
profile.json files downloaded in QDT working directory.

It does not include:

- the installation/copy of downloaded plugins
- the local plugins
  • Loading branch information
Guts committed Jan 18, 2023
2 parents a66a367 + dc2b91f commit c7952a6
Show file tree
Hide file tree
Showing 17 changed files with 797 additions and 32 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/tests.yml
Expand Up @@ -56,7 +56,7 @@ jobs:
strategy:
matrix:
os: [macos-latest, ubuntu-22.04, windows-latest]
python-version: ["3.8", "3.9", "3.10"]
python-version: ["3.8", "3.9", "3.10", "3.11"]

runs-on: ${{ matrix.os }}
steps:
Expand Down
2 changes: 1 addition & 1 deletion .vscode/settings.json
Expand Up @@ -36,7 +36,7 @@
"python.testing.pytestEnabled": true,
// extensions
"autoDocstring.guessTypes": true,
"autoDocstring.docstringFormat": "one-line-sphinx",
"autoDocstring.docstringFormat": "google",
"autoDocstring.generateDocstringOnEnter": false,
"yaml.schemas": {
"docs/schemas/schema.json": "tests/fixtures/scenarios/*.qdt.yml",
Expand Down
1 change: 1 addition & 0 deletions docs/jobs/index.md
Expand Up @@ -5,5 +5,6 @@
caption: Jobs
maxdepth: 1
---
plugins_manager.md
splash_screen_manager.md
```
105 changes: 105 additions & 0 deletions docs/jobs/plugins_manager.md
@@ -0,0 +1,105 @@
# Plugins manager

This job download plugins into QDT local folder and synchronize them with installed profiles.

----

## Use it

Sample job configuration in your scenario file:

```yaml
- name: Synchronize plugins
uses: qplugins-manager
with:
action: create_or_restore
```

----

## Options

### action

Tell the job what to do with plugins in **installed profiles**:

Possible_values:

- `create`: add plugins if they are not present
- `create_or_restore`: add plugins if not present and replace eventual existing one
- `remove`: remove plugins which are not listed

### force

Controls download mode.

Possible_values:

- `false` (_default_): download only plugins which are not present into the local QDT folder
- `true`: download every plugin referenced in profile.json files into the local QDT folder, even if the archive is already here

### threads

Number of threads to use for downloading.

Possible_values:

- `1`: do not use multi-thread but download plugins synchroneously
- `2`, `3`, `4` or `5` (_default_): number of threads to parallelize plugins download

----

## How does it work

### Specify the file to use in the `profile.json`

Add the image file to the profile folder and specify the relative filepath under the `splash` attribute:

```json
{
[...]
"plugins": [
{
"name": "french_locator_filter",
"version": "1.0.4",
"official_repository": true,
},
{
"name": "pg_metadata",
"version": "1.2.1",
"url": "https://plugins.qgis.org/plugins/pg_metadata/version/1.2.1/download/",
"location": "remote",
"official_repository": true,
},
{
"name": "Geotuileur",
"version": "1.0.0",
"url": "https://oslandia.gitlab.io/qgis/ign-geotuileur/geotuileur.1.0.0.zip",
"location": "remote",
"official_repository": false,
"repository_url_xml": "https://oslandia.gitlab.io/qgis/ign-geotuileur/plugins.xml"
}
[...]
}
```

### Store the image file under the default path

If the path is not specified into the `profile.json`, the job looks for the default filepath `images/splash.png`. If the file exists, it will be used as splash screen image.

### Workflow

1. Create a subfolder `plugins` into the local QDT working directory. Default: `~/.cache/qgis-deployment-toolbelt/plugins`
1. Parse profiles downloaded by QDT (not the installed)
1. Create an unified list of used plugins
1. Download, if not already existing, every plugin into the plugins subfolder with this structure: `plugins/{plugin-name-slufigied}/{plugin-version}/{plugin-name-version}.zip`
1. Unzip plugins in installed profiles

```mermaid
graph TD
A[Christmas] -->|Get money| B(Go shopping)
B --> C{Let me think}
C -->|One| D[Laptop]
C -->|Two| E[iPhone]
C -->|Three| F[fa:fa-car Car]
```
9 changes: 5 additions & 4 deletions qgis_deployment_toolbelt/cli.py
Expand Up @@ -20,6 +20,7 @@
# submodules
from qgis_deployment_toolbelt.__about__ import __version__
from qgis_deployment_toolbelt.commands import cli_check, cli_clean, cli_upgrade
from qgis_deployment_toolbelt.constants import get_qdt_working_directory
from qgis_deployment_toolbelt.jobs import JobsOrchestrator
from qgis_deployment_toolbelt.scenarios import ScenarioReader
from qgis_deployment_toolbelt.utils.bouncer import exit_cli_error, exit_cli_normal
Expand Down Expand Up @@ -123,10 +124,6 @@ def qgis_deployment_toolbelt(
if result_scenario_validity is not None:
exit_cli_error(result_scenario_validity)

# let's be clear or not
if clear:
click.clear()

# -- LOG/VERBOSITY MANAGEMENT ------------------------------------------------------
# if verbose, override conf value
if verbose:
Expand Down Expand Up @@ -172,6 +169,10 @@ def qgis_deployment_toolbelt(
else:
logger.debug(f"Ignored None value: {var}.")

logger.info(
f"QDT working folder: {get_qdt_working_directory(specific_value=scenario.settings.get('LOCAL_QDT_WORKDIR'), identifier=scenario.metadata.get('id'))}"
)

# -- STEPS JOBS
steps_ok = []
orchestrator = JobsOrchestrator()
Expand Down
1 change: 0 additions & 1 deletion qgis_deployment_toolbelt/commands/cli_upgrade.py
Expand Up @@ -31,7 +31,6 @@
exit_cli_success,
)
from qgis_deployment_toolbelt.utils.file_downloader import download_remote_file_to_local
from qgis_deployment_toolbelt.utils.slugger import sluggy

# #############################################################################
# ########## Globals ###############
Expand Down
42 changes: 40 additions & 2 deletions qgis_deployment_toolbelt/constants.py
Expand Up @@ -14,8 +14,9 @@
# Standard library
import logging
from dataclasses import dataclass
from os import getenv
from os.path import expandvars
from functools import lru_cache
from os import PathLike, getenv
from os.path import expanduser, expandvars
from pathlib import Path
from typing import Tuple

Expand All @@ -26,6 +27,43 @@
# logs
logger = logging.getLogger(__name__)

# #############################################################################
# ########## Functions #############
# ##################################


@lru_cache(maxsize=128)
def get_qdt_working_directory(
specific_value: PathLike = None, identifier: str = "default"
) -> Path:
"""Get QDT working directory.
Args:
specific_value (PathLike, optional): a specific path to use. If set it's \
expanded and returned. Defaults to None.
identifier (str, optional): used to make the folder unique. If not set, \
'default' (sure, not so unique...) is used. Defaults to None.
Returns:
Path: path to the QDT working directory
"""
if specific_value:
return Path(expandvars(expanduser(specific_value)))
elif getenv("QDT_PROFILES_PATH"):
return Path(expandvars(expanduser(getenv("QDT_PROFILES_PATH"))))
else:
return Path(
expandvars(
expanduser(
getenv(
"LOCAL_QDT_WORKDIR",
f"~/.cache/qgis-deployment-toolbelt/{identifier}",
),
)
)
)


# #############################################################################
# ########## Classes ###############
# ##################################
Expand Down

0 comments on commit c7952a6

Please sign in to comment.