Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ENG-5675] Phase X: add and apply (black+isort|ruff) #10703

Open
wants to merge 18 commits into
base: develop
Choose a base branch
from
Open
  •  
  •  
  •  
8 changes: 8 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,11 @@ repos:
rev: v2.13.6
hooks:
- id: jshint

- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.5.7
hooks:
- id: ruff
args: [ --fix ]
- id: ruff-format
args: ["--line-length=79"]
1 change: 1 addition & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ RUN apk add --no-cache --virtual .run-deps \
libpq-dev \
libffi \
libev \
libev-dev \
libevent \
&& yarn global add bower \
&& mkdir -p /var/www \
Expand Down
9 changes: 5 additions & 4 deletions addons/base/__init__.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
from django.db.models import options
default_app_config = 'addons.base.apps.BaseAddonAppConfig'

default_app_config = "addons.base.apps.BaseAddonAppConfig"


# Patch to make abstractproperties overridable by djangofields
if 'add_field' not in options.DEFAULT_NAMES:
options.DEFAULT_NAMES += ('add_field', )
if "add_field" not in options.DEFAULT_NAMES:
options.DEFAULT_NAMES += ("add_field",)
original_add_field = options.Options.add_field

def add_field_patched(self, field, **kwargs):
prop = getattr(field.model, field.name, None)
if prop and getattr(prop, '__isabstractmethod__', None):
if prop and getattr(prop, "__isabstractmethod__", None):
setattr(field.model, field.name, None)
return original_add_field(field.model._meta, field, **kwargs)

Expand Down
64 changes: 31 additions & 33 deletions addons/base/apps.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,20 @@

def _is_image(filename):
mtype, _ = mimetypes.guess_type(filename)
return mtype and mtype.startswith('image')
return mtype and mtype.startswith("image")


NODE_SETTINGS_TEMPLATE_DEFAULT = os.path.join(
settings.TEMPLATES_PATH,
'project',
'addon',
'node_settings_default.mako',
"project",
"addon",
"node_settings_default.mako",
)

USER_SETTINGS_TEMPLATE_DEFAULT = os.path.join(
settings.TEMPLATES_PATH,
'profile',
'user_settings_default.mako',
"profile",
"user_settings_default.mako",
)


Expand All @@ -42,16 +43,17 @@ def _root_folder(node_settings, auth, **kwargs):
permissions=auth,
nodeUrl=node.url,
nodeApiUrl=node.api_url,
private_key=kwargs.get('view_only', None),
private_key=kwargs.get("view_only", None),
)
return [root]
_root_folder.__name__ = f'{addon_short_name}_root_folder'

_root_folder.__name__ = f"{addon_short_name}_root_folder"
return _root_folder


class BaseAddonAppConfig(AppConfig):
name = 'addons.base'
label = 'addons_base'
name = "addons.base"
label = "addons_base"

actions = tuple()
user_settings = None
Expand Down Expand Up @@ -81,26 +83,20 @@ def __init__(self, *args, **kwargs):
paths.append(os.path.dirname(self.user_settings_template))
if self.node_settings_template:
paths.append(os.path.dirname(self.node_settings_template))
template_dirs = list(
{
path
for path in paths
if os.path.exists(path)
}
)
template_dirs = list({path for path in paths if os.path.exists(path)})
if template_dirs:
self.template_lookup = TemplateLookup(
directories=template_dirs,
default_filters=[
'unicode', # default filter; must set explicitly when overriding
'temp_ampersand_fixer',
"unicode", # default filter; must set explicitly when overriding
"temp_ampersand_fixer",
# FIXME: Temporary workaround for data stored in wrong format in DB. Unescape it before it gets re-escaped by Markupsafe. See [#OSF-4432]
'h',
"h",
],
imports=[
'from website.util.sanitize import temp_ampersand_fixer',
"from website.util.sanitize import temp_ampersand_fixer",
# FIXME: Temporary workaround for data stored in wrong format in DB. Unescape it before it gets re-escaped by Markupsafe. See [#OSF-4432]
]
],
)
else:
self.template_lookup = None
Expand All @@ -119,8 +115,8 @@ def icon(self):
try:
return self._icon
except Exception:
static_path = os.path.join('addons', self.short_name, 'static')
static_files = glob.glob(os.path.join(static_path, 'comicon.*'))
static_path = os.path.join("addons", self.short_name, "static")
static_files = glob.glob(os.path.join(static_path, "comicon.*"))
image_files = [
os.path.split(filename)[1]
for filename in static_files
Expand All @@ -144,22 +140,24 @@ def _static_url(self, filename):
:return str: Static URL for file

"""
if filename.startswith('/'):
if filename.startswith("/"):
return filename
return '/static/addons/{addon}/{filename}'.format(
return "/static/addons/{addon}/{filename}".format(
addon=self.short_name,
filename=filename,
)

def to_json(self):
return {
'short_name': self.short_name,
'full_name': self.full_name,
'capabilities': self.short_name in settings.ADDON_CAPABILITIES,
'addon_capabilities': settings.ADDON_CAPABILITIES.get(self.short_name),
'icon': self.icon_url,
'has_page': 'page' in self.views,
'has_widget': 'widget' in self.views,
"short_name": self.short_name,
"full_name": self.full_name,
"capabilities": self.short_name in settings.ADDON_CAPABILITIES,
"addon_capabilities": settings.ADDON_CAPABILITIES.get(
self.short_name
),
"icon": self.icon_url,
"has_page": "page" in self.views,
"has_widget": "widget" in self.views,
}

# Override Appconfig
Expand Down
1 change: 1 addition & 0 deletions addons/base/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,5 @@ class DoesNotExist(AddonError):

class NotApplicableError(AddonError):
"""This exception is used by non-storage and/or non-oauth add-ons when they don't need or have certain features."""

pass
70 changes: 39 additions & 31 deletions addons/base/generic_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,18 @@


def import_auth(addon_short_name, Serializer):
@must_have_addon(addon_short_name, 'user')
@must_have_addon(addon_short_name, 'node')
@must_have_addon(addon_short_name, "user")
@must_have_addon(addon_short_name, "node")
@must_have_permission(permissions.WRITE)
def _import_auth(auth, node_addon, user_addon, **kwargs):
"""Import add-on credentials from the currently logged-in user to a node.
"""
"""Import add-on credentials from the currently logged-in user to a node."""
external_account = ExternalAccount.load(
request.json['external_account_id']
request.json["external_account_id"]
)

if not user_addon.external_accounts.filter(id=external_account.id).exists():
if not user_addon.external_accounts.filter(
id=external_account.id
).exists():
raise HTTPError(http_status.HTTP_403_FORBIDDEN)

try:
Expand All @@ -36,10 +37,11 @@ def _import_auth(auth, node_addon, user_addon, **kwargs):
node_addon.save()

return {
'result': Serializer().serialize_settings(node_addon, auth.user),
'message': 'Successfully imported credentials from profile.',
"result": Serializer().serialize_settings(node_addon, auth.user),
"message": "Successfully imported credentials from profile.",
}
_import_auth.__name__ = f'{addon_short_name}_import_auth'

_import_auth.__name__ = f"{addon_short_name}_import_auth"
return _import_auth


Expand All @@ -49,74 +51,80 @@ def _account_list(auth):
user_settings = auth.user.get_addon(addon_short_name)
serializer = Serializer(user_settings=user_settings)
return serializer.serialized_user_settings
_account_list.__name__ = f'{addon_short_name}_account_list'

_account_list.__name__ = f"{addon_short_name}_account_list"
return _account_list


def folder_list(addon_short_name, addon_full_name, get_folders):
# TODO [OSF-6678]: Generalize this for API use after node settings have been refactored
@must_have_addon(addon_short_name, 'node')
@must_have_addon(addon_short_name, "node")
@must_be_addon_authorizer(addon_short_name)
def _folder_list(node_addon, **kwargs):
"""Returns a list of folders"""
if not node_addon.has_auth:
raise HTTPError(http_status.HTTP_403_FORBIDDEN)

folder_id = request.args.get('folderId')
folder_id = request.args.get("folderId")
return get_folders(node_addon, folder_id)
_folder_list.__name__ = f'{addon_short_name}_folder_list'

_folder_list.__name__ = f"{addon_short_name}_folder_list"
return _folder_list


def get_config(addon_short_name, Serializer):
@must_be_logged_in
@must_have_addon(addon_short_name, 'node')
@must_have_addon(addon_short_name, "node")
@must_be_valid_project
@must_have_permission(permissions.WRITE)
def _get_config(node_addon, auth, **kwargs):
"""API that returns the serialized node settings."""
return {
'result': Serializer().serialize_settings(
node_addon,
auth.user
)
"result": Serializer().serialize_settings(node_addon, auth.user)
}
_get_config.__name__ = f'{addon_short_name}_get_config'

_get_config.__name__ = f"{addon_short_name}_get_config"
return _get_config


def set_config(addon_short_name, addon_full_name, Serializer, set_folder):
@must_not_be_registration
@must_have_addon(addon_short_name, 'user')
@must_have_addon(addon_short_name, 'node')
@must_have_addon(addon_short_name, "user")
@must_have_addon(addon_short_name, "node")
@must_be_addon_authorizer(addon_short_name)
@must_have_permission(permissions.WRITE)
def _set_config(node_addon, user_addon, auth, **kwargs):
"""View for changing a node's linked folder."""
folder = request.json.get('selected')
folder = request.json.get("selected")
set_folder(node_addon, folder, auth)

path = node_addon.folder_path
return {
'result': {
'folder': {
'name': path.replace('All Files', '') if path != '/' else f'/ (Full {addon_full_name})',
'path': path,
"result": {
"folder": {
"name": path.replace("All Files", "")
if path != "/"
else f"/ (Full {addon_full_name})",
"path": path,
},
'urls': Serializer(node_settings=node_addon).addon_serialized_urls,
"urls": Serializer(
node_settings=node_addon
).addon_serialized_urls,
},
'message': 'Successfully updated settings.',
"message": "Successfully updated settings.",
}
_set_config.__name__ = f'{addon_short_name}_set_config'

_set_config.__name__ = f"{addon_short_name}_set_config"
return _set_config


def deauthorize_node(addon_short_name):
@must_not_be_registration
@must_have_addon(addon_short_name, 'node')
@must_have_addon(addon_short_name, "node")
@must_have_permission(permissions.WRITE)
def _deauthorize_node(auth, node_addon, **kwargs):
node_addon.deauthorize(auth=auth)
node_addon.save()
_deauthorize_node.__name__ = f'{addon_short_name}_deauthorize_node'

_deauthorize_node.__name__ = f"{addon_short_name}_deauthorize_node"
return _deauthorize_node
48 changes: 29 additions & 19 deletions addons/base/logger.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import abc


class AddonNodeLogger:
"""Helper class for adding correctly-formatted addon logs to nodes.

:param Node node: The node to add logs to
:param Auth auth: Authorization of the person who did the action.
"""

__metaclass__ = abc.ABCMeta

@property
Expand All @@ -14,13 +16,15 @@ def addon_short_name(self):
pass

def _log_params(self):
node_settings = self.node.get_addon(self.addon_short_name, is_deleted=True)
node_settings = self.node.get_addon(
self.addon_short_name, is_deleted=True
)
return {
'project': self.node.parent_id,
'node': self.node._primary_key,
'folder_id': node_settings.folder_id,
'folder_name': node_settings.folder_name,
'folder': node_settings.folder_path
"project": self.node.parent_id,
"node": self.node._primary_key,
"folder_id": node_settings.folder_id,
"folder_name": node_settings.folder_name,
"folder": node_settings.folder_path,
}

def __init__(self, node, auth, path=None):
Expand All @@ -39,24 +43,30 @@ def log(self, action, extra=None, save=False):
params = self._log_params()
# If logging a file-related action, add the file's view and download URLs
if self.path:
params.update({
'urls': {
'view': self.node.web_url_for('addon_view_or_download_file', path=self.path, provider=self.addon_short_name),
'download': self.node.web_url_for(
'addon_view_or_download_file',
path=self.path,
provider=self.addon_short_name
)
},
'path': self.path,
})
params.update(
{
"urls": {
"view": self.node.web_url_for(
"addon_view_or_download_file",
path=self.path,
provider=self.addon_short_name,
),
"download": self.node.web_url_for(
"addon_view_or_download_file",
path=self.path,
provider=self.addon_short_name,
),
},
"path": self.path,
}
)
if extra:
params.update(extra)

self.node.add_log(
action=f'{self.addon_short_name}_{action}',
action=f"{self.addon_short_name}_{action}",
params=params,
auth=self.auth
auth=self.auth,
)
if save:
self.node.save()
Loading