Repository: beeware/briefcase
Pull request #1762 (2024-04-29 17:59:45)

Fix minor holes in PEP-508 name validation
## Changes
- This resolves a hole in the recommended implementation of name validation from [PEP-508](https://peps.python.org/pep-0508/#names) to avoid allowing non-ASCII values.
```
The regex (run with re.IGNORECASE) is:

^([A-Z0-9]|[A-Z0-9][A-Z0-9._-]*[A-Z0-9])$
```
- The implementation of `re.IGNORECASE` is ostensibly coercing the case of the input because it will match on non-ASCII.
  - This matters for, at least, İ ([0x130](https://everythingfonts.com/unicode/0x0130)) and K ([0x212a](https://everythingfonts.com/unicode/0x212A)).
```pycon
>>> import re
>>> PEP508_NAME_RE = re.compile(r"^([A-Z0-9]|[A-Z0-9][A-Z0-9._-]*[A-Z0-9])$", re.IGNORECASE)
>>> 
>>> bool(PEP508_NAME_RE.match("helloworld"))
True
>>> bool(PEP508_NAME_RE.match("İstanbul"))
True
>>> bool(PEP508_NAME_RE.match("Kelvin"))
True
>>> bool(PEP508_NAME_RE.match("Æolia"))
False
>>> bool(PEP508_NAME_RE.match("jalapeño"))
False
>>> bool(PEP508_NAME_RE.match("Beyoncé"))
False
>>> bool(PEP508_NAME_RE.match("naïve"))
False
```

## Related
- https://github.com/beeware/briefcase/issues/1011

## PR Checklist:
<!--- Go over all the following points, and put an `x` in all the boxes that apply. -->
- [x] All new features have been tested
- [x] All new features have been documented
- [X] I have read the **CONTRIBUTING.md** file
- [X] I will abide by the code of conduct


Patch:
diff --git a/changes/1762.bugfix.rst b/changes/1762.bugfix.rst
new file mode 100644
index 00000000..3a1d9c95
--- /dev/null
+++ b/changes/1762.bugfix.rst
@@ -0,0 +1,1 @@
+When creating a new project, the validation for App Name now rejects all non-ASCII values.
diff --git a/src/briefcase/config.py b/src/briefcase/config.py
index a86f8f2a..9665e006 100644
--- a/src/briefcase/config.py
+++ b/src/briefcase/config.py
@@ -15,8 +15,12 @@ from briefcase.platforms import get_output_formats, get_platforms
 from .constants import RESERVED_WORDS
 from .exceptions import BriefcaseConfigError
 
-# PEP508 provides a basic restriction on naming
-PEP508_NAME_RE = re.compile(r"^([A-Z0-9]|[A-Z0-9][A-Z0-9._-]*[A-Z0-9])$", re.IGNORECASE)
+# PEP 508 restricts the naming of modules. The PEP defines a regex that uses
+# re.IGNORECASE; but in in practice, packaging uses a version that rolls out the lower
+# case, which has very slightly different semantics with non-ASCII characters. This
+# definition is the one from
+# https://github.com/pypa/packaging/blob/24.0/src/packaging/_tokenizer.py#L80
+PEP508_NAME_RE = re.compile(r"^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9._-]*[a-zA-Z0-9])$")
 
 
 def is_valid_pep508_name(app_name):


Test patch:
diff --git a/tests/commands/new/test_validate_app_name.py b/tests/commands/new/test_validate_app_name.py
index d481eb6d..a7426f4c 100644
--- a/tests/commands/new/test_validate_app_name.py
+++ b/tests/commands/new/test_validate_app_name.py
@@ -10,7 +10,6 @@ import pytest
         "42helloworld",  # ?? Are we sure this is correct?
         "hello_world",
         "hello-world",
-        "helloworld_ı",
     ],
 )
 def test_valid_app_name(new_command, name):
diff --git a/tests/config/test_is_valid_app_name.py b/tests/config/test_is_valid_app_name.py
index 56d7ab49..936824a4 100644
--- a/tests/config/test_is_valid_app_name.py
+++ b/tests/config/test_is_valid_app_name.py
@@ -34,6 +34,12 @@ def test_is_valid_app_name(name):
         "main",
         "socket",
         "test",
+        # ı, İ and K (i.e. 0x212a) are valid ASCII when made lowercase and as such are
+        # accepted by the official PEP 508 regex... but they are rejected here to ensure
+        # compliance with the regex that is used in practice.
+        "helloworld_ı",
+        "İstanbul",
+        "Kelvin",
     ],
 )
 def test_is_invalid_app_name(name):