aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Niklas Hasse <jhasse@bixense.com>2024-04-09 17:57:03 +0200
committerGitHub <noreply@github.com>2024-04-09 17:57:03 +0200
commit4afe2a62103a401b38c8fc64a4190d21c5ec8ae0 (patch)
tree2b7eb9edbc6fca14f0f37172396094fee6775a1a
parentd7bb3f397db674396eae37ee49173d7eaaf216ab (diff)
parent9cabe6a3f3e69ea7ef3665c97e46d4f14433f7d8 (diff)
downloadninja-4afe2a62103a401b38c8fc64a4190d21c5ec8ae0.tar.gz
Merge pull request #2407 from Repiteo/type-hints
Implement type hints in `ninja_syntax.py`
-rw-r--r--misc/ninja_syntax.py74
1 files changed, 53 insertions, 21 deletions
diff --git a/misc/ninja_syntax.py b/misc/ninja_syntax.py
index ca73b5b..2aa8456 100644
--- a/misc/ninja_syntax.py
+++ b/misc/ninja_syntax.py
@@ -23,37 +23,54 @@ use Python.
import re
import textwrap
+from io import TextIOWrapper
+from typing import Dict, List, Match, Optional, Tuple, Union
-def escape_path(word):
+def escape_path(word: str) -> str:
return word.replace('$ ', '$$ ').replace(' ', '$ ').replace(':', '$:')
class Writer(object):
- def __init__(self, output, width=78):
+ def __init__(self, output: TextIOWrapper, width: int = 78) -> None:
self.output = output
self.width = width
- def newline(self):
+ def newline(self) -> None:
self.output.write('\n')
- def comment(self, text):
+ def comment(self, text: str) -> None:
for line in textwrap.wrap(text, self.width - 2, break_long_words=False,
break_on_hyphens=False):
self.output.write('# ' + line + '\n')
- def variable(self, key, value, indent=0):
+ def variable(
+ self,
+ key: str,
+ value: Optional[Union[bool, int, float, str, List[str]]],
+ indent: int = 0,
+ ) -> None:
if value is None:
return
if isinstance(value, list):
value = ' '.join(filter(None, value)) # Filter out empty strings.
self._line('%s = %s' % (key, value), indent)
- def pool(self, name, depth):
+ def pool(self, name: str, depth: int) -> None:
self._line('pool %s' % name)
self.variable('depth', depth, indent=1)
- def rule(self, name, command, description=None, depfile=None,
- generator=False, pool=None, restat=False, rspfile=None,
- rspfile_content=None, deps=None):
+ def rule(
+ self,
+ name: str,
+ command: str,
+ description: Optional[str] = None,
+ depfile: Optional[str] = None,
+ generator: bool = False,
+ pool: Optional[str] = None,
+ restat: bool = False,
+ rspfile: Optional[str] = None,
+ rspfile_content: Optional[str] = None,
+ deps: Optional[Union[str, List[str]]] = None,
+ ) -> None:
self._line('rule %s' % name)
self.variable('command', command, indent=1)
if description:
@@ -73,8 +90,23 @@ class Writer(object):
if deps:
self.variable('deps', deps, indent=1)
- def build(self, outputs, rule, inputs=None, implicit=None, order_only=None,
- variables=None, implicit_outputs=None, pool=None, dyndep=None):
+ def build(
+ self,
+ outputs: Union[str, List[str]],
+ rule: str,
+ inputs: Optional[Union[str, List[str]]] = None,
+ implicit: Optional[Union[str, List[str]]] = None,
+ order_only: Optional[Union[str, List[str]]] = None,
+ variables: Optional[
+ Union[
+ List[Tuple[str, Optional[Union[str, List[str]]]]],
+ Dict[str, Optional[Union[str, List[str]]]],
+ ]
+ ] = None,
+ implicit_outputs: Optional[Union[str, List[str]]] = None,
+ pool: Optional[str] = None,
+ dyndep: Optional[str] = None,
+ ) -> List[str]:
outputs = as_list(outputs)
out_outputs = [escape_path(x) for x in outputs]
all_inputs = [escape_path(x) for x in as_list(inputs)]
@@ -111,16 +143,16 @@ class Writer(object):
return outputs
- def include(self, path):
+ def include(self, path: str) -> None:
self._line('include %s' % path)
- def subninja(self, path):
+ def subninja(self, path: str) -> None:
self._line('subninja %s' % path)
- def default(self, paths):
+ def default(self, paths: Union[str, List[str]]) -> None:
self._line('default %s' % ' '.join(as_list(paths)))
- def _count_dollars_before_index(self, s, i):
+ def _count_dollars_before_index(self, s: str, i: int) -> int:
"""Returns the number of '$' characters right in front of s[i]."""
dollar_count = 0
dollar_index = i - 1
@@ -129,7 +161,7 @@ class Writer(object):
dollar_index -= 1
return dollar_count
- def _line(self, text, indent=0):
+ def _line(self, text: str, indent: int = 0) -> None:
"""Write 'text' word-wrapped at self.width characters."""
leading_space = ' ' * indent
while len(leading_space) + len(text) > self.width:
@@ -165,11 +197,11 @@ class Writer(object):
self.output.write(leading_space + text + '\n')
- def close(self):
+ def close(self) -> None:
self.output.close()
-def as_list(input):
+def as_list(input: Optional[Union[str, List[str]]]) -> List[str]:
if input is None:
return []
if isinstance(input, list):
@@ -177,7 +209,7 @@ def as_list(input):
return [input]
-def escape(string):
+def escape(string: str) -> str:
"""Escape a string such that it can be embedded into a Ninja file without
further interpretation."""
assert '\n' not in string, 'Ninja syntax does not allow newlines'
@@ -185,13 +217,13 @@ def escape(string):
return string.replace('$', '$$')
-def expand(string, vars, local_vars={}):
+def expand(string: str, vars: Dict[str, str], local_vars: Dict[str, str] = {}) -> str:
"""Expand a string containing $vars as Ninja would.
Note: doesn't handle the full Ninja variable syntax, but it's enough
to make configure.py's use of it work.
"""
- def exp(m):
+ def exp(m: Match[str]) -> str:
var = m.group(1)
if var == '$':
return '$'