Repository: geopandas/xyzservices

Issue:
Add method to check if token is required 
Some providers require an access token to get the tiles. It could be handy to have a method in `TileProvider` checking this requirement and returning boolean. Now you have to check if the `accessToken` key is present. Something like

```python
>>> xyz.MapBox.requires_token()
True

>>> xyz.Stamen.Toner.requires_token()
False
```

Discussion:
martinfleis: Ah, I just found out that the token keyword depends on the provider. So we have `accessToken`, `apiKey`, `key` and probably some others. I'll need to adapt this PR before merging then.
jorisvandenbossche: Is the "insert your" always consistent? (so reliable to use for this check?)
martinfleis: > Is the "insert your" always consistent? (so reliable to use for this check?)

It is the most reliable way I have found. The keywords are random.
martinfleis: It actually is not really reliable, because once you feed your own token to the TileProvider object this check will return `False`. Maybe we can have a list of keywords representing tokens and check against that?
jorisvandenbossche: But maybe that's fine, as at that point, the provider object no longer "requires" a token, in the sense that it still needs to receive the information. 

All depends on the use case you have for this, I think. 
If it is to know in general whether a provider class needs a key/token, then indeed that's not reliable and we will need to keep a list of all possible keywords for this . 
If it is to check if the specific provider object still needs to receive the information (eg to give a nicer error message to the user like "you still need to provide a token"), then it's actually fine that it returns False once the values are fed in.
martinfleis: True. If we can apply the second option here, then we can directly use `requires_token` in #28 and raise that nice error there.

Patch:
diff --git a/provider_sources/xyzservices-providers.json b/provider_sources/xyzservices-providers.json
index ab1e15b..c3abecb 100644
--- a/provider_sources/xyzservices-providers.json
+++ b/provider_sources/xyzservices-providers.json
@@ -13,10 +13,11 @@
             "name": "OpenStreetMap.Mapnik"
         },
         "second_provider_name": {
-            "url": "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
+            "url": "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png?access-token={accessToken}",
             "max_zoom": 19,
             "attribution": "(C) OpenStreetMap contributors",
-            "name": "OpenStreetMap.Mapnik"
+            "name": "OpenStreetMap.Mapnik",
+            "accessToken": "<insert your access token here>"
         }
     }
 }
\ No newline at end of file
diff --git a/xyzservices/lib.py b/xyzservices/lib.py
index 48294f6..b4743e2 100644
--- a/xyzservices/lib.py
+++ b/xyzservices/lib.py
@@ -68,6 +68,17 @@ class TileProvider(Bunch):
         new.update(kwargs)
         return new
 
+    def requires_token(self):
+        """
+        Returns True if the TileProvider requires access token to fetch tiles
+        """
+        # both attribute and placeholder in url are required to make it work
+        for key, val in self.items():
+            if isinstance(val, str) and "<insert your" in val:
+                if key in self.url:
+                    return True
+        return False
+
     def _repr_html_(self, inside=False):
         provider_info = ""
         for key, val in self.items():


Test patch:
diff --git a/tests/test_providers.py b/tests/test_providers.py
index 5005905..fd688b2 100644
--- a/tests/test_providers.py
+++ b/tests/test_providers.py
@@ -24,6 +24,28 @@ def test_minimal_provider_metadata(provider_name):
             check_provider(xyz[provider_name][variant])
 
 
+def test_requires_token():
+    private_provider = TileProvider(
+        {
+            "url": "https://myserver.com/tiles/{z}/{x}/{y}?access_token={accessToken}",
+            "attribution": "(C) xyzservices",
+            "accessToken": "<insert your access token here>",
+            "name": "my_private_provider",
+        }
+    )
+
+    public_provider = TileProvider(
+        {
+            "url": "https://myserver.com/tiles/{z}/{x}/{y}",
+            "attribution": "(C) xyzservices",
+            "name": "my_public_provider",
+        }
+    )
+
+    assert private_provider.requires_token() == True
+    assert public_provider.requires_token() == False
+
+
 def test_html_repr():
     provider = TileProvider(
         {