Repository: holoviz/panel

Issue:
Extensions with no `cdn_url` cause `pn.extension` to fail
#### ALL software version info
```
panel==1.2.3
bokeh==3.2.2

jupyterlab==4.0.6
jupyterlab-pygments==0.2.2
jupyterlab-widgets==3.0.3
jupyterlab_server==2.25.0
```
Running on Windows 10, Python 3.9, with the crash occurring in both VS Code and standalone Jupyter Lab.

#### Description of expected behavior and the observed behavior
If you load other Python modules that include a pre-compiled extension (or, seemingly, any local extension that does not have `cdn_url` set), then `pn.extension()` crashes in one of the checks that assumes that `cdn_url` is not `None`. The expected behavior is that calling `pn.extension` succeeds.

#### Complete, minimal, self-contained example code that reproduces the issue
I could put together a MWE but this only seems to happen for pre-compiled Bokeh extension models, which is difficult to set up (has a separate typescript build step), and I don't fully understand how Bokeh registers the module.

If needed, I'll come up with a MWE, but this looks like a one line change. The basic way to reproduce the bug is:
```
import cydnus.PolygonGateTool # any pre-compiled Bokeh module, this is just my local one
import panel as pn
pn.extension()
```

I edited my local Panel install to add `print(extensions)` right before [lines 373-376](https://github.com/holoviz/panel/blob/9ea8c34d2029f6ed6a486aa2360566e7d16ca405/panel/io/resources.py#L373-L376)
```
    print(extensions)
    if reloading:
        extensions = [
            ext for ext in extensions if not ext.cdn_url.startswith('https://unpkg.com/@holoviz/panel@')
        ]
```
and the loaded extensions look like:
```
[
  ExtensionEmbed(
    artifact_path='C:\\local_venv_path\\lib\\site-packages\\panel\\dist\\panel.min.js', 
    server_url='http://localhost:5006/static/extensions/panel/panel.min.jsv=c47f5b18b8a430e698b9fe15e51f6119984e78334bcf3f45e210d30c37ef2f9e',
    cdn_url='https://unpkg.com/@holoviz/panel@1.2.3/dist/panel.min.js'), 
  ExtensionEmbed(
    artifact_path='c:\\local_extension_path\\cydnus.js',
    server_url='http://localhost:5006/static/extensions/cydnus/cydnus.js?v=6b13789e43e5485634533de16a65d8ba9d34c4c9758588b665805435f80eb115',
    cdn_url=None)
]
```

Note the **`cdn_url=None`** line on the `cydnus` local extension.

#### Stack traceback and/or browser JavaScript console output
```
Traceback (most recent call last):
  File "C:\local_venv_path\site-packages\IPython\core\interactiveshell.py", line 3378, in run_code
    exec(code_obj, self.user_global_ns, self.user_ns)
  File "C:\local_temp_path\Temp\ipykernel_1860\1180023464.py", line 4, in <module>
    pn.extension()
  File "C:\local_venv_path\lib\site-packages\pyviz_comms\__init__.py", line 64, in __new__
    return param.ParameterizedFunction.__new__(cls, *args, **kwargs)
  File "C:\local_venv_path\lib\site-packages\param\parameterized.py", line 3654, in __new__
    return inst.__call__(*args,**params)
  File "C:\local_venv_path\lib\site-packages\panel\config.py", line 807, in __call__
    load_notebook(
  File "C:\local_venv_path\lib\site-packages\panel\io\notebook.py", line 364, in load_notebook
    bundle = bundle_resources(
  File "local_venv_path\lib\site-packages\panel\io\resources.py", line 375, in bundle_resources
    extensions = [
  File "local_venv_path\lib\site-packages\panel\io\resources.py", line 377, in <listcomp>
    ext for ext in extensions if not (ext.cdn_url.startswith('https://unpkg.com/@holoviz/panel@'))
AttributeError: 'NoneType' object has no attribute 'startswith'
```
- [x] I may be interested in making a pull request to address this



Discussion:

Resolving patch:
diff --git a/panel/io/resources.py b/panel/io/resources.py
--- a/panel/io/resources.py
+++ b/panel/io/resources.py
@@ -372,7 +372,7 @@ def bundle_resources(roots, resources, notebook=False, reloading=False, enable_m
     extensions = _bundle_extensions(None, js_resources)
     if reloading:
         extensions = [
-            ext for ext in extensions if not ext.cdn_url.startswith('https://unpkg.com/@holoviz/panel@')
+            ext for ext in extensions if not (ext.cdn_url is not None and ext.cdn_url.startswith('https://unpkg.com/@holoviz/panel@'))
         ]
     extra_js = []
     if mode == "inline":


Test patch: