diff --git a/qgis-app/plugins/forms.py b/qgis-app/plugins/forms.py index a179e1fe..0884bd19 100644 --- a/qgis-app/plugins/forms.py +++ b/qgis-app/plugins/forms.py @@ -195,7 +195,7 @@ def clean_package(self): """ package = self.cleaned_data.get("package") try: - self.cleaned_data.update(validator(package)) + self.cleaned_data.update(validator(package, is_new=True)) except ValidationError as e: msg = _( "There were errors reading plugin package (please check also your plugin's metadata)." diff --git a/qgis-app/plugins/tests/test_validator.py b/qgis-app/plugins/tests/test_validator.py index c96ba947..67fc919f 100644 --- a/qgis-app/plugins/tests/test_validator.py +++ b/qgis-app/plugins/tests/test_validator.py @@ -211,6 +211,33 @@ def test_zipfile_with_gitignore(self, mock_namelist): ) +class TestValidatorInvalidPackageName(TestCase): + """Test if plugin's directory is not PEP8 compliant """ + + def setUp(self) -> None: + invalid_package_name = os.path.join(TESTFILE_DIR, "invalid_package_name.zip_") + self.plugin_package = open(invalid_package_name, "rb") + + def tearDown(self): + self.plugin_package.close() + + # Package name does not match PEP8 + def test_new_plugin_invalid_package_name(self): + self.assertRaises( + ValidationError, + validator, + InMemoryUploadedFile( + self.plugin_package, + field_name="tempfile", + name="testfile.zip", + content_type="application/zip", + size=39889, + charset="utf8", + ), + is_new=True + ) + + class TestLicenseValidator(TestCase): """Test if zipfile contains LICENSE file """ diff --git a/qgis-app/plugins/tests/testfiles/invalid_package_name.zip_ b/qgis-app/plugins/tests/testfiles/invalid_package_name.zip_ new file mode 100644 index 00000000..24026d2d Binary files /dev/null and b/qgis-app/plugins/tests/testfiles/invalid_package_name.zip_ differ diff --git a/qgis-app/plugins/validator.py b/qgis-app/plugins/validator.py index a6a9f2b2..639c03a8 100644 --- a/qgis-app/plugins/validator.py +++ b/qgis-app/plugins/validator.py @@ -149,7 +149,7 @@ def error_check_if_exist(url: str)->bool: ) -def validator(package): +def validator(package, is_new: bool = False): """ Analyzes a zipped file, returns metadata if success, False otherwise. If the new icon metadata is found, an inmemory file object is also returned @@ -162,6 +162,7 @@ def validator(package): * mandatory metadata: ('name', 'description', 'version', 'qgisMinimumVersion', 'author', 'email') * package_name regexp: [A-Za-z][A-Za-z0-9-_]+ * author regexp: [^/]+ + * New plugins package_name is PEP8 compliant """ try: @@ -243,6 +244,15 @@ def validator(package): "Cannot find a folder inside the compressed package: this does not seems a valid plugin" ) ) + # Check if package_name is PEP 8 compliant + if is_new and not package_name.isidentifier(): + raise ValidationError( + _( + "The name of the top level directory inside the zip package must be PEP 8 compliant: " + "a valid Python identifier, which means it must start with a letter or underscore, " + "and can only contain letters, digits, and underscores." + ) + ) # Cuts the trailing slash if package_name.endswith("/"):