Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
# Remove tag from tag_src if it's already in tag_dest
highlights_in_dest = (
self.db.query(database.HighlightTag.highlight_id)
.filter(database.HighlightTag.tag_id == tag_dest.id)
)
(
self.db.query(database.HighlightTag)
.filter(database.HighlightTag.tag_id == tag_src.id)
.filter(database.HighlightTag.highlight_id.in_(
highlights_in_dest
))
).delete(synchronize_session=False)
# Update tags that are in tag_src to be in tag_dest
self.db.execute(
database.HighlightTag.__table__.update()
.where(database.HighlightTag.tag_id == tag_src.id)
.values(tag_id=tag_dest.id)
)
# Delete tag_src
self.db.delete(tag_src)
cmd = database.Command.tag_merge(
self.current_user,
project.id,
tag_src.id,
tag_dest.id,
)
self.db.add(cmd)
self.db.commit()
self.db.refresh(cmd)
self.application.notify_project(project.id, cmd)
def post(self, project_id, document_id):
obj = self.get_json()
document = self.get_document(project_id, document_id, True)
start, end = obj['start_offset'], obj['end_offset']
snippet = extract.extract(document.contents, start, end)
hl = database.Highlight(document=document,
start_offset=start,
end_offset=end,
snippet=snippet)
self.db.add(hl)
self.db.flush() # Need to flush to get hl.id
self.db.bulk_insert_mappings(database.HighlightTag, [
dict(
highlight_id=hl.id,
tag_id=tag,
)
for tag in obj.get('tags', [])
])
cmd = database.Command.highlight_add(
self.current_user,
document,
hl,
obj.get('tags', []),
)
self.db.add(cmd)
self.db.commit()
self.db.refresh(cmd)
self.application.notify_project(document.project_id, cmd)
hl.start_offset = obj['start_offset']
if 'end_offset' in obj:
hl.end_offset = obj['end_offset']
if 'tags' in obj:
# Obtain old tags from database
old_tags = (
self.db.query(database.HighlightTag)
.filter(database.HighlightTag.highlight == hl)
.all()
)
old_tags = set(hl_tag.tag_id for hl_tag in old_tags)
new_tags = set(obj['tags'])
# Update tags in database
(
self.db.query(database.HighlightTag)
.filter(database.HighlightTag.highlight == hl)
).delete()
self.db.bulk_insert_mappings(database.HighlightTag, [
dict(
highlight_id=hl.id,
tag_id=tag,
)
for tag in new_tags
])
# Compute the change in tag counts
tag_count_changes = {}
for tag in old_tags - new_tags:
tag_count_changes[tag] = -1
for tag in new_tags - old_tags:
tag_count_changes[tag] = 1
def post(self, project_id):
project, privileges = self.get_project(project_id)
if not privileges.can_merge_tags():
self.set_status(403)
return self.send_json({'error': "Unauthorized"})
obj = self.get_json()
tag_src = self.db.query(database.Tag).get(obj['src'])
tag_dest = self.db.query(database.Tag).get(obj['dest'])
if (tag_src is None or tag_src.project_id != project.id or
tag_dest is None or tag_dest.project_id != project.id):
self.set_status(404)
return self.send_json({'error': "No such tag"})
# Remove tag from tag_src if it's already in tag_dest
highlights_in_dest = (
self.db.query(database.HighlightTag.highlight_id)
.filter(database.HighlightTag.tag_id == tag_dest.id)
)
(
self.db.query(database.HighlightTag)
.filter(database.HighlightTag.tag_id == tag_src.id)
.filter(database.HighlightTag.highlight_id.in_(
highlights_in_dest
))
).delete(synchronize_session=False)
# Update tags that are in tag_src to be in tag_dest
self.db.execute(
database.HighlightTag.__table__.update()
.where(database.HighlightTag.tag_id == tag_src.id)
.values(tag_id=tag_dest.id)
)
# Delete tag_src
def post(self, project_id, document_id, highlight_id):
obj = self.get_json()
document = self.get_document(project_id, document_id)
hl = self.db.query(database.Highlight).get(int(highlight_id))
if hl.document_id != document.id:
raise HTTPError(404)
if obj:
if 'start_offset' in obj:
hl.start_offset = obj['start_offset']
if 'end_offset' in obj:
hl.end_offset = obj['end_offset']
if 'tags' in obj:
(
self.db.query(database.HighlightTag)
.filter(database.HighlightTag.highlight == hl)
).delete()
self.db.bulk_insert_mappings(database.HighlightTag, [
dict(
highlight_id=hl.id,
tag_id=tag,
)
for tag in obj.get('tags', [])
])
cmd = database.Command.highlight_add(
self.current_user,
document,
hl,
obj.get('tags', []),
)
self.db.add(cmd)
class HighlightTag(Base):
__tablename__ = 'highlight_tags'
highlight_id = Column(Integer, ForeignKey('highlights.id',
ondelete='CASCADE'),
primary_key=True)
highlight = relationship('Highlight')
tag_id = Column(Integer, ForeignKey('tags.id',
ondelete='CASCADE'),
primary_key=True)
tag = relationship('Tag')
Tag.highlights_count = column_property(
select(
[functions.count(HighlightTag.highlight_id)],
).where(
HighlightTag.tag_id == Tag.id,
).correlate_except(HighlightTag)
)
def connect(db_url):
"""Connect to the database using an environment variable.
"""
logger.info("Connecting to SQL database %r", db_url)
kwargs = {}
if db_url.startswith('sqlite:'):
kwargs['connect_args'] = {'check_same_thread': False}
engine = create_engine(db_url, **kwargs)
# logging.getLogger('sqlalchemy.engine').setLevel(logging.INFO)
project, privileges = self.get_project(project_id)
if not privileges.can_merge_tags():
self.set_status(403)
return self.send_json({'error': "Unauthorized"})
obj = self.get_json()
tag_src = self.db.query(database.Tag).get(obj['src'])
tag_dest = self.db.query(database.Tag).get(obj['dest'])
if (tag_src is None or tag_src.project_id != project.id or
tag_dest is None or tag_dest.project_id != project.id):
self.set_status(404)
return self.send_json({'error': "No such tag"})
# Remove tag from tag_src if it's already in tag_dest
highlights_in_dest = (
self.db.query(database.HighlightTag.highlight_id)
.filter(database.HighlightTag.tag_id == tag_dest.id)
)
(
self.db.query(database.HighlightTag)
.filter(database.HighlightTag.tag_id == tag_src.id)
.filter(database.HighlightTag.highlight_id.in_(
highlights_in_dest
))
).delete(synchronize_session=False)
# Update tags that are in tag_src to be in tag_dest
self.db.execute(
database.HighlightTag.__table__.update()
.where(database.HighlightTag.tag_id == tag_src.id)
.values(tag_id=tag_dest.id)
)
# Delete tag_src
self.db.delete(tag_src)
def get_highlights_for_export(self, project_id, path):
project, _ = self.get_project(project_id)
if path:
tag = aliased(database.Tag)
hltag = aliased(database.HighlightTag)
highlights = (
self.db.query(database.Highlight)
.options(joinedload(database.Highlight.document))
.join(hltag, hltag.highlight_id == database.Highlight.id)
.join(tag, hltag.tag_id == tag.id)
.filter(tag.path.startswith(path))
.filter(tag.project == project)
.order_by(database.Highlight.document_id,
database.Highlight.start_offset)
).all()
name = None
else:
# Special case to select all highlights: we also need to select
# highlights that have no tag at all
document = aliased(database.Document)
highlights = (
highlight_id = Column(Integer, ForeignKey('highlights.id',
ondelete='CASCADE'),
primary_key=True)
highlight = relationship('Highlight')
tag_id = Column(Integer, ForeignKey('tags.id',
ondelete='CASCADE'),
primary_key=True)
tag = relationship('Tag')
Tag.highlights_count = column_property(
select(
[functions.count(HighlightTag.highlight_id)],
).where(
HighlightTag.tag_id == Tag.id,
).correlate_except(HighlightTag)
)
def connect(db_url):
"""Connect to the database using an environment variable.
"""
logger.info("Connecting to SQL database %r", db_url)
kwargs = {}
if db_url.startswith('sqlite:'):
kwargs['connect_args'] = {'check_same_thread': False}
engine = create_engine(db_url, **kwargs)
# logging.getLogger('sqlalchemy.engine').setLevel(logging.INFO)
if db_url.startswith('sqlite:'):
@sqlalchemy.event.listens_for(sqlalchemy.engine.Engine, "connect")
def set_sqlite_pragma(dbapi_connection, connection_record):
if 'tags' in obj:
# Obtain old tags from database
old_tags = (
self.db.query(database.HighlightTag)
.filter(database.HighlightTag.highlight == hl)
.all()
)
old_tags = set(hl_tag.tag_id for hl_tag in old_tags)
new_tags = set(obj['tags'])
# Update tags in database
(
self.db.query(database.HighlightTag)
.filter(database.HighlightTag.highlight == hl)
).delete()
self.db.bulk_insert_mappings(database.HighlightTag, [
dict(
highlight_id=hl.id,
tag_id=tag,
)
for tag in new_tags
])
# Compute the change in tag counts
tag_count_changes = {}
for tag in old_tags - new_tags:
tag_count_changes[tag] = -1
for tag in new_tags - old_tags:
tag_count_changes[tag] = 1
else:
new_tags = None
tag_count_changes = None