aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDylan Baker <dylan@pnwbakers.com>2019-04-22 14:26:18 -0700
committerJussi Pakkanen <jpakkane@gmail.com>2019-04-23 02:03:19 +0300
commitadd821db64b3c1fd7568736aaa67de53ad382eb4 (patch)
treee27276655f7e251706552e9093f86b49a1b5b6d6
parent0259cc6de21c223f1f38f0a6d118779f455b881f (diff)
downloadmeson-add821db64b3c1fd7568736aaa67de53ad382eb4.zip
meson-add821db64b3c1fd7568736aaa67de53ad382eb4.tar.gz
meson-add821db64b3c1fd7568736aaa67de53ad382eb4.tar.bz2
Don't use mutable types as default arguments
This isn't safe given the way python implements default arguments. Basically python store a reference to the instance it was passed, and then if that argument is not provided it uses the default. That means that two calls to the same function get the same instance, if one of them mutates that instance every subsequent call that gets the default will receive the mutated instance. The idiom to this in python is to use None and replace the None, def in(value: str, container: Optional[List[str]]) -> boolean: return src in (container or []) if there is no chance of mutation it's less code to use or and take advantage of None being falsy. If you may want to mutate the value passed in you need a ternary (this example is stupid): def add(value: str, container: Optional[List[str]]) -> None: container = container if container is not None else [] container.append(value) I've used or everywhere I'm sure that the value will not be mutated by the function and erred toward caution by using ternaries for the rest.
-rw-r--r--mesonbuild/ast/interpreter.py6
-rw-r--r--mesonbuild/ast/introspection.py3
-rw-r--r--mesonbuild/backend/ninjabackend.py12
-rw-r--r--mesonbuild/build.py16
-rw-r--r--mesonbuild/interpreter.py4
-rw-r--r--mesonbuild/mesonmain.py3
-rwxr-xr-xrun_unittests.py3
7 files changed, 28 insertions, 19 deletions
diff --git a/mesonbuild/ast/interpreter.py b/mesonbuild/ast/interpreter.py
index a82ba5d..a75c0b7 100644
--- a/mesonbuild/ast/interpreter.py
+++ b/mesonbuild/ast/interpreter.py
@@ -22,7 +22,7 @@ from .. import environment
from ..interpreterbase import InvalidArguments, BreakRequest, ContinueRequest
import os, sys
-from typing import List
+from typing import List, Optional
class DontCareObject(interpreterbase.InterpreterObject):
pass
@@ -46,9 +46,9 @@ ADD_SOURCE = 0
REMOVE_SOURCE = 1
class AstInterpreter(interpreterbase.InterpreterBase):
- def __init__(self, source_root: str, subdir: str, visitors: List[AstVisitor] = []):
+ def __init__(self, source_root: str, subdir: str, visitors: Optional[List[AstVisitor]] = None):
super().__init__(source_root, subdir)
- self.visitors = visitors
+ self.visitors = visitors if visitors is not None else []
self.visited_subdirs = {}
self.assignments = {}
self.assign_vals = {}
diff --git a/mesonbuild/ast/introspection.py b/mesonbuild/ast/introspection.py
index 5a12e29..f8fb2e8 100644
--- a/mesonbuild/ast/introspection.py
+++ b/mesonbuild/ast/introspection.py
@@ -35,7 +35,8 @@ class IntrospectionHelper:
class IntrospectionInterpreter(AstInterpreter):
# Interpreter to detect the options without a build directory
# Most of the code is stolen from interperter.Interpreter
- def __init__(self, source_root, subdir, backend, visitors=[], cross_file=None, subproject='', subproject_dir='subprojects', env=None):
+ def __init__(self, source_root, subdir, backend, visitors=None, cross_file=None, subproject='', subproject_dir='subprojects', env=None):
+ visitors = visitors if visitors is not None else []
super().__init__(source_root, subdir, visitors=visitors)
options = IntrospectionHelper(cross_file)
diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py
index 08b14c8..8edaeec 100644
--- a/mesonbuild/backend/ninjabackend.py
+++ b/mesonbuild/backend/ninjabackend.py
@@ -2098,10 +2098,13 @@ rule FORTRAN_DEP_HACK%s
commands += compiler.get_include_args(self.get_target_private_dir(target), False)
return commands
- def generate_single_compile(self, target, outfile, src, is_generated=False, header_deps=[], order_deps=[]):
+ def generate_single_compile(self, target, outfile, src, is_generated=False, header_deps=None, order_deps=None):
"""
Compiles C/C++, ObjC/ObjC++, Fortran, and D sources
"""
+ header_deps = header_deps if header_deps is not None else []
+ order_deps = order_deps if order_deps is not None else []
+
if isinstance(src, str) and src.endswith('.h'):
raise AssertionError('BUG: sources should not contain headers {!r}'.format(src))
@@ -2256,7 +2259,8 @@ rule FORTRAN_DEP_HACK%s
dep = dst + '.' + compiler.get_depfile_suffix()
return commands, dep, dst, [] # Gcc does not create an object file during pch generation.
- def generate_pch(self, target, outfile, header_deps=[]):
+ def generate_pch(self, target, outfile, header_deps=None):
+ header_deps = header_deps if header_deps is not None else []
cstr = ''
pch_objects = []
if target.is_cross:
@@ -2435,7 +2439,9 @@ rule FORTRAN_DEP_HACK%s
return guessed_dependencies + absolute_libs
- def generate_link(self, target, outfile, outname, obj_list, linker, extra_args=[], stdlib_args=[]):
+ def generate_link(self, target, outfile, outname, obj_list, linker, extra_args=None, stdlib_args=None):
+ extra_args = extra_args if extra_args is not None else []
+ stdlib_args = stdlib_args if stdlib_args is not None else []
if isinstance(target, build.StaticLibrary):
linker_base = 'STATIC'
else:
diff --git a/mesonbuild/build.py b/mesonbuild/build.py
index 66f08d8..5248d97 100644
--- a/mesonbuild/build.py
+++ b/mesonbuild/build.py
@@ -249,12 +249,12 @@ class ExtractedObjects:
'''
Holds a list of sources for which the objects must be extracted
'''
- def __init__(self, target, srclist=[], genlist=[], objlist=[], recursive=True):
+ def __init__(self, target, srclist=None, genlist=None, objlist=None, recursive=True):
self.target = target
self.recursive = recursive
- self.srclist = srclist
- self.genlist = genlist
- self.objlist = objlist
+ self.srclist = srclist if srclist is not None else []
+ self.genlist = genlist if genlist is not None else []
+ self.objlist = objlist if objlist is not None else []
if self.target.is_unity:
self.check_unity_compatible()
@@ -1339,8 +1339,8 @@ class Generator:
relpath = pathlib.PurePath(trial).relative_to(parent)
return relpath.parts[0] != '..' # For subdirs we can only go "down".
- def process_files(self, name, files, state, preserve_path_from=None, extra_args=[]):
- output = GeneratedList(self, state.subdir, preserve_path_from, extra_args=extra_args)
+ def process_files(self, name, files, state, preserve_path_from=None, extra_args=None):
+ output = GeneratedList(self, state.subdir, preserve_path_from, extra_args=extra_args if extra_args is not None else [])
for f in files:
if isinstance(f, str):
f = File.from_source_file(state.environment.source_dir, state.subdir, f)
@@ -1355,7 +1355,7 @@ class Generator:
class GeneratedList:
- def __init__(self, generator, subdir, preserve_path_from=None, extra_args=[]):
+ def __init__(self, generator, subdir, preserve_path_from=None, extra_args=None):
if hasattr(generator, 'held_object'):
generator = generator.held_object
self.generator = generator
@@ -1367,7 +1367,7 @@ class GeneratedList:
self.extra_depends = []
self.depend_files = []
self.preserve_path_from = preserve_path_from
- self.extra_args = extra_args
+ self.extra_args = extra_args if extra_args is not None else []
if isinstance(generator.exe, dependencies.ExternalProgram):
if not generator.exe.found():
raise InvalidArguments('Tried to use not-found external program as generator')
diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py
index 3a3fb81..b107a25 100644
--- a/mesonbuild/interpreter.py
+++ b/mesonbuild/interpreter.py
@@ -560,10 +560,10 @@ class GeneratorHolder(InterpreterObject, ObjectHolder):
class GeneratedListHolder(InterpreterObject, ObjectHolder):
- def __init__(self, arg1, extra_args=[]):
+ def __init__(self, arg1, extra_args=None):
InterpreterObject.__init__(self)
if isinstance(arg1, GeneratorHolder):
- ObjectHolder.__init__(self, build.GeneratedList(arg1.held_object, extra_args))
+ ObjectHolder.__init__(self, build.GeneratedList(arg1.held_object, extra_args if extra_args is not None else []))
else:
ObjectHolder.__init__(self, arg1)
diff --git a/mesonbuild/mesonmain.py b/mesonbuild/mesonmain.py
index e7005e9..f80dfdd 100644
--- a/mesonbuild/mesonmain.py
+++ b/mesonbuild/mesonmain.py
@@ -67,7 +67,8 @@ class CommandLineParser:
self.add_command('unstable-coredata', munstable_coredata.add_arguments, munstable_coredata.run,
help=argparse.SUPPRESS)
- def add_command(self, name, add_arguments_func, run_func, help, aliases=[]):
+ def add_command(self, name, add_arguments_func, run_func, help, aliases=None):
+ aliases = aliases or []
# FIXME: Cannot have hidden subparser:
# https://bugs.python.org/issue22848
if help == argparse.SUPPRESS:
diff --git a/run_unittests.py b/run_unittests.py
index 4d70d86..d37e805 100755
--- a/run_unittests.py
+++ b/run_unittests.py
@@ -2345,8 +2345,9 @@ int main(int argc, char **argv) {
shared_suffix = 'so'
return (cc, stlinker, object_suffix, shared_suffix)
- def pbcompile(self, compiler, source, objectfile, extra_args=[]):
+ def pbcompile(self, compiler, source, objectfile, extra_args=None):
cmd = compiler.get_exelist()
+ extra_args = extra_args or []
if compiler.get_argument_syntax() == 'msvc':
cmd += ['/nologo', '/Fo' + objectfile, '/c', source] + extra_args
else: