Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,10 @@ repos:
rev: v2.13.6
hooks:
- id: jshint
- repo: https://github.com/codespell-project/codespell
rev: v2.4.2
hooks:
- id: codespell
args:
- --ignore-words-list=bu,doesnt,indx,nd,ser,theses,usera
- --skip="*.aff,*.dic,*.js,*.json,*.lock,*.svg,*.vcl"
10 changes: 5 additions & 5 deletions CHANGELOG
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ We follow the CalVer (https://calver.org/) versioning scheme: YY.MINOR.MICRO.
26.6.3 (2026-04-02)
===================

- Readd reindex share button
- Re-add reindex share button
- Fix missing notification during email throttle check
- Fix filter query in AbstractProviderSubscriptionList

Expand Down Expand Up @@ -83,7 +83,7 @@ We follow the CalVer (https://calver.org/) versioning scheme: YY.MINOR.MICRO.

- Permanently update two notification types
- Link digest to types and fix/log incorrect usage
- Update notifiction dedupe command
- Update notification dedupe command

26.2.0
======
Expand All @@ -94,7 +94,7 @@ We follow the CalVer (https://calver.org/) versioning scheme: YY.MINOR.MICRO.
===================

- Rework NR verification and de-duplication command
- Fix the rest of regsitration links in moderator digest email
- Fix the rest of registration links in moderator digest email
- Mark fail-to-render notifications as fake sent

26.1.5 (2026-01-12)
Expand Down Expand Up @@ -128,7 +128,7 @@ We follow the CalVer (https://calver.org/) versioning scheme: YY.MINOR.MICRO.
* Fix adding moderator email in admin
* Fix preprint/registration withdrawal request email in digest
* Fix subjects for schema response update emails
* Update defauls for triggered emails
* Update defaults for triggered emails

26.1.1 (2026-01-02)
===================
Expand Down Expand Up @@ -737,7 +737,7 @@ domains

20.11.0 (2020-06-17)
====================
- Add more tests for ending embargos
- Add more tests for ending embargoes
- Fix filenames containing &s preventing registrations from registering
- Ensure API complains when trying to embargo using deprecated methods
- Modify EGAP form and add new form
Expand Down
2 changes: 1 addition & 1 deletion NOTICE
Original file line number Diff line number Diff line change
Expand Up @@ -460,7 +460,7 @@ Common Public Attribution License Version 1.0 (CPAL-1.0)

8.1 This License and the rights granted hereunder will terminate automatically if You fail to comply with terms herein and fail to cure such breach within 30 days of becoming aware of the breach. All sublicenses to the Covered Code which are properly granted shall survive any termination of this License. Provisions which, by their nature, must remain in effect beyond the termination of this License shall survive.

8.2 If You initiate litigation by asserting a patent infringement claim (excluding declatory judgment actions) against Initial Developer, Original Developer or a Contributor (the Initial Developer, Original Developer or Contributor against whom You file such action is referred to as “Participant”) alleging that:
8.2 If You initiate litigation by asserting a patent infringement claim (excluding declaratory judgment actions) against Initial Developer, Original Developer or a Contributor (the Initial Developer, Original Developer or Contributor against whom You file such action is referred to as “Participant”) alleging that:

(a) such Participant’s Contributor Version directly or indirectly infringes any patent, then any and all rights granted by such Participant to You under Sections 2.1 and/or 2.2 of this License shall, upon 60 days notice from Participant terminate prospectively, unless if within 60 days after receipt of notice You either: (i) agree in writing to pay Participant a mutually agreeable reasonable royalty for Your past and future use of Modifications made by such Participant, or (ii) withdraw Your litigation claim with respect to the Contributor Version against such Participant. If within 60 days of notice, a reasonable royalty and payment arrangement are not mutually agreed upon in writing by the parties or the litigation claim is not withdrawn, the rights granted by Participant to You under Sections 2.1 and/or 2.2 automatically terminate at the expiration of the 60 day notice period specified above.

Expand Down
2 changes: 1 addition & 1 deletion README-docker-compose.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
sudo ifconfig lo:0 192.168.168.167 netmask 255.255.255.255 up
```

- For persistance, add to /etc/network/interfaces...
- For persistence, add to /etc/network/interfaces...
Add lo:0 to auto line...
```bash
auto lo lo:0
Expand Down
4 changes: 2 additions & 2 deletions addons/boa/tests/test_tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ class TestSubmitToBoa(OsfTestCase):

def setUp(self):
super().setUp()
self.host = 'http://locahost:9999/boa/?q=boa/api'
self.host = 'http://localhost:9999/boa/?q=boa/api'
self.username = 'fake-boa-username'
self.password = 'fake-boa-password'
self.user_guid = AuthUserFactory()._id
Expand Down Expand Up @@ -120,7 +120,7 @@ class TestSubmitToBoaAsync(OsfTestCase):

def setUp(self):
super().setUp()
self.host = 'http://locahost:9999/boa/?q=boa/api'
self.host = 'http://localhost:9999/boa/?q=boa/api'
self.username = 'fake-boa-username'
self.password = 'fake-boa-password'
self.user = AuthUserFactory()
Expand Down
2 changes: 1 addition & 1 deletion addons/dataverse/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ def _hashes(self):
return None

def update(self, revision, data, save=True, user=None):
"""Note: Dataverse only has psuedo versions (_history), pass None to not save them
"""Note: Dataverse only has pseudo versions (_history), pass None to not save them
Call super to update _history and last_touched anyway.
"""
version = super().update(None, data, user=user, save=save)
Expand Down
2 changes: 1 addition & 1 deletion addons/dropbox/views.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""Views fo the node settings page."""
"""Views of the node settings page."""
from flask import request
import logging

Expand Down
2 changes: 1 addition & 1 deletion addons/github/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ def __init__(self, external_account=None, access_token=None):

self.access_token = getattr(external_account, 'oauth_key', None) or access_token
session = GitHubSession()
# Caching libary
# Caching library
if github_settings.CACHE:
session.mount('https://api.github.com/user', default_adapter)
session.mount('https://', https_cache)
Expand Down
2 changes: 1 addition & 1 deletion addons/osfstorage/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ def osfstorage_get_storage_quota_status(target, **kwargs):
@must_be_signed
@decorators.autoload_filenode(must_be='file')
def osfstorage_get_revisions(file_node, payload, target, **kwargs):
from osf.models import PageCounter, FileVersion # TODO Fix me onces django works
from osf.models import PageCounter, FileVersion # TODO Fix me once django works
is_anon = has_anonymous_link(target, Auth(private_key=request.args.get('view_only')))

counter_prefix = f'download:{file_node.target._id}:{file_node._id}:'
Expand Down
2 changes: 1 addition & 1 deletion addons/s3/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ def bucket_exists(access_key, secret_key, bucket_name):

def can_list(access_key, secret_key):
"""Return whether or not a user can list
all buckets accessable by this keys
all buckets accessible by this keys
"""
# Bail out early as boto does not handle getting
# Called with (None, None)
Expand Down
4 changes: 2 additions & 2 deletions admin_tests/preprints/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ def test_change_preprint_provider_subjects_to_osf(self, plain_view, preprint_use
assert subject_osf in preprint.subjects.all()

def test_change_preprint_provider_subjects_problem_subject(self, plain_view, preprint_user, provider_one, provider_osf, subject_osf):
""" Testing that subjects are changed when providers are changed and theres no related mapping between subjects, the old subject stays in place.
""" Testing that subjects are changed when providers are changed and there's no related mapping between subjects, the old subject stays in place.
"""

preprint = PreprintFactory(subjects=[[subject_osf._id]], provider=provider_osf, creator=preprint_user)
Expand All @@ -313,7 +313,7 @@ def test_change_preprint_provider_subjects_problem_subject(self, plain_view, pre
assert subject_osf in preprint.subjects.all()

def test_change_preprint_provider_subjects_change_permissions(self, plain_view, preprint_user, provider_one, provider_osf, subject_osf):
""" Testing that subjects are changed when providers are changed and theres no related mapping between subjects, the old subject stays in place.
""" Testing that subjects are changed when providers are changed and there's no related mapping between subjects, the old subject stays in place.
"""
auth_user = AuthUserFactory()
change_permission = Permission.objects.get(codename='change_preprint')
Expand Down
2 changes: 1 addition & 1 deletion api/base/permissions.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ def has_object_permission(self, request, view, obj):


def PermissionWithGetter(Base, getter):
"""A psuedo class for checking permissions
"""A pseudo class for checking permissions
of subresources without having to redefine permission classes
"""
class Perm(Base):
Expand Down
2 changes: 1 addition & 1 deletion api/crossref/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ def post(self, request):
# Sets preprint_doi_created and saves the preprint
preprint.set_identifier_values(doi=doi, save=True)
# Double records returned when possible matching DOI is found in crossref
elif 'possible preprint/vor pair' not in msg.lower():
elif 'possible preprint/for pair' not in msg.lower():
Copy link
Copy Markdown
Author

@cclauss cclauss May 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extra review, please. Should this be doi ?!?

# Directly updates the identifier
preprint.set_identifier_value(category='doi', value=doi)

Expand Down
4 changes: 2 additions & 2 deletions api_tests/resources/views/test_resource_detail.py
Original file line number Diff line number Diff line change
Expand Up @@ -538,8 +538,8 @@ def test_patch__finalized__adds_log(self, app):
@pytest.mark.django_db
class TestResourceDetailDELETEPermissions:

# Don't bother exhaustive Registration state checking for DELETEing.
# If the Resource exists and the Registration isn't WITHDRAWN or DELETED, the Resource should be DELETEable
# Don't bother exhaustive Registration state checking for deleting.
# If the Resource exists and the Registration isn't WITHDRAWN or DELETED, the Resource should be deletable
@pytest.mark.parametrize('user_role', UserRoles.write_roles())
def test_status_code__user_can_write(self, app, user_role):
test_artifact, test_auth, _ = configure_test_preconditions(user_role=user_role)
Expand Down
4 changes: 2 additions & 2 deletions conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ def mock_crossref():
def mock_oopspam():
"""
This should be used to mock our anti-spam service oopspam.
Relevent endpoints:
Relevant endpoints:
'https://oopspam.p.rapidapi.com/v1/spamdetection'
"""
with mock.patch.object(website_settings, 'SPAM_SERVICES_ENABLED', True):
Expand All @@ -247,7 +247,7 @@ def mock_oopspam():
def mock_pigeon():
"""
This should be used to mock our Internet Archive archiving microservice osf-pigeon.
Relevent endpoints:
Relevant endpoints:
'{settings.OSF_PIGEON_URL}archive/{guid}'
'{settings.OSF_PIGEON_URL}metadata/{guid}'

Expand Down
2 changes: 1 addition & 1 deletion osf/external/gravy_valet/request_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -403,7 +403,7 @@ def _format_included_entities(included_entities_json):
'''Processes all entries of a JSONAPI `include` element into JSONAPIResultEntries.

Returns a dictionary of JSONAPIResultEntires keyed by type and id for easy lookup
and linking. Also links these entires in the case of nested Includes.
and linking. Also links these entries in the case of nested Includes.
'''
included_entities_by_type_and_id = {
(entity['type'], entity['id']): JSONAPIResultEntry(entity)
Expand Down
2 changes: 1 addition & 1 deletion osf/metadata/rdfutils.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ def primitivify_rdf(thing):
primitivify_rdf(key): primitivify_rdf(val)
for key, val in thing.items()
}
return thing # end recursion with pass-thru
return thing # end recursion with pass-through


def without_namespace(iri: rdflib.URIRef, namespace: rdflib.Namespace) -> str:
Expand Down
2 changes: 1 addition & 1 deletion osf/metadata/serializers/google_dataset_json_ld.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ def metadata_as_dict(self) -> dict:
'name': 'Center For Open Science'
},
'creator': format_creators(self.basket),
'identifier': [identifer for identifer in self.basket[DCTERMS.identifier]],
'identifier': [identifier for identifier in self.basket[DCTERMS.identifier]],
'license': format_license_list(self.basket),
}

Expand Down
2 changes: 1 addition & 1 deletion osf/migrations/0033_notification_system.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class Migration(migrations.Migration):
]

operations = [
# Step 1: Create legacy tables needs for managment command `migrate_notifications``
# Step 1: Create legacy tables needs for management command `migrate_notifications``
migrations.RunSQL(
sql="""
-- 1. Rename the existing table and its indexes
Expand Down
2 changes: 1 addition & 1 deletion osf/models/files.py
Original file line number Diff line number Diff line change
Expand Up @@ -505,7 +505,7 @@ def update(self, revision, data, user=None, save=True):
data['modified'] = parse_date(
data['modified'],
ignoretz=True,
default=timezone.now() # Just incase nothing can be parsed
default=timezone.now() # Just in case nothing can be parsed
)

# if revision is none then version is the latest version
Expand Down
2 changes: 1 addition & 1 deletion osf/models/institution.py
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ def deactivate(self):
self.sso_availability = SSOAvailability.HIDDEN.value

self.save()
# Django mangers aren't used when querying on related models. Thus, we can query
# Django managers aren't used when querying on related models. Thus, we can query
# affiliated users and send notification emails after the institution has been deactivated.
self._send_deactivation_email()
else:
Expand Down
2 changes: 1 addition & 1 deletion osf/models/notification_subscription.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ def emit(

Args:
event_context (OSFUser): The info for context for the template
destination_address (optional): overides the user's email address for the notification. Good for sending
destination_address (optional): overrides the user's email address for the notification. Good for sending
to a test address or OSF desk support'
email_context (dict, optional): Context for sending the email bcc, reply_to header etc
save (bool, optional): save the notification and creates a subscription object if true, otherwise just
Expand Down
2 changes: 1 addition & 1 deletion osf/models/outcome_artifacts.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ def update(
)

def _update_identifier(self, new_pid_value, pid_type='doi', api_request=None):
'''Changes the linked Identifer to one matching the new pid_value and handles callbacks.
'''Changes the linked Identifier to one matching the new pid_value and handles callbacks.

If `finalized` is True, will also log the change on the parent Outcome if invoked via API.
Will attempt to delete the previous identifier to avoid orphaned entries.
Expand Down
4 changes: 2 additions & 2 deletions osf/models/provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -416,15 +416,15 @@ def all_subjects(self):
if self.subjects.exists():
return self.subjects.all()
else:
# TODO: Delet this when all PreprintProviders have a mapping
# TODO: Delete this when all PreprintProviders have a mapping
return rules_to_subjects(self.subjects_acceptable)

@property
def top_level_subjects(self):
if self.subjects.exists():
return optimize_subject_query(self.subjects.filter(parent__isnull=True))
else:
# TODO: Delet this when all PreprintProviders have a mapping
# TODO: Delete this when all PreprintProviders have a mapping
if len(self.subjects_acceptable) == 0:
return optimize_subject_query(Subject.objects.filter(parent__isnull=True, provider___id='osf'))
tops = {sub[0][0] for sub in self.subjects_acceptable}
Expand Down
2 changes: 1 addition & 1 deletion osf_tests/default_test_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
}, {
'block_type': 'question-label',
'display_text': 'Multi-select input',
'help_text': 'This allows the user to select several entires from a list of options',
'help_text': 'This allows the user to select several entries from a list of options',
}, {
'block_type': 'multi-select-input',
'registration_response_key': 'q4',
Expand Down
2 changes: 1 addition & 1 deletion osf_tests/embargoes/test_embargoes.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ def registration(self, user):
@pytest.mark.usefixtures('mock_gravy_valet_get_verified_links')
def test_request_early_termination_too_late(self, registration, user):
"""
This is for an edge case test for where embargos are frozen and never expire when the user requests they be
This is for an edge case test for where embargoes are frozen and never expire when the user requests they be
terminated with embargo with less than 48 hours before it would expire anyway.
"""
with capture_notifications():
Expand Down
2 changes: 1 addition & 1 deletion osf_tests/external/gravy_valet/gv_fakes.py
Original file line number Diff line number Diff line change
Expand Up @@ -828,7 +828,7 @@ def _format_response_body(
list_view: bool = False,
include_param='',
) -> str:
"""Formates the stringified json body for responses."""
"""Formats the stringified json body for responses."""
if not data:
return json.dumps({'data': [] if list_view else None})
if list_view:
Expand Down
2 changes: 1 addition & 1 deletion osf_tests/test_node.py
Original file line number Diff line number Diff line change
Expand Up @@ -1163,7 +1163,7 @@ def test_permission_override_on_readded_contributor(self, node, user):
user2 = UserFactory()
child_node.add_contributor(user2, permissions=permissions.READ)

# user is readded with permission admin
# user is re-added with permission admin
child_node.add_contributor(user2, permissions=permissions.ADMIN)
child_node.save()

Expand Down
2 changes: 1 addition & 1 deletion osf_tests/test_user.py
Original file line number Diff line number Diff line change
Expand Up @@ -1920,7 +1920,7 @@ def test_validate_social_profile_website_many_different(self):
if fails_at_end:
raise

# Not all domains that are permissable are possible to use as spam,
# Not all domains that are permissible are possible to use as spam,
# some are correctly not extracted and not kept in notable domain so spot
# check some, not all, because not all `testsPositive` urls should be in
# NotableDomains
Expand Down
2 changes: 1 addition & 1 deletion scripts/triggered_mails.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ def find_inactive_users_without_enqueued_or_sent_no_login():
Q(no_login_email_last_sent__lt=F('date_last_login'))
)
)
# Exlude users who already have a pending/started/retrying EmailTask for no-login
# Exclude users who already have a pending/started/retrying EmailTask for no-login
base_q = base_q.exclude(
emailtask__task_id__startswith=NO_LOGIN_PREFIX,
emailtask__status__in=['PENDING', 'STARTED', 'RETRY']
Expand Down
2 changes: 1 addition & 1 deletion tests/test_addons.py
Original file line number Diff line number Diff line change
Expand Up @@ -1590,7 +1590,7 @@ def test_update_logs_to_sentry_when_called_with_disordered_metadata(self, mock_c
file_node.history.append({'modified': parse_date(
'2017-08-22T13:54:32.100900',
ignoretz=True,
default=timezone.now() # Just incase nothing can be parsed
default=timezone.now() # Just in case nothing can be parsed
)})
data = {
'name': 'a name',
Expand Down
4 changes: 2 additions & 2 deletions tests/test_claim_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,7 @@ def test_claim_user_when_user_is_registered_with_orcid(self, mock_response_from_
url_with_service_ticket = f'{url}?ticket={service_ticket}'
res = self.app.get(url_with_service_ticket)
# The response of this request is expected to be a 302 with `Location`.
# And the redirect URL must equal to the originial service URL
# And the redirect URL must equal to the original service URL
assert res.status_code == 302
redirect_url = res.headers['Location']
assert redirect_url == url
Expand Down Expand Up @@ -461,7 +461,7 @@ def test_claim_url_with_bad_token_returns_400(self):
assert res.status_code == 400

def test_cannot_claim_user_with_user_who_is_already_contributor(self):
# user who is already a contirbutor to the project
# user who is already a contributor to the project
contrib = AuthUserFactory()
self.project.add_contributor(contrib, auth=Auth(self.project.creator))
self.project.save()
Expand Down
2 changes: 1 addition & 1 deletion tests/test_registrations/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -449,7 +449,7 @@ def embargoed_registration(self, provider):
return registration


# API paths for registrations that are not publically available on non-public Registrations
# API paths for registrations that are not publicly available on non-public Registrations
PROTECTED_REGISTRATION_SUB_ROUTES = [
'',
'bibliographic_contributors',
Expand Down
Loading