Repository: beeware/briefcase

Issue:
Valid domain names are rejected as bundle identifiers.

Briefcase was recently modified to add protection against reserved words in app and bundle names. This change ensured that each part in the bundle name isn't a reserved word.

Unfortunately - `example.in` is a valid domain name for India, `in.example` is the corresponding bundle... but `in` is a reserved word.

The same problem will also exist for `is` (Iceland), `do` (Dominican Republic), `to` (Tonga), `.int` (International), and potentially others, given the proliferation of TLDs.

**To Reproduce**
Steps to reproduce the behavior:
1. Try to create an app with a bundle ID of `example.in`.

**Expected behavior**

Bundle identifiers shouldn't be checked for reserved word safety.

**Environment:**
 - Operating System: all
 - Python version: all
 - Software versions:
   - Briefcase: git 3187be6ae


Discussion:

Patch:
diff --git a/changes/709.bugfix.rst b/changes/709.bugfix.rst
new file mode 100644
index 00000000..bbcd118f
--- /dev/null
+++ b/changes/709.bugfix.rst
@@ -0,0 +1,1 @@
+Bundle name validation no longer excludes valid country identifiers (like ``in.example``).
diff --git a/src/briefcase/config.py b/src/briefcase/config.py
index 4f529580..1096c326 100644
--- a/src/briefcase/config.py
+++ b/src/briefcase/config.py
@@ -199,7 +199,12 @@ def is_valid_bundle_identifier(bundle):
         return False
 
     for part in bundle.split('.'):
-        if is_reserved_keyword(part):
+        # *Some* 2-letter country codes are valid identifiers,
+        # even though they're reserved words; see:
+        #    https://www.oracle.com/java/technologies/javase/codeconventions-namingconventions.html
+        # `.do` *should* be on this list, but as of Apr 2022, `.do` breaks
+        # the Android build tooling.
+        if is_reserved_keyword(part) and part not in {'in', 'is'}:
             return False
 
     return True


Test patch:
diff --git a/tests/config/test_is_valid_bundle_identifier.py b/tests/config/test_is_valid_bundle_identifier.py
index 0ad9f5fb..ecfca00d 100644
--- a/tests/config/test_is_valid_bundle_identifier.py
+++ b/tests/config/test_is_valid_bundle_identifier.py
@@ -10,6 +10,9 @@ from briefcase.config import is_valid_bundle_identifier
         'com.example.more',
         'com.example42.more',
         'com.example-42.more',
+        'in.example',  # Valid identifier with a country code as the TLD
+        'is.example',  # Valid identifier with a country code as the TLD
+        'com.example.in',  # Country codes can appear anywhere.
     ]
 )
 def test_valid_bundle(bundle):
@@ -29,6 +32,8 @@ def test_valid_bundle(bundle):
         'com.pass.example',  # Python reserved word
         'com.switch',  # Java reserved word
         'com.switch.example',  # Java reserved word
+        'int.example',  # Valid identifier with a reserved word as the TLD
+        'do.example',  # This *should* be valid by the Java spec, but Android chokes.
     ]
 )
 def test_invalid_bundle(bundle):