flaskのソースコードを読んでいく(3)

以下のソースコードを読んでいきます。

https://github.com/pallets/flask/blob/master/src/flask/sessions.py

SecureCookieSessionのクラスの実装を読んでいきます。

```Python
class SecureCookieSession(CallbackDict, SessionMixin):
    """Base class for sessions based on signed cookies.
    This session backend will set the :attr:`modified` and
    :attr:`accessed` attributes. It cannot reliably track whether a
    session is new (vs. empty), so :attr:`new` remains hard coded to
    ``False``.
    """

    #: When data is changed, this is set to ``True``. Only the session
    #: dictionary itself is tracked; if the session contains mutable
    #: data (for example a nested dict) then this must be set to
    #: ``True`` manually when modifying that data. The session cookie
    #: will only be written to the response if this is ``True``.
    modified = False

    #: When data is read or written, this is set to ``True``. Used by
    # :class:`.SecureCookieSessionInterface` to add a ``Vary: Cookie``
    #: header, which allows caching proxies to cache different pages for
    #: different users.
    accessed = False

    def __init__(self, initial=None):
        def on_update(self):
            self.modified = True
            self.accessed = True

        super(SecureCookieSession, self).__init__(initial, on_update)

    def __getitem__(self, key):
        self.accessed = True
        return super(SecureCookieSession, self).__getitem__(key)

    def get(self, key, default=None):
        self.accessed = True
        return super(SecureCookieSession, self).get(key, default)

    def setdefault(self, key, default=None):
        self.accessed = True
        return super(SecureCookieSession, self).setdefault(key, default)
```


```Python
    """Base class for sessions based on signed cookies.
    This session backend will set the :attr:`modified` and
    :attr:`accessed` attributes. It cannot reliably track whether a
    session is new (vs. empty), so :attr:`new` remains hard coded to
    ``False``.
    """
```
SecureCookieSessionはCallbackDictとSessionMixinを継承します。Pythonは多重継承をサポートするようですね。
署名されたクッキーの上のセッションのための基底クラスです。セッションのバックエンドは`modified`属性と`accessed`属性を設定します。しかしながら、セッションが新しいかどうかを信頼性を持って追跡できません。よって、属性`new`はFalseにハードコードされています。

```Python
    #: When data is changed, this is set to ``True``. Only the session
    #: dictionary itself is tracked; if the session contains mutable
    #: data (for example a nested dict) then this must be set to
    #: ``True`` manually when modifying that data. The session cookie
    #: will only be written to the response if this is ``True``.
    modified = False
```
modified属性については、SessionMixinクラスから継承されています。データが変更された場合は、これはTrueに設定されます。セッションの辞書自体が追跡されているばあいのみ、もしも、セッションが、ミュータブルなデータが格納されていた場合、(例えばネストされた辞書）データを変更する時に、Trueに手動で変更されるべきです。もしこれがTrueだった場合、セッションクッキーはそれに反応して書き換えられるべきです。

```Python
    #: When data is read or written, this is set to ``True``. Used by
    # :class:`.SecureCookieSessionInterface` to add a ``Vary: Cookie``
    #: header, which allows caching proxies to cache different pages for
    #: different users.
    accessed = False
```
accessed属性は、SessionMixinクラスから継承されています。データが読まれたまたは書き込まれた時、Trueに設定されます。SecureCookieSessionInterfaceのクラスがVary: Cookieヘッダーを追加するのに使われます。これはキャッシングプロクシが違うページを違うユーザーのためのキャッシュするのを許します。

```Python
    def __init__(self, initial=None):
        def on_update(self):
            self.modified = True
            self.accessed = True

        super(SecureCookieSession, self).__init__(initial, on_update)
```
これはコンストラクタです。関数内の関数、つまりクロージャを使っています。スーパークラスを参照していますが、多重継承を使用しているため、どちらのスーパークラスを参照しているかどうかが謎になるわけです。ここで、CallbackDictのドキュメントを確認してみます。

https://tedboy.github.io/flask/generated/generated/werkzeug.CallbackDict.html

メソッドの一つに、`__init__([initial, on_update])`がありますね。よって、CallbackDictのコンストラクタを呼び出していることがわかります。
クロージャの`def on_update(self):`メソッドでは、modifiedプロパティと、accessedプロパティが両方とも、Trueに設定されています。updateしたときの挙動が見えます。
`super(SecureCookieSession, self).__init__(initial, on_update)`においての、SecureCookieSessionは、自分のクラスであるため省略しても大丈夫です。（逆になぜこれがあるのかわからない。自明なのに）

```Python
    def __getitem__(self, key):
        self.accessed = True
        return super(SecureCookieSession, self).__getitem__(key)
```

SecureCookieSessionはCallbackDictを継承しているため、基本的には辞書です。よって、キーに対応する値を取得するためのメソッドが必要です。これがまさにそれになります。
`self.accessed = True`のコードにより、このメソッドが実行された時、accessed属性がTrueになります。
スーパークラスであるCallbackDictクラスの`__getitem__(key)`メソッドを呼び出します。`__getitem__`は特殊なメソッドで、角カッコ`[]`でアクセスした時の値を返します。

```Python
    def get(self, key, default=None):
        self.accessed = True
        return super(SecureCookieSession, self).get(key, default)
```
キーに対応する値を返すメソッドです。CallbackDictのメソッドを呼び出しています。角カッコでアクセスした時の値を返す仕組みと、メソッドでアクセスした時の値を返す仕組み両方を準備しているんですね。

```Python
    def setdefault(self, key, default=None):
        self.accessed = True
        return super(SecureCookieSession, self).setdefault(key, default)
```
setdefaultは、キーが存在ない場合は、デフォルトの値を格納、キーが存在した場合は、元々の値を保持して値を変更しないメソッドです。これもCallbackDictのメソッドを呼び出しています。