Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions dmoj/executors/compiled_executor.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import abc
import hashlib
import os
import signal
Expand All @@ -10,6 +9,7 @@
import pylru

from dmoj.error import CompileError, OutputLimitExceeded
from dmoj.executors.metaclass import ExecutorMeta
from dmoj.judgeenv import env
from dmoj.utils.communicate import safe_communicate
from dmoj.utils.unicode import utf8bytes
Expand All @@ -26,7 +26,7 @@
# Contract: if cached=True is specified and an entry exists in the cache,
# `create_files` and `compile` will not be run, and `_executable` will be loaded
# from the cache.
class _CompiledExecutorMeta(abc.ABCMeta):
class _CompiledExecutorMeta(ExecutorMeta):
@staticmethod
def _cleanup_cache_entry(_key, executor: object) -> None:
# Mark the executor as not-cached, so that if this is the very last reference
Expand Down
20 changes: 20 additions & 0 deletions dmoj/executors/metaclass.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import abc


class ExecutorMeta(abc.ABCMeta):
"""This metaclass treats class attributes that are annotated but never assigned as abstract.

For example:
>>> class Example(ExecutorMeta):
... x: int
would be an abstract class unless `x` is implemented.

This means that when instantiating, an exception will be raised:
>>> Example()
TypeError: Can't instantiate abstract class Example with abstract methods x
"""

def __new__(mcs, *args, **kwargs):
cls = super().__new__(mcs, *args, **kwargs)
cls.__abstractmethods__ |= {a for a in getattr(cls, '__annotations__', {}).keys() if not hasattr(cls, a)}
return cls
4 changes: 2 additions & 2 deletions dmoj/executors/mixins.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import abc
import os
import re
import shutil
Expand All @@ -7,6 +6,7 @@
from dmoj.cptbox import IsolateTracer, TracedPopen, syscalls
from dmoj.cptbox.handlers import ALLOW
from dmoj.error import InternalError
from dmoj.executors.metaclass import ExecutorMeta
from dmoj.judgeenv import env
from dmoj.utils import setbufsize_path
from dmoj.utils.unicode import utf8bytes
Expand Down Expand Up @@ -36,7 +36,7 @@
BASE_FILESYSTEM += [r'/etc/ld\.so\.(?:nohwcap|preload|cache)$']


class PlatformExecutorMixin(metaclass=abc.ABCMeta):
class PlatformExecutorMixin(metaclass=ExecutorMeta):
address_grace = 65536
data_grace = 0
fsize = 0
Expand Down