{"record":{"id":"a96fe1df70612fef","repo":"apache/beam","slug":"notimplementederror-watch","errorCode":null,"errorMessage":"NotImplementedError","messagePattern":"NotImplementedError","errorType":"exception","errorClass":"NotImplementedError","httpStatus":null,"severity":"error","filePath":"sdks/python/apache_beam/io/watch.py","lineNumber":192,"sourceCode":"  \"\"\"Optional base for a poll function ``input -> PollResult``.\n\n  Any callable with that signature works; subclass only to attach an output\n  coder hint via :meth:`default_output_coder`::\n\n      from apache_beam import coders\n\n      class ListFiles(PollFn):\n        def __call__(self, prefix):\n          return PollResult.incomplete(list_files(prefix))\n\n        def default_output_coder(self):\n          return coders.StrUtf8Coder()\n\n  A plain function can instead annotate its return type as ``PollResult[V]``\n  and have the output coder inferred from ``V``.\n  \"\"\"\n  def __call__(self, element: Any) -> PollResult:\n    raise NotImplementedError\n\n  def default_output_coder(self) -> Optional[Coder]:\n    return None\n\n\nclass TerminationCondition(object):\n  \"\"\"Per-input stop policy with immutable, encodable state.\n\n  Hooks follow the lifecycle of one input's polling loop. ``state`` flows from\n  :meth:`for_new_input` through the per-round hooks and is serialized with\n  :meth:`state_coder`.\n  \"\"\"\n  def for_new_input(self, now: Timestamp, element: Any) -> Any:\n    raise NotImplementedError\n\n  def on_seen_new_output(self, now: Timestamp, state: Any) -> Any:\n    return state\n","sourceCodeStart":174,"sourceCodeEnd":210,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/python/apache_beam/io/watch.py#L174-L210","documentation":"PollFn is an abstract callable interface for the watch() source: __call__(element) must return a PollResult describing one poll round. The base class raises NotImplementedError to signal that subclasses must override __call__; it is a pure contract, not a runtime failure of the library.","triggerScenarios":"Defining a custom PollFn subclass without overriding __call__, or passing a bare PollFn/object lacking a __call__ implementation into watch() so the base implementation executes.","commonSituations":"Subclassing PollFn but naming the method wrongly (e.g. poll instead of __call__); instantiating the abstract base directly in tests; forgetting __call__ when implementing only default_output_coder.","solutions":["Override __call__ in your PollFn subclass and return a PollResult (e.g. PollResult([items], timestamps) or None to signal end)","If you have a plain function, annotate its return type as PollResult[V] and pass the function instead of a PollFn subclass","Verify the object passed to watch() is the subclass instance, not the abstract base"],"exampleFix":"# before\nclass MyPoll(PollFn):\n    def poll(self, element):\n        return PollResult(fetch(element))\n# after\nclass MyPoll(PollFn):\n    def __call__(self, element):\n        return PollResult(fetch(element))","handlingStrategy":"type-guard","validationCode":"poll = poll_fn()\nassert type(poll).__call__ is not PollFn.__call__, 'PollFn subclass must override __call__'","typeGuard":"def has_call_impl(fn) -> bool:\n    return isinstance(fn, PollFn) and type(fn).__call__ is not PollFn.__call__","tryCatchPattern":"try:\n    _ = poll_fn(element)\nexcept NotImplementedError:\n    raise TypeError('pass a PollFn subclass overriding __call__ or a typed function')","preventionTips":["Name the override __call__ exactly (not poll or run)","In quick tests, instantiate the concrete subclass, never the base class","Prefer plain functions annotated with PollResult[V] return types when possible"],"tags":["python","apache-beam","abstract-method","watch"],"backgroundTag":"method-not-implemented","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}