From 5f1bdfd77db0820c896bb80d5a899f6fb63ef0b1 Mon Sep 17 00:00:00 2001 From: Abdullahi Abdalla Date: Mon, 1 Apr 2024 20:57:04 -0700 Subject: [PATCH] Fix some long-standing type-hinting issues in SAPP models. Summary: # Problem We have a lot of Pyre type-errors we've been suppressing since D22039123 landed back in 2020. # Solution The thing is, we don't have to live like this. We can just annotate these Column fields on Tables ourselves, with the correct type. So let's do that, and let's. Reviewed By: alexblanck, compositor Differential Revision: D55171548 fbshipit-source-id: 56f6e2978102438de176de48ca05d8711bb1195d --- sapp/db_support.py | 7 +- sapp/models.py | 143 +++++++++++++---------- sapp/tests/primary_key_generator_test.py | 10 +- sapp/trace_graph.py | 14 ++- sapp/trimmed_trace_graph.py | 3 +- sapp/ui/interactive.py | 1 - sapp/ui/issues.py | 4 +- sapp/ui/tests/interactive_test.py | 60 +++++----- sapp/ui/tests/issues_test.py | 34 +++--- sapp/ui/typeahead.py | 7 -- 10 files changed, 150 insertions(+), 133 deletions(-) diff --git a/sapp/db_support.py b/sapp/db_support.py index 00117a94..342650a8 100644 --- a/sapp/db_support.py +++ b/sapp/db_support.py @@ -301,17 +301,14 @@ class PrimaryKeyBase(PrepareMixin, RecordMixin): # noqa __tablename__ = "primary_keys" __table_args__: Tuple[Dict[str, str]] = BASE_TABLE_ARGS - # pyre-fixme[8]: Attribute has type `str`; used as `Column[str]`. - table_name: str = Column( + table_name: Column[str] = Column( String(length=100), doc="Name of the table that this row stores the next available primary key for", nullable=False, primary_key=True, ) - # pyre-fixme[8]: Attribute has type `int`; used as - # `Column[Variable[sqlalchemy.sql.type_api._U]]`. - current_id: int = Column( + current_id: Column[int] = Column( BIGINT(unsigned=True).with_variant(BIGINT, "sqlite"), doc="The current/latest id used in the table.", nullable=False, diff --git a/sapp/models.py b/sapp/models.py index 56831360..40fcb54f 100644 --- a/sapp/models.py +++ b/sapp/models.py @@ -246,6 +246,17 @@ def SINK_DETAIL(cls) -> "SharedTextKind": # noqa def from_string(cls, string: str) -> Optional[SharedTextKind]: return cls.__members__.get(string) + @classmethod + def from_string_with_exception(cls, string: str) -> SharedTextKind: + result: Optional[SharedTextKind] = None + if isinstance(string, SharedTextKind): + result = string + elif isinstance(string, str): + result = cls.__members__.get(string) + if result is None: + raise ValueError(f"Unknown SharedTextKind: {string}") + return result + class SharedText(Base, PrepareMixin, RecordMixin): """Any string-ish type that can be shared as a property of some other @@ -262,17 +273,14 @@ class SharedText(Base, PrepareMixin, RecordMixin): ), ) + BASE_TABLE_ARGS - # pyre-fixme[8]: Attribute has type `DBID`; used as `Column[typing.Any]`. - id: DBID = Column(BIGDBIDType, primary_key=True) + id: Column[DBID] = Column(BIGDBIDType, primary_key=True) - # pyre-fixme[8]: Attribute has type `str`; used as `Column[str]`. - contents: str = Column( + contents: Column[str] = Column( String(length=SHARED_TEXT_LENGTH), nullable=False, ) - # pyre-fixme[8]: Attribute has type `SharedTextKind`; used as `Column[str]`. - kind: SharedTextKind = Column( + kind: Column[str] = Column( Enum(SharedTextKind), server_default="feature", nullable=False ) @@ -333,11 +341,13 @@ class IssueInstanceSharedTextAssoc(Base, PrepareMixin, RecordMixin): __tablename__ = "issue_instance_feature_assoc" __table_args__ = BASE_TABLE_ARGS - issue_instance_id = Column( + issue_instance_id: Column[DBID] = Column( "issue_instance_id", BIGDBIDType, primary_key=True, nullable=False ) - shared_text_id = Column("feature_id", BIGDBIDType, primary_key=True, nullable=False) + shared_text_id: Column[DBID] = Column( + "feature_id", BIGDBIDType, primary_key=True, nullable=False + ) issue_instance = relationship( "IssueInstance", @@ -429,16 +439,17 @@ class IssueInstance(Base, PrepareMixin, MutableRecordMixin): Index("ix_issue_instances_run_id_purge_status", "run_id", "purge_status"), ) + BASE_TABLE_ARGS - # pyre-fixme[8]: Attribute has type `DBID`; used as `Column[typing.Any]`. - id: DBID = Column(BIGDBIDType, primary_key=True) + id: Column[DBID] = Column(BIGDBIDType, primary_key=True) - location = Column( + location: Column[SourceLocation] = Column( SourceLocationType, nullable=False, doc="Location (possibly a range) of the issue", ) - filename_id = Column(BIGDBIDType, nullable=False, server_default="0", default=0) + filename_id: Column[DBID] = Column( + BIGDBIDType, nullable=False, server_default="0", default=0 + ) filename = relationship( "SharedText", @@ -447,7 +458,9 @@ class IssueInstance(Base, PrepareMixin, MutableRecordMixin): viewonly=True, ) - callable_id = Column(BIGDBIDType, nullable=False, server_default="0", default=0) + callable_id: Column[DBID] = Column( + BIGDBIDType, nullable=False, server_default="0", default=0 + ) callable = relationship( "SharedText", @@ -463,9 +476,9 @@ class IssueInstance(Base, PrepareMixin, MutableRecordMixin): doc="True if the issue did not exist before this instance", ) - run_id = Column(BIGDBIDType, nullable=False, index=False) + run_id: Column[DBID] = Column(BIGDBIDType, nullable=False, index=False) - issue_id = Column(BIGDBIDType, nullable=False, index=True) + issue_id: Column[DBID] = Column(BIGDBIDType, nullable=False, index=True) issue = relationship( "Issue", @@ -474,7 +487,7 @@ class IssueInstance(Base, PrepareMixin, MutableRecordMixin): viewonly=True, ) - fix_info_id = Column(BIGDBIDType, nullable=True) + fix_info_id: Column[Optional[DBID]] = Column(BIGDBIDType, nullable=True) fix_info = relationship( "IssueInstanceFixInfo", @@ -483,7 +496,7 @@ class IssueInstance(Base, PrepareMixin, MutableRecordMixin): viewonly=True, ) - message_id = Column(BIGDBIDType, nullable=True) + message_id: Column[Optional[DBID]] = Column(BIGDBIDType, nullable=True) message = relationship( "SharedText", @@ -646,8 +659,7 @@ class Issue(Base, PrepareMixin, MutableRecordMixin): Index("ix_issues_status_severity", "status", "severity"), ) + BASE_TABLE_ARGS - # pyre-fixme[8]: Attribute has type `IssueDBID`; used as `Column[typing.Any]`. - id: IssueDBID = Column(IssueBIGDBIDType, primary_key=True, nullable=False) + id: Column[IssueDBID] = Column(IssueBIGDBIDType, primary_key=True, nullable=False) handle: Column[str] = Column( String(length=HANDLE_LENGTH), @@ -657,7 +669,7 @@ class Issue(Base, PrepareMixin, MutableRecordMixin): + "different code revisions", ) - callable_id = Column( + callable_id: Column[DBID] = Column( BIGDBIDType, nullable=False, index=True, server_default="0", default=0 ) @@ -733,9 +745,13 @@ class Issue(Base, PrepareMixin, MutableRecordMixin): doc="FBID for EntInternUser (typically actor of first triage from history)", ) - first_instance_id = Column(BIGDBIDType, nullable=True, index=False) + first_instance_id: Column[Optional[DBID]] = Column( + BIGDBIDType, nullable=True, index=False + ) - triaged_instance_id = Column(BIGDBIDType, nullable=True, index=False) + triaged_instance_id: Column[Optional[DBID]] = Column( + BIGDBIDType, nullable=True, index=False + ) update_time: Column[int] = Column( BIGINT(20, unsigned=True), @@ -868,7 +884,7 @@ class Run(Base): Index("ix_runs_purge_status_run_status_date", "purge_status", "status", "date"), ) + BASE_TABLE_ARGS - id = Column(BIGDBIDType, primary_key=True) + id: Column[DBID] = Column(BIGDBIDType, primary_key=True) job_id: Column[Optional[str]] = Column(String(length=255), index=True) @@ -1005,7 +1021,7 @@ class MetaRun(Base): __tablename__ = "metaruns" __table_args__ = BASE_TABLE_ARGS - id = Column(BIGDBIDType, primary_key=True, autoincrement=False) + id: Column[DBID] = Column(BIGDBIDType, primary_key=True, autoincrement=False) # This is the moral equivalent of job_id, but named in a more intuitive manner. # Allows determining the latest meta run for each custom run separately. @@ -1081,8 +1097,8 @@ class MetaRunToRunAssoc(Base, PrepareMixin, RecordMixin): __tablename__ = "metarun_run_assoc" __table_args__ = BASE_TABLE_ARGS - meta_run_id = Column(BIGDBIDType, nullable=False, primary_key=True) - run_id = Column(BIGDBIDType, nullable=False, primary_key=True) + meta_run_id: Column[DBID] = Column(BIGDBIDType, nullable=False, primary_key=True) + run_id: Column[DBID] = Column(BIGDBIDType, nullable=False, primary_key=True) meta_run = relationship( "MetaRun", primaryjoin=("MetaRunToRunAssoc.meta_run_id == foreign(MetaRun.id)"), @@ -1096,7 +1112,7 @@ class MetaRunToRunAssoc(Base, PrepareMixin, RecordMixin): viewonly=True, ) - run_label = Column( + run_label: Column[Optional[str]] = Column( String(length=1024), nullable=True, doc="Optional label associated with a child run (eg. Buck target)", @@ -1112,9 +1128,11 @@ class TraceFrameLeafAssoc(Base, PrepareMixin, RecordMixin): __tablename__ = "trace_frame_message_assoc" __table_args__ = BASE_TABLE_ARGS - trace_frame_id = Column(BIGDBIDType, nullable=False, primary_key=True) + trace_frame_id: Column[DBID] = Column(BIGDBIDType, nullable=False, primary_key=True) - leaf_id = Column("message_id", BIGDBIDType, nullable=False, primary_key=True) + leaf_id: Column[DBID] = Column( + "message_id", BIGDBIDType, nullable=False, primary_key=True + ) # The minimum trace length unfortunately can be off and actually lead to # loops. This is a known problem and any code generating traces should @@ -1146,8 +1164,7 @@ class IssueInstanceFixInfo(Base, PrepareMixin, RecordMixin): __tablename__ = "issue_instance_fix_info" __table_args__ = BASE_TABLE_ARGS - # pyre-fixme[8]: Attribute has type `DBID`; used as `Column[typing.Any]`. - id: DBID = Column(BIGDBIDType, nullable=False, primary_key=True) + id: Column[DBID] = Column(BIGDBIDType, nullable=False, primary_key=True) fix_info: Column[str] = Column( String(length=INNODB_MAX_INDEX_LENGTH), nullable=False @@ -1169,8 +1186,7 @@ class TraceFrame(Base, PrepareMixin, RecordMixin): Index("ix_traceframe_run_callee_port", "run_id", "callee_id", "callee_port"), ) + BASE_TABLE_ARGS - # pyre-fixme[8]: Attribute has type `DBID`; used as `Column[typing.Any]`. - id: DBID = Column(BIGDBIDType, nullable=False, primary_key=True) + id: Column[DBID] = Column(BIGDBIDType, nullable=False, primary_key=True) kind: Column[str] = Column(Enum(TraceKind), nullable=False, index=False) @@ -1190,7 +1206,9 @@ class TraceFrame(Base, PrepareMixin, RecordMixin): doc="The caller port of this call edge", ) - callee_id = Column(BIGDBIDType, nullable=False, server_default="0", default=0) + callee_id: Column[DBID] = Column( + BIGDBIDType, nullable=False, server_default="0", default=0 + ) callee = relationship( "SharedText", @@ -1199,7 +1217,7 @@ class TraceFrame(Base, PrepareMixin, RecordMixin): viewonly=True, ) - callee_location = Column( + callee_location: Column[SourceLocation] = Column( SourceLocationType, nullable=False, doc="The location of the callee in the source code (line|start|end)", @@ -1212,9 +1230,11 @@ class TraceFrame(Base, PrepareMixin, RecordMixin): doc="The callee port of this call edge'", ) - filename_id = Column(BIGDBIDType, nullable=False, server_default="0", default=0) + filename_id: Column[DBID] = Column( + BIGDBIDType, nullable=False, server_default="0", default=0 + ) - run_id = Column("run_id", BIGDBIDType, nullable=False, index=False) + run_id: Column[DBID] = Column("run_id", BIGDBIDType, nullable=False, index=False) type_interval_lower: Column[Optional[int]] = Column( Integer, nullable=True, doc="Class interval lower-bound (inclusive)" @@ -1232,7 +1252,7 @@ class TraceFrame(Base, PrepareMixin, RecordMixin): doc="Whether the call preserves the calling type context", ) - titos = Column( + titos: Column[SourceLocation] = Column( SourceLocationsType, doc="Locations of TITOs aka abductions for the trace frame", nullable=False, @@ -1332,23 +1352,21 @@ class TraceFrameAnnotation(Base, PrepareMixin, RecordMixin): __tablename__ = "trace_frame_annotations" __table_args__ = BASE_TABLE_ARGS - # pyre-fixme[8]: Attribute has type `DBID`; used as `Column[typing.Any]`. - id: DBID = Column(BIGDBIDType, nullable=False, primary_key=True) + id: Column[DBID] = Column(BIGDBIDType, nullable=False, primary_key=True) - location = Column( + location: Column[SourceLocation] = Column( SourceLocationType, nullable=False, doc="The location for the message" ) kind: Column[Optional[str]] = Column(String(length=255), nullable=True, index=True) - # pyre-fixme[8]: Attribute has type `str`; used as `Column[str]`. - message: str = Column( + message: Column[str] = Column( String(length=4096), doc="Message describing info about the trace", nullable=False, ) - leaf_id = Column(BIGDBIDType, nullable=True) + leaf_id: Column[DBID] = Column(BIGDBIDType, nullable=True) leaf = relationship( "SharedText", primaryjoin="foreign(SharedText.id) == TraceFrameAnnotation.leaf_id", @@ -1356,22 +1374,19 @@ class TraceFrameAnnotation(Base, PrepareMixin, RecordMixin): viewonly=True, ) - # pyre-fixme[8]: Attribute has type `Optional[str]`; used as `Column[str]`. - link: Optional[str] = Column( + link: Column[Optional[str]] = Column( String(length=4096), doc="An optional URL linking the message to more info (Quandary)", nullable=True, ) - # pyre-fixme[8]: Attribute has type `Optional[str]`; used as `Column[str]`. - trace_key: Optional[str] = Column( + trace_key: Column[Optional[str]] = Column( String(length=INNODB_MAX_INDEX_LENGTH), nullable=True, doc="Link to possible pre/post traces (caller_condition).", ) - # pyre-fixme[8]: Attribute has type `DBID`; used as `Column[typing.Any]`. - trace_frame_id: DBID = Column(BIGDBIDType, nullable=False, index=True) + trace_frame_id: Column[DBID] = Column(BIGDBIDType, nullable=False, index=True) trace_frame = relationship( "TraceFrame", primaryjoin=("TraceFrame.id == foreign(TraceFrameAnnotation.trace_frame_id)"), @@ -1402,11 +1417,11 @@ class TraceFrameAnnotationTraceFrameAssoc(Base, PrepareMixin, RecordMixin): __tablename__ = "trace_frame_annotation_trace_frame_assoc" __table_args__ = BASE_TABLE_ARGS - trace_frame_annotation_id = Column( + trace_frame_annotation_id: Column[DBID] = Column( "trace_frame_annotation_id", BIGDBIDType, primary_key=True, nullable=False ) - trace_frame_id = Column( + trace_frame_id: Column[DBID] = Column( "trace_frame_id", BIGDBIDType, primary_key=True, nullable=False, index=True ) @@ -1580,9 +1595,9 @@ class RunOrigin(Base, PrepareMixin, RecordMixin): __tablename__ = "run_origins" __table_args__ = BASE_TABLE_ARGS - id = Column(BIGDBIDType, nullable=False, primary_key=True) - run_id = Column(BIGDBIDType, nullable=False, index=True) - origin = Column(String(length=255), nullable=False) + id: Column[DBID] = Column(BIGDBIDType, nullable=False, primary_key=True) + run_id: Column[DBID] = Column(BIGDBIDType, nullable=False, index=True) + origin: Column[str] = Column(String(length=255), nullable=False) run = relationship( "Run", @@ -1612,12 +1627,14 @@ class ClassTypeInterval(Base, PrepareMixin, RecordMixin): # Synthetic primary key allows easier pagination when compared to # using (run_id, class_name) as a composite primary key - id = Column("id", BIGDBIDType, nullable=False, primary_key=True) + id: Column[DBID] = Column("id", BIGDBIDType, nullable=False, primary_key=True) - run_id = Column(BIGDBIDType, nullable=False) - class_name = Column(String(length=INNODB_MAX_INDEX_LENGTH), nullable=False) - lower_bound = Column(Integer, nullable=False) - upper_bound = Column(Integer, nullable=False) + run_id: Column[DBID] = Column(BIGDBIDType, nullable=False) + class_name: Column[str] = Column( + String(length=INNODB_MAX_INDEX_LENGTH), nullable=False + ) + lower_bound: Column[int] = Column(Integer, nullable=False) + upper_bound: Column[int] = Column(Integer, nullable=False) class MetaRunIssueInstanceIndex(Base, PrepareMixin, RecordMixin): @@ -1629,8 +1646,10 @@ class MetaRunIssueInstanceIndex(Base, PrepareMixin, RecordMixin): Index("ix_metarun_issue_instance_index", "meta_run_id", "issue_instance_hash"), ) + BASE_TABLE_ARGS - issue_instance_id = Column(BIGDBIDType, nullable=False, primary_key=True) - meta_run_id = Column(BIGDBIDType, nullable=False) + issue_instance_id: Column[DBID] = Column( + BIGDBIDType, nullable=False, primary_key=True + ) + meta_run_id: Column[DBID] = Column(BIGDBIDType, nullable=False) issue_instance_hash: Column[str] = Column( String(length=META_RUN_ISSUE_INSTANCE_HASH_LENGTH), nullable=False, diff --git a/sapp/tests/primary_key_generator_test.py b/sapp/tests/primary_key_generator_test.py index f4064f1d..bf3eb624 100644 --- a/sapp/tests/primary_key_generator_test.py +++ b/sapp/tests/primary_key_generator_test.py @@ -7,7 +7,7 @@ from unittest import TestCase -from tools.sapp.sapp.models import IssueDBID, SharedText, TraceFrame +from tools.sapp.sapp.models import DBID, IssueDBID, SharedText, TraceFrame from ..db import DB, DBType from ..models import create as create_tables, Issue, PrimaryKey, PrimaryKeyGenerator @@ -41,7 +41,7 @@ def test_backfill_from_highest_value(self) -> None: id=IssueDBID(4), handle="1", code=6015, - callable_id=11111, + callable_id=DBID(11111), detected_time=10, ) ) @@ -50,7 +50,7 @@ def test_backfill_from_highest_value(self) -> None: id=IssueDBID(7), handle="2", code=6015, - callable_id=11111, + callable_id=DBID(11111), detected_time=10, ) ) @@ -163,7 +163,7 @@ def test_allowed_id_range_existing_data_outside_allowed_range(self) -> None: id=IssueDBID(4), handle="1", code=6015, - callable_id=11111, + callable_id=DBID(11111), detected_time=10, ) ) @@ -172,7 +172,7 @@ def test_allowed_id_range_existing_data_outside_allowed_range(self) -> None: id=IssueDBID(7), handle="2", code=6015, - callable_id=11111, + callable_id=DBID(11111), detected_time=10, ) ) diff --git a/sapp/trace_graph.py b/sapp/trace_graph.py index c3dc50b8..70de3fb0 100644 --- a/sapp/trace_graph.py +++ b/sapp/trace_graph.py @@ -260,9 +260,9 @@ def add_shared_text(self, shared_text: SharedText) -> None: # Allow look up of SharedTexts by name and kind (to optimize # get_shared_text which is called when parsing each issue instance) - self._shared_text_lookup[shared_text.kind][ - shared_text.contents - ] = shared_text.id.local_id + self._shared_text_lookup[ + SharedTextKind.from_string_with_exception(shared_text.kind) + ][shared_text.contents] = shared_text.id.local_id def get_or_add_shared_text(self, kind: SharedTextKind, name: str) -> SharedText: name = name[:SHARED_TEXT_LENGTH] @@ -523,7 +523,9 @@ def get_transform_normalized_caller_kind_id(self, leaf_kind: SharedText) -> int: ) if "@" in leaf_kind.contents or "!" in leaf_kind.contents: normal_name = self.get_transform_normalized_caller_kind(leaf_kind.contents) - normal_kind = self.get_or_add_shared_text(leaf_kind.kind, normal_name) + normal_kind = self.get_or_add_shared_text( + SharedTextKind.from_string_with_exception(leaf_kind.kind), normal_name + ) return normal_kind.id.local_id else: return leaf_kind.id.local_id @@ -542,7 +544,9 @@ def get_transformed_callee_kind_id(self, leaf_kind: SharedText) -> int: ) if "@" in leaf_kind.contents or "!" in leaf_kind.contents: rest = self.get_transformed_callee_kind(leaf_kind.contents) - remaining_kind = self.get_or_add_shared_text(leaf_kind.kind, rest) + remaining_kind = self.get_or_add_shared_text( + SharedTextKind.from_string_with_exception(leaf_kind.kind), rest + ) return remaining_kind.id.local_id else: return leaf_kind.id.local_id diff --git a/sapp/trimmed_trace_graph.py b/sapp/trimmed_trace_graph.py index 16f528c2..c9b9a4fd 100644 --- a/sapp/trimmed_trace_graph.py +++ b/sapp/trimmed_trace_graph.py @@ -729,7 +729,8 @@ def _populate_issue(self, graph: TraceGraph, instance_id: int) -> None: """ instance = graph._issue_instances[instance_id] issue = graph._issues[instance.issue_id.local_id] - self._populate_shared_text(graph, instance.message_id) + if instance.message_id is not None: + self._populate_shared_text(graph, instance.message_id) self._populate_shared_text(graph, instance.filename_id) self._populate_shared_text(graph, instance.callable_id) diff --git a/sapp/ui/interactive.py b/sapp/ui/interactive.py index fb5061c4..0a30bb3d 100644 --- a/sapp/ui/interactive.py +++ b/sapp/ui/interactive.py @@ -1585,7 +1585,6 @@ def _resolve_pager(self, use_pager: bool): def _get_current_issue(self, session: Session) -> IssueQueryResult: return ( session.query( - # pyre-ignore[16]: SQLAlchemy IssueInstance.id.label("issue_instance_id"), FilenameText.contents.label("filename"), IssueInstance.location, diff --git a/sapp/ui/issues.py b/sapp/ui/issues.py index 1610bd95..037eb9f9 100644 --- a/sapp/ui/issues.py +++ b/sapp/ui/issues.py @@ -146,7 +146,6 @@ def __init__(self, session: Session, run_id: Optional[DBID] = None) -> None: def get(self) -> List[IssueQueryResult]: features = ( self._session.query( - # pyre-ignore: SQAlchemy sadness. IssueInstance.id.label("id"), func.group_concat(FeatureText.contents.distinct()).label( "concatenated_features" @@ -248,7 +247,6 @@ def get(self) -> List[IssueQueryResult]: IssueInstance.id.label("issue_instance_id"), FilenameText.contents.label("filename"), IssueInstance.location, - # pyre-ignore[16]: SQLAlchemy Issue.id.label("issue_id"), Issue.code, Issue.status, @@ -303,7 +301,7 @@ def where(self, *predicates: filter_predicates.Predicate) -> "Instance": def where_issue_instance_id_is(self, issue_id: Optional[int]) -> "Instance": if issue_id is not None: self._predicates.append( - filter_predicates.Equals(IssueInstance.id, issue_id) + filter_predicates.Equals(IssueInstance.id, DBID(issue_id)) ) return self diff --git a/sapp/ui/tests/interactive_test.py b/sapp/ui/tests/interactive_test.py index 677b26ee..1a8d371d 100644 --- a/sapp/ui/tests/interactive_test.py +++ b/sapp/ui/tests/interactive_test.py @@ -376,10 +376,10 @@ def testListIssuesFilterAllFeature(self) -> None: assocs = [ IssueInstanceSharedTextAssoc( - shared_text_id=feature1.id, issue_instance_id=1 + shared_text_id=feature1.id, issue_instance_id=DBID(1) ), IssueInstanceSharedTextAssoc( - shared_text_id=feature2.id, issue_instance_id=1 + shared_text_id=feature2.id, issue_instance_id=DBID(1) ), ] @@ -419,10 +419,10 @@ def testListIssuesFilterAnyFeature(self) -> None: assocs = [ IssueInstanceSharedTextAssoc( - shared_text_id=feature1.id, issue_instance_id=1 + shared_text_id=feature1.id, issue_instance_id=DBID(1) ), IssueInstanceSharedTextAssoc( - shared_text_id=feature2.id, issue_instance_id=1 + shared_text_id=feature2.id, issue_instance_id=DBID(1) ), ] @@ -462,10 +462,10 @@ def testListIssuesFilterExcludeFeature(self) -> None: assocs = [ IssueInstanceSharedTextAssoc( - shared_text_id=feature1.id, issue_instance_id=1 + shared_text_id=feature1.id, issue_instance_id=DBID(1) ), IssueInstanceSharedTextAssoc( - shared_text_id=feature2.id, issue_instance_id=1 + shared_text_id=feature2.id, issue_instance_id=DBID(1) ), ] @@ -507,19 +507,19 @@ def testListIssuesFilterAllFeatureAndAnyFeature(self) -> None: session, [ IssueInstanceSharedTextAssoc( - shared_text_id=feature1.id, issue_instance_id=1 + shared_text_id=feature1.id, issue_instance_id=DBID(1) ), IssueInstanceSharedTextAssoc( - shared_text_id=feature2.id, issue_instance_id=1 + shared_text_id=feature2.id, issue_instance_id=DBID(1) ), IssueInstanceSharedTextAssoc( - shared_text_id=feature3.id, issue_instance_id=1 + shared_text_id=feature3.id, issue_instance_id=DBID(1) ), IssueInstanceSharedTextAssoc( - shared_text_id=feature1.id, issue_instance_id=2 + shared_text_id=feature1.id, issue_instance_id=DBID(2) ), IssueInstanceSharedTextAssoc( - shared_text_id=feature2.id, issue_instance_id=2 + shared_text_id=feature2.id, issue_instance_id=DBID(2) ), ], ) @@ -555,9 +555,9 @@ def testNoRunsFound(self) -> None: def testListRuns(self) -> None: runs = [ - Run(id=1, date=datetime.now(), status=RunStatus.FINISHED), - Run(id=2, date=datetime.now(), status=RunStatus.INCOMPLETE), - Run(id=3, date=datetime.now(), status=RunStatus.FINISHED), + Run(id=DBID(1), date=datetime.now(), status=RunStatus.FINISHED), + Run(id=DBID(2), date=datetime.now(), status=RunStatus.INCOMPLETE), + Run(id=DBID(3), date=datetime.now(), status=RunStatus.FINISHED), ] with self.db.make_session() as session: @@ -597,8 +597,8 @@ def testSetRun(self) -> None: def testSetRunNonExistent(self) -> None: runs = [ - Run(id=1, date=datetime.now(), status=RunStatus.FINISHED), - Run(id=2, date=datetime.now(), status=RunStatus.INCOMPLETE), + Run(id=DBID(1), date=datetime.now(), status=RunStatus.FINISHED), + Run(id=DBID(2), date=datetime.now(), status=RunStatus.INCOMPLETE), ] with self.db.make_session() as session: @@ -615,12 +615,12 @@ def testSetRunNonExistent(self) -> None: def testSetLatestRun(self) -> None: runs = [ - Run(id=1, date=datetime.now(), status=RunStatus.FINISHED, kind="a"), - Run(id=2, date=datetime.now(), status=RunStatus.FINISHED, kind="a"), - Run(id=3, date=datetime.now(), status=RunStatus.FINISHED, kind="a"), - Run(id=4, date=datetime.now(), status=RunStatus.FINISHED, kind="b"), - Run(id=5, date=datetime.now(), status=RunStatus.FINISHED, kind="b"), - Run(id=6, date=datetime.now(), status=RunStatus.FINISHED, kind="c"), + Run(id=DBID(1), date=datetime.now(), status=RunStatus.FINISHED, kind="a"), + Run(id=DBID(2), date=datetime.now(), status=RunStatus.FINISHED, kind="a"), + Run(id=DBID(3), date=datetime.now(), status=RunStatus.FINISHED, kind="a"), + Run(id=DBID(4), date=datetime.now(), status=RunStatus.FINISHED, kind="b"), + Run(id=DBID(5), date=datetime.now(), status=RunStatus.FINISHED, kind="b"), + Run(id=DBID(6), date=datetime.now(), status=RunStatus.FINISHED, kind="c"), ] with self.db.make_session() as session: @@ -708,10 +708,10 @@ def testGetSources(self) -> None: self.fakes.save_all(self.db) assocs = [ IssueInstanceSharedTextAssoc( - shared_text_id=source1.id, issue_instance_id=1 + shared_text_id=source1.id, issue_instance_id=DBID(1) ), IssueInstanceSharedTextAssoc( - shared_text_id=source2.id, issue_instance_id=1 + shared_text_id=source2.id, issue_instance_id=DBID(1) ), ] @@ -738,8 +738,12 @@ def testGetSinks(self) -> None: self.fakes.sink("sink3") self.fakes.save_all(self.db) assocs = [ - IssueInstanceSharedTextAssoc(shared_text_id=sink1.id, issue_instance_id=1), - IssueInstanceSharedTextAssoc(shared_text_id=sink2.id, issue_instance_id=1), + IssueInstanceSharedTextAssoc( + shared_text_id=sink1.id, issue_instance_id=DBID(1) + ), + IssueInstanceSharedTextAssoc( + shared_text_id=sink2.id, issue_instance_id=DBID(1) + ), ] with self.db.make_session() as session: @@ -766,10 +770,10 @@ def testGetFeatures(self) -> None: self.fakes.save_all(self.db) assocs = [ IssueInstanceSharedTextAssoc( - shared_text_id=feature1.id, issue_instance_id=1 + shared_text_id=feature1.id, issue_instance_id=DBID(1) ), IssueInstanceSharedTextAssoc( - shared_text_id=feature2.id, issue_instance_id=1 + shared_text_id=feature2.id, issue_instance_id=DBID(1) ), ] diff --git a/sapp/ui/tests/issues_test.py b/sapp/ui/tests/issues_test.py index c2ec3f42..19ceda21 100644 --- a/sapp/ui/tests/issues_test.py +++ b/sapp/ui/tests/issues_test.py @@ -7,6 +7,8 @@ from unittest import TestCase +from tools.sapp.sapp.models import DBID + from ... import queries from ...db import DB, DBType from ...models import create as create_models, IssueInstanceSharedTextAssoc @@ -305,12 +307,12 @@ def testWhereSourceName(self) -> None: with self.db.make_session() as session: session.add( IssueInstanceSharedTextAssoc( - shared_text_id=source_name_1.id, issue_instance_id=1 + shared_text_id=source_name_1.id, issue_instance_id=DBID(1) ) ) session.add( IssueInstanceSharedTextAssoc( - shared_text_id=source_name_2.id, issue_instance_id=2 + shared_text_id=source_name_2.id, issue_instance_id=DBID(2) ) ) session.commit() @@ -361,12 +363,12 @@ def testWhereSourceKind(self) -> None: with self.db.make_session() as session: session.add( IssueInstanceSharedTextAssoc( - shared_text_id=source_kind_1.id, issue_instance_id=1 + shared_text_id=source_kind_1.id, issue_instance_id=DBID(1) ) ) session.add( IssueInstanceSharedTextAssoc( - shared_text_id=source_kind_2.id, issue_instance_id=2 + shared_text_id=source_kind_2.id, issue_instance_id=DBID(2) ) ) session.commit() @@ -417,12 +419,12 @@ def testWhereSinkName(self) -> None: with self.db.make_session() as session: session.add( IssueInstanceSharedTextAssoc( - shared_text_id=sink_name_1.id, issue_instance_id=1 + shared_text_id=sink_name_1.id, issue_instance_id=DBID(1) ) ) session.add( IssueInstanceSharedTextAssoc( - shared_text_id=sink_name_2.id, issue_instance_id=2 + shared_text_id=sink_name_2.id, issue_instance_id=DBID(2) ) ) session.commit() @@ -471,12 +473,12 @@ def testWhereSinkKind(self) -> None: with self.db.make_session() as session: session.add( IssueInstanceSharedTextAssoc( - shared_text_id=sink_kind_1.id, issue_instance_id=1 + shared_text_id=sink_kind_1.id, issue_instance_id=DBID(1) ) ) session.add( IssueInstanceSharedTextAssoc( - shared_text_id=sink_kind_2.id, issue_instance_id=2 + shared_text_id=sink_kind_2.id, issue_instance_id=DBID(2) ) ) session.commit() @@ -526,12 +528,12 @@ def testWhereAnyFeatures(self) -> None: with self.db.make_session() as session: session.add( IssueInstanceSharedTextAssoc( - shared_text_id=feature1.id, issue_instance_id=1 + shared_text_id=feature1.id, issue_instance_id=DBID(1) ) ) session.add( IssueInstanceSharedTextAssoc( - shared_text_id=feature2.id, issue_instance_id=1 + shared_text_id=feature2.id, issue_instance_id=DBID(1) ) ) session.commit() @@ -578,12 +580,12 @@ def testAssertAllFeatures(self) -> None: with self.db.make_session() as session: session.add( IssueInstanceSharedTextAssoc( - shared_text_id=feature1.id, issue_instance_id=1 + shared_text_id=feature1.id, issue_instance_id=DBID(1) ) ) session.add( IssueInstanceSharedTextAssoc( - shared_text_id=feature2.id, issue_instance_id=1 + shared_text_id=feature2.id, issue_instance_id=DBID(1) ) ) session.commit() @@ -631,22 +633,22 @@ def testAssertExcludeFeatures(self) -> None: with self.db.make_session() as session: session.add( IssueInstanceSharedTextAssoc( - shared_text_id=feature1.id, issue_instance_id=1 + shared_text_id=feature1.id, issue_instance_id=DBID(1) ) ) session.add( IssueInstanceSharedTextAssoc( - shared_text_id=feature2.id, issue_instance_id=1 + shared_text_id=feature2.id, issue_instance_id=DBID(1) ) ) session.add( IssueInstanceSharedTextAssoc( - shared_text_id=feature1.id, issue_instance_id=2 + shared_text_id=feature1.id, issue_instance_id=DBID(2) ) ) session.add( IssueInstanceSharedTextAssoc( - shared_text_id=feature4.id, issue_instance_id=2 + shared_text_id=feature4.id, issue_instance_id=DBID(2) ) ) session.commit() diff --git a/sapp/ui/typeahead.py b/sapp/ui/typeahead.py index 6c5eb988..ba8d05c0 100644 --- a/sapp/ui/typeahead.py +++ b/sapp/ui/typeahead.py @@ -29,7 +29,6 @@ class Path(graphene.ObjectType): def all_paths(session: Session) -> List[Path]: return ( - # pyre-fixme[16]: `str` has no attribute `label`. session.query(IssueInstance, SharedText.contents.label("path")) .join(SharedText, SharedText.id == IssueInstance.filename_id) .group_by(SharedText) @@ -43,7 +42,6 @@ class SourceName(graphene.ObjectType): def all_source_names(session: Session) -> List[SourceName]: return ( - # pyre-fixme[16]: `str` has no attribute `label` session.query(IssueInstance, SharedText.contents.label("source_name")) .join(SharedText, SharedText.kind == SharedTextKind.SOURCE_DETAIL) .group_by(SharedText) @@ -57,7 +55,6 @@ class SourceKind(graphene.ObjectType): def all_source_kinds(session: Session) -> List[SourceName]: return ( - # pyre-fixme[16]: `str` has no attribute `label` session.query(IssueInstance, SharedText.contents.label("source_kind")) .join(SharedText, SharedText.kind == SharedTextKind.SOURCE) .group_by(SharedText) @@ -71,7 +68,6 @@ class SinkName(graphene.ObjectType): def all_sink_names(session: Session) -> List[SourceName]: return ( - # pyre-fixme[16]: `str` has no attribute `label` session.query(IssueInstance, SharedText.contents.label("sink_name")) .join(SharedText, SharedText.kind == SharedTextKind.SINK_DETAIL) .group_by(SharedText) @@ -85,7 +81,6 @@ class SinkKind(graphene.ObjectType): def all_sink_kinds(session: Session) -> List[SourceName]: return ( - # pyre-fixme[16]: `str` has no attribute `label` session.query(IssueInstance, SharedText.contents.label("sink_kind")) .join(SharedText, SharedText.kind == SharedTextKind.SINK) .group_by(SharedText) @@ -107,7 +102,6 @@ class Callable(graphene.ObjectType): def all_callables(session: Session) -> List[Callable]: return ( - # pyre-fixme[16]: `str` has no attribute `label`. session.query(IssueInstance, SharedText.contents.label("callable")) .join(SharedText, SharedText.id == IssueInstance.callable_id) .group_by(SharedText) @@ -121,7 +115,6 @@ class Feature(graphene.ObjectType): def all_features(session: Session) -> List[Feature]: return ( - # pyre-fixme[16]: `str` has no attribute `label`. session.query(SharedText, SharedText.contents.label("feature")) .filter(SharedText.kind == SharedTextKind.FEATURE) .all()