-
Notifications
You must be signed in to change notification settings - Fork 2
BugReport reporter #770
base: master
Are you sure you want to change the base?
BugReport reporter #770
Conversation
src/pyk/utils.py
Outdated
def add_file(self, finput: Path, arcname: Path) -> None: | ||
pass | ||
|
||
def add_file_contents(self, input: str, arcname: Path) -> None: | ||
pass | ||
|
||
def add_command(self, args: Iterable[str]) -> None: | ||
pass |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
By organizing the code this way, this will not break:
br = BugReporter(Path('foo'))
br.add_file(Path('bar'), Path('baz'))
yet the bug report entry will not be written.
BugReporter
should not be a BugReport
, and these methods should be removed from BugReport
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Then spurious methods like _check_bug_report
can also be removed from BugReporter
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How should users instantiate a bug report? It looks to me that currently the bug_report_arg
parameter from cli
is the primary use case, and I've ensured that the reporter coming from there works. The intent was to have BugReporter
only be instantiated by a call to BugReport.reporter
, and have BugReport
hold the base interface, file paths, and synchronization primitive to spawn reporters from. Something like your example that doesn't write to a file can certainly be a problem if it isn't discouraged in some way, like renaming the class to _BugReporter
so it doesn't get imported or used as easily.
If we want to allow users to directly create a BugReport
or a BugReporter
then I'll have to think a bit more about what this should look like.
I made BugReporter
an inherited class because BugReport
is expected in many places like KRun and Kompile, and wanted to keep those interfaces stable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How should users instantiate a bug report?
In the final design, users should be able to instantiate a BugReport
(i.e. the BugReporter
factory) directly. On the other hand, BugReporter
(i.e. the replacement of the old BugReport
) should only be instantiated through BugReporter
.
(We can also consider a composite design where a BugReporter
can instantiate further BugReporter
instances, e.g. a BugReporter
for a proof process creates a BugReporter
for one of the KoreClient
instances it manages.)
BugReport
is expected in many places likeKRun
andKompile
, and wanted to keep those interfaces stable.
I see why this is a good approach, but ultimately the goal is to get rid of the old interface, and instead
- Let the user decide where to write the archive:
BugReport
. - Let the application (e.g.
kontrol
) decide how to structure the archive:BugReporter
. - Let the library (e.g.
KoreServer
) be responsible only for what's written to the archive.
One way to achieve this:
- Turn
BugReport
into an abstract class - Have two implementations: 1) old behavior 2)
BugReporter
- Gradually replace old behavior by
BugReporter
- Do the renamings
All this doesn't have to be achieved in a single PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've force pushed this branch with a change that implements 1 and 2. There's no thread safety over the BugReporter yet, if you're happy with deferring that to a later PR then we should be able to merge this.
src/pyk/utils.py
Outdated
_command_id: int | ||
_defn_id: int | ||
_file_remap: dict[str, str] | ||
_lock: Lock |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What properties does this lock ensure?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Assuming the usage pattern expected in my above comment, this Lock should be shared by all BugReporters that were created off of the same BugReport, so that only one of them can write to the file at a time.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What happens in a multiprocessing scenario, i.e. when the Lock
gets pickled and sent to another Python process? Will it still ensure mutual exclusion?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
By the looks of it, pickling Lock objects isn't supported. Would this be an issue?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
src/pyk/utils.py
Outdated
def add_command(self, args: Iterable[str]) -> None: | ||
pass | ||
|
||
def reporter(self, prefix: Path) -> BugReporter: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
def reporter(self, prefix: Path) -> BugReporter: | |
def reporter(self, prefix: str) -> BugReporter: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What happens if two threads request a reporter to the same prefix
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They will both be writing to the same prefix in the bug report archive. The Lock should ensure that they don't write at the same time, but it is possible that they write to the same path, which in this implementation I believe will work like an append. It should probably be up to the user whether that's an issue or not.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can safely introduce this restriction (i.e. let the BugReporter
own its prefix) as the way we use the archive is always adding new things to it.
If the same prefix is requested twice, the call can either fail, or the target directory can be renamed to make it unique:
foo
foo_1
foo_2
...
What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Renaming while logging a message about it sounds reasonable.
56f932e
to
078e994
Compare
@@ -524,3 +521,26 @@ def _remap_arg(_a: str) -> str: | |||
shebang = '#!/usr/bin/env bash\nset -euxo pipefail\n' | |||
self.add_file_contents(shebang + ' '.join(remapped_args) + '\n', arcname) | |||
self._command_id += 1 | |||
|
|||
|
|||
class BugReport(BugReportBase): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider this hierarchy instead:
BugReportBase
- abstract class without any actual implementation.BugReport
- same as before, but now implementsBugReportBase
.BugReport2
- something that can instantiate aBugReporter
for a prefix.BugReporter
- aBugReportBase
that writes into a folder of an archive.
This is the easy part as so far, nothing breaks. The hard part is eliminating BugReport
in favor of the new design, which will be a breaking change in pyk
and in downstream projects.
We should only merge the PR with the new classes once we have a plan on how to manage the rest. To get the intuition of what needs to be changed, you can rename BugReport
and see where the type checker complains.
fixes: runtimeverification/k#4189