Paths API
Last Updated: September 2024
Tip
If you are transitioning from using the Workspaces API then refer to the Guide to transitioning to the Paths API.
The Paths API makes it easy for you to retrieve the proper directories for accessing resource files in your app or writing files at runtime. This can be a tricky task for a web application, because of the multi-user, simultaneous-connection environment of the web. The Paths API provides a simple mechanism for creating and managing global, writable directories for your app and individual directories for each user of your app to prevent unwanted overwrites and file lock conflicts. It also provides a simple way to retrieve read-only file resources that are version controlled with the app source code.
Path Types
The Paths API provides access to the following types of Paths:
Read/Write
App Workspace: A location were the app can write files at runtime
App Media: A location were the app can store uploaded (publicly accessible) information
User Workspace: A location were the app can write user files at runtime
User Media: A location were the app can store user uploaded (publicly accessible) information
Read-Only
App Public: The location of the app's public directory (i.e. were static files like css and JavaScrip are stored)
App Resources: The location where version-controlled app resource files (e.g. configuration files) are stored
Getting Paths
There are several methods for obtaining the paths that are supported in Tethys Platform as follows:
Routing Decorators
The Tethys paths can easily be accessed in controllers, consumers, and handlers by specifying arguments to the various routing decorators. The arguments for each routing decorator is described below:
Controller Decorator
The method for obtaining Tethys paths in controllers is to use the following arguments in controller
decorator:
app_workspace
user_workspace
app_media
user_media
app_public
app_resources
When you specify the argument in the controller
decorator you must also specify the argument in the controller function itself as this is how the path will be passed to the controller function:
from tethys_sdk.routing import controller
@controller(app_workspace=True)
def my_controller(request, app_workspace):
...
@controller(user_workspace=True)
def my_controller(request, user_workspace):
...
@controller(app_media=True)
def my_controller(request, app_media):
...
@controller(user_media=True)
def my_controller(request, user_media):
...
@controller(app_public=True)
def my_controller(request, app_public):
...
@controller(app_resources=True)
def my_controller(request, app_resources):
...
@controller(
app_workspace=True,
user_workspace=True,
app_media=True,
user_media=True,
app_public=True,
app_resources=True,
)
def my_controller(request, app_workspace, user_workspace, app_media, user_media, app_public, app_resources):
...
Note that the argument name in the controller function must match the argument to the controller
decorator since the paths are passed to the controller function as key-word arguments.
To learn more about the controller
decorator, see: Controller Decorator
Consumer Decorator
To access Tethys paths in consumers, the with_paths
argument to the consumer
decorator should be set to True
. The paths will then be accessible as attributes on the class object.
from channels.generic.websocket import AsyncWebsocketConsumer
from tethys_sdk.routing import consumer
@consumer(
with_paths=True,
login_required=True,
)
class MyConsumer(AsyncWebsocketConsumer):
async def authorized_connect(self):
self.app_workspace
self.user_workspace
self.app_media
self.user_media
self.app_public
self.app_resources
Handler Decorator
To access Tethys paths in handlers, the with_paths
argument to the handler
decorator should be set to True
. The paths will then be accessible on the document
object that is passed to the handler.
from tethys_sdk.routing import handler
@handler(
with_paths=True
)
def my_app_handler(document):
# attributes available when using "with_paths" argument
request = document.request
user_workspace = document.user_workspace
user_media = document.user_media
app_workspace = document.app_workspace
app_media = document.app_media
app_public = document.app_public
app_resources = document.app_resources
...
App Class Methods and Properties
In some cases, it may be necessary (or more convenient) to use the app class to access the Tethys paths:
from .app import App
from django.contrib.auth.models import User
user = User.objects.get(id=1)
app_workspace = App.get_app_workspace()
user_workspace = App.get_user_workspace(user)
app_media = App.get_app_media()
user_media = App.get_user_media(user)
app_public = App.public_path
app_resources App.resources_path
...
Note
While the workspace and media directories are accessed through methods on the app class, public_path
and resources_path
are properties of the App
class.
For more details see App Base Class API
Path Functions
In the rare cases where you need to use a Tethys path where it is not convenient or not possible to use one of the decorators OR the app class methods, the Paths API provides function versions of the getters. Import them from tethys_sdk.paths
:
- paths.get_app_workspace()
- Parameters:
app_or_request (TethysAppBase, TethysApp, or HttpRequest) -- The Tethys app class that is defined in app.py or HttpRequest to app endpoint.
- Raises:
ValueError -- if app_or_request is not correct type.
AssertionError -- if quota for the app workspace/media directory has been exceeded.
- Return type:
Returns: TethysPath representing the app workspace.
- paths.get_user_workspace(user_or_request)
Get the dedicated user workspace for the given app. If an HttpRequest is given, the workspace of the logged-in user will be returned (i.e. request.user).
- Parameters:
app_or_request (TethysAppBase, TethysApp, or HttpRequest) -- The Tethys app class that is defined in app.py or HttpRequest to app endpoint.
user_or_request (User or HttpRequest) -- Either an HttpRequest with active user session or Django User object.
- Raises:
ValueError -- if app_or_request or user_or_request are not correct types.
AssertionError -- if quota for the user workspace/media directory has been exceeded.
- Return type:
- Returns:
TethysPath representing the user's workspace directory.
from tethys_sdk.workspaces import get_user_workspace from .app import App def some_function(user): user_workspace = get_user_workspace(App, user) ...
- paths.get_app_media()
- Parameters:
app_or_request (TethysAppBase, TethysApp, or HttpRequest) -- The Tethys app class that is defined in app.py or HttpRequest to app endpoint.
- Raises:
ValueError -- if app_or_request is not correct type.
AssertionError -- if quota for the app workspace/media directory has been exceeded.
Returns: TethysPath representing the media directory for the app.
- paths.get_user_media(username_or_request)
- Parameters:
app_or_request (TethysAppBase, TethysApp, or HttpRequest) -- The Tethys app class that is defined in app.py or HttpRequest to app endpoint.
username_or_request (User or HttpRequest) -- A User instance or an authenticated request to get the media directory for.
- Raises:
ValueError -- if app_or_request or user_or_request are not correct types.
AssertionError -- if quota for the user workspace/media directory has been exceeded.
Returns: TethysPath representing the user's media directory for the app.
- paths.get_app_public()
Gets the public directory of an app or extension as a read-only TethysPath
- Parameters:
app_or_request (TethysAppBase, TethysApp, TethysExtensionBase, TethysExtension, or HttpRequest) -- The Tethys app class that is defined in app.py (or extension class in ext.py) or HttpRequest to app endpoint.
- Raises:
ValueError -- if app_or_request is not correct type.
Returns: TethysPath representing the public directory of the app (or extension).
- paths.get_app_resources()
Gets the resources directory of an app or extension as a read-only TethysPath
- Parameters:
app_or_request (TethysAppBase, TethysApp, TethysExtensionBase, TethysExtension, or HttpRequest) -- The Tethys app class that is defined in app.py (or extension class in ext.py) or HttpRequest to app endpoint.
- Raises:
ValueError -- if app_or_request is not correct type.
Returns: TethysPath representing the public directory of the app (or extension).
Working with Tethys Paths
All of the methods described above return a TethysPath
object that contains the location to the Tethys path and several convenience methods for working with the Tethys path directory. An explanation of the TethysPath
object and examples of its usage are provided below.
TethysPath Objects
- class tethys_apps.base.TethysPath(path, read_only=False)
Defines objects that represent paths (directories) for apps and users.
- Parameters:
path (Path) -- The path to a directory. Cannot be overwritten.
- clear(exclude=None, exclude_files=False, exclude_directories=False)
Remove all files and directories in the TethysPath directory.
- Parameters:
exclude (iterable) -- A list or tuple of file and directory names to exclude from clearing operation.
exclude_files (bool) -- Excludes all files from clearing operation when True. Defaults to False.
exclude_directories (bool) -- Excludes all directories from clearing operation when True. Defaults to False.
Examples:
# Clear everything tethys_path.clear() # Clear directories only tethys_path.clear(exclude_files=True) # Clear files only tethys_path.clear(exclude_directories=True) # Clear all but specified files and directories tethys_path.clear(exclude=['file1.txt', '/full/path/to/directory1', 'directory2', '/full/path/to/file2.txt'])
- directories(names_only=False)
Return a list of directories (as Path objects by default) that are in the TethysPath directory.
- Parameters:
names_only (bool) -- Returns list of directory names as strings when True. Defaults to False.
- Returns:
A list of directories in the TethysPath directory.
- Return type:
list
Examples:
# List Path objects for each directory tethys_path.directories() # List of directory names tethys_path.directories(names_only=True)
- files(names_only=False)
Return a list of files (as Path objects by default) that are in the TethysPath directory.
- Parameters:
names_only (bool) -- Returns list of filenames as strings when True. Defaults to False.
- Returns:
A list of files in the TethysPath directory.
- Return type:
list
Examples:
# List of Path objects for each file tethys_path.files() # List of file names tethys_path.files(names_only=True)
- remove(item)
Remove a file or directory from the TethysPath directory.
- Parameters:
item (str | Path) -- Name, string path, or Path object of the item to remove from the TethysPath directory.
Examples:
tethys_path.remove('file.txt') tethys_path.remove('/full/path/to/file.txt') tethys_path.remove('relative/path/to/file.txt') tethys_path.remove('directory') tethys_path.remove('/full/path/to/directory') tethys_path.remove('relative/path/to/directory') tethys_path.remove(path_object)
Note: Though you can specify relative paths, the
remove()
method will not allow you to back into other directories using "../" or similar notation. Furthermore, absolute paths given must contain the path of the tethys_path to be valid.
Centralized Paths
For the workspace
and media
paths the location of the paths from all apps is centralized based on the TETHYS_WORKSPACES_ROOT
and MEDIA_ROOT
settings. By default these paths will be in the TETHYS_HOME
directory, but they can be specified in the portal_config.yml
file.
TETHYS_WORKSPACES_ROOT: /var/www/tethys/workspaces
MEDIA_ROOT: /var/www/tethys/media
Note
The public
and the resources
directories are relative to the source code of the app (i.e. not centralized). Even when the collectstatic
command is used to copy all static files to a central location the Paths API will return the the public directory that is relative to the app source code.
Handling Workspace/Media Clearing
Users and portal administrators are able to clear their user and app workspaces through pages in the Tethys Portal. The app class provides methods to allow the app developer to customize how the app handles clearing user/app workspaces and media directories. Override these methods in your app class to handle clearing workspaces and media directories appropriately in your app. When a workspace/media directory is cleared through the portal admin pages or user profile pages, the appropriate 'pre-delete' method is called, the workspace or media directory is cleared, and then the appropriate 'post-delete' method is called.
- classmethod TethysAppBase.pre_delete_app_workspace()
Override this method to pre-process the app workspace before it is emptied
- classmethod TethysAppBase.post_delete_app_workspace()
Override this method to post-process the app workspace after it is emptied
- classmethod TethysAppBase.pre_delete_user_workspace(user)
Override this method to pre-process a user's workspace before it is emptied
- Parameters:
user (User, required) -- User that requested to clear their workspace
- classmethod TethysAppBase.post_delete_user_workspace(user)
Override this method to post-process a user's workspace after it is emptied
- Parameters:
user (User, required) -- User that requested to clear their workspace
- classmethod TethysAppBase.pre_delete_app_media()
Override this method to pre-process the app media directory before it is emptied
- classmethod TethysAppBase.post_delete_app_media()
Override this method to post-process the app media directory after it is emptied
- classmethod TethysAppBase.pre_delete_user_media(user)
Override this method to pre-process a user's media directory before it is emptied
- Parameters:
user (User, required) -- User that requested to clear their media directory
- classmethod TethysAppBase.post_delete_user_media(user)
Override this method to post-process a user's media directory after it is emptied
- Parameters:
user (User, required) -- User that requested to clear their media directory