python url設定 include　関数に関して

#URLの設定でinclude　は実際何してるんだろう？

include()を使用してPATHの設定を引きとれるとなっているが、実際何をしているんだろう

（参考）
<a href = "https://docs.djangoproject.com/ja/3.1/intro/tutorial01/"> mysite/urls.py </a>


```python
from django.contrib import admin
from django.urls import include, path

urlpatterns = [
    path('polls/', include('polls.urls')),
    path('admin/', admin.site.urls),
]
```

実際の関数内原文

```pyson
def include(arg, namespace=None):
    app_name = None
    if isinstance(arg, tuple):
        try:
            urlconf_module, app_name = arg
        except ValueError:
            if namespace:
                raise ImproperlyConfigured(
                    'Cannot override the namespace for a dynamic module that '
                    'provides a namespace.'
                )
            raise ImproperlyConfigured(
                'Passing a %d-tuple to include() is not supported. Pass a '
                '2-tuple containing the list of patterns and app_name, and '
                'provide the namespace argument to include() instead.' % len(arg)
            )
    else:
        urlconf_module = arg

    if isinstance(urlconf_module, str):
        urlconf_module = import_module(urlconf_module)
    patterns = getattr(urlconf_module, 'urlpatterns', urlconf_module)
    app_name = getattr(urlconf_module, 'app_name', app_name)
    if namespace and not app_name:
        raise ImproperlyConfigured(
            'Specifying a namespace in include() without providing an app_name '
            'is not supported. Set the app_name attribute in the included '
            'module, or pass a 2-tuple containing the list of patterns and '
            'app_name instead.',
        )
    namespace = namespace or app_name
    if isinstance(patterns, (list, tuple)):
        for url_pattern in patterns:
            pattern = getattr(url_pattern, 'pattern', None)
            if isinstance(pattern, LocalePrefixPattern):
                raise ImproperlyConfigured(
                    'Using i18n_patterns in an included URLconf is not allowed.'
                )
    return (urlconf_module, app_name, namespace)
```

## ここから調べた結果

```
def include(arg, namespace=None):
```
arg は必須　namespace　は任意

```
if isinstance(arg, tuple):
```
arg　が　tuple型(配列)かチェックしている　(<a href="https://qiita.com/kathythekid42/items/bb6fd59349774ee3eb2f">isinstance関数</a>)

```
urlconf_module, app_name = arg
```
arg = ('a','b') の場合
urlconf_module ='a'
app_name = 'b'　となる
arg = ('a','b','c') の場合はエラーになる
エラーの場合は例外で返る

このことにより

```
arg = 'hoge'
　　or
arg = ('hoge','fuga')
```
が通過できるようになるということがわかる

```
    if isinstance(urlconf_module, str):
        urlconf_module = import_module(urlconf_module)
```
urlconf_module　が文字列かどうかチェックしている
文字列の場合　import_module　の関数を実行している

---
呼び出されている　import_module　について
---

`/AppData/Local/Programs/Python/Python38/Lib/importlib/__init__.py`

```
def import_module(name, package=None):
    level = 0
    if name.startswith('.'): 
        if not package:
            msg = ("the 'package' argument is required to perform a relative "
                   "import for {!r}")
            raise TypeError(msg.format(name))
        for character in name:
            if character != '.':
                break
            level += 1
    return _bootstrap._gcd_import(name[level:], package, level)
```
import　moduleに関する調査

```
if name.startswith('.'):
```
文字列の最初が'.'で始まっているか調べる <a href ="https://qiita.com/kathythekid42/items/803fcd9e3f63e351aaba">startswith</a>

```
if not package:
```
ここはtrueが返ってくる？
ならエラーで終わるやん。



```
 for character in name:
    if character != '.':
        break
    level += 1
```

ここでは、最初の'.'以外の文字が出るまで繰り返す。
「../test」なら「/test」になる様子

しかし、ここではlavel=0以外はかんがえられない

```
return _bootstrap._gcd_import(name[level:], package, level)
```
name[level:] nameの文字列
package　は　None
level は　0

※name[level:] は
name[0:] と同じで文字列の切り出しです。
name[最初の文字位置:最後の文字位置] という意味
数字が入っていないと必然的に一番最初・一番最後という意味になる。


---
呼び出されている　_bootstrap._gcd_import　について
---

`C:\Users\（ユーザー名）\AppData\Local\Programs\Python\Python38\Lib\importlib\_bootstrap.py`

```
def _gcd_import(name, package=None, level=0):
    _sanity_check(name, package, level)
    if level > 0:
        name = _resolve_name(name, package, level)
    return _find_and_load(name, _gcd_import)
```
level は0しかありえないので必然的に return _find_and_load (name, _gcd_import)
name はそのまま引き継がれ、
_gcd_import　は実行された関数が含まれている

関数を引数に入れる発想がなかった！

---
呼び出されている　_find_and_loadについて
---

`C:\Users\（ユーザー名）\AppData\Local\Programs\Python\Python38\Lib\importlib\_bootstrap.py`

```
def _find_and_load(name, import_):
    """Find and load the module."""
    with _ModuleLockManager(name):
        module = sys.modules.get(name, _NEEDS_LOADING)
        if module is _NEEDS_LOADING:
            return _find_and_load_unlocked(name, import_)

    if module is None:
        message = ('import of {} halted; '
                   'None in sys.modules'.format(name))
        raise ModuleNotFoundError(message, name=name)

    _lock_unlock_module(name)
    return module
```