Skip to content
40 changes: 39 additions & 1 deletion openreview/api/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -3318,6 +3318,9 @@ def to_json(self):
if self.replyto:
body['replyto'] = self.replyto
if self.content:
print('Updating note content for to_json', self.content)
if 'authors' in self.content and 'authorids' in self.content and self.content['authors'].get('value') and isinstance(self.content['authors']['value'][0], dict):
del self.content['authorids']
body['content'] = self.content
if self.invitations:
body['invitations'] = self.invitations
Expand Down Expand Up @@ -3345,6 +3348,24 @@ def to_json(self):
body['license'] = self.license
return body

def get_author_names(self):
"""
Retrieves the author names from the Note content

:return: List of author names
:rtype: list[str]
"""
author_names = []
if self.content and 'authors' in self.content:
if isinstance(self.content['authors'], list):
return self.content['authors']
for author in self.content['authors'].get('value', []):
if isinstance(author, dict) and 'fullname' in author:
author_names.append(author['fullname'])
else:
author_names.append(author)
return author_names

@classmethod
def from_json(Note,n):
"""
Expand All @@ -3356,6 +3377,23 @@ def from_json(Note,n):
:return: Note whose instance variables contain the values from the dictionary
:rtype: Note
"""
content = n.get('content')
authorids_value = []
authorids_readers = []
if content and 'authorids' not in content and 'authors' in content:
for author in content['authors'].get('value', []):
authorids_value.append(author['username'] if 'username' in author else author)
authorids_readers = content['authors'].get('readers')

if authorids_value or authorids_readers:
content['authorids'] = {}

if authorids_value:
content['authorids']['value'] = authorids_value

if authorids_readers:
content['authorids']['readers'] = authorids_readers

note = Note(
id = n.get('id'),
external_ids = n.get('externalIds'),
Expand All @@ -3367,7 +3405,7 @@ def from_json(Note,n):
tcdate = n.get('tcdate'),
tmdate =n.get('tmdate'),
ddate=n.get('ddate'),
content=n.get('content'),
content=content,
forum=n.get('forum'),
invitations=n.get('invitations'),
parent_invitations=n.get('parentInvitations'),
Expand Down
11 changes: 6 additions & 5 deletions openreview/conference/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -576,8 +576,7 @@ def get_submission_stage(request_forum, venue):

submission_remove_options = request_forum.content.get('remove_submission_options', [])
submission_release=(request_forum.content.get('submissions_visibility', '') == 'Yes, submissions should be immediately revealed to the public.')
create_groups=(not double_blind) and public and submission_release


author_names_revealed = 'Reveal author identities of all submissions to the public' in request_forum.content.get('reveal_authors', '') or 'Reveal author identities of only accepted submissions to the public' in request_forum.content.get('reveal_authors', '')
papers_released = 'Release all submissions to the public'in request_forum.content.get('release_submissions', '') or 'Release only accepted submission to the public' in request_forum.content.get('release_submissions', '') or 'Make accepted submissions public and hide rejected submissions' in request_forum.content.get('submission_readers', '')

Expand Down Expand Up @@ -625,7 +624,6 @@ def get_submission_stage(request_forum, venue):
remove_fields=submission_remove_options,
hide_fields=hide_fields,
subject_areas=subject_areas,
create_groups=create_groups,
withdraw_submission_exp_date=withdraw_submission_exp_date,
withdrawn_submission_public=withdrawn_submission_public,
withdrawn_submission_reveal_authors=withdrawn_submission_reveal_authors,
Expand All @@ -643,7 +641,9 @@ def get_submission_stage(request_forum, venue):
second_deadline_additional_fields=second_deadline_additional_fields,
second_deadline_remove_fields=second_deadline_remove_fields,
commitments_venue=commitments_venue,
description=request_forum.content.get('submission_description', None))
description=request_forum.content.get('submission_description', None),
authors_with_institutions=request_forum.content.get('authors_with_institutions', 'No') == 'Yes'
)

def get_bid_stages(request_forum, reviewers_id=None, area_chairs_id=None, senior_area_chairs_id=None):
bid_start_date = request_forum.content.get('bid_start_date', '').strip()
Expand Down Expand Up @@ -1066,7 +1066,8 @@ def get_submission_revision_stage(request_forum):
remove_fields=submission_revision_remove_options,
only_accepted=only_accepted,
allow_author_reorder=allow_author_reorder,
revision_history_readers=submission_revision_history_readers)
revision_history_readers=submission_revision_history_readers,
authors_with_institutions=request_forum.content.get('authors_with_institutions', 'No') == 'Yes')

def get_comment_stage(request_forum):

Expand Down
114 changes: 79 additions & 35 deletions openreview/stages/venue_stages.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,6 @@ def __init__(
hide_fields=[],
subject_areas=[],
email_pcs=False,
create_groups=False,
# We need to assume the Official Review super invitation is already created and active
create_review_invitation=False,
withdraw_submission_exp_date=None,
withdrawn_submission_public=False,
withdrawn_submission_reveal_authors=False,
Expand All @@ -89,7 +86,8 @@ def __init__(
second_deadline_remove_fields=[],
commitments_venue=False,
description=None,
withdraw_additional_fields={}
withdraw_additional_fields={},
authors_with_institutions=False
):

self.start_date = start_date
Expand All @@ -105,8 +103,6 @@ def __init__(
self.hide_fields = hide_fields
self.subject_areas = subject_areas
self.email_pcs = email_pcs
self.create_groups = create_groups
self.create_review_invitation = create_review_invitation
self.withdraw_submission_exp_date = withdraw_submission_exp_date
self.withdrawn_submission_public = withdrawn_submission_public
self.withdrawn_submission_reveal_authors = withdrawn_submission_reveal_authors
Expand All @@ -127,6 +123,8 @@ def __init__(
self.commitments_venue = commitments_venue
self.description = description
self.withdraw_additional_fields = withdraw_additional_fields
self.authors_with_institutions = force_profiles and authors_with_institutions
self.author_identifying_fields = ['authors'] if self.authors_with_institutions else ['authors', 'authorids']

def get_readers(self, conference, number, decision=None, accept_options=None):

Expand Down Expand Up @@ -179,10 +177,19 @@ def get_readers(self, conference, number, decision=None, accept_options=None):
submission_readers.append(conference.get_authors_id(number=number))
return submission_readers


def get_invitation_note_edit_readers(self, venue_id):
if self.authors_with_institutions:
return [venue_id, '${2/note/content/authors/value/*/username}']
return [venue_id, '${2/note/content/authorids/value}']

def get_invitation_note_readers(self, venue_id):
if self.authors_with_institutions:
return [venue_id, '${2/content/authors/value/*/username}']
return [venue_id, '${2/content/authorids/value}']


def get_invitation_readers(self, conference, under_submission):
# Rolling review should be release right away
if self.create_groups:
return {'values': ['everyone']}

if under_submission or self.double_blind:
has_authorids = 'authorids' in self.get_content()
Expand Down Expand Up @@ -302,16 +309,44 @@ def get_content(self, api_version='1', conference=None, venue_id=None):
content[key] = value

if self.force_profiles:
content['authorids'] = {
'order': 3,
'description': 'Search author profile by first, middle and last name or email address. All authors must have an OpenReview profile prior to submitting a paper.',
'value': {
'param': {
'type': 'profile{}',
'regex': r'~.*',
}

if self.authors_with_institutions:
del content['authorids']
content['authors'] = {
'order': 2,
'value': {
'param': {
'type': 'author{}',
'properties': {
'fullname': { 'param': { 'type': 'string' } },
'username': { 'param': { 'type': 'string' } },
'institutions': {
'param': {
'type': 'object{}',
'properties': {
'name': { 'param': { 'type': 'string' } },
'domain': { 'param': { 'type': 'string' } },
'country': { 'param': { 'type': 'string' } },
},
'optional': True
},
},
},
},
},
'description': 'Authors of paper.',
}
}
else:
content['authorids'] = {
'order': 3,
'description': 'Search author profile by first, middle and last name or email address. All authors must have an OpenReview profile prior to submitting a paper.',
'value': {
'param': {
'type': 'profile{}',
'regex': r'~.*',
}
}
}

if self.commitments_venue and 'paper_link' not in content:
content['paper_link'] = {
Expand Down Expand Up @@ -384,7 +419,7 @@ def get_content(self, api_version='1', conference=None, venue_id=None):
return content

def get_hidden_field_names(self):
return (['authors', 'authorids'] if self.double_blind and not self.author_names_revealed else []) + self.hide_fields
return (self.author_identifying_fields if self.double_blind and not self.author_names_revealed else []) + self.hide_fields

def is_under_submission(self):
return self.due_date is None or datetime.datetime.now() < self.due_date
Expand Down Expand Up @@ -550,7 +585,8 @@ def __init__(self,
allow_author_reorder=False,
allow_license_edition=False,
preprocess_path=None,
revision_history_readers=None):
revision_history_readers=None,
authors_with_institutions=False):
self.name = name
self.start_date = start_date
self.due_date = due_date
Expand All @@ -564,6 +600,7 @@ def __init__(self,
self.preprocess_path = preprocess_path
self.source = source
self.revision_history_readers = revision_history_readers
self.authors_with_institutions = authors_with_institutions


def get_edit_readers(self, venue, number):
Expand All @@ -588,24 +625,31 @@ def get_content(self, api_version='2', conference=None):
content[key] = value

if self.allow_author_reorder == AuthorReorder.ALLOW_REORDER:
content['authors'] = {
'value': {
'param': {
'type': 'string[]',
'const': ['${{6/id}/content/authors/value}'],
'hidden': True,
}
},
'order': 3
}
content['authorids'] = {
'value': ['${{4/id}/content/authorids/value}'],
'order':4
}

if self.authors_with_institutions:
content['authors'] = {
'value': ['${{4/id}/content/authors/value}'],
'order': 3
}
else:
content['authors'] = {
'value': {
'param': {
'type': 'string[]',
'const': ['${{6/id}/content/authors/value}'],
'hidden': True,
}
},
'order': 3
}
content['authorids'] = {
'value': ['${{4/id}/content/authorids/value}'],
'order':4
}
elif self.allow_author_reorder == AuthorReorder.DISALLOW_EDIT:
if 'authors' in content:
del content['authors']
if 'authorids' in content:
if 'authorids' in content and not self.authors_with_institutions:
del content['authorids']

if conference:
Expand Down
2 changes: 1 addition & 1 deletion openreview/tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -514,7 +514,7 @@ def generate_bibtex(note, venue_fullname, year, url_forum=None, paper_status='un
first_author_last_name = 'anonymous'
authors = 'Anonymous'
else:
note_author_list = note.content['authors'] if isinstance(note.content['authors'], list) else note.content['authors']['value']
note_author_list = note.get_author_names()
first_author_last_name = note_author_list[0].split(' ')[-1].lower()
if names_reversed:
# last, first
Expand Down
3 changes: 3 additions & 0 deletions openreview/venue/group.py
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,9 @@ def create_venue_group(self):
if self.venue.submission_stage.subject_areas:
content['subject_areas'] = { 'value': self.venue.submission_stage.subject_areas }

if self.venue.submission_stage.authors_with_institutions:
content['authors_with_institutions'] = { 'value': self.venue.submission_stage.authors_with_institutions }

if self.venue.use_area_chairs:
content['area_chair_roles'] = { 'value': self.venue.area_chair_roles }
content['area_chairs_id'] = { 'value': self.venue.get_area_chairs_id() }
Expand Down
8 changes: 4 additions & 4 deletions openreview/venue/invitation.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,8 +145,8 @@ def set_submission_invitation(self):

content = submission_stage.get_content(api_version='2', conference=self.venue, venue_id=self.venue.get_submission_venue_id())

edit_readers = ['everyone'] if submission_stage.create_groups else [venue_id, '${2/note/content/authorids/value}']
note_readers = ['everyone'] if submission_stage.create_groups else [venue_id, '${2/content/authorids/value}']
edit_readers = submission_stage.get_invitation_note_edit_readers(self.venue.id)
note_readers = submission_stage.get_invitation_note_readers(self.venue.id)

submission_id = submission_stage.get_submission_id(self.venue)
submission_cdate = tools.datetime_millis(submission_stage.start_date if submission_stage.start_date else datetime.datetime.now())
Expand Down Expand Up @@ -186,7 +186,7 @@ def set_submission_invitation(self):
}
},
'readers': edit_readers,
'writers': [venue_id, '${2/note/content/authorids/value}'],
'writers': edit_readers,
'ddate': {
'param': {
'range': [ 0, 9999999999999 ],
Expand All @@ -210,7 +210,7 @@ def set_submission_invitation(self):
},
'signatures': [ '${3/signatures}' ],
'readers': note_readers,
'writers': [venue_id, '${2/content/authorids/value}'],
'writers': note_readers,
'content': content
}
},
Expand Down
28 changes: 27 additions & 1 deletion openreview/venue/process/pc_submission_revision_process.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,20 @@ def process(client, edit, invitation):
members = submission_authors
)
)
elif 'authors' in submission.content:
author_group = openreview.tools.get_group(client, f'{venue_id}/{submission_name}{submission.number}/{authors_name}')
submission_authors = [a.get('username') for a in submission.content['authors']['value']]
if author_group and set(author_group.members) != set(submission_authors):
client.post_group_edit(
invitation=meta_invitation_id,
readers = [venue_id],
writers = [venue_id],
signatures = [venue_id],
group = openreview.api.Group(
id = author_group.id,
members = submission_authors
)
)

invitation_invitations = [i for i in client.get_all_invitations(prefix=f'{venue_id}/-/', type='invitation', domain=venue_id) if i.is_active()]

Expand All @@ -63,4 +77,16 @@ def process(client, edit, invitation):
'noteNumber': { 'value': submission.number }
},
invitation=openreview.api.Invitation()
)
)

if invitation_content and isinstance(invitation_content, dict) and 'authors' in invitation_content:
authorids = invitation_content.get('authors', {}).get('value', [])
if '${{4/id}/content/authors/value}' in authorids:
print('post invitation edit: ', venue_invitation.id)
client.post_invitation_edit(invitations=venue_invitation.id,
content={
'noteId': { 'value': submission.id },
'noteNumber': { 'value': submission.number }
},
invitation=openreview.api.Invitation()
)
Loading