diff --git a/.flake8 b/.flake8 index 8c58050..a6fac56 100644 --- a/.flake8 +++ b/.flake8 @@ -1,6 +1,6 @@ [flake8] ignore = E203, W503 -exclude = .git, __pycache__, SentinelHub/resources.py +exclude = .git, __pycache__, SentinelHub/resources.py, SentinelHub/external, SentinelHub/zip_build max-line-length= 120 max-complexity = 13 per-file-ignores = diff --git a/README.md b/README.md index ff83b55..d064135 100644 --- a/README.md +++ b/README.md @@ -2,13 +2,18 @@ SentinelHub QGIS Plugin enables users to harness the power of [Sentinel Hub services](https://www.sentinel-hub.com/) directly from QGIS. -Since version `2.0.0` the plugin only works with QGIS 3 and Python version `>=3.5` while earlier versions support both QGIS 2 and QGIS 3. - ## Install -SentinelHub QGIS Plugin is available in QGIS Official Plugin Repository. For install just open QGIS, select `Plugins -> Manage and Install Plugins` and search for the plugin. +SentinelHub QGIS Plugin is available in the official [QGIS Python Plugins Repository](https://plugins.qgis.org/plugins/SentinelHub/). For install just open QGIS, select `Plugins -> Manage and Install Plugins` and search for `SentinelHub` plugin. + +In case of manual installation, you can download a [released version](https://github.com/sentinel-hub/sentinelhub-qgis-plugin/releases), unzip it into QGIS Plugin directory and enable the plugin under QGIS Installed Plugins. + +Compatibility: + +- versions `<2.0.0` support both QGIS 2 and QGIS 3, +- version `2.0.0` supports QGIS 3 and Python version `>=3.5, +- version `2.1.0` supports QGIS versions `>=3.22` and Python versions `>=3.8`. -In case of manual installation, you can download [latest release](https://github.com/sentinel-hub/sentinelhub-qgis-plugin/releases/latest), unzip it into QGIS Plugin directory and enable plugin under QGIS Installed Plugins. ## Usage diff --git a/SentinelHub/__init__.py b/SentinelHub/__init__.py index 25fb162..689153c 100644 --- a/SentinelHub/__init__.py +++ b/SentinelHub/__init__.py @@ -18,6 +18,21 @@ This script initializes the plugin, making it known to QGIS. """ +WHEELS = [ # TODO: separate wheels requirements and import them from requirements file + "oauthlib", + "requests-oauthlib", + "click", + "aenum", + "tqdm", + "dataclasses-json", + "marshmallow", + "marshmallow-enum", + "packaging", + "typing-inspect", + "mypy-extensions", + "typing-extensions", +] + def classFactory(iface): """Load SentinelHub class from file SentinelHub. @@ -29,13 +44,21 @@ def classFactory(iface): # pylint: disable=import-outside-toplevel # pylint: disable=unused-import - # The following initializes UI - from . import resources - from .utils.meta import ensure_import + from .utils.meta import configure_external_import_path, ensure_wheel_import + + configure_external_import_path() + for package_name in WHEELS: + ensure_wheel_import(package_name) - ensure_import("oauthlib") - ensure_import("requests_oauthlib") + # TODO: this import is just for testing purpose: + import sentinelhub + from .exceptions import MessageType, show_message + + show_message(f"Imported sentinelhub-py {sentinelhub.__version__} !!", MessageType.INFO) + + # The following initializes UI + from . import resources from .main import SentinelHubPlugin return SentinelHubPlugin(iface) diff --git a/SentinelHub/metadata.txt b/SentinelHub/metadata.txt index a90b476..1b3a7ec 100644 --- a/SentinelHub/metadata.txt +++ b/SentinelHub/metadata.txt @@ -3,10 +3,10 @@ # Mandatory items: [general] name=SentinelHub -qgisMinimumVersion=3.0 +qgisMinimumVersion=3.22 qgisMaximumVersion=3.99 description=SentinelHub plugin enables users to harness the power of Sentinel Hub services directly from QGIS. -version=2.0.0 +version=2.1.0 author=Sinergise email=info@sentinel-hub.com diff --git a/SentinelHub/utils/meta.py b/SentinelHub/utils/meta.py index 78934e7..5d2b350 100644 --- a/SentinelHub/utils/meta.py +++ b/SentinelHub/utils/meta.py @@ -8,22 +8,37 @@ from qgis.utils import plugins_metadata_parser -def ensure_import(package_name): +def configure_external_import_path() -> None: + """Adds path to the folder with external packages to the list of Python package import paths. This way if a package + doesn't exist in the Python environment used by QGIS it will be imported from the external folder. + + Note that on Windows QGIS typically uses its own Python environment with an installation of most common Python + packages. But on Linux and macOS it typically uses the default system Python environment. + """ + plugin_dir = _get_main_dir() + external_path = os.path.join(plugin_dir, "external") + + sys.path.append(external_path) + + +def ensure_wheel_import(package_name: str) -> None: """Ensures that a dependency package could be imported. It is either already available in the QGIS environment or it is available in a subfolder `external` of this plugin and should be added to PATH """ + package_name = package_name.replace("-", "_") + try: __import__(package_name) except ImportError as exception: plugin_dir = _get_main_dir() external_path = os.path.join(plugin_dir, "external") - for wheel_name in os.listdir(external_path): - if wheel_name.startswith(package_name): + for wheel_name in sorted(os.listdir(external_path)): + if wheel_name.startswith(package_name) and wheel_name.endswith(".whl"): wheel_path = os.path.join(external_path, wheel_name) sys.path.append(wheel_path) return - raise ImportError(f"Package {package_name} not found") from exception + raise ImportError(f"A wheel of a package {package_name} not found in {external_path}") from exception def _get_plugin_name(missing="SentinelHub"): diff --git a/pyproject.toml b/pyproject.toml index 4c2ea3b..3abe000 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,17 +1,17 @@ [tool.black] line-length = 120 preview = true +extend-exclude = "SentinelHub/resources.py|SentinelHub/external|SentinelHub/zip_build" [tool.isort] profile = "black" known_first_party = "sentinelhub" sections = ["FUTURE", "STDLIB", "THIRDPARTY", "LOCALFOLDER"] line_length = 120 +skip = ["SentinelHub/resources.py", "SentinelHub/external", "SentinelHub/zip_build"] [tool.pylint] -ignore = [ - "resources.py" -] +ignore = ["resources.py", "external", "zip_build"] [tool.pylint.format] max-line-length = 120 diff --git a/requirements.txt b/requirements.txt index 628b33a..59d5981 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,14 @@ oauthlib requests-oauthlib +click +aenum>=2.1.4 +utm +tqdm +dataclasses-json +marshmallow +marshmallow-enum +packaging +typing-inspect +mypy-extensions +typing-extensions +sentinelhub