Out of the box Stackoverflow Watcher does nothing special. It doesn’t even perform any type of filtering. The components that make up the underlying library are intentionally very bare-bones. This is because any custom functionality is added by subclassing one of these components. This gives you a lot of flexibility while at the same time, keeps everything very simple.
The `tag` argument to the “stack-watcher” command and
Retriever class does not do any filtering, it simply grabs
the feed from Stack Overflow for that specific tag. Real filtering is
achieved through subclassing the
Components and Subclassing¶
The two main components can be found in the
Question subclass) instance represents
an individual question on Stack Overflow. Question objects have the ability to
‘verify’ that they are relevant by comparing themselves to a set of rules.
If all of the rules return True, then the question object is considered relevant.
A rule is any Python property in a
Question subclass that begins with
“is_”. This is inspired by the same technique used in unit testing with Python.
To run all of the rules in a question object, you can check the
adheres_to_rules property. This will only return True if there are
no rules or all of the rules return True.
If we had this
from stack_watcher import Question class MammothQuestion(Question): @property def is_asked_by_a_woolly_mammoth(self): return False
It would never be considered a relevant question:
>>> question = MammothQuestion() >>> question.adheres_to_rules False
This class is responsible for retrieving the questions from Stack Overflow. One of the reasons to subclass this would be to add functionality that helps make the retrieval more reliable, for instance: handling throttling or authentication.
In this example the
MyQuestion class will only consider a question
relevant if it’s unanswered and has 25 or more views.
from stack_watcher import Question class MyQuestion(Question): @property def is_not_answered(self): return not self.answered @property def is_eye_catching(self): return self.view_count >= 25
If I save this code into a file called
questions.py I’ll be able to
run the following command from the terminal to begin fetching questions that
match this criteria:
$ stack-watcher --question questions.MyQuestion
A useful reason to subclass
Retriever is to override the
throttled() method and do something useful. For instance, instead of
just waiting for the time out period to end - we could change the IP address
and try again.
class ThrottleRetriever(Retriever): def throttled(self): self.change_ip_address() time.sleep(5) def change_ip_address(self): call(['sudo', 'systemctl', 'restart', 'openvpn@random'])
change_ip_address() method could implement anything you need to do
on your system to change the IP address. You could even add proxy server