# A Filesystem-based Sage Notebook Datastore

A Filesystem-based Sage Notebook Datastore

Here is the filesystem layout for this datastore. Note that the all of the pickles are pickles of basic Python objects, so can be unpickled in any version of Python with or without Sage or the Sage notebook installed. They are also not compressed, so are reasonably easy to read ASCII.

The filesystem layout is as follows. It mirrors the URL’s used by the Sage notebook server:

    sage_notebook.sagenb
         conf.pickle
         users.pickle
         openid.pickle (optional)
         readonly.txt (optional)
         home/
             username0/
                history.pickle
                id_number0/
                    worksheet.html
                    worksheet_conf.pickle
                    cells/
                    data/
                    snapshots/
                id_number1/
                    worksheet.html
                    worksheet_conf.pickle
                    cells/
                    data/
                    snapshots/
                ...
             username1/
             ...

class `sagenb.storage.filesystem_storage.``FilesystemDatastore`(path)

  Bases: `sagenb.storage.abstract_storage.Datastore`

  `create_worksheet`(username, id_number)

    Create worksheet with given id_number belonging to the given user.

    If the worksheet already exists, return ValueError.

    INPUT:

    > - `username` – string
    > - `id_number` – integer

    OUTPUT:

    > - a worksheet

  `delete`()

    Delete all files associated with this datastore. Dangerous! This is only here because it is useful for doctesting.

  `export_worksheet`(username, id_number, filename, title)

    Export the worksheet with given username and id_number to the given filename (e.g., ‘worksheet.sws’).

    INPUT:

    > - `title` - title to use for the exported worksheet (if
    >     None, just use current title)

  `import_worksheet`(username, id_number, filename)

    Import the worksheet username/id_number from the file with given filename.

  `load_openid`()

    Loads an open_id dict read from the disk.

  `load_server_conf`()
  `load_user_history`(username)

    Return the history log for the given user.

    INPUT:

    > - `username` – string

    OUTPUT:

    > - list of strings

  `load_users`(user_manager)

    OUTPUT:

    > - dictionary of user info

    EXAMPLES:

        sage: from sagenb.notebook.user import User
        sage: from sagenb.notebook.user_manager import SimpleUserManager
        sage: U = SimpleUserManager()
        sage: users = {'admin':User('admin','abc','a@b.c','admin'), 'wstein':User('wstein','xyz','b@c.d','user')}
        sage: from sagenb.storage import FilesystemDatastore
        sage: ds = FilesystemDatastore(tmp_dir())
        sage: ds.save_users(users)
        sage: 'users.pickle' in os.listdir(ds._path)
        True
        sage: users = ds.load_users(U)
        sage: U.users()
        {'admin': admin, 'wstein': wstein}

  `load_worksheet`(username, id_number)

    Return worksheet with given id_number belonging to the given user.

    If the worksheet does not exist, return ValueError.

    INPUT:

    > - `username` – string
    > - `id_number` – integer

    OUTPUT:

    > - a worksheet

  `readonly_user`(username)

    Each line of the readonly file has a username.

  `save_openid`(openid_dict)

    Saves an open_id dict to the disk.

  `save_server_conf`(server_conf)

    INPUT:

    > - `server` –

  `save_user_history`(username, history)

    Save the history log (a list of strings) for the given user.

    INPUT:

    > - `username` – string
    > - `history` – list of strings

  `save_users`(users)

    INPUT:

    > - `users` – dictionary mapping user names to users

    EXAMPLES:

        sage: from sagenb.notebook.user import User
        sage: from sagenb.notebook.user_manager import SimpleUserManager
        sage: U = SimpleUserManager()
        sage: users = {'admin':User('admin','abc','a@b.c','admin'), 'wstein':User('wstein','xyz','b@c.d','user')}
        sage: from sagenb.storage import FilesystemDatastore
        sage: ds = FilesystemDatastore(tmp_dir())
        sage: ds.save_users(users)
        sage: 'users.pickle' in os.listdir(ds._path)
        True
        sage: users = ds.load_users(U)
        sage: U.users()
        {'admin': admin, 'wstein': wstein}

  `save_worksheet`(worksheet, conf_only=False)

    INPUT:

    > - `worksheet` – a Sage worksheet
    > - `conf_only` – default: False; if True, only save the config file, not the actual body of the worksheet

    EXAMPLES:

        sage: from sagenb.notebook.worksheet import Worksheet
        sage: tmp = tmp_dir()
        sage: W = Worksheet('test', 2, tmp, system='gap', owner='sageuser')
        sage: from sagenb.storage import FilesystemDatastore
        sage: DS = FilesystemDatastore(tmp)
        sage: DS.save_worksheet(W)

  `worksheets`(username)

    Return list of all the worksheets belonging to the user with given name. If the given user does not exists, an empty list is returned.

    EXAMPLES: The load_user_data function must be defined in the derived class:

        sage: from sagenb.storage import FilesystemDatastore
        sage: tmp = tmp_dir()
        sage: FilesystemDatastore(tmp).worksheets('foobar')
        []
        sage: from sagenb.notebook.worksheet import Worksheet
        sage: W = Worksheet('test', 2, tmp, system='gap', owner='sageuser')
        sage: from sagenb.storage import FilesystemDatastore
        sage: DS = FilesystemDatastore(tmp)
        sage: DS.save_worksheet(W)
        sage: DS.worksheets('sageuser')
        [sageuser/2: [Cell 0: in=, out=]]

`sagenb.storage.filesystem_storage.``is_safe`(a)

  Used when importing contents of various directories from Sage worksheet files. We define this function to avoid the possibility of a user crafting fake sws file such that extracting it creates files outside where we want, e.g., by including .. or / in the path of some file.