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_workspaceuser_workspaceapp_mediauser_mediaapp_publicapp_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.
Command Line Interface
The Paths API can be accessed through the command line interface (CLI) using the paths command. This command provides a way to list paths for specific apps or users and add files to those destinations.
Examples
Command:
tethys paths get -t app_workspace -a my_app
Output:
App Workspace for app 'my_app':
/home/user/.tethys/tethys/workspaces/my_app/app_workspace
Command:
tethys paths get -t user_workspace -a my_app -u my_user
Output:
User Workspace for user 'my_user' and app 'my_app':
/home/user/.tethys/tethys/workspaces/my_app/user_workspaces/my_user
Command:
tethys paths add -t user_media -a my_app -u my_user -f /path/to/file.txt
Output:
File 'file.txt' has been added to the User Media at '/home/user/.tethys/tethys/media/my_app/user/my_user/file.txt'
Command:
tethys paths add -t app_media -a my_app -f /path/to/file.txt
Output:
File 'file.txt' has been added to the App Media at '/home/user/.tethys/tethys/media/my_app/app/file.txt'`
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