Merged
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
9 changes: 9 additions & 0 deletions doc/source/hacking/using_the_testsuite.rst
Original file line numberDiff line numberDiff line change
Expand Up@@ -190,13 +190,22 @@ consists of running the ``pylint`` tool, run the following::

.. _contributing_formatting_code:

Running Static Type Checkers
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Static Type Checking is performed separately from testing. In order to run the static type checking step which
consists of running the ``mypy`` tool, run the following::

tox -e mypy

Formatting code
~~~~~~~~~~~~~~~
Similar to linting, code formatting is also done via a ``tox`` environment. To
format the code using the ``black`` tool, run the following::

tox -e format

In CI `tox -e format-check` is used to ensure formatting has been run.

Observing coverage
~~~~~~~~~~~~~~~~~~
Once you have run the tests using `tox` (or `detox`), some coverage reports will
Expand Down
6 changes: 3 additions & 3 deletions src/buildstream/_elementproxy.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -95,7 +95,7 @@ def stage_artifact(
sandbox: "Sandbox",
*,
path: Optional[str] = None,
action: str = OverlapAction.WARNING,
action: OverlapAction = OverlapAction.WARNING,
include: Optional[List[str]] = None,
exclude: Optional[List[str]] = None,
orphans: bool = True
Expand All@@ -120,7 +120,7 @@ def stage_dependency_artifacts(
selection: Optional[Sequence["Element"]] = None,
*,
path: Optional[str] = None,
action: str = OverlapAction.WARNING,
action: OverlapAction = OverlapAction.WARNING,
include: Optional[List[str]] = None,
exclude: Optional[List[str]] = None,
orphans: bool = True
Expand DownExpand Up@@ -168,7 +168,7 @@ def _stage_artifact(
sandbox: "Sandbox",
*,
path: Optional[str] = None,
action: str = OverlapAction.WARNING,
action: OverlapAction = OverlapAction.WARNING,
include: Optional[List[str]] = None,
exclude: Optional[List[str]] = None,
orphans: bool = True,
Expand Down
6 changes: 3 additions & 3 deletions src/buildstream/_overlapcollector.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -66,7 +66,7 @@ def __init__(self, element: "Element"):
# location (str): The Sandbox relative location this session was created for
#
@contextmanager
def session(self, action: str, location: Optional[str]):
def session(self, action: OverlapAction, location: Optional[str]):
assert self._session is None, "Stage session already started"

if location is None:
Expand DownExpand Up@@ -108,13 +108,13 @@ def collect_stage_result(self, element: "Element", result: FileListResult):
# location (str): The Sandbox relative location this session was created for
#
class OverlapCollectorSession:
def __init__(self, element: "Element", action: str, location: str):
def __init__(self, element: "Element", action: OverlapAction, location: str):

# The Element we are staging for, on which we'll issue warnings
self._element = element # type: Element

# The OverlapAction for this session
self._action = action # type: str
self._action = action # type: OverlapAction

# The Sandbox relative directory this session was created for
self._location = location # type: str
Expand Down
9 changes: 7 additions & 2 deletions src/buildstream/_pipeline.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -44,7 +44,7 @@
# Yields:
# Elements in the scope of the specified target elements
#
def dependencies(targets: List[Element], scope: int, *, recurse: bool = True) -> Iterator[Element]:
def dependencies(targets: List[Element], scope: _Scope, *, recurse: bool = True) -> Iterator[Element]:
Comment thread
juergbi marked this conversation as resolved.
# Keep track of 'visited' in this scope, so that all targets
# share the same context.
visited = (BitMap(), BitMap())
Expand DownExpand Up@@ -73,7 +73,12 @@ def dependencies(targets: List[Element], scope: int, *, recurse: bool = True) ->
# A list of Elements appropriate for the specified selection mode
#
def get_selection(
context: Context, targets: List[Element], mode: str, *, silent: bool = True, depth_sort: bool = False
context: Context,
targets: List[Element],
mode: _PipelineSelection,
*,
silent: bool = True,
depth_sort: bool = False
) -> List[Element]:
def redirect_and_log() -> List[Element]:
# Redirect and log if permitted
Expand Down
16 changes: 8 additions & 8 deletions src/buildstream/_stream.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -153,7 +153,7 @@ def load_selection(
self,
targets: Iterable[str],
*,
selection: str = _PipelineSelection.NONE,
selection: _PipelineSelection = _PipelineSelection.NONE,
except_targets: Iterable[str] = (),
load_artifacts: bool = False,
connect_artifact_cache: bool = False,
Expand DownExpand Up@@ -259,7 +259,7 @@ def query_cache(self, elements, *, sources_of_cached_elements=False, only_source
def shell(
self,
target: str,
scope: int,
scope: _Scope,
prompt: Callable[[Element], str],
*,
unique_id: Optional[str] = None,
Expand DownExpand Up@@ -382,7 +382,7 @@ def build(
self,
targets: Iterable[str],
*,
selection: str = _PipelineSelection.NONE,
selection: _PipelineSelection = _PipelineSelection.NONE,
ignore_junction_targets: bool = False,
artifact_remotes: Iterable[RemoteSpec] = (),
source_remotes: Iterable[RemoteSpec] = (),
Expand DownExpand Up@@ -456,7 +456,7 @@ def fetch(
self,
targets: Iterable[str],
*,
selection: str = _PipelineSelection.NONE,
selection: _PipelineSelection = _PipelineSelection.NONE,
except_targets: Iterable[str] = (),
source_remotes: Iterable[RemoteSpec] = (),
ignore_project_source_remotes: bool = False,
Expand DownExpand Up@@ -579,7 +579,7 @@ def pull(
self,
targets: Iterable[str],
*,
selection: str = _PipelineSelection.NONE,
selection: _PipelineSelection = _PipelineSelection.NONE,
ignore_junction_targets: bool = False,
artifact_remotes: Iterable[RemoteSpec] = (),
ignore_project_artifact_remotes: bool = False,
Expand DownExpand Up@@ -633,7 +633,7 @@ def push(
self,
targets: Iterable[str],
*,
selection: str = _PipelineSelection.NONE,
selection: _PipelineSelection = _PipelineSelection.NONE,
ignore_junction_targets: bool = False,
artifact_remotes: Iterable[RemoteSpec] = (),
ignore_project_artifact_remotes: bool = False,
Expand DownExpand Up@@ -688,7 +688,7 @@ def checkout(
*,
location: Optional[str] = None,
force: bool = False,
selection: str = _PipelineSelection.RUN,
selection: _PipelineSelection = _PipelineSelection.RUN,
integrate: bool = True,
hardlinks: bool = False,
compression: str = "",
Expand DownExpand Up@@ -1668,7 +1668,7 @@ def _load(
self,
targets: Iterable[str],
*,
selection: str = _PipelineSelection.NONE,
selection: _PipelineSelection = _PipelineSelection.NONE,
except_targets: Iterable[str] = (),
ignore_junction_targets: bool = False,
dynamic_plan: bool = False,
Expand Down
21 changes: 15 additions & 6 deletions src/buildstream/element.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -90,7 +90,7 @@
from .sandbox import _SandboxFlags, SandboxCommandError
from .sandbox._config import SandboxConfig
from .sandbox._sandboxremote import SandboxRemote
from .types import _Scope, _CacheBuildTrees, _KeyStrength, OverlapAction, _DisplayKey
from .types import _HostMount, _Scope, _CacheBuildTrees, _KeyStrength, OverlapAction, _DisplayKey
from ._artifact import Artifact
from ._elementproxy import ElementProxy
from ._elementsources import ElementSources
Expand DownExpand Up@@ -604,7 +604,7 @@ def stage_artifact(
sandbox: "Sandbox",
*,
path: Optional[str] = None,
action: str = OverlapAction.WARNING,
action: OverlapAction = OverlapAction.WARNING,
include: Optional[List[str]] = None,
exclude: Optional[List[str]] = None,
orphans: bool = True,
Expand DownExpand Up@@ -664,7 +664,7 @@ def stage_dependency_artifacts(
selection: Optional[Sequence["Element"]] = None,
*,
path: Optional[str] = None,
action: str = OverlapAction.WARNING,
action: OverlapAction = OverlapAction.WARNING,
include: Optional[List[str]] = None,
exclude: Optional[List[str]] = None,
orphans: bool = True,
Expand DownExpand Up@@ -864,7 +864,7 @@ def subsandbox(self, sandbox: "Sandbox") -> Iterator["Sandbox"]:
# Yields:
# (Element): The dependencies in `scope`, in deterministic staging order
#
def _dependencies(self, scope, *, recurse=True, visited=None):
def _dependencies(self, scope: _Scope, *, recurse=True, visited=None):

# The format of visited is (BitMap(), BitMap()), with the first BitMap
# containing element that have been visited for the `_Scope.BUILD` case
Expand DownExpand Up@@ -971,7 +971,7 @@ def _stage_artifact(
sandbox: "Sandbox",
*,
path: Optional[str] = None,
action: str = OverlapAction.WARNING,
action: OverlapAction = OverlapAction.WARNING,
include: Optional[List[str]] = None,
exclude: Optional[List[str]] = None,
orphans: bool = True,
Expand DownExpand Up@@ -2060,7 +2060,16 @@ def _push(self):
# usebuildtree (bool): Use the buildtree as its source
#
# Returns: Exit code
def _shell(self, scope=None, *, mounts=None, isolate=False, prompt=None, command=None, usebuildtree=False):
def _shell(
self,
scope: _Scope | None = None,
*,
mounts: List[_HostMount] | None = None,
isolate: bool = False,
prompt: str | None = None,
command: List[str] | None = None,
usebuildtree: bool = False,
):

with self._prepare_sandbox(scope, shell=True, usebuildtree=usebuildtree) as sandbox:
environment = sandbox._get_configured_environment() or self.get_environment()
Expand Down
8 changes: 5 additions & 3 deletions src/buildstream/types.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -35,6 +35,9 @@ class FastEnum(metaclass=MetaFastEnum):

:class:`enum.Enum` attributes accesses can be really slow, and slow down the execution noticeably.
This reimplementation doesn't suffer the same problems, but also does not reimplement everything.

For mypy Enum static type checking support, all FastEnum should be stubbed as inheriting from enum.Enum.
Use `stubgen src/buildstream/types.py --include-docstrings` to generate the stubs, add `from enum import Enum` and replace all `(FastEnum)` with `(Enum)`
"""

name = None
Expand All@@ -61,7 +64,7 @@ def __new__(cls, value):
try:
return cls._value_to_entry[value]
except KeyError:
if type(value) is cls: # pylint: disable=unidiomatic-typecheck
if isinstance(value, cls): # pylint: disable=unidiomatic-typecheck

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AFAICT your are now doing this right.

https://pylint.pycqa.org/en/latest/user_guide/messages/convention/unidiomatic-typecheck.html

Suggested change
ifisinstance(value, cls):# pylint: disable=unidiomatic-typecheck
ifisinstance(value, cls):

So you dont need to disable the lint.

return value
raise ValueError("Unknown enum value: {}".format(value))

Expand DownExpand Up@@ -169,7 +172,6 @@ class OverlapAction(FastEnum):
# Defines the scope of dependencies to include for a given element
# when iterating over the dependency graph in APIs like
# Element._dependencies().
#
class _Scope(FastEnum):

# All elements which the given element depends on, following
Expand DownExpand Up@@ -384,7 +386,7 @@ def new_from_node(cls, node: MappingNode) -> "_SourceMirror":
alias_node: MappingNode = node.get_mapping("aliases")

for alias, uris in alias_node.items():
assert type(uris) is SequenceNode # pylint: disable=unidiomatic-typecheck
assert isinstance(uris, SequenceNode) # pylint: disable=unidiomatic-typecheck
aliases[alias] = uris.as_str_list()

return cls(name, aliases)
Expand Down
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all \u003cpre\u003e\u003ccode\u003e blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks"); } } catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); } })(); (function(){ try { var __m = "github.com"; var __re = new RegExp('^' + "github\\.com" + '
Skip to content
Merged
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
9 changes: 9 additions & 0 deletions doc/source/hacking/using_the_testsuite.rst
Original file line numberDiff line numberDiff line change
Expand Up@@ -190,13 +190,22 @@ consists of running the ``pylint`` tool, run the following::

.. _contributing_formatting_code:

Running Static Type Checkers
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Static Type Checking is performed separately from testing. In order to run the static type checking step which
consists of running the ``mypy`` tool, run the following::

tox -e mypy

Formatting code
~~~~~~~~~~~~~~~
Similar to linting, code formatting is also done via a ``tox`` environment. To
format the code using the ``black`` tool, run the following::

tox -e format

In CI `tox -e format-check` is used to ensure formatting has been run.

Observing coverage
~~~~~~~~~~~~~~~~~~
Once you have run the tests using `tox` (or `detox`), some coverage reports will
Expand Down
6 changes: 3 additions & 3 deletions src/buildstream/_elementproxy.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -95,7 +95,7 @@ def stage_artifact(
sandbox: "Sandbox",
*,
path: Optional[str] = None,
action: str = OverlapAction.WARNING,
action: OverlapAction = OverlapAction.WARNING,
include: Optional[List[str]] = None,
exclude: Optional[List[str]] = None,
orphans: bool = True
Expand All@@ -120,7 +120,7 @@ def stage_dependency_artifacts(
selection: Optional[Sequence["Element"]] = None,
*,
path: Optional[str] = None,
action: str = OverlapAction.WARNING,
action: OverlapAction = OverlapAction.WARNING,
include: Optional[List[str]] = None,
exclude: Optional[List[str]] = None,
orphans: bool = True
Expand DownExpand Up@@ -168,7 +168,7 @@ def _stage_artifact(
sandbox: "Sandbox",
*,
path: Optional[str] = None,
action: str = OverlapAction.WARNING,
action: OverlapAction = OverlapAction.WARNING,
include: Optional[List[str]] = None,
exclude: Optional[List[str]] = None,
orphans: bool = True,
Expand Down
6 changes: 3 additions & 3 deletions src/buildstream/_overlapcollector.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -66,7 +66,7 @@ def __init__(self, element: "Element"):
# location (str): The Sandbox relative location this session was created for
#
@contextmanager
def session(self, action: str, location: Optional[str]):
def session(self, action: OverlapAction, location: Optional[str]):
assert self._session is None, "Stage session already started"

if location is None:
Expand DownExpand Up@@ -108,13 +108,13 @@ def collect_stage_result(self, element: "Element", result: FileListResult):
# location (str): The Sandbox relative location this session was created for
#
class OverlapCollectorSession:
def __init__(self, element: "Element", action: str, location: str):
def __init__(self, element: "Element", action: OverlapAction, location: str):

# The Element we are staging for, on which we'll issue warnings
self._element = element # type: Element

# The OverlapAction for this session
self._action = action # type: str
self._action = action # type: OverlapAction

# The Sandbox relative directory this session was created for
self._location = location # type: str
Expand Down
9 changes: 7 additions & 2 deletions src/buildstream/_pipeline.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -44,7 +44,7 @@
# Yields:
# Elements in the scope of the specified target elements
#
def dependencies(targets: List[Element], scope: int, *, recurse: bool = True) -> Iterator[Element]:
def dependencies(targets: List[Element], scope: _Scope, *, recurse: bool = True) -> Iterator[Element]:
Comment thread
juergbi marked this conversation as resolved.
# Keep track of 'visited' in this scope, so that all targets
# share the same context.
visited = (BitMap(), BitMap())
Expand DownExpand Up@@ -73,7 +73,12 @@ def dependencies(targets: List[Element], scope: int, *, recurse: bool = True) ->
# A list of Elements appropriate for the specified selection mode
#
def get_selection(
context: Context, targets: List[Element], mode: str, *, silent: bool = True, depth_sort: bool = False
context: Context,
targets: List[Element],
mode: _PipelineSelection,
*,
silent: bool = True,
depth_sort: bool = False
) -> List[Element]:
def redirect_and_log() -> List[Element]:
# Redirect and log if permitted
Expand Down
16 changes: 8 additions & 8 deletions src/buildstream/_stream.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -153,7 +153,7 @@ def load_selection(
self,
targets: Iterable[str],
*,
selection: str = _PipelineSelection.NONE,
selection: _PipelineSelection = _PipelineSelection.NONE,
except_targets: Iterable[str] = (),
load_artifacts: bool = False,
connect_artifact_cache: bool = False,
Expand DownExpand Up@@ -259,7 +259,7 @@ def query_cache(self, elements, *, sources_of_cached_elements=False, only_source
def shell(
self,
target: str,
scope: int,
scope: _Scope,
prompt: Callable[[Element], str],
*,
unique_id: Optional[str] = None,
Expand DownExpand Up@@ -382,7 +382,7 @@ def build(
self,
targets: Iterable[str],
*,
selection: str = _PipelineSelection.NONE,
selection: _PipelineSelection = _PipelineSelection.NONE,
ignore_junction_targets: bool = False,
artifact_remotes: Iterable[RemoteSpec] = (),
source_remotes: Iterable[RemoteSpec] = (),
Expand DownExpand Up@@ -456,7 +456,7 @@ def fetch(
self,
targets: Iterable[str],
*,
selection: str = _PipelineSelection.NONE,
selection: _PipelineSelection = _PipelineSelection.NONE,
except_targets: Iterable[str] = (),
source_remotes: Iterable[RemoteSpec] = (),
ignore_project_source_remotes: bool = False,
Expand DownExpand Up@@ -579,7 +579,7 @@ def pull(
self,
targets: Iterable[str],
*,
selection: str = _PipelineSelection.NONE,
selection: _PipelineSelection = _PipelineSelection.NONE,
ignore_junction_targets: bool = False,
artifact_remotes: Iterable[RemoteSpec] = (),
ignore_project_artifact_remotes: bool = False,
Expand DownExpand Up@@ -633,7 +633,7 @@ def push(
self,
targets: Iterable[str],
*,
selection: str = _PipelineSelection.NONE,
selection: _PipelineSelection = _PipelineSelection.NONE,
ignore_junction_targets: bool = False,
artifact_remotes: Iterable[RemoteSpec] = (),
ignore_project_artifact_remotes: bool = False,
Expand DownExpand Up@@ -688,7 +688,7 @@ def checkout(
*,
location: Optional[str] = None,
force: bool = False,
selection: str = _PipelineSelection.RUN,
selection: _PipelineSelection = _PipelineSelection.RUN,
integrate: bool = True,
hardlinks: bool = False,
compression: str = "",
Expand DownExpand Up@@ -1668,7 +1668,7 @@ def _load(
self,
targets: Iterable[str],
*,
selection: str = _PipelineSelection.NONE,
selection: _PipelineSelection = _PipelineSelection.NONE,
except_targets: Iterable[str] = (),
ignore_junction_targets: bool = False,
dynamic_plan: bool = False,
Expand Down
21 changes: 15 additions & 6 deletions src/buildstream/element.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -90,7 +90,7 @@
from .sandbox import _SandboxFlags, SandboxCommandError
from .sandbox._config import SandboxConfig
from .sandbox._sandboxremote import SandboxRemote
from .types import _Scope, _CacheBuildTrees, _KeyStrength, OverlapAction, _DisplayKey
from .types import _HostMount, _Scope, _CacheBuildTrees, _KeyStrength, OverlapAction, _DisplayKey
from ._artifact import Artifact
from ._elementproxy import ElementProxy
from ._elementsources import ElementSources
Expand DownExpand Up@@ -604,7 +604,7 @@ def stage_artifact(
sandbox: "Sandbox",
*,
path: Optional[str] = None,
action: str = OverlapAction.WARNING,
action: OverlapAction = OverlapAction.WARNING,
include: Optional[List[str]] = None,
exclude: Optional[List[str]] = None,
orphans: bool = True,
Expand DownExpand Up@@ -664,7 +664,7 @@ def stage_dependency_artifacts(
selection: Optional[Sequence["Element"]] = None,
*,
path: Optional[str] = None,
action: str = OverlapAction.WARNING,
action: OverlapAction = OverlapAction.WARNING,
include: Optional[List[str]] = None,
exclude: Optional[List[str]] = None,
orphans: bool = True,
Expand DownExpand Up@@ -864,7 +864,7 @@ def subsandbox(self, sandbox: "Sandbox") -> Iterator["Sandbox"]:
# Yields:
# (Element): The dependencies in `scope`, in deterministic staging order
#
def _dependencies(self, scope, *, recurse=True, visited=None):
def _dependencies(self, scope: _Scope, *, recurse=True, visited=None):

# The format of visited is (BitMap(), BitMap()), with the first BitMap
# containing element that have been visited for the `_Scope.BUILD` case
Expand DownExpand Up@@ -971,7 +971,7 @@ def _stage_artifact(
sandbox: "Sandbox",
*,
path: Optional[str] = None,
action: str = OverlapAction.WARNING,
action: OverlapAction = OverlapAction.WARNING,
include: Optional[List[str]] = None,
exclude: Optional[List[str]] = None,
orphans: bool = True,
Expand DownExpand Up@@ -2060,7 +2060,16 @@ def _push(self):
# usebuildtree (bool): Use the buildtree as its source
#
# Returns: Exit code
def _shell(self, scope=None, *, mounts=None, isolate=False, prompt=None, command=None, usebuildtree=False):
def _shell(
self,
scope: _Scope | None = None,
*,
mounts: List[_HostMount] | None = None,
isolate: bool = False,
prompt: str | None = None,
command: List[str] | None = None,
usebuildtree: bool = False,
):

with self._prepare_sandbox(scope, shell=True, usebuildtree=usebuildtree) as sandbox:
environment = sandbox._get_configured_environment() or self.get_environment()
Expand Down
8 changes: 5 additions & 3 deletions src/buildstream/types.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -35,6 +35,9 @@ class FastEnum(metaclass=MetaFastEnum):

:class:`enum.Enum` attributes accesses can be really slow, and slow down the execution noticeably.
This reimplementation doesn't suffer the same problems, but also does not reimplement everything.

For mypy Enum static type checking support, all FastEnum should be stubbed as inheriting from enum.Enum.
Use `stubgen src/buildstream/types.py --include-docstrings` to generate the stubs, add `from enum import Enum` and replace all `(FastEnum)` with `(Enum)`
"""

name = None
Expand All@@ -61,7 +64,7 @@ def __new__(cls, value):
try:
return cls._value_to_entry[value]
except KeyError:
if type(value) is cls: # pylint: disable=unidiomatic-typecheck
if isinstance(value, cls): # pylint: disable=unidiomatic-typecheck

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AFAICT your are now doing this right.

https://pylint.pycqa.org/en/latest/user_guide/messages/convention/unidiomatic-typecheck.html

Suggested change
ifisinstance(value, cls):# pylint: disable=unidiomatic-typecheck
ifisinstance(value, cls):

So you dont need to disable the lint.

return value
raise ValueError("Unknown enum value: {}".format(value))

Expand DownExpand Up@@ -169,7 +172,6 @@ class OverlapAction(FastEnum):
# Defines the scope of dependencies to include for a given element
# when iterating over the dependency graph in APIs like
# Element._dependencies().
#
class _Scope(FastEnum):

# All elements which the given element depends on, following
Expand DownExpand Up@@ -384,7 +386,7 @@ def new_from_node(cls, node: MappingNode) -> "_SourceMirror":
alias_node: MappingNode = node.get_mapping("aliases")

for alias, uris in alias_node.items():
assert type(uris) is SequenceNode # pylint: disable=unidiomatic-typecheck
assert isinstance(uris, SequenceNode) # pylint: disable=unidiomatic-typecheck
aliases[alias] = uris.as_str_list()

return cls(name, aliases)
Expand Down
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
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
9 changes: 9 additions & 0 deletions doc/source/hacking/using_the_testsuite.rst
Original file line numberDiff line numberDiff line change
Expand Up@@ -190,13 +190,22 @@ consists of running the ``pylint`` tool, run the following::

.. _contributing_formatting_code:

Running Static Type Checkers
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Static Type Checking is performed separately from testing. In order to run the static type checking step which
consists of running the ``mypy`` tool, run the following::

tox -e mypy

Formatting code
~~~~~~~~~~~~~~~
Similar to linting, code formatting is also done via a ``tox`` environment. To
format the code using the ``black`` tool, run the following::

tox -e format

In CI `tox -e format-check` is used to ensure formatting has been run.

Observing coverage
~~~~~~~~~~~~~~~~~~
Once you have run the tests using `tox` (or `detox`), some coverage reports will
Expand Down
6 changes: 3 additions & 3 deletions src/buildstream/_elementproxy.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -95,7 +95,7 @@ def stage_artifact(
sandbox: "Sandbox",
*,
path: Optional[str] = None,
action: str = OverlapAction.WARNING,
action: OverlapAction = OverlapAction.WARNING,
include: Optional[List[str]] = None,
exclude: Optional[List[str]] = None,
orphans: bool = True
Expand All@@ -120,7 +120,7 @@ def stage_dependency_artifacts(
selection: Optional[Sequence["Element"]] = None,
*,
path: Optional[str] = None,
action: str = OverlapAction.WARNING,
action: OverlapAction = OverlapAction.WARNING,
include: Optional[List[str]] = None,
exclude: Optional[List[str]] = None,
orphans: bool = True
Expand DownExpand Up@@ -168,7 +168,7 @@ def _stage_artifact(
sandbox: "Sandbox",
*,
path: Optional[str] = None,
action: str = OverlapAction.WARNING,
action: OverlapAction = OverlapAction.WARNING,
include: Optional[List[str]] = None,
exclude: Optional[List[str]] = None,
orphans: bool = True,
Expand Down
6 changes: 3 additions & 3 deletions src/buildstream/_overlapcollector.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -66,7 +66,7 @@ def __init__(self, element: "Element"):
# location (str): The Sandbox relative location this session was created for
#
@contextmanager
def session(self, action: str, location: Optional[str]):
def session(self, action: OverlapAction, location: Optional[str]):
assert self._session is None, "Stage session already started"

if location is None:
Expand DownExpand Up@@ -108,13 +108,13 @@ def collect_stage_result(self, element: "Element", result: FileListResult):
# location (str): The Sandbox relative location this session was created for
#
class OverlapCollectorSession:
def __init__(self, element: "Element", action: str, location: str):
def __init__(self, element: "Element", action: OverlapAction, location: str):

# The Element we are staging for, on which we'll issue warnings
self._element = element # type: Element

# The OverlapAction for this session
self._action = action # type: str
self._action = action # type: OverlapAction

# The Sandbox relative directory this session was created for
self._location = location # type: str
Expand Down
9 changes: 7 additions & 2 deletions src/buildstream/_pipeline.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -44,7 +44,7 @@
# Yields:
# Elements in the scope of the specified target elements
#
def dependencies(targets: List[Element], scope: int, *, recurse: bool = True) -> Iterator[Element]:
def dependencies(targets: List[Element], scope: _Scope, *, recurse: bool = True) -> Iterator[Element]:
Comment thread
juergbi marked this conversation as resolved.
# Keep track of 'visited' in this scope, so that all targets
# share the same context.
visited = (BitMap(), BitMap())
Expand DownExpand Up@@ -73,7 +73,12 @@ def dependencies(targets: List[Element], scope: int, *, recurse: bool = True) ->
# A list of Elements appropriate for the specified selection mode
#
def get_selection(
context: Context, targets: List[Element], mode: str, *, silent: bool = True, depth_sort: bool = False
context: Context,
targets: List[Element],
mode: _PipelineSelection,
*,
silent: bool = True,
depth_sort: bool = False
) -> List[Element]:
def redirect_and_log() -> List[Element]:
# Redirect and log if permitted
Expand Down
16 changes: 8 additions & 8 deletions src/buildstream/_stream.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -153,7 +153,7 @@ def load_selection(
self,
targets: Iterable[str],
*,
selection: str = _PipelineSelection.NONE,
selection: _PipelineSelection = _PipelineSelection.NONE,
except_targets: Iterable[str] = (),
load_artifacts: bool = False,
connect_artifact_cache: bool = False,
Expand DownExpand Up@@ -259,7 +259,7 @@ def query_cache(self, elements, *, sources_of_cached_elements=False, only_source
def shell(
self,
target: str,
scope: int,
scope: _Scope,
prompt: Callable[[Element], str],
*,
unique_id: Optional[str] = None,
Expand DownExpand Up@@ -382,7 +382,7 @@ def build(
self,
targets: Iterable[str],
*,
selection: str = _PipelineSelection.NONE,
selection: _PipelineSelection = _PipelineSelection.NONE,
ignore_junction_targets: bool = False,
artifact_remotes: Iterable[RemoteSpec] = (),
source_remotes: Iterable[RemoteSpec] = (),
Expand DownExpand Up@@ -456,7 +456,7 @@ def fetch(
self,
targets: Iterable[str],
*,
selection: str = _PipelineSelection.NONE,
selection: _PipelineSelection = _PipelineSelection.NONE,
except_targets: Iterable[str] = (),
source_remotes: Iterable[RemoteSpec] = (),
ignore_project_source_remotes: bool = False,
Expand DownExpand Up@@ -579,7 +579,7 @@ def pull(
self,
targets: Iterable[str],
*,
selection: str = _PipelineSelection.NONE,
selection: _PipelineSelection = _PipelineSelection.NONE,
ignore_junction_targets: bool = False,
artifact_remotes: Iterable[RemoteSpec] = (),
ignore_project_artifact_remotes: bool = False,
Expand DownExpand Up@@ -633,7 +633,7 @@ def push(
self,
targets: Iterable[str],
*,
selection: str = _PipelineSelection.NONE,
selection: _PipelineSelection = _PipelineSelection.NONE,
ignore_junction_targets: bool = False,
artifact_remotes: Iterable[RemoteSpec] = (),
ignore_project_artifact_remotes: bool = False,
Expand DownExpand Up@@ -688,7 +688,7 @@ def checkout(
*,
location: Optional[str] = None,
force: bool = False,
selection: str = _PipelineSelection.RUN,
selection: _PipelineSelection = _PipelineSelection.RUN,
integrate: bool = True,
hardlinks: bool = False,
compression: str = "",
Expand DownExpand Up@@ -1668,7 +1668,7 @@ def _load(
self,
targets: Iterable[str],
*,
selection: str = _PipelineSelection.NONE,
selection: _PipelineSelection = _PipelineSelection.NONE,
except_targets: Iterable[str] = (),
ignore_junction_targets: bool = False,
dynamic_plan: bool = False,
Expand Down
21 changes: 15 additions & 6 deletions src/buildstream/element.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -90,7 +90,7 @@
from .sandbox import _SandboxFlags, SandboxCommandError
from .sandbox._config import SandboxConfig
from .sandbox._sandboxremote import SandboxRemote
from .types import _Scope, _CacheBuildTrees, _KeyStrength, OverlapAction, _DisplayKey
from .types import _HostMount, _Scope, _CacheBuildTrees, _KeyStrength, OverlapAction, _DisplayKey
from ._artifact import Artifact
from ._elementproxy import ElementProxy
from ._elementsources import ElementSources
Expand DownExpand Up@@ -604,7 +604,7 @@ def stage_artifact(
sandbox: "Sandbox",
*,
path: Optional[str] = None,
action: str = OverlapAction.WARNING,
action: OverlapAction = OverlapAction.WARNING,
include: Optional[List[str]] = None,
exclude: Optional[List[str]] = None,
orphans: bool = True,
Expand DownExpand Up@@ -664,7 +664,7 @@ def stage_dependency_artifacts(
selection: Optional[Sequence["Element"]] = None,
*,
path: Optional[str] = None,
action: str = OverlapAction.WARNING,
action: OverlapAction = OverlapAction.WARNING,
include: Optional[List[str]] = None,
exclude: Optional[List[str]] = None,
orphans: bool = True,
Expand DownExpand Up@@ -864,7 +864,7 @@ def subsandbox(self, sandbox: "Sandbox") -> Iterator["Sandbox"]:
# Yields:
# (Element): The dependencies in `scope`, in deterministic staging order
#
def _dependencies(self, scope, *, recurse=True, visited=None):
def _dependencies(self, scope: _Scope, *, recurse=True, visited=None):

# The format of visited is (BitMap(), BitMap()), with the first BitMap
# containing element that have been visited for the `_Scope.BUILD` case
Expand DownExpand Up@@ -971,7 +971,7 @@ def _stage_artifact(
sandbox: "Sandbox",
*,
path: Optional[str] = None,
action: str = OverlapAction.WARNING,
action: OverlapAction = OverlapAction.WARNING,
include: Optional[List[str]] = None,
exclude: Optional[List[str]] = None,
orphans: bool = True,
Expand DownExpand Up@@ -2060,7 +2060,16 @@ def _push(self):
# usebuildtree (bool): Use the buildtree as its source
#
# Returns: Exit code
def _shell(self, scope=None, *, mounts=None, isolate=False, prompt=None, command=None, usebuildtree=False):
def _shell(
self,
scope: _Scope | None = None,
*,
mounts: List[_HostMount] | None = None,
isolate: bool = False,
prompt: str | None = None,
command: List[str] | None = None,
usebuildtree: bool = False,
):

with self._prepare_sandbox(scope, shell=True, usebuildtree=usebuildtree) as sandbox:
environment = sandbox._get_configured_environment() or self.get_environment()
Expand Down
8 changes: 5 additions & 3 deletions src/buildstream/types.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -35,6 +35,9 @@ class FastEnum(metaclass=MetaFastEnum):

:class:`enum.Enum` attributes accesses can be really slow, and slow down the execution noticeably.
This reimplementation doesn't suffer the same problems, but also does not reimplement everything.

For mypy Enum static type checking support, all FastEnum should be stubbed as inheriting from enum.Enum.
Use `stubgen src/buildstream/types.py --include-docstrings` to generate the stubs, add `from enum import Enum` and replace all `(FastEnum)` with `(Enum)`
"""

name = None
Expand All@@ -61,7 +64,7 @@ def __new__(cls, value):
try:
return cls._value_to_entry[value]
except KeyError:
if type(value) is cls: # pylint: disable=unidiomatic-typecheck
if isinstance(value, cls): # pylint: disable=unidiomatic-typecheck

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AFAICT your are now doing this right.

https://pylint.pycqa.org/en/latest/user_guide/messages/convention/unidiomatic-typecheck.html

Suggested change
ifisinstance(value, cls):# pylint: disable=unidiomatic-typecheck
ifisinstance(value, cls):

So you dont need to disable the lint.

return value
raise ValueError("Unknown enum value: {}".format(value))

Expand DownExpand Up@@ -169,7 +172,6 @@ class OverlapAction(FastEnum):
# Defines the scope of dependencies to include for a given element
# when iterating over the dependency graph in APIs like
# Element._dependencies().
#
class _Scope(FastEnum):

# All elements which the given element depends on, following
Expand DownExpand Up@@ -384,7 +386,7 @@ def new_from_node(cls, node: MappingNode) -> "_SourceMirror":
alias_node: MappingNode = node.get_mapping("aliases")

for alias, uris in alias_node.items():
assert type(uris) is SequenceNode # pylint: disable=unidiomatic-typecheck
assert isinstance(uris, SequenceNode) # pylint: disable=unidiomatic-typecheck
aliases[alias] = uris.as_str_list()

return cls(name, aliases)
Expand Down
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length \u003e 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
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
9 changes: 9 additions & 0 deletions doc/source/hacking/using_the_testsuite.rst
Original file line numberDiff line numberDiff line change
Expand Up@@ -190,13 +190,22 @@ consists of running the ``pylint`` tool, run the following::

.. _contributing_formatting_code:

Running Static Type Checkers
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Static Type Checking is performed separately from testing. In order to run the static type checking step which
consists of running the ``mypy`` tool, run the following::

tox -e mypy

Formatting code
~~~~~~~~~~~~~~~
Similar to linting, code formatting is also done via a ``tox`` environment. To
format the code using the ``black`` tool, run the following::

tox -e format

In CI `tox -e format-check` is used to ensure formatting has been run.

Observing coverage
~~~~~~~~~~~~~~~~~~
Once you have run the tests using `tox` (or `detox`), some coverage reports will
Expand Down
6 changes: 3 additions & 3 deletions src/buildstream/_elementproxy.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -95,7 +95,7 @@ def stage_artifact(
sandbox: "Sandbox",
*,
path: Optional[str] = None,
action: str = OverlapAction.WARNING,
action: OverlapAction = OverlapAction.WARNING,
include: Optional[List[str]] = None,
exclude: Optional[List[str]] = None,
orphans: bool = True
Expand All@@ -120,7 +120,7 @@ def stage_dependency_artifacts(
selection: Optional[Sequence["Element"]] = None,
*,
path: Optional[str] = None,
action: str = OverlapAction.WARNING,
action: OverlapAction = OverlapAction.WARNING,
include: Optional[List[str]] = None,
exclude: Optional[List[str]] = None,
orphans: bool = True
Expand DownExpand Up@@ -168,7 +168,7 @@ def _stage_artifact(
sandbox: "Sandbox",
*,
path: Optional[str] = None,
action: str = OverlapAction.WARNING,
action: OverlapAction = OverlapAction.WARNING,
include: Optional[List[str]] = None,
exclude: Optional[List[str]] = None,
orphans: bool = True,
Expand Down
6 changes: 3 additions & 3 deletions src/buildstream/_overlapcollector.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -66,7 +66,7 @@ def __init__(self, element: "Element"):
# location (str): The Sandbox relative location this session was created for
#
@contextmanager
def session(self, action: str, location: Optional[str]):
def session(self, action: OverlapAction, location: Optional[str]):
assert self._session is None, "Stage session already started"

if location is None:
Expand DownExpand Up@@ -108,13 +108,13 @@ def collect_stage_result(self, element: "Element", result: FileListResult):
# location (str): The Sandbox relative location this session was created for
#
class OverlapCollectorSession:
def __init__(self, element: "Element", action: str, location: str):
def __init__(self, element: "Element", action: OverlapAction, location: str):

# The Element we are staging for, on which we'll issue warnings
self._element = element # type: Element

# The OverlapAction for this session
self._action = action # type: str
self._action = action # type: OverlapAction

# The Sandbox relative directory this session was created for
self._location = location # type: str
Expand Down
9 changes: 7 additions & 2 deletions src/buildstream/_pipeline.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -44,7 +44,7 @@
# Yields:
# Elements in the scope of the specified target elements
#
def dependencies(targets: List[Element], scope: int, *, recurse: bool = True) -> Iterator[Element]:
def dependencies(targets: List[Element], scope: _Scope, *, recurse: bool = True) -> Iterator[Element]:
Comment thread
juergbi marked this conversation as resolved.
# Keep track of 'visited' in this scope, so that all targets
# share the same context.
visited = (BitMap(), BitMap())
Expand DownExpand Up@@ -73,7 +73,12 @@ def dependencies(targets: List[Element], scope: int, *, recurse: bool = True) ->
# A list of Elements appropriate for the specified selection mode
#
def get_selection(
context: Context, targets: List[Element], mode: str, *, silent: bool = True, depth_sort: bool = False
context: Context,
targets: List[Element],
mode: _PipelineSelection,
*,
silent: bool = True,
depth_sort: bool = False
) -> List[Element]:
def redirect_and_log() -> List[Element]:
# Redirect and log if permitted
Expand Down
16 changes: 8 additions & 8 deletions src/buildstream/_stream.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -153,7 +153,7 @@ def load_selection(
self,
targets: Iterable[str],
*,
selection: str = _PipelineSelection.NONE,
selection: _PipelineSelection = _PipelineSelection.NONE,
except_targets: Iterable[str] = (),
load_artifacts: bool = False,
connect_artifact_cache: bool = False,
Expand DownExpand Up@@ -259,7 +259,7 @@ def query_cache(self, elements, *, sources_of_cached_elements=False, only_source
def shell(
self,
target: str,
scope: int,
scope: _Scope,
prompt: Callable[[Element], str],
*,
unique_id: Optional[str] = None,
Expand DownExpand Up@@ -382,7 +382,7 @@ def build(
self,
targets: Iterable[str],
*,
selection: str = _PipelineSelection.NONE,
selection: _PipelineSelection = _PipelineSelection.NONE,
ignore_junction_targets: bool = False,
artifact_remotes: Iterable[RemoteSpec] = (),
source_remotes: Iterable[RemoteSpec] = (),
Expand DownExpand Up@@ -456,7 +456,7 @@ def fetch(
self,
targets: Iterable[str],
*,
selection: str = _PipelineSelection.NONE,
selection: _PipelineSelection = _PipelineSelection.NONE,
except_targets: Iterable[str] = (),
source_remotes: Iterable[RemoteSpec] = (),
ignore_project_source_remotes: bool = False,
Expand DownExpand Up@@ -579,7 +579,7 @@ def pull(
self,
targets: Iterable[str],
*,
selection: str = _PipelineSelection.NONE,
selection: _PipelineSelection = _PipelineSelection.NONE,
ignore_junction_targets: bool = False,
artifact_remotes: Iterable[RemoteSpec] = (),
ignore_project_artifact_remotes: bool = False,
Expand DownExpand Up@@ -633,7 +633,7 @@ def push(
self,
targets: Iterable[str],
*,
selection: str = _PipelineSelection.NONE,
selection: _PipelineSelection = _PipelineSelection.NONE,
ignore_junction_targets: bool = False,
artifact_remotes: Iterable[RemoteSpec] = (),
ignore_project_artifact_remotes: bool = False,
Expand DownExpand Up@@ -688,7 +688,7 @@ def checkout(
*,
location: Optional[str] = None,
force: bool = False,
selection: str = _PipelineSelection.RUN,
selection: _PipelineSelection = _PipelineSelection.RUN,
integrate: bool = True,
hardlinks: bool = False,
compression: str = "",
Expand DownExpand Up@@ -1668,7 +1668,7 @@ def _load(
self,
targets: Iterable[str],
*,
selection: str = _PipelineSelection.NONE,
selection: _PipelineSelection = _PipelineSelection.NONE,
except_targets: Iterable[str] = (),
ignore_junction_targets: bool = False,
dynamic_plan: bool = False,
Expand Down
21 changes: 15 additions & 6 deletions src/buildstream/element.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -90,7 +90,7 @@
from .sandbox import _SandboxFlags, SandboxCommandError
from .sandbox._config import SandboxConfig
from .sandbox._sandboxremote import SandboxRemote
from .types import _Scope, _CacheBuildTrees, _KeyStrength, OverlapAction, _DisplayKey
from .types import _HostMount, _Scope, _CacheBuildTrees, _KeyStrength, OverlapAction, _DisplayKey
from ._artifact import Artifact
from ._elementproxy import ElementProxy
from ._elementsources import ElementSources
Expand DownExpand Up@@ -604,7 +604,7 @@ def stage_artifact(
sandbox: "Sandbox",
*,
path: Optional[str] = None,
action: str = OverlapAction.WARNING,
action: OverlapAction = OverlapAction.WARNING,
include: Optional[List[str]] = None,
exclude: Optional[List[str]] = None,
orphans: bool = True,
Expand DownExpand Up@@ -664,7 +664,7 @@ def stage_dependency_artifacts(
selection: Optional[Sequence["Element"]] = None,
*,
path: Optional[str] = None,
action: str = OverlapAction.WARNING,
action: OverlapAction = OverlapAction.WARNING,
include: Optional[List[str]] = None,
exclude: Optional[List[str]] = None,
orphans: bool = True,
Expand DownExpand Up@@ -864,7 +864,7 @@ def subsandbox(self, sandbox: "Sandbox") -> Iterator["Sandbox"]:
# Yields:
# (Element): The dependencies in `scope`, in deterministic staging order
#
def _dependencies(self, scope, *, recurse=True, visited=None):
def _dependencies(self, scope: _Scope, *, recurse=True, visited=None):

# The format of visited is (BitMap(), BitMap()), with the first BitMap
# containing element that have been visited for the `_Scope.BUILD` case
Expand DownExpand Up@@ -971,7 +971,7 @@ def _stage_artifact(
sandbox: "Sandbox",
*,
path: Optional[str] = None,
action: str = OverlapAction.WARNING,
action: OverlapAction = OverlapAction.WARNING,
include: Optional[List[str]] = None,
exclude: Optional[List[str]] = None,
orphans: bool = True,
Expand DownExpand Up@@ -2060,7 +2060,16 @@ def _push(self):
# usebuildtree (bool): Use the buildtree as its source
#
# Returns: Exit code
def _shell(self, scope=None, *, mounts=None, isolate=False, prompt=None, command=None, usebuildtree=False):
def _shell(
self,
scope: _Scope | None = None,
*,
mounts: List[_HostMount] | None = None,
isolate: bool = False,
prompt: str | None = None,
command: List[str] | None = None,
usebuildtree: bool = False,
):

with self._prepare_sandbox(scope, shell=True, usebuildtree=usebuildtree) as sandbox:
environment = sandbox._get_configured_environment() or self.get_environment()
Expand Down
8 changes: 5 additions & 3 deletions src/buildstream/types.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -35,6 +35,9 @@ class FastEnum(metaclass=MetaFastEnum):

:class:`enum.Enum` attributes accesses can be really slow, and slow down the execution noticeably.
This reimplementation doesn't suffer the same problems, but also does not reimplement everything.

For mypy Enum static type checking support, all FastEnum should be stubbed as inheriting from enum.Enum.
Use `stubgen src/buildstream/types.py --include-docstrings` to generate the stubs, add `from enum import Enum` and replace all `(FastEnum)` with `(Enum)`
"""

name = None
Expand All@@ -61,7 +64,7 @@ def __new__(cls, value):
try:
return cls._value_to_entry[value]
except KeyError:
if type(value) is cls: # pylint: disable=unidiomatic-typecheck
if isinstance(value, cls): # pylint: disable=unidiomatic-typecheck

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AFAICT your are now doing this right.

https://pylint.pycqa.org/en/latest/user_guide/messages/convention/unidiomatic-typecheck.html

Suggested change
ifisinstance(value, cls):# pylint: disable=unidiomatic-typecheck
ifisinstance(value, cls):

So you dont need to disable the lint.

return value
raise ValueError("Unknown enum value: {}".format(value))

Expand DownExpand Up@@ -169,7 +172,6 @@ class OverlapAction(FastEnum):
# Defines the scope of dependencies to include for a given element
# when iterating over the dependency graph in APIs like
# Element._dependencies().
#
class _Scope(FastEnum):

# All elements which the given element depends on, following
Expand DownExpand Up@@ -384,7 +386,7 @@ def new_from_node(cls, node: MappingNode) -> "_SourceMirror":
alias_node: MappingNode = node.get_mapping("aliases")

for alias, uris in alias_node.items():
assert type(uris) is SequenceNode # pylint: disable=unidiomatic-typecheck
assert isinstance(uris, SequenceNode) # pylint: disable=unidiomatic-typecheck
aliases[alias] = uris.as_str_list()

return cls(name, aliases)
Expand Down
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content
Merged
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
9 changes: 9 additions & 0 deletions doc/source/hacking/using_the_testsuite.rst
Original file line numberDiff line numberDiff line change
Expand Up@@ -190,13 +190,22 @@ consists of running the ``pylint`` tool, run the following::

.. _contributing_formatting_code:

Running Static Type Checkers
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Static Type Checking is performed separately from testing. In order to run the static type checking step which
consists of running the ``mypy`` tool, run the following::

tox -e mypy

Formatting code
~~~~~~~~~~~~~~~
Similar to linting, code formatting is also done via a ``tox`` environment. To
format the code using the ``black`` tool, run the following::

tox -e format

In CI `tox -e format-check` is used to ensure formatting has been run.

Observing coverage
~~~~~~~~~~~~~~~~~~
Once you have run the tests using `tox` (or `detox`), some coverage reports will
Expand Down
6 changes: 3 additions & 3 deletions src/buildstream/_elementproxy.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -95,7 +95,7 @@ def stage_artifact(
sandbox: "Sandbox",
*,
path: Optional[str] = None,
action: str = OverlapAction.WARNING,
action: OverlapAction = OverlapAction.WARNING,
include: Optional[List[str]] = None,
exclude: Optional[List[str]] = None,
orphans: bool = True
Expand All@@ -120,7 +120,7 @@ def stage_dependency_artifacts(
selection: Optional[Sequence["Element"]] = None,
*,
path: Optional[str] = None,
action: str = OverlapAction.WARNING,
action: OverlapAction = OverlapAction.WARNING,
include: Optional[List[str]] = None,
exclude: Optional[List[str]] = None,
orphans: bool = True
Expand DownExpand Up@@ -168,7 +168,7 @@ def _stage_artifact(
sandbox: "Sandbox",
*,
path: Optional[str] = None,
action: str = OverlapAction.WARNING,
action: OverlapAction = OverlapAction.WARNING,
include: Optional[List[str]] = None,
exclude: Optional[List[str]] = None,
orphans: bool = True,
Expand Down
6 changes: 3 additions & 3 deletions src/buildstream/_overlapcollector.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -66,7 +66,7 @@ def __init__(self, element: "Element"):
# location (str): The Sandbox relative location this session was created for
#
@contextmanager
def session(self, action: str, location: Optional[str]):
def session(self, action: OverlapAction, location: Optional[str]):
assert self._session is None, "Stage session already started"

if location is None:
Expand DownExpand Up@@ -108,13 +108,13 @@ def collect_stage_result(self, element: "Element", result: FileListResult):
# location (str): The Sandbox relative location this session was created for
#
class OverlapCollectorSession:
def __init__(self, element: "Element", action: str, location: str):
def __init__(self, element: "Element", action: OverlapAction, location: str):

# The Element we are staging for, on which we'll issue warnings
self._element = element # type: Element

# The OverlapAction for this session
self._action = action # type: str
self._action = action # type: OverlapAction

# The Sandbox relative directory this session was created for
self._location = location # type: str
Expand Down
9 changes: 7 additions & 2 deletions src/buildstream/_pipeline.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -44,7 +44,7 @@
# Yields:
# Elements in the scope of the specified target elements
#
def dependencies(targets: List[Element], scope: int, *, recurse: bool = True) -> Iterator[Element]:
def dependencies(targets: List[Element], scope: _Scope, *, recurse: bool = True) -> Iterator[Element]:
Comment thread
juergbi marked this conversation as resolved.
# Keep track of 'visited' in this scope, so that all targets
# share the same context.
visited = (BitMap(), BitMap())
Expand DownExpand Up@@ -73,7 +73,12 @@ def dependencies(targets: List[Element], scope: int, *, recurse: bool = True) ->
# A list of Elements appropriate for the specified selection mode
#
def get_selection(
context: Context, targets: List[Element], mode: str, *, silent: bool = True, depth_sort: bool = False
context: Context,
targets: List[Element],
mode: _PipelineSelection,
*,
silent: bool = True,
depth_sort: bool = False
) -> List[Element]:
def redirect_and_log() -> List[Element]:
# Redirect and log if permitted
Expand Down
16 changes: 8 additions & 8 deletions src/buildstream/_stream.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -153,7 +153,7 @@ def load_selection(
self,
targets: Iterable[str],
*,
selection: str = _PipelineSelection.NONE,
selection: _PipelineSelection = _PipelineSelection.NONE,
except_targets: Iterable[str] = (),
load_artifacts: bool = False,
connect_artifact_cache: bool = False,
Expand DownExpand Up@@ -259,7 +259,7 @@ def query_cache(self, elements, *, sources_of_cached_elements=False, only_source
def shell(
self,
target: str,
scope: int,
scope: _Scope,
prompt: Callable[[Element], str],
*,
unique_id: Optional[str] = None,
Expand DownExpand Up@@ -382,7 +382,7 @@ def build(
self,
targets: Iterable[str],
*,
selection: str = _PipelineSelection.NONE,
selection: _PipelineSelection = _PipelineSelection.NONE,
ignore_junction_targets: bool = False,
artifact_remotes: Iterable[RemoteSpec] = (),
source_remotes: Iterable[RemoteSpec] = (),
Expand DownExpand Up@@ -456,7 +456,7 @@ def fetch(
self,
targets: Iterable[str],
*,
selection: str = _PipelineSelection.NONE,
selection: _PipelineSelection = _PipelineSelection.NONE,
except_targets: Iterable[str] = (),
source_remotes: Iterable[RemoteSpec] = (),
ignore_project_source_remotes: bool = False,
Expand DownExpand Up@@ -579,7 +579,7 @@ def pull(
self,
targets: Iterable[str],
*,
selection: str = _PipelineSelection.NONE,
selection: _PipelineSelection = _PipelineSelection.NONE,
ignore_junction_targets: bool = False,
artifact_remotes: Iterable[RemoteSpec] = (),
ignore_project_artifact_remotes: bool = False,
Expand DownExpand Up@@ -633,7 +633,7 @@ def push(
self,
targets: Iterable[str],
*,
selection: str = _PipelineSelection.NONE,
selection: _PipelineSelection = _PipelineSelection.NONE,
ignore_junction_targets: bool = False,
artifact_remotes: Iterable[RemoteSpec] = (),
ignore_project_artifact_remotes: bool = False,
Expand DownExpand Up@@ -688,7 +688,7 @@ def checkout(
*,
location: Optional[str] = None,
force: bool = False,
selection: str = _PipelineSelection.RUN,
selection: _PipelineSelection = _PipelineSelection.RUN,
integrate: bool = True,
hardlinks: bool = False,
compression: str = "",
Expand DownExpand Up@@ -1668,7 +1668,7 @@ def _load(
self,
targets: Iterable[str],
*,
selection: str = _PipelineSelection.NONE,
selection: _PipelineSelection = _PipelineSelection.NONE,
except_targets: Iterable[str] = (),
ignore_junction_targets: bool = False,
dynamic_plan: bool = False,
Expand Down
21 changes: 15 additions & 6 deletions src/buildstream/element.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -90,7 +90,7 @@
from .sandbox import _SandboxFlags, SandboxCommandError
from .sandbox._config import SandboxConfig
from .sandbox._sandboxremote import SandboxRemote
from .types import _Scope, _CacheBuildTrees, _KeyStrength, OverlapAction, _DisplayKey
from .types import _HostMount, _Scope, _CacheBuildTrees, _KeyStrength, OverlapAction, _DisplayKey
from ._artifact import Artifact
from ._elementproxy import ElementProxy
from ._elementsources import ElementSources
Expand DownExpand Up@@ -604,7 +604,7 @@ def stage_artifact(
sandbox: "Sandbox",
*,
path: Optional[str] = None,
action: str = OverlapAction.WARNING,
action: OverlapAction = OverlapAction.WARNING,
include: Optional[List[str]] = None,
exclude: Optional[List[str]] = None,
orphans: bool = True,
Expand DownExpand Up@@ -664,7 +664,7 @@ def stage_dependency_artifacts(
selection: Optional[Sequence["Element"]] = None,
*,
path: Optional[str] = None,
action: str = OverlapAction.WARNING,
action: OverlapAction = OverlapAction.WARNING,
include: Optional[List[str]] = None,
exclude: Optional[List[str]] = None,
orphans: bool = True,
Expand DownExpand Up@@ -864,7 +864,7 @@ def subsandbox(self, sandbox: "Sandbox") -> Iterator["Sandbox"]:
# Yields:
# (Element): The dependencies in `scope`, in deterministic staging order
#
def _dependencies(self, scope, *, recurse=True, visited=None):
def _dependencies(self, scope: _Scope, *, recurse=True, visited=None):

# The format of visited is (BitMap(), BitMap()), with the first BitMap
# containing element that have been visited for the `_Scope.BUILD` case
Expand DownExpand Up@@ -971,7 +971,7 @@ def _stage_artifact(
sandbox: "Sandbox",
*,
path: Optional[str] = None,
action: str = OverlapAction.WARNING,
action: OverlapAction = OverlapAction.WARNING,
include: Optional[List[str]] = None,
exclude: Optional[List[str]] = None,
orphans: bool = True,
Expand DownExpand Up@@ -2060,7 +2060,16 @@ def _push(self):
# usebuildtree (bool): Use the buildtree as its source
#
# Returns: Exit code
def _shell(self, scope=None, *, mounts=None, isolate=False, prompt=None, command=None, usebuildtree=False):
def _shell(
self,
scope: _Scope | None = None,
*,
mounts: List[_HostMount] | None = None,
isolate: bool = False,
prompt: str | None = None,
command: List[str] | None = None,
usebuildtree: bool = False,
):

with self._prepare_sandbox(scope, shell=True, usebuildtree=usebuildtree) as sandbox:
environment = sandbox._get_configured_environment() or self.get_environment()
Expand Down
8 changes: 5 additions & 3 deletions src/buildstream/types.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -35,6 +35,9 @@ class FastEnum(metaclass=MetaFastEnum):

:class:`enum.Enum` attributes accesses can be really slow, and slow down the execution noticeably.
This reimplementation doesn't suffer the same problems, but also does not reimplement everything.

For mypy Enum static type checking support, all FastEnum should be stubbed as inheriting from enum.Enum.
Use `stubgen src/buildstream/types.py --include-docstrings` to generate the stubs, add `from enum import Enum` and replace all `(FastEnum)` with `(Enum)`
"""

name = None
Expand All@@ -61,7 +64,7 @@ def __new__(cls, value):
try:
return cls._value_to_entry[value]
except KeyError:
if type(value) is cls: # pylint: disable=unidiomatic-typecheck
if isinstance(value, cls): # pylint: disable=unidiomatic-typecheck

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AFAICT your are now doing this right.

https://pylint.pycqa.org/en/latest/user_guide/messages/convention/unidiomatic-typecheck.html

Suggested change
ifisinstance(value, cls):# pylint: disable=unidiomatic-typecheck
ifisinstance(value, cls):

So you dont need to disable the lint.

return value
raise ValueError("Unknown enum value: {}".format(value))

Expand DownExpand Up@@ -169,7 +172,6 @@ class OverlapAction(FastEnum):
# Defines the scope of dependencies to include for a given element
# when iterating over the dependency graph in APIs like
# Element._dependencies().
#
class _Scope(FastEnum):

# All elements which the given element depends on, following
Expand DownExpand Up@@ -384,7 +386,7 @@ def new_from_node(cls, node: MappingNode) -> "_SourceMirror":
alias_node: MappingNode = node.get_mapping("aliases")

for alias, uris in alias_node.items():
assert type(uris) is SequenceNode # pylint: disable=unidiomatic-typecheck
assert isinstance(uris, SequenceNode) # pylint: disable=unidiomatic-typecheck
aliases[alias] = uris.as_str_list()

return cls(name, aliases)
Expand Down
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
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
9 changes: 9 additions & 0 deletions doc/source/hacking/using_the_testsuite.rst
Original file line numberDiff line numberDiff line change
Expand Up@@ -190,13 +190,22 @@ consists of running the ``pylint`` tool, run the following::

.. _contributing_formatting_code:

Running Static Type Checkers
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Static Type Checking is performed separately from testing. In order to run the static type checking step which
consists of running the ``mypy`` tool, run the following::

tox -e mypy

Formatting code
~~~~~~~~~~~~~~~
Similar to linting, code formatting is also done via a ``tox`` environment. To
format the code using the ``black`` tool, run the following::

tox -e format

In CI `tox -e format-check` is used to ensure formatting has been run.

Observing coverage
~~~~~~~~~~~~~~~~~~
Once you have run the tests using `tox` (or `detox`), some coverage reports will
Expand Down
6 changes: 3 additions & 3 deletions src/buildstream/_elementproxy.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -95,7 +95,7 @@ def stage_artifact(
sandbox: "Sandbox",
*,
path: Optional[str] = None,
action: str = OverlapAction.WARNING,
action: OverlapAction = OverlapAction.WARNING,
include: Optional[List[str]] = None,
exclude: Optional[List[str]] = None,
orphans: bool = True
Expand All@@ -120,7 +120,7 @@ def stage_dependency_artifacts(
selection: Optional[Sequence["Element"]] = None,
*,
path: Optional[str] = None,
action: str = OverlapAction.WARNING,
action: OverlapAction = OverlapAction.WARNING,
include: Optional[List[str]] = None,
exclude: Optional[List[str]] = None,
orphans: bool = True
Expand DownExpand Up@@ -168,7 +168,7 @@ def _stage_artifact(
sandbox: "Sandbox",
*,
path: Optional[str] = None,
action: str = OverlapAction.WARNING,
action: OverlapAction = OverlapAction.WARNING,
include: Optional[List[str]] = None,
exclude: Optional[List[str]] = None,
orphans: bool = True,
Expand Down
6 changes: 3 additions & 3 deletions src/buildstream/_overlapcollector.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -66,7 +66,7 @@ def __init__(self, element: "Element"):
# location (str): The Sandbox relative location this session was created for
#
@contextmanager
def session(self, action: str, location: Optional[str]):
def session(self, action: OverlapAction, location: Optional[str]):
assert self._session is None, "Stage session already started"

if location is None:
Expand DownExpand Up@@ -108,13 +108,13 @@ def collect_stage_result(self, element: "Element", result: FileListResult):
# location (str): The Sandbox relative location this session was created for
#
class OverlapCollectorSession:
def __init__(self, element: "Element", action: str, location: str):
def __init__(self, element: "Element", action: OverlapAction, location: str):

# The Element we are staging for, on which we'll issue warnings
self._element = element # type: Element

# The OverlapAction for this session
self._action = action # type: str
self._action = action # type: OverlapAction

# The Sandbox relative directory this session was created for
self._location = location # type: str
Expand Down
9 changes: 7 additions & 2 deletions src/buildstream/_pipeline.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -44,7 +44,7 @@
# Yields:
# Elements in the scope of the specified target elements
#
def dependencies(targets: List[Element], scope: int, *, recurse: bool = True) -> Iterator[Element]:
def dependencies(targets: List[Element], scope: _Scope, *, recurse: bool = True) -> Iterator[Element]:
Comment thread
juergbi marked this conversation as resolved.
# Keep track of 'visited' in this scope, so that all targets
# share the same context.
visited = (BitMap(), BitMap())
Expand DownExpand Up@@ -73,7 +73,12 @@ def dependencies(targets: List[Element], scope: int, *, recurse: bool = True) ->
# A list of Elements appropriate for the specified selection mode
#
def get_selection(
context: Context, targets: List[Element], mode: str, *, silent: bool = True, depth_sort: bool = False
context: Context,
targets: List[Element],
mode: _PipelineSelection,
*,
silent: bool = True,
depth_sort: bool = False
) -> List[Element]:
def redirect_and_log() -> List[Element]:
# Redirect and log if permitted
Expand Down
16 changes: 8 additions & 8 deletions src/buildstream/_stream.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -153,7 +153,7 @@ def load_selection(
self,
targets: Iterable[str],
*,
selection: str = _PipelineSelection.NONE,
selection: _PipelineSelection = _PipelineSelection.NONE,
except_targets: Iterable[str] = (),
load_artifacts: bool = False,
connect_artifact_cache: bool = False,
Expand DownExpand Up@@ -259,7 +259,7 @@ def query_cache(self, elements, *, sources_of_cached_elements=False, only_source
def shell(
self,
target: str,
scope: int,
scope: _Scope,
prompt: Callable[[Element], str],
*,
unique_id: Optional[str] = None,
Expand DownExpand Up@@ -382,7 +382,7 @@ def build(
self,
targets: Iterable[str],
*,
selection: str = _PipelineSelection.NONE,
selection: _PipelineSelection = _PipelineSelection.NONE,
ignore_junction_targets: bool = False,
artifact_remotes: Iterable[RemoteSpec] = (),
source_remotes: Iterable[RemoteSpec] = (),
Expand DownExpand Up@@ -456,7 +456,7 @@ def fetch(
self,
targets: Iterable[str],
*,
selection: str = _PipelineSelection.NONE,
selection: _PipelineSelection = _PipelineSelection.NONE,
except_targets: Iterable[str] = (),
source_remotes: Iterable[RemoteSpec] = (),
ignore_project_source_remotes: bool = False,
Expand DownExpand Up@@ -579,7 +579,7 @@ def pull(
self,
targets: Iterable[str],
*,
selection: str = _PipelineSelection.NONE,
selection: _PipelineSelection = _PipelineSelection.NONE,
ignore_junction_targets: bool = False,
artifact_remotes: Iterable[RemoteSpec] = (),
ignore_project_artifact_remotes: bool = False,
Expand DownExpand Up@@ -633,7 +633,7 @@ def push(
self,
targets: Iterable[str],
*,
selection: str = _PipelineSelection.NONE,
selection: _PipelineSelection = _PipelineSelection.NONE,
ignore_junction_targets: bool = False,
artifact_remotes: Iterable[RemoteSpec] = (),
ignore_project_artifact_remotes: bool = False,
Expand DownExpand Up@@ -688,7 +688,7 @@ def checkout(
*,
location: Optional[str] = None,
force: bool = False,
selection: str = _PipelineSelection.RUN,
selection: _PipelineSelection = _PipelineSelection.RUN,
integrate: bool = True,
hardlinks: bool = False,
compression: str = "",
Expand DownExpand Up@@ -1668,7 +1668,7 @@ def _load(
self,
targets: Iterable[str],
*,
selection: str = _PipelineSelection.NONE,
selection: _PipelineSelection = _PipelineSelection.NONE,
except_targets: Iterable[str] = (),
ignore_junction_targets: bool = False,
dynamic_plan: bool = False,
Expand Down
21 changes: 15 additions & 6 deletions src/buildstream/element.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -90,7 +90,7 @@
from .sandbox import _SandboxFlags, SandboxCommandError
from .sandbox._config import SandboxConfig
from .sandbox._sandboxremote import SandboxRemote
from .types import _Scope, _CacheBuildTrees, _KeyStrength, OverlapAction, _DisplayKey
from .types import _HostMount, _Scope, _CacheBuildTrees, _KeyStrength, OverlapAction, _DisplayKey
from ._artifact import Artifact
from ._elementproxy import ElementProxy
from ._elementsources import ElementSources
Expand DownExpand Up@@ -604,7 +604,7 @@ def stage_artifact(
sandbox: "Sandbox",
*,
path: Optional[str] = None,
action: str = OverlapAction.WARNING,
action: OverlapAction = OverlapAction.WARNING,
include: Optional[List[str]] = None,
exclude: Optional[List[str]] = None,
orphans: bool = True,
Expand DownExpand Up@@ -664,7 +664,7 @@ def stage_dependency_artifacts(
selection: Optional[Sequence["Element"]] = None,
*,
path: Optional[str] = None,
action: str = OverlapAction.WARNING,
action: OverlapAction = OverlapAction.WARNING,
include: Optional[List[str]] = None,
exclude: Optional[List[str]] = None,
orphans: bool = True,
Expand DownExpand Up@@ -864,7 +864,7 @@ def subsandbox(self, sandbox: "Sandbox") -> Iterator["Sandbox"]:
# Yields:
# (Element): The dependencies in `scope`, in deterministic staging order
#
def _dependencies(self, scope, *, recurse=True, visited=None):
def _dependencies(self, scope: _Scope, *, recurse=True, visited=None):

# The format of visited is (BitMap(), BitMap()), with the first BitMap
# containing element that have been visited for the `_Scope.BUILD` case
Expand DownExpand Up@@ -971,7 +971,7 @@ def _stage_artifact(
sandbox: "Sandbox",
*,
path: Optional[str] = None,
action: str = OverlapAction.WARNING,
action: OverlapAction = OverlapAction.WARNING,
include: Optional[List[str]] = None,
exclude: Optional[List[str]] = None,
orphans: bool = True,
Expand DownExpand Up@@ -2060,7 +2060,16 @@ def _push(self):
# usebuildtree (bool): Use the buildtree as its source
#
# Returns: Exit code
def _shell(self, scope=None, *, mounts=None, isolate=False, prompt=None, command=None, usebuildtree=False):
def _shell(
self,
scope: _Scope | None = None,
*,
mounts: List[_HostMount] | None = None,
isolate: bool = False,
prompt: str | None = None,
command: List[str] | None = None,
usebuildtree: bool = False,
):

with self._prepare_sandbox(scope, shell=True, usebuildtree=usebuildtree) as sandbox:
environment = sandbox._get_configured_environment() or self.get_environment()
Expand Down
8 changes: 5 additions & 3 deletions src/buildstream/types.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -35,6 +35,9 @@ class FastEnum(metaclass=MetaFastEnum):

:class:`enum.Enum` attributes accesses can be really slow, and slow down the execution noticeably.
This reimplementation doesn't suffer the same problems, but also does not reimplement everything.

For mypy Enum static type checking support, all FastEnum should be stubbed as inheriting from enum.Enum.
Use `stubgen src/buildstream/types.py --include-docstrings` to generate the stubs, add `from enum import Enum` and replace all `(FastEnum)` with `(Enum)`
"""

name = None
Expand All@@ -61,7 +64,7 @@ def __new__(cls, value):
try:
return cls._value_to_entry[value]
except KeyError:
if type(value) is cls: # pylint: disable=unidiomatic-typecheck
if isinstance(value, cls): # pylint: disable=unidiomatic-typecheck

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AFAICT your are now doing this right.

https://pylint.pycqa.org/en/latest/user_guide/messages/convention/unidiomatic-typecheck.html

Suggested change
ifisinstance(value, cls):# pylint: disable=unidiomatic-typecheck
ifisinstance(value, cls):

So you dont need to disable the lint.

return value
raise ValueError("Unknown enum value: {}".format(value))

Expand DownExpand Up@@ -169,7 +172,6 @@ class OverlapAction(FastEnum):
# Defines the scope of dependencies to include for a given element
# when iterating over the dependency graph in APIs like
# Element._dependencies().
#
class _Scope(FastEnum):

# All elements which the given element depends on, following
Expand DownExpand Up@@ -384,7 +386,7 @@ def new_from_node(cls, node: MappingNode) -> "_SourceMirror":
alias_node: MappingNode = node.get_mapping("aliases")

for alias, uris in alias_node.items():
assert type(uris) is SequenceNode # pylint: disable=unidiomatic-typecheck
assert isinstance(uris, SequenceNode) # pylint: disable=unidiomatic-typecheck
aliases[alias] = uris.as_str_list()

return cls(name, aliases)
Expand Down
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
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
9 changes: 9 additions & 0 deletions doc/source/hacking/using_the_testsuite.rst
Original file line numberDiff line numberDiff line change
Expand Up@@ -190,13 +190,22 @@ consists of running the ``pylint`` tool, run the following::

.. _contributing_formatting_code:

Running Static Type Checkers
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Static Type Checking is performed separately from testing. In order to run the static type checking step which
consists of running the ``mypy`` tool, run the following::

tox -e mypy

Formatting code
~~~~~~~~~~~~~~~
Similar to linting, code formatting is also done via a ``tox`` environment. To
format the code using the ``black`` tool, run the following::

tox -e format

In CI `tox -e format-check` is used to ensure formatting has been run.

Observing coverage
~~~~~~~~~~~~~~~~~~
Once you have run the tests using `tox` (or `detox`), some coverage reports will
Expand Down
6 changes: 3 additions & 3 deletions src/buildstream/_elementproxy.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -95,7 +95,7 @@ def stage_artifact(
sandbox: "Sandbox",
*,
path: Optional[str] = None,
action: str = OverlapAction.WARNING,
action: OverlapAction = OverlapAction.WARNING,
include: Optional[List[str]] = None,
exclude: Optional[List[str]] = None,
orphans: bool = True
Expand All@@ -120,7 +120,7 @@ def stage_dependency_artifacts(
selection: Optional[Sequence["Element"]] = None,
*,
path: Optional[str] = None,
action: str = OverlapAction.WARNING,
action: OverlapAction = OverlapAction.WARNING,
include: Optional[List[str]] = None,
exclude: Optional[List[str]] = None,
orphans: bool = True
Expand DownExpand Up@@ -168,7 +168,7 @@ def _stage_artifact(
sandbox: "Sandbox",
*,
path: Optional[str] = None,
action: str = OverlapAction.WARNING,
action: OverlapAction = OverlapAction.WARNING,
include: Optional[List[str]] = None,
exclude: Optional[List[str]] = None,
orphans: bool = True,
Expand Down
6 changes: 3 additions & 3 deletions src/buildstream/_overlapcollector.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -66,7 +66,7 @@ def __init__(self, element: "Element"):
# location (str): The Sandbox relative location this session was created for
#
@contextmanager
def session(self, action: str, location: Optional[str]):
def session(self, action: OverlapAction, location: Optional[str]):
assert self._session is None, "Stage session already started"

if location is None:
Expand DownExpand Up@@ -108,13 +108,13 @@ def collect_stage_result(self, element: "Element", result: FileListResult):
# location (str): The Sandbox relative location this session was created for
#
class OverlapCollectorSession:
def __init__(self, element: "Element", action: str, location: str):
def __init__(self, element: "Element", action: OverlapAction, location: str):

# The Element we are staging for, on which we'll issue warnings
self._element = element # type: Element

# The OverlapAction for this session
self._action = action # type: str
self._action = action # type: OverlapAction

# The Sandbox relative directory this session was created for
self._location = location # type: str
Expand Down
9 changes: 7 additions & 2 deletions src/buildstream/_pipeline.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -44,7 +44,7 @@
# Yields:
# Elements in the scope of the specified target elements
#
def dependencies(targets: List[Element], scope: int, *, recurse: bool = True) -> Iterator[Element]:
def dependencies(targets: List[Element], scope: _Scope, *, recurse: bool = True) -> Iterator[Element]:
Comment thread
juergbi marked this conversation as resolved.
# Keep track of 'visited' in this scope, so that all targets
# share the same context.
visited = (BitMap(), BitMap())
Expand DownExpand Up@@ -73,7 +73,12 @@ def dependencies(targets: List[Element], scope: int, *, recurse: bool = True) ->
# A list of Elements appropriate for the specified selection mode
#
def get_selection(
context: Context, targets: List[Element], mode: str, *, silent: bool = True, depth_sort: bool = False
context: Context,
targets: List[Element],
mode: _PipelineSelection,
*,
silent: bool = True,
depth_sort: bool = False
) -> List[Element]:
def redirect_and_log() -> List[Element]:
# Redirect and log if permitted
Expand Down
16 changes: 8 additions & 8 deletions src/buildstream/_stream.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -153,7 +153,7 @@ def load_selection(
self,
targets: Iterable[str],
*,
selection: str = _PipelineSelection.NONE,
selection: _PipelineSelection = _PipelineSelection.NONE,
except_targets: Iterable[str] = (),
load_artifacts: bool = False,
connect_artifact_cache: bool = False,
Expand DownExpand Up@@ -259,7 +259,7 @@ def query_cache(self, elements, *, sources_of_cached_elements=False, only_source
def shell(
self,
target: str,
scope: int,
scope: _Scope,
prompt: Callable[[Element], str],
*,
unique_id: Optional[str] = None,
Expand DownExpand Up@@ -382,7 +382,7 @@ def build(
self,
targets: Iterable[str],
*,
selection: str = _PipelineSelection.NONE,
selection: _PipelineSelection = _PipelineSelection.NONE,
ignore_junction_targets: bool = False,
artifact_remotes: Iterable[RemoteSpec] = (),
source_remotes: Iterable[RemoteSpec] = (),
Expand DownExpand Up@@ -456,7 +456,7 @@ def fetch(
self,
targets: Iterable[str],
*,
selection: str = _PipelineSelection.NONE,
selection: _PipelineSelection = _PipelineSelection.NONE,
except_targets: Iterable[str] = (),
source_remotes: Iterable[RemoteSpec] = (),
ignore_project_source_remotes: bool = False,
Expand DownExpand Up@@ -579,7 +579,7 @@ def pull(
self,
targets: Iterable[str],
*,
selection: str = _PipelineSelection.NONE,
selection: _PipelineSelection = _PipelineSelection.NONE,
ignore_junction_targets: bool = False,
artifact_remotes: Iterable[RemoteSpec] = (),
ignore_project_artifact_remotes: bool = False,
Expand DownExpand Up@@ -633,7 +633,7 @@ def push(
self,
targets: Iterable[str],
*,
selection: str = _PipelineSelection.NONE,
selection: _PipelineSelection = _PipelineSelection.NONE,
ignore_junction_targets: bool = False,
artifact_remotes: Iterable[RemoteSpec] = (),
ignore_project_artifact_remotes: bool = False,
Expand DownExpand Up@@ -688,7 +688,7 @@ def checkout(
*,
location: Optional[str] = None,
force: bool = False,
selection: str = _PipelineSelection.RUN,
selection: _PipelineSelection = _PipelineSelection.RUN,
integrate: bool = True,
hardlinks: bool = False,
compression: str = "",
Expand DownExpand Up@@ -1668,7 +1668,7 @@ def _load(
self,
targets: Iterable[str],
*,
selection: str = _PipelineSelection.NONE,
selection: _PipelineSelection = _PipelineSelection.NONE,
except_targets: Iterable[str] = (),
ignore_junction_targets: bool = False,
dynamic_plan: bool = False,
Expand Down
21 changes: 15 additions & 6 deletions src/buildstream/element.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -90,7 +90,7 @@
from .sandbox import _SandboxFlags, SandboxCommandError
from .sandbox._config import SandboxConfig
from .sandbox._sandboxremote import SandboxRemote
from .types import _Scope, _CacheBuildTrees, _KeyStrength, OverlapAction, _DisplayKey
from .types import _HostMount, _Scope, _CacheBuildTrees, _KeyStrength, OverlapAction, _DisplayKey
from ._artifact import Artifact
from ._elementproxy import ElementProxy
from ._elementsources import ElementSources
Expand DownExpand Up@@ -604,7 +604,7 @@ def stage_artifact(
sandbox: "Sandbox",
*,
path: Optional[str] = None,
action: str = OverlapAction.WARNING,
action: OverlapAction = OverlapAction.WARNING,
include: Optional[List[str]] = None,
exclude: Optional[List[str]] = None,
orphans: bool = True,
Expand DownExpand Up@@ -664,7 +664,7 @@ def stage_dependency_artifacts(
selection: Optional[Sequence["Element"]] = None,
*,
path: Optional[str] = None,
action: str = OverlapAction.WARNING,
action: OverlapAction = OverlapAction.WARNING,
include: Optional[List[str]] = None,
exclude: Optional[List[str]] = None,
orphans: bool = True,
Expand DownExpand Up@@ -864,7 +864,7 @@ def subsandbox(self, sandbox: "Sandbox") -> Iterator["Sandbox"]:
# Yields:
# (Element): The dependencies in `scope`, in deterministic staging order
#
def _dependencies(self, scope, *, recurse=True, visited=None):
def _dependencies(self, scope: _Scope, *, recurse=True, visited=None):

# The format of visited is (BitMap(), BitMap()), with the first BitMap
# containing element that have been visited for the `_Scope.BUILD` case
Expand DownExpand Up@@ -971,7 +971,7 @@ def _stage_artifact(
sandbox: "Sandbox",
*,
path: Optional[str] = None,
action: str = OverlapAction.WARNING,
action: OverlapAction = OverlapAction.WARNING,
include: Optional[List[str]] = None,
exclude: Optional[List[str]] = None,
orphans: bool = True,
Expand DownExpand Up@@ -2060,7 +2060,16 @@ def _push(self):
# usebuildtree (bool): Use the buildtree as its source
#
# Returns: Exit code
def _shell(self, scope=None, *, mounts=None, isolate=False, prompt=None, command=None, usebuildtree=False):
def _shell(
self,
scope: _Scope | None = None,
*,
mounts: List[_HostMount] | None = None,
isolate: bool = False,
prompt: str | None = None,
command: List[str] | None = None,
usebuildtree: bool = False,
):

with self._prepare_sandbox(scope, shell=True, usebuildtree=usebuildtree) as sandbox:
environment = sandbox._get_configured_environment() or self.get_environment()
Expand Down
8 changes: 5 additions & 3 deletions src/buildstream/types.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -35,6 +35,9 @@ class FastEnum(metaclass=MetaFastEnum):

:class:`enum.Enum` attributes accesses can be really slow, and slow down the execution noticeably.
This reimplementation doesn't suffer the same problems, but also does not reimplement everything.

For mypy Enum static type checking support, all FastEnum should be stubbed as inheriting from enum.Enum.
Use `stubgen src/buildstream/types.py --include-docstrings` to generate the stubs, add `from enum import Enum` and replace all `(FastEnum)` with `(Enum)`
"""

name = None
Expand All@@ -61,7 +64,7 @@ def __new__(cls, value):
try:
return cls._value_to_entry[value]
except KeyError:
if type(value) is cls: # pylint: disable=unidiomatic-typecheck
if isinstance(value, cls): # pylint: disable=unidiomatic-typecheck

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AFAICT your are now doing this right.

https://pylint.pycqa.org/en/latest/user_guide/messages/convention/unidiomatic-typecheck.html

Suggested change
ifisinstance(value, cls):# pylint: disable=unidiomatic-typecheck
ifisinstance(value, cls):

So you dont need to disable the lint.

return value
raise ValueError("Unknown enum value: {}".format(value))

Expand DownExpand Up@@ -169,7 +172,6 @@ class OverlapAction(FastEnum):
# Defines the scope of dependencies to include for a given element
# when iterating over the dependency graph in APIs like
# Element._dependencies().
#
class _Scope(FastEnum):

# All elements which the given element depends on, following
Expand DownExpand Up@@ -384,7 +386,7 @@ def new_from_node(cls, node: MappingNode) -> "_SourceMirror":
alias_node: MappingNode = node.get_mapping("aliases")

for alias, uris in alias_node.items():
assert type(uris) is SequenceNode # pylint: disable=unidiomatic-typecheck
assert isinstance(uris, SequenceNode) # pylint: disable=unidiomatic-typecheck
aliases[alias] = uris.as_str_list()

return cls(name, aliases)
Expand Down
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content
Merged
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
9 changes: 9 additions & 0 deletions doc/source/hacking/using_the_testsuite.rst
Original file line numberDiff line numberDiff line change
Expand Up@@ -190,13 +190,22 @@ consists of running the ``pylint`` tool, run the following::

.. _contributing_formatting_code:

Running Static Type Checkers
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Static Type Checking is performed separately from testing. In order to run the static type checking step which
consists of running the ``mypy`` tool, run the following::

tox -e mypy

Formatting code
~~~~~~~~~~~~~~~
Similar to linting, code formatting is also done via a ``tox`` environment. To
format the code using the ``black`` tool, run the following::

tox -e format

In CI `tox -e format-check` is used to ensure formatting has been run.

Observing coverage
~~~~~~~~~~~~~~~~~~
Once you have run the tests using `tox` (or `detox`), some coverage reports will
Expand Down
6 changes: 3 additions & 3 deletions src/buildstream/_elementproxy.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -95,7 +95,7 @@ def stage_artifact(
sandbox: "Sandbox",
*,
path: Optional[str] = None,
action: str = OverlapAction.WARNING,
action: OverlapAction = OverlapAction.WARNING,
include: Optional[List[str]] = None,
exclude: Optional[List[str]] = None,
orphans: bool = True
Expand All@@ -120,7 +120,7 @@ def stage_dependency_artifacts(
selection: Optional[Sequence["Element"]] = None,
*,
path: Optional[str] = None,
action: str = OverlapAction.WARNING,
action: OverlapAction = OverlapAction.WARNING,
include: Optional[List[str]] = None,
exclude: Optional[List[str]] = None,
orphans: bool = True
Expand DownExpand Up@@ -168,7 +168,7 @@ def _stage_artifact(
sandbox: "Sandbox",
*,
path: Optional[str] = None,
action: str = OverlapAction.WARNING,
action: OverlapAction = OverlapAction.WARNING,
include: Optional[List[str]] = None,
exclude: Optional[List[str]] = None,
orphans: bool = True,
Expand Down
6 changes: 3 additions & 3 deletions src/buildstream/_overlapcollector.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -66,7 +66,7 @@ def __init__(self, element: "Element"):
# location (str): The Sandbox relative location this session was created for
#
@contextmanager
def session(self, action: str, location: Optional[str]):
def session(self, action: OverlapAction, location: Optional[str]):
assert self._session is None, "Stage session already started"

if location is None:
Expand DownExpand Up@@ -108,13 +108,13 @@ def collect_stage_result(self, element: "Element", result: FileListResult):
# location (str): The Sandbox relative location this session was created for
#
class OverlapCollectorSession:
def __init__(self, element: "Element", action: str, location: str):
def __init__(self, element: "Element", action: OverlapAction, location: str):

# The Element we are staging for, on which we'll issue warnings
self._element = element # type: Element

# The OverlapAction for this session
self._action = action # type: str
self._action = action # type: OverlapAction

# The Sandbox relative directory this session was created for
self._location = location # type: str
Expand Down
9 changes: 7 additions & 2 deletions src/buildstream/_pipeline.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -44,7 +44,7 @@
# Yields:
# Elements in the scope of the specified target elements
#
def dependencies(targets: List[Element], scope: int, *, recurse: bool = True) -> Iterator[Element]:
def dependencies(targets: List[Element], scope: _Scope, *, recurse: bool = True) -> Iterator[Element]:
Comment thread
juergbi marked this conversation as resolved.
# Keep track of 'visited' in this scope, so that all targets
# share the same context.
visited = (BitMap(), BitMap())
Expand DownExpand Up@@ -73,7 +73,12 @@ def dependencies(targets: List[Element], scope: int, *, recurse: bool = True) ->
# A list of Elements appropriate for the specified selection mode
#
def get_selection(
context: Context, targets: List[Element], mode: str, *, silent: bool = True, depth_sort: bool = False
context: Context,
targets: List[Element],
mode: _PipelineSelection,
*,
silent: bool = True,
depth_sort: bool = False
) -> List[Element]:
def redirect_and_log() -> List[Element]:
# Redirect and log if permitted
Expand Down
16 changes: 8 additions & 8 deletions src/buildstream/_stream.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -153,7 +153,7 @@ def load_selection(
self,
targets: Iterable[str],
*,
selection: str = _PipelineSelection.NONE,
selection: _PipelineSelection = _PipelineSelection.NONE,
except_targets: Iterable[str] = (),
load_artifacts: bool = False,
connect_artifact_cache: bool = False,
Expand DownExpand Up@@ -259,7 +259,7 @@ def query_cache(self, elements, *, sources_of_cached_elements=False, only_source
def shell(
self,
target: str,
scope: int,
scope: _Scope,
prompt: Callable[[Element], str],
*,
unique_id: Optional[str] = None,
Expand DownExpand Up@@ -382,7 +382,7 @@ def build(
self,
targets: Iterable[str],
*,
selection: str = _PipelineSelection.NONE,
selection: _PipelineSelection = _PipelineSelection.NONE,
ignore_junction_targets: bool = False,
artifact_remotes: Iterable[RemoteSpec] = (),
source_remotes: Iterable[RemoteSpec] = (),
Expand DownExpand Up@@ -456,7 +456,7 @@ def fetch(
self,
targets: Iterable[str],
*,
selection: str = _PipelineSelection.NONE,
selection: _PipelineSelection = _PipelineSelection.NONE,
except_targets: Iterable[str] = (),
source_remotes: Iterable[RemoteSpec] = (),
ignore_project_source_remotes: bool = False,
Expand DownExpand Up@@ -579,7 +579,7 @@ def pull(
self,
targets: Iterable[str],
*,
selection: str = _PipelineSelection.NONE,
selection: _PipelineSelection = _PipelineSelection.NONE,
ignore_junction_targets: bool = False,
artifact_remotes: Iterable[RemoteSpec] = (),
ignore_project_artifact_remotes: bool = False,
Expand DownExpand Up@@ -633,7 +633,7 @@ def push(
self,
targets: Iterable[str],
*,
selection: str = _PipelineSelection.NONE,
selection: _PipelineSelection = _PipelineSelection.NONE,
ignore_junction_targets: bool = False,
artifact_remotes: Iterable[RemoteSpec] = (),
ignore_project_artifact_remotes: bool = False,
Expand DownExpand Up@@ -688,7 +688,7 @@ def checkout(
*,
location: Optional[str] = None,
force: bool = False,
selection: str = _PipelineSelection.RUN,
selection: _PipelineSelection = _PipelineSelection.RUN,
integrate: bool = True,
hardlinks: bool = False,
compression: str = "",
Expand DownExpand Up@@ -1668,7 +1668,7 @@ def _load(
self,
targets: Iterable[str],
*,
selection: str = _PipelineSelection.NONE,
selection: _PipelineSelection = _PipelineSelection.NONE,
except_targets: Iterable[str] = (),
ignore_junction_targets: bool = False,
dynamic_plan: bool = False,
Expand Down
21 changes: 15 additions & 6 deletions src/buildstream/element.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -90,7 +90,7 @@
from .sandbox import _SandboxFlags, SandboxCommandError
from .sandbox._config import SandboxConfig
from .sandbox._sandboxremote import SandboxRemote
from .types import _Scope, _CacheBuildTrees, _KeyStrength, OverlapAction, _DisplayKey
from .types import _HostMount, _Scope, _CacheBuildTrees, _KeyStrength, OverlapAction, _DisplayKey
from ._artifact import Artifact
from ._elementproxy import ElementProxy
from ._elementsources import ElementSources
Expand DownExpand Up@@ -604,7 +604,7 @@ def stage_artifact(
sandbox: "Sandbox",
*,
path: Optional[str] = None,
action: str = OverlapAction.WARNING,
action: OverlapAction = OverlapAction.WARNING,
include: Optional[List[str]] = None,
exclude: Optional[List[str]] = None,
orphans: bool = True,
Expand DownExpand Up@@ -664,7 +664,7 @@ def stage_dependency_artifacts(
selection: Optional[Sequence["Element"]] = None,
*,
path: Optional[str] = None,
action: str = OverlapAction.WARNING,
action: OverlapAction = OverlapAction.WARNING,
include: Optional[List[str]] = None,
exclude: Optional[List[str]] = None,
orphans: bool = True,
Expand DownExpand Up@@ -864,7 +864,7 @@ def subsandbox(self, sandbox: "Sandbox") -> Iterator["Sandbox"]:
# Yields:
# (Element): The dependencies in `scope`, in deterministic staging order
#
def _dependencies(self, scope, *, recurse=True, visited=None):
def _dependencies(self, scope: _Scope, *, recurse=True, visited=None):

# The format of visited is (BitMap(), BitMap()), with the first BitMap
# containing element that have been visited for the `_Scope.BUILD` case
Expand DownExpand Up@@ -971,7 +971,7 @@ def _stage_artifact(
sandbox: "Sandbox",
*,
path: Optional[str] = None,
action: str = OverlapAction.WARNING,
action: OverlapAction = OverlapAction.WARNING,
include: Optional[List[str]] = None,
exclude: Optional[List[str]] = None,
orphans: bool = True,
Expand DownExpand Up@@ -2060,7 +2060,16 @@ def _push(self):
# usebuildtree (bool): Use the buildtree as its source
#
# Returns: Exit code
def _shell(self, scope=None, *, mounts=None, isolate=False, prompt=None, command=None, usebuildtree=False):
def _shell(
self,
scope: _Scope | None = None,
*,
mounts: List[_HostMount] | None = None,
isolate: bool = False,
prompt: str | None = None,
command: List[str] | None = None,
usebuildtree: bool = False,
):

with self._prepare_sandbox(scope, shell=True, usebuildtree=usebuildtree) as sandbox:
environment = sandbox._get_configured_environment() or self.get_environment()
Expand Down
8 changes: 5 additions & 3 deletions src/buildstream/types.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -35,6 +35,9 @@ class FastEnum(metaclass=MetaFastEnum):

:class:`enum.Enum` attributes accesses can be really slow, and slow down the execution noticeably.
This reimplementation doesn't suffer the same problems, but also does not reimplement everything.

For mypy Enum static type checking support, all FastEnum should be stubbed as inheriting from enum.Enum.
Use `stubgen src/buildstream/types.py --include-docstrings` to generate the stubs, add `from enum import Enum` and replace all `(FastEnum)` with `(Enum)`
"""

name = None
Expand All@@ -61,7 +64,7 @@ def __new__(cls, value):
try:
return cls._value_to_entry[value]
except KeyError:
if type(value) is cls: # pylint: disable=unidiomatic-typecheck
if isinstance(value, cls): # pylint: disable=unidiomatic-typecheck

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AFAICT your are now doing this right.

https://pylint.pycqa.org/en/latest/user_guide/messages/convention/unidiomatic-typecheck.html

Suggested change
ifisinstance(value, cls):# pylint: disable=unidiomatic-typecheck
ifisinstance(value, cls):

So you dont need to disable the lint.

return value
raise ValueError("Unknown enum value: {}".format(value))

Expand DownExpand Up@@ -169,7 +172,6 @@ class OverlapAction(FastEnum):
# Defines the scope of dependencies to include for a given element
# when iterating over the dependency graph in APIs like
# Element._dependencies().
#
class _Scope(FastEnum):

# All elements which the given element depends on, following
Expand DownExpand Up@@ -384,7 +386,7 @@ def new_from_node(cls, node: MappingNode) -> "_SourceMirror":
alias_node: MappingNode = node.get_mapping("aliases")

for alias, uris in alias_node.items():
assert type(uris) is SequenceNode # pylint: disable=unidiomatic-typecheck
assert isinstance(uris, SequenceNode) # pylint: disable=unidiomatic-typecheck
aliases[alias] = uris.as_str_list()

return cls(name, aliases)
Expand Down
Loading
Loading