We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
0.60 fails to build GNOME components
Using the new meson 0.60, either from upstream or Debian, GNOME components started to fail to build

Example of the eog snap build
https://launchpadlibrarian.net/565502418/buildlog_snap_ubuntu_focal_amd64_eog_BUILDING.txt.gz
```
Configuring org.gnome.eog.desktop.in using configuration

../src/data/meson.build:25:5: ERROR: Function does not take positional arguments.
```

Trying to build the current eog deb in Ubuntu with the new meson 0.60 deb from Debian unstable leads to a similar error

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `mesonbuild/modules/i18n.py`
Content:
```
1 # Copyright 2016 The Meson development team
2 
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 
7 #     http://www.apache.org/licenses/LICENSE-2.0
8 
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14 
15 from os import path
16 import shutil
17 import typing as T
18 
19 from . import ExtensionModule, ModuleReturnValue
20 from .. import build
21 from .. import mesonlib
22 from .. import mlog
23 from ..interpreter.type_checking import CT_BUILD_BY_DEFAULT, CT_INPUT_KW, CT_INSTALL_DIR_KW, CT_INSTALL_TAG_KW, CT_OUTPUT_KW, INSTALL_KW, NoneType, in_set_validator
24 from ..interpreterbase import FeatureNew
25 from ..interpreterbase.decorators import ContainerTypeInfo, KwargInfo, noPosargs, typed_kwargs, typed_pos_args
26 from ..scripts.gettext import read_linguas
27 
28 if T.TYPE_CHECKING:
29     from typing_extensions import Literal, TypedDict
30 
31     from . import ModuleState
32     from ..build import Target
33     from ..interpreter import Interpreter
34     from ..interpreterbase import TYPE_var
35     from ..programs import ExternalProgram
36 
37     class MergeFile(TypedDict):
38 
39         input: T.List[T.Union[
40             str, build.BuildTarget, build.CustomTarget, build.CustomTargetIndex,
41             build.ExtractedObjects, build.GeneratedList, ExternalProgram,
42             mesonlib.File]]
43         output: T.List[str]
44         build_by_default: bool
45         install: bool
46         install_dir: T.List[T.Union[str, bool]]
47         install_tag: T.List[str]
48         args: T.List[str]
49         data_dirs: T.List[str]
50         po_dir: str
51         type: Literal['xml', 'desktop']
52 
53     class Gettext(TypedDict):
54 
55         args: T.List[str]
56         data_dirs: T.List[str]
57         install: bool
58         install_dir: T.Optional[str]
59         languages: T.List[str]
60         preset: T.Optional[str]
61 
62 
63 _ARGS: KwargInfo[T.List[str]] = KwargInfo(
64     'args',
65     ContainerTypeInfo(list, str),
66     default=[],
67     listify=True,
68 )
69 
70 _DATA_DIRS: KwargInfo[T.List[str]] = KwargInfo(
71     'data_dirs',
72     ContainerTypeInfo(list, str),
73     default=[],
74     listify=True
75 )
76 
77 PRESET_ARGS = {
78     'glib': [
79         '--from-code=UTF-8',
80         '--add-comments',
81 
82         # https://developer.gnome.org/glib/stable/glib-I18N.html
83         '--keyword=_',
84         '--keyword=N_',
85         '--keyword=C_:1c,2',
86         '--keyword=NC_:1c,2',
87         '--keyword=g_dcgettext:2',
88         '--keyword=g_dngettext:2,3',
89         '--keyword=g_dpgettext2:2c,3',
90 
91         '--flag=N_:1:pass-c-format',
92         '--flag=C_:2:pass-c-format',
93         '--flag=NC_:2:pass-c-format',
94         '--flag=g_dngettext:2:pass-c-format',
95         '--flag=g_strdup_printf:1:c-format',
96         '--flag=g_string_printf:2:c-format',
97         '--flag=g_string_append_printf:2:c-format',
98         '--flag=g_error_new:3:c-format',
99         '--flag=g_set_error:4:c-format',
100         '--flag=g_markup_printf_escaped:1:c-format',
101         '--flag=g_log:3:c-format',
102         '--flag=g_print:1:c-format',
103         '--flag=g_printerr:1:c-format',
104         '--flag=g_printf:1:c-format',
105         '--flag=g_fprintf:2:c-format',
106         '--flag=g_sprintf:2:c-format',
107         '--flag=g_snprintf:3:c-format',
108     ]
109 }
110 
111 
112 class I18nModule(ExtensionModule):
113     def __init__(self, interpreter: 'Interpreter'):
114         super().__init__(interpreter)
115         self.methods.update({
116             'merge_file': self.merge_file,
117             'gettext': self.gettext,
118         })
119 
120     @staticmethod
121     def nogettext_warning() -> None:
122         mlog.warning('Gettext not found, all translation targets will be ignored.', once=True)
123 
124     @staticmethod
125     def _get_data_dirs(state: 'ModuleState', dirs: T.Iterable[str]) -> T.List[str]:
126         """Returns source directories of relative paths"""
127         src_dir = path.join(state.environment.get_source_dir(), state.subdir)
128         return [path.join(src_dir, d) for d in dirs]
129 
130     @FeatureNew('i18n.merge_file', '0.37.0')
131     @noPosargs
132     @typed_kwargs(
133         'i18n.merge_file',
134         CT_BUILD_BY_DEFAULT,
135         CT_INPUT_KW,
136         CT_INSTALL_DIR_KW,
137         CT_INSTALL_TAG_KW,
138         CT_OUTPUT_KW,
139         INSTALL_KW,
140         _ARGS.evolve(since='0.51.0'),
141         _DATA_DIRS,
142         KwargInfo('po_dir', str, required=True),
143         KwargInfo('type', str, default='xml', validator=in_set_validator({'xml', 'desktop'})),
144     )
145     def merge_file(self, state: 'ModuleState', args: T.List['TYPE_var'], kwargs: 'MergeFile') -> ModuleReturnValue:
146         if not shutil.which('xgettext'):
147             self.nogettext_warning()
148             return ModuleReturnValue(None, [])
149         podir = path.join(state.build_to_src, state.subdir, kwargs['po_dir'])
150 
151         ddirs = self._get_data_dirs(state, kwargs['data_dirs'])
152         datadirs = '--datadirs=' + ':'.join(ddirs) if ddirs else None
153 
154         command: T.List[T.Union[str, build.BuildTarget, build.CustomTarget,
155                                 build.CustomTargetIndex, 'ExternalProgram', mesonlib.File]] = []
156         command.extend(state.environment.get_build_command())
157         command.extend([
158             '--internal', 'msgfmthelper',
159             '@INPUT@', '@OUTPUT@', kwargs['type'], podir
160         ])
161         if datadirs:
162             command.append(datadirs)
163 
164         if kwargs['args']:
165             command.append('--')
166             command.extend(kwargs['args'])
167 
168         build_by_default = kwargs['build_by_default']
169         if build_by_default is None:
170             build_by_default = kwargs['install']
171 
172         real_kwargs = {
173             'build_by_default': build_by_default,
174             'command': command,
175             'install': kwargs['install'],
176             'install_dir': kwargs['install_dir'],
177             'output': kwargs['output'],
178             'input': kwargs['input'],
179             'install_tag': kwargs['install_tag'],
180         }
181 
182         # We only use this input file to create a name of the custom target.
183         # Thus we can ignore the other entries.
184         inputfile = kwargs['input'][0]
185         if isinstance(inputfile, str):
186             inputfile = mesonlib.File.from_source_file(state.environment.source_dir,
187                                                        state.subdir, inputfile)
188         if isinstance(inputfile, mesonlib.File):
189             # output could be '@BASENAME@' in which case we need to do substitutions
190             # to get a unique target name.
191             outputs = kwargs['output']
192             ifile_abs = inputfile.absolute_path(state.environment.source_dir,
193                                                 state.environment.build_dir)
194             values = mesonlib.get_filenames_templates_dict([ifile_abs], None)
195             outputs = mesonlib.substitute_values(outputs, values)
196             output = outputs[0]
197             ct = build.CustomTarget(
198                 output + '_' + state.subdir.replace('/', '@').replace('\\', '@') + '_merge',
199                 state.subdir, state.subproject, T.cast(T.Dict[str, T.Any], real_kwargs))
200         else:
201             ct = build.CustomTarget(
202                 kwargs['output'][0] + '_merge', state.subdir, state.subproject,
203                 T.cast(T.Dict[str, T.Any], real_kwargs))
204 
205         return ModuleReturnValue(ct, [ct])
206 
207     @typed_pos_args('i81n.gettex', str)
208     @typed_kwargs(
209         'i18n.gettext',
210         _ARGS,
211         _DATA_DIRS,
212         INSTALL_KW.evolve(default=True),
213         KwargInfo('install_dir', (str, NoneType), since='0.50.0'),
214         KwargInfo('languages', ContainerTypeInfo(list, str), default=[], listify=True),
215         KwargInfo(
216             'preset',
217             (str, NoneType),
218             validator=in_set_validator(set(PRESET_ARGS)),
219             since='0.37.0',
220         ),
221     )
222     def gettext(self, state: 'ModuleState', args: T.Tuple[str], kwargs: 'Gettext') -> ModuleReturnValue:
223         if not shutil.which('xgettext'):
224             self.nogettext_warning()
225             return ModuleReturnValue(None, [])
226         packagename = args[0]
227         pkg_arg = f'--pkgname={packagename}'
228 
229         languages = kwargs['languages']
230         lang_arg = '--langs=' + '@@'.join(languages) if languages else None
231 
232         _datadirs = ':'.join(self._get_data_dirs(state, kwargs['data_dirs']))
233         datadirs = f'--datadirs={_datadirs}' if _datadirs else None
234 
235         extra_args = kwargs['args']
236         targets: T.List['Target'] = []
237         gmotargets: T.List['build.CustomTarget'] = []
238 
239         preset = kwargs['preset']
240         if preset:
241             preset_args = PRESET_ARGS[preset]
242             extra_args = list(mesonlib.OrderedSet(preset_args + extra_args))
243 
244         extra_arg = '--extra-args=' + '@@'.join(extra_args) if extra_args else None
245 
246         potargs = state.environment.get_build_command() + ['--internal', 'gettext', 'pot', pkg_arg]
247         if datadirs:
248             potargs.append(datadirs)
249         if extra_arg:
250             potargs.append(extra_arg)
251         pottarget = build.RunTarget(packagename + '-pot', potargs, [], state.subdir, state.subproject)
252         targets.append(pottarget)
253 
254         install = kwargs['install']
255         install_dir = kwargs['install_dir'] or state.environment.coredata.get_option(mesonlib.OptionKey('localedir'))
256         assert isinstance(install_dir, str), 'for mypy'
257         if not languages:
258             languages = read_linguas(path.join(state.environment.source_dir, state.subdir))
259         for l in languages:
260             po_file = mesonlib.File.from_source_file(state.environment.source_dir,
261                                                      state.subdir, l+'.po')
262             gmo_kwargs = {'command': ['msgfmt', '@INPUT@', '-o', '@OUTPUT@'],
263                           'input': po_file,
264                           'output': packagename+'.mo',
265                           'install': install,
266                           # We have multiple files all installed as packagename+'.mo' in different install subdirs.
267                           # What we really wanted to do, probably, is have a rename: kwarg, but that's not available
268                           # to custom_targets. Crude hack: set the build target's subdir manually.
269                           # Bonus: the build tree has something usable as an uninstalled bindtextdomain() target dir.
270                           'install_dir': path.join(install_dir, l, 'LC_MESSAGES'),
271                           'install_tag': 'i18n',
272                           }
273             gmotarget = build.CustomTarget(f'{packagename}-{l}.mo', path.join(state.subdir, l, 'LC_MESSAGES'), state.subproject, gmo_kwargs)
274             targets.append(gmotarget)
275             gmotargets.append(gmotarget)
276 
277         allgmotarget = build.AliasTarget(packagename + '-gmo', gmotargets, state.subdir, state.subproject)
278         targets.append(allgmotarget)
279 
280         updatepoargs = state.environment.get_build_command() + ['--internal', 'gettext', 'update_po', pkg_arg]
281         if lang_arg:
282             updatepoargs.append(lang_arg)
283         if datadirs:
284             updatepoargs.append(datadirs)
285         if extra_arg:
286             updatepoargs.append(extra_arg)
287         updatepotarget = build.RunTarget(packagename + '-update-po', updatepoargs, [], state.subdir, state.subproject)
288         targets.append(updatepotarget)
289 
290         return ModuleReturnValue([gmotargets, pottarget, updatepotarget], targets)
291 
292 def initialize(interp: 'Interpreter') -> I18nModule:
293     return I18nModule(interp)
294
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/mesonbuild/modules/i18n.py b/mesonbuild/modules/i18n.py
--- a/mesonbuild/modules/i18n.py
+++ b/mesonbuild/modules/i18n.py
@@ -22,7 +22,7 @@
 from .. import mlog
 from ..interpreter.type_checking import CT_BUILD_BY_DEFAULT, CT_INPUT_KW, CT_INSTALL_DIR_KW, CT_INSTALL_TAG_KW, CT_OUTPUT_KW, INSTALL_KW, NoneType, in_set_validator
 from ..interpreterbase import FeatureNew
-from ..interpreterbase.decorators import ContainerTypeInfo, KwargInfo, noPosargs, typed_kwargs, typed_pos_args
+from ..interpreterbase.decorators import ContainerTypeInfo, KwargInfo, typed_kwargs, typed_pos_args
 from ..scripts.gettext import read_linguas
 
 if T.TYPE_CHECKING:
@@ -128,7 +128,6 @@
         return [path.join(src_dir, d) for d in dirs]
 
     @FeatureNew('i18n.merge_file', '0.37.0')
-    @noPosargs
     @typed_kwargs(
         'i18n.merge_file',
         CT_BUILD_BY_DEFAULT,
@@ -143,6 +142,9 @@
         KwargInfo('type', str, default='xml', validator=in_set_validator({'xml', 'desktop'})),
     )
     def merge_file(self, state: 'ModuleState', args: T.List['TYPE_var'], kwargs: 'MergeFile') -> ModuleReturnValue:
+        if args:
+            mlog.deprecation('i18n.merge_file does not take any positional arguments. '
+                             'This will become a hard error in the next Meson release.')
         if not shutil.which('xgettext'):
             self.nogettext_warning()
             return ModuleReturnValue(None, [])

{"golden_diff": "diff --git a/mesonbuild/modules/i18n.py b/mesonbuild/modules/i18n.py\n--- a/mesonbuild/modules/i18n.py\n+++ b/mesonbuild/modules/i18n.py\n@@ -22,7 +22,7 @@\n from .. import mlog\n from ..interpreter.type_checking import CT_BUILD_BY_DEFAULT, CT_INPUT_KW, CT_INSTALL_DIR_KW, CT_INSTALL_TAG_KW, CT_OUTPUT_KW, INSTALL_KW, NoneType, in_set_validator\n from ..interpreterbase import FeatureNew\n-from ..interpreterbase.decorators import ContainerTypeInfo, KwargInfo, noPosargs, typed_kwargs, typed_pos_args\n+from ..interpreterbase.decorators import ContainerTypeInfo, KwargInfo, typed_kwargs, typed_pos_args\n from ..scripts.gettext import read_linguas\n \n if T.TYPE_CHECKING:\n@@ -128,7 +128,6 @@\n         return [path.join(src_dir, d) for d in dirs]\n \n     @FeatureNew('i18n.merge_file', '0.37.0')\n-    @noPosargs\n     @typed_kwargs(\n         'i18n.merge_file',\n         CT_BUILD_BY_DEFAULT,\n@@ -143,6 +142,9 @@\n         KwargInfo('type', str, default='xml', validator=in_set_validator({'xml', 'desktop'})),\n     )\n     def merge_file(self, state: 'ModuleState', args: T.List['TYPE_var'], kwargs: 'MergeFile') -> ModuleReturnValue:\n+        if args:\n+            mlog.deprecation('i18n.merge_file does not take any positional arguments. '\n+                             'This will become a hard error in the next Meson release.')\n         if not shutil.which('xgettext'):\n             self.nogettext_warning()\n             return ModuleReturnValue(None, [])\n", "issue": "0.60 fails to build GNOME components\nUsing the new meson 0.60, either from upstream or Debian, GNOME components started to fail to build\r\n\r\nExample of the eog snap build\r\nhttps://launchpadlibrarian.net/565502418/buildlog_snap_ubuntu_focal_amd64_eog_BUILDING.txt.gz\r\n```\r\nConfiguring org.gnome.eog.desktop.in using configuration\r\n\r\n../src/data/meson.build:25:5: ERROR: Function does not take positional arguments.\r\n```\r\n\r\nTrying to build the current eog deb in Ubuntu with the new meson 0.60 deb from Debian unstable leads to a similar error\n", "before_files": [{"content": "# Copyright 2016 The Meson development team\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n\n#     http://www.apache.org/licenses/LICENSE-2.0\n\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nfrom os import path\nimport shutil\nimport typing as T\n\nfrom . import ExtensionModule, ModuleReturnValue\nfrom .. import build\nfrom .. import mesonlib\nfrom .. import mlog\nfrom ..interpreter.type_checking import CT_BUILD_BY_DEFAULT, CT_INPUT_KW, CT_INSTALL_DIR_KW, CT_INSTALL_TAG_KW, CT_OUTPUT_KW, INSTALL_KW, NoneType, in_set_validator\nfrom ..interpreterbase import FeatureNew\nfrom ..interpreterbase.decorators import ContainerTypeInfo, KwargInfo, noPosargs, typed_kwargs, typed_pos_args\nfrom ..scripts.gettext import read_linguas\n\nif T.TYPE_CHECKING:\n    from typing_extensions import Literal, TypedDict\n\n    from . import ModuleState\n    from ..build import Target\n    from ..interpreter import Interpreter\n    from ..interpreterbase import TYPE_var\n    from ..programs import ExternalProgram\n\n    class MergeFile(TypedDict):\n\n        input: T.List[T.Union[\n            str, build.BuildTarget, build.CustomTarget, build.CustomTargetIndex,\n            build.ExtractedObjects, build.GeneratedList, ExternalProgram,\n            mesonlib.File]]\n        output: T.List[str]\n        build_by_default: bool\n        install: bool\n        install_dir: T.List[T.Union[str, bool]]\n        install_tag: T.List[str]\n        args: T.List[str]\n        data_dirs: T.List[str]\n        po_dir: str\n        type: Literal['xml', 'desktop']\n\n    class Gettext(TypedDict):\n\n        args: T.List[str]\n        data_dirs: T.List[str]\n        install: bool\n        install_dir: T.Optional[str]\n        languages: T.List[str]\n        preset: T.Optional[str]\n\n\n_ARGS: KwargInfo[T.List[str]] = KwargInfo(\n    'args',\n    ContainerTypeInfo(list, str),\n    default=[],\n    listify=True,\n)\n\n_DATA_DIRS: KwargInfo[T.List[str]] = KwargInfo(\n    'data_dirs',\n    ContainerTypeInfo(list, str),\n    default=[],\n    listify=True\n)\n\nPRESET_ARGS = {\n    'glib': [\n        '--from-code=UTF-8',\n        '--add-comments',\n\n        # https://developer.gnome.org/glib/stable/glib-I18N.html\n        '--keyword=_',\n        '--keyword=N_',\n        '--keyword=C_:1c,2',\n        '--keyword=NC_:1c,2',\n        '--keyword=g_dcgettext:2',\n        '--keyword=g_dngettext:2,3',\n        '--keyword=g_dpgettext2:2c,3',\n\n        '--flag=N_:1:pass-c-format',\n        '--flag=C_:2:pass-c-format',\n        '--flag=NC_:2:pass-c-format',\n        '--flag=g_dngettext:2:pass-c-format',\n        '--flag=g_strdup_printf:1:c-format',\n        '--flag=g_string_printf:2:c-format',\n        '--flag=g_string_append_printf:2:c-format',\n        '--flag=g_error_new:3:c-format',\n        '--flag=g_set_error:4:c-format',\n        '--flag=g_markup_printf_escaped:1:c-format',\n        '--flag=g_log:3:c-format',\n        '--flag=g_print:1:c-format',\n        '--flag=g_printerr:1:c-format',\n        '--flag=g_printf:1:c-format',\n        '--flag=g_fprintf:2:c-format',\n        '--flag=g_sprintf:2:c-format',\n        '--flag=g_snprintf:3:c-format',\n    ]\n}\n\n\nclass I18nModule(ExtensionModule):\n    def __init__(self, interpreter: 'Interpreter'):\n        super().__init__(interpreter)\n        self.methods.update({\n            'merge_file': self.merge_file,\n            'gettext': self.gettext,\n        })\n\n    @staticmethod\n    def nogettext_warning() -> None:\n        mlog.warning('Gettext not found, all translation targets will be ignored.', once=True)\n\n    @staticmethod\n    def _get_data_dirs(state: 'ModuleState', dirs: T.Iterable[str]) -> T.List[str]:\n        \"\"\"Returns source directories of relative paths\"\"\"\n        src_dir = path.join(state.environment.get_source_dir(), state.subdir)\n        return [path.join(src_dir, d) for d in dirs]\n\n    @FeatureNew('i18n.merge_file', '0.37.0')\n    @noPosargs\n    @typed_kwargs(\n        'i18n.merge_file',\n        CT_BUILD_BY_DEFAULT,\n        CT_INPUT_KW,\n        CT_INSTALL_DIR_KW,\n        CT_INSTALL_TAG_KW,\n        CT_OUTPUT_KW,\n        INSTALL_KW,\n        _ARGS.evolve(since='0.51.0'),\n        _DATA_DIRS,\n        KwargInfo('po_dir', str, required=True),\n        KwargInfo('type', str, default='xml', validator=in_set_validator({'xml', 'desktop'})),\n    )\n    def merge_file(self, state: 'ModuleState', args: T.List['TYPE_var'], kwargs: 'MergeFile') -> ModuleReturnValue:\n        if not shutil.which('xgettext'):\n            self.nogettext_warning()\n            return ModuleReturnValue(None, [])\n        podir = path.join(state.build_to_src, state.subdir, kwargs['po_dir'])\n\n        ddirs = self._get_data_dirs(state, kwargs['data_dirs'])\n        datadirs = '--datadirs=' + ':'.join(ddirs) if ddirs else None\n\n        command: T.List[T.Union[str, build.BuildTarget, build.CustomTarget,\n                                build.CustomTargetIndex, 'ExternalProgram', mesonlib.File]] = []\n        command.extend(state.environment.get_build_command())\n        command.extend([\n            '--internal', 'msgfmthelper',\n            '@INPUT@', '@OUTPUT@', kwargs['type'], podir\n        ])\n        if datadirs:\n            command.append(datadirs)\n\n        if kwargs['args']:\n            command.append('--')\n            command.extend(kwargs['args'])\n\n        build_by_default = kwargs['build_by_default']\n        if build_by_default is None:\n            build_by_default = kwargs['install']\n\n        real_kwargs = {\n            'build_by_default': build_by_default,\n            'command': command,\n            'install': kwargs['install'],\n            'install_dir': kwargs['install_dir'],\n            'output': kwargs['output'],\n            'input': kwargs['input'],\n            'install_tag': kwargs['install_tag'],\n        }\n\n        # We only use this input file to create a name of the custom target.\n        # Thus we can ignore the other entries.\n        inputfile = kwargs['input'][0]\n        if isinstance(inputfile, str):\n            inputfile = mesonlib.File.from_source_file(state.environment.source_dir,\n                                                       state.subdir, inputfile)\n        if isinstance(inputfile, mesonlib.File):\n            # output could be '@BASENAME@' in which case we need to do substitutions\n            # to get a unique target name.\n            outputs = kwargs['output']\n            ifile_abs = inputfile.absolute_path(state.environment.source_dir,\n                                                state.environment.build_dir)\n            values = mesonlib.get_filenames_templates_dict([ifile_abs], None)\n            outputs = mesonlib.substitute_values(outputs, values)\n            output = outputs[0]\n            ct = build.CustomTarget(\n                output + '_' + state.subdir.replace('/', '@').replace('\\\\', '@') + '_merge',\n                state.subdir, state.subproject, T.cast(T.Dict[str, T.Any], real_kwargs))\n        else:\n            ct = build.CustomTarget(\n                kwargs['output'][0] + '_merge', state.subdir, state.subproject,\n                T.cast(T.Dict[str, T.Any], real_kwargs))\n\n        return ModuleReturnValue(ct, [ct])\n\n    @typed_pos_args('i81n.gettex', str)\n    @typed_kwargs(\n        'i18n.gettext',\n        _ARGS,\n        _DATA_DIRS,\n        INSTALL_KW.evolve(default=True),\n        KwargInfo('install_dir', (str, NoneType), since='0.50.0'),\n        KwargInfo('languages', ContainerTypeInfo(list, str), default=[], listify=True),\n        KwargInfo(\n            'preset',\n            (str, NoneType),\n            validator=in_set_validator(set(PRESET_ARGS)),\n            since='0.37.0',\n        ),\n    )\n    def gettext(self, state: 'ModuleState', args: T.Tuple[str], kwargs: 'Gettext') -> ModuleReturnValue:\n        if not shutil.which('xgettext'):\n            self.nogettext_warning()\n            return ModuleReturnValue(None, [])\n        packagename = args[0]\n        pkg_arg = f'--pkgname={packagename}'\n\n        languages = kwargs['languages']\n        lang_arg = '--langs=' + '@@'.join(languages) if languages else None\n\n        _datadirs = ':'.join(self._get_data_dirs(state, kwargs['data_dirs']))\n        datadirs = f'--datadirs={_datadirs}' if _datadirs else None\n\n        extra_args = kwargs['args']\n        targets: T.List['Target'] = []\n        gmotargets: T.List['build.CustomTarget'] = []\n\n        preset = kwargs['preset']\n        if preset:\n            preset_args = PRESET_ARGS[preset]\n            extra_args = list(mesonlib.OrderedSet(preset_args + extra_args))\n\n        extra_arg = '--extra-args=' + '@@'.join(extra_args) if extra_args else None\n\n        potargs = state.environment.get_build_command() + ['--internal', 'gettext', 'pot', pkg_arg]\n        if datadirs:\n            potargs.append(datadirs)\n        if extra_arg:\n            potargs.append(extra_arg)\n        pottarget = build.RunTarget(packagename + '-pot', potargs, [], state.subdir, state.subproject)\n        targets.append(pottarget)\n\n        install = kwargs['install']\n        install_dir = kwargs['install_dir'] or state.environment.coredata.get_option(mesonlib.OptionKey('localedir'))\n        assert isinstance(install_dir, str), 'for mypy'\n        if not languages:\n            languages = read_linguas(path.join(state.environment.source_dir, state.subdir))\n        for l in languages:\n            po_file = mesonlib.File.from_source_file(state.environment.source_dir,\n                                                     state.subdir, l+'.po')\n            gmo_kwargs = {'command': ['msgfmt', '@INPUT@', '-o', '@OUTPUT@'],\n                          'input': po_file,\n                          'output': packagename+'.mo',\n                          'install': install,\n                          # We have multiple files all installed as packagename+'.mo' in different install subdirs.\n                          # What we really wanted to do, probably, is have a rename: kwarg, but that's not available\n                          # to custom_targets. Crude hack: set the build target's subdir manually.\n                          # Bonus: the build tree has something usable as an uninstalled bindtextdomain() target dir.\n                          'install_dir': path.join(install_dir, l, 'LC_MESSAGES'),\n                          'install_tag': 'i18n',\n                          }\n            gmotarget = build.CustomTarget(f'{packagename}-{l}.mo', path.join(state.subdir, l, 'LC_MESSAGES'), state.subproject, gmo_kwargs)\n            targets.append(gmotarget)\n            gmotargets.append(gmotarget)\n\n        allgmotarget = build.AliasTarget(packagename + '-gmo', gmotargets, state.subdir, state.subproject)\n        targets.append(allgmotarget)\n\n        updatepoargs = state.environment.get_build_command() + ['--internal', 'gettext', 'update_po', pkg_arg]\n        if lang_arg:\n            updatepoargs.append(lang_arg)\n        if datadirs:\n            updatepoargs.append(datadirs)\n        if extra_arg:\n            updatepoargs.append(extra_arg)\n        updatepotarget = build.RunTarget(packagename + '-update-po', updatepoargs, [], state.subdir, state.subproject)\n        targets.append(updatepotarget)\n\n        return ModuleReturnValue([gmotargets, pottarget, updatepotarget], targets)\n\ndef initialize(interp: 'Interpreter') -> I18nModule:\n    return I18nModule(interp)\n", "path": "mesonbuild/modules/i18n.py"}], "after_files": [{"content": "# Copyright 2016 The Meson development team\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n\n#     http://www.apache.org/licenses/LICENSE-2.0\n\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nfrom os import path\nimport shutil\nimport typing as T\n\nfrom . import ExtensionModule, ModuleReturnValue\nfrom .. import build\nfrom .. import mesonlib\nfrom .. import mlog\nfrom ..interpreter.type_checking import CT_BUILD_BY_DEFAULT, CT_INPUT_KW, CT_INSTALL_DIR_KW, CT_INSTALL_TAG_KW, CT_OUTPUT_KW, INSTALL_KW, NoneType, in_set_validator\nfrom ..interpreterbase import FeatureNew\nfrom ..interpreterbase.decorators import ContainerTypeInfo, KwargInfo, typed_kwargs, typed_pos_args\nfrom ..scripts.gettext import read_linguas\n\nif T.TYPE_CHECKING:\n    from typing_extensions import Literal, TypedDict\n\n    from . import ModuleState\n    from ..build import Target\n    from ..interpreter import Interpreter\n    from ..interpreterbase import TYPE_var\n    from ..programs import ExternalProgram\n\n    class MergeFile(TypedDict):\n\n        input: T.List[T.Union[\n            str, build.BuildTarget, build.CustomTarget, build.CustomTargetIndex,\n            build.ExtractedObjects, build.GeneratedList, ExternalProgram,\n            mesonlib.File]]\n        output: T.List[str]\n        build_by_default: bool\n        install: bool\n        install_dir: T.List[T.Union[str, bool]]\n        install_tag: T.List[str]\n        args: T.List[str]\n        data_dirs: T.List[str]\n        po_dir: str\n        type: Literal['xml', 'desktop']\n\n    class Gettext(TypedDict):\n\n        args: T.List[str]\n        data_dirs: T.List[str]\n        install: bool\n        install_dir: T.Optional[str]\n        languages: T.List[str]\n        preset: T.Optional[str]\n\n\n_ARGS: KwargInfo[T.List[str]] = KwargInfo(\n    'args',\n    ContainerTypeInfo(list, str),\n    default=[],\n    listify=True,\n)\n\n_DATA_DIRS: KwargInfo[T.List[str]] = KwargInfo(\n    'data_dirs',\n    ContainerTypeInfo(list, str),\n    default=[],\n    listify=True\n)\n\nPRESET_ARGS = {\n    'glib': [\n        '--from-code=UTF-8',\n        '--add-comments',\n\n        # https://developer.gnome.org/glib/stable/glib-I18N.html\n        '--keyword=_',\n        '--keyword=N_',\n        '--keyword=C_:1c,2',\n        '--keyword=NC_:1c,2',\n        '--keyword=g_dcgettext:2',\n        '--keyword=g_dngettext:2,3',\n        '--keyword=g_dpgettext2:2c,3',\n\n        '--flag=N_:1:pass-c-format',\n        '--flag=C_:2:pass-c-format',\n        '--flag=NC_:2:pass-c-format',\n        '--flag=g_dngettext:2:pass-c-format',\n        '--flag=g_strdup_printf:1:c-format',\n        '--flag=g_string_printf:2:c-format',\n        '--flag=g_string_append_printf:2:c-format',\n        '--flag=g_error_new:3:c-format',\n        '--flag=g_set_error:4:c-format',\n        '--flag=g_markup_printf_escaped:1:c-format',\n        '--flag=g_log:3:c-format',\n        '--flag=g_print:1:c-format',\n        '--flag=g_printerr:1:c-format',\n        '--flag=g_printf:1:c-format',\n        '--flag=g_fprintf:2:c-format',\n        '--flag=g_sprintf:2:c-format',\n        '--flag=g_snprintf:3:c-format',\n    ]\n}\n\n\nclass I18nModule(ExtensionModule):\n    def __init__(self, interpreter: 'Interpreter'):\n        super().__init__(interpreter)\n        self.methods.update({\n            'merge_file': self.merge_file,\n            'gettext': self.gettext,\n        })\n\n    @staticmethod\n    def nogettext_warning() -> None:\n        mlog.warning('Gettext not found, all translation targets will be ignored.', once=True)\n\n    @staticmethod\n    def _get_data_dirs(state: 'ModuleState', dirs: T.Iterable[str]) -> T.List[str]:\n        \"\"\"Returns source directories of relative paths\"\"\"\n        src_dir = path.join(state.environment.get_source_dir(), state.subdir)\n        return [path.join(src_dir, d) for d in dirs]\n\n    @FeatureNew('i18n.merge_file', '0.37.0')\n    @typed_kwargs(\n        'i18n.merge_file',\n        CT_BUILD_BY_DEFAULT,\n        CT_INPUT_KW,\n        CT_INSTALL_DIR_KW,\n        CT_INSTALL_TAG_KW,\n        CT_OUTPUT_KW,\n        INSTALL_KW,\n        _ARGS.evolve(since='0.51.0'),\n        _DATA_DIRS,\n        KwargInfo('po_dir', str, required=True),\n        KwargInfo('type', str, default='xml', validator=in_set_validator({'xml', 'desktop'})),\n    )\n    def merge_file(self, state: 'ModuleState', args: T.List['TYPE_var'], kwargs: 'MergeFile') -> ModuleReturnValue:\n        if args:\n            mlog.deprecation('i18n.merge_file does not take any positional arguments. '\n                             'This will become a hard error in the next Meson release.')\n        if not shutil.which('xgettext'):\n            self.nogettext_warning()\n            return ModuleReturnValue(None, [])\n        podir = path.join(state.build_to_src, state.subdir, kwargs['po_dir'])\n\n        ddirs = self._get_data_dirs(state, kwargs['data_dirs'])\n        datadirs = '--datadirs=' + ':'.join(ddirs) if ddirs else None\n\n        command: T.List[T.Union[str, build.BuildTarget, build.CustomTarget,\n                                build.CustomTargetIndex, 'ExternalProgram', mesonlib.File]] = []\n        command.extend(state.environment.get_build_command())\n        command.extend([\n            '--internal', 'msgfmthelper',\n            '@INPUT@', '@OUTPUT@', kwargs['type'], podir\n        ])\n        if datadirs:\n            command.append(datadirs)\n\n        if kwargs['args']:\n            command.append('--')\n            command.extend(kwargs['args'])\n\n        build_by_default = kwargs['build_by_default']\n        if build_by_default is None:\n            build_by_default = kwargs['install']\n\n        real_kwargs = {\n            'build_by_default': build_by_default,\n            'command': command,\n            'install': kwargs['install'],\n            'install_dir': kwargs['install_dir'],\n            'output': kwargs['output'],\n            'input': kwargs['input'],\n            'install_tag': kwargs['install_tag'],\n        }\n\n        # We only use this input file to create a name of the custom target.\n        # Thus we can ignore the other entries.\n        inputfile = kwargs['input'][0]\n        if isinstance(inputfile, str):\n            inputfile = mesonlib.File.from_source_file(state.environment.source_dir,\n                                                       state.subdir, inputfile)\n        if isinstance(inputfile, mesonlib.File):\n            # output could be '@BASENAME@' in which case we need to do substitutions\n            # to get a unique target name.\n            outputs = kwargs['output']\n            ifile_abs = inputfile.absolute_path(state.environment.source_dir,\n                                                state.environment.build_dir)\n            values = mesonlib.get_filenames_templates_dict([ifile_abs], None)\n            outputs = mesonlib.substitute_values(outputs, values)\n            output = outputs[0]\n            ct = build.CustomTarget(\n                output + '_' + state.subdir.replace('/', '@').replace('\\\\', '@') + '_merge',\n                state.subdir, state.subproject, T.cast(T.Dict[str, T.Any], real_kwargs))\n        else:\n            ct = build.CustomTarget(\n                kwargs['output'][0] + '_merge', state.subdir, state.subproject,\n                T.cast(T.Dict[str, T.Any], real_kwargs))\n\n        return ModuleReturnValue(ct, [ct])\n\n    @typed_pos_args('i81n.gettex', str)\n    @typed_kwargs(\n        'i18n.gettext',\n        _ARGS,\n        _DATA_DIRS,\n        INSTALL_KW.evolve(default=True),\n        KwargInfo('install_dir', (str, NoneType), since='0.50.0'),\n        KwargInfo('languages', ContainerTypeInfo(list, str), default=[], listify=True),\n        KwargInfo(\n            'preset',\n            (str, NoneType),\n            validator=in_set_validator(set(PRESET_ARGS)),\n            since='0.37.0',\n        ),\n    )\n    def gettext(self, state: 'ModuleState', args: T.Tuple[str], kwargs: 'Gettext') -> ModuleReturnValue:\n        if not shutil.which('xgettext'):\n            self.nogettext_warning()\n            return ModuleReturnValue(None, [])\n        packagename = args[0]\n        pkg_arg = f'--pkgname={packagename}'\n\n        languages = kwargs['languages']\n        lang_arg = '--langs=' + '@@'.join(languages) if languages else None\n\n        _datadirs = ':'.join(self._get_data_dirs(state, kwargs['data_dirs']))\n        datadirs = f'--datadirs={_datadirs}' if _datadirs else None\n\n        extra_args = kwargs['args']\n        targets: T.List['Target'] = []\n        gmotargets: T.List['build.CustomTarget'] = []\n\n        preset = kwargs['preset']\n        if preset:\n            preset_args = PRESET_ARGS[preset]\n            extra_args = list(mesonlib.OrderedSet(preset_args + extra_args))\n\n        extra_arg = '--extra-args=' + '@@'.join(extra_args) if extra_args else None\n\n        potargs = state.environment.get_build_command() + ['--internal', 'gettext', 'pot', pkg_arg]\n        if datadirs:\n            potargs.append(datadirs)\n        if extra_arg:\n            potargs.append(extra_arg)\n        pottarget = build.RunTarget(packagename + '-pot', potargs, [], state.subdir, state.subproject)\n        targets.append(pottarget)\n\n        install = kwargs['install']\n        install_dir = kwargs['install_dir'] or state.environment.coredata.get_option(mesonlib.OptionKey('localedir'))\n        assert isinstance(install_dir, str), 'for mypy'\n        if not languages:\n            languages = read_linguas(path.join(state.environment.source_dir, state.subdir))\n        for l in languages:\n            po_file = mesonlib.File.from_source_file(state.environment.source_dir,\n                                                     state.subdir, l+'.po')\n            gmo_kwargs = {'command': ['msgfmt', '@INPUT@', '-o', '@OUTPUT@'],\n                          'input': po_file,\n                          'output': packagename+'.mo',\n                          'install': install,\n                          # We have multiple files all installed as packagename+'.mo' in different install subdirs.\n                          # What we really wanted to do, probably, is have a rename: kwarg, but that's not available\n                          # to custom_targets. Crude hack: set the build target's subdir manually.\n                          # Bonus: the build tree has something usable as an uninstalled bindtextdomain() target dir.\n                          'install_dir': path.join(install_dir, l, 'LC_MESSAGES'),\n                          'install_tag': 'i18n',\n                          }\n            gmotarget = build.CustomTarget(f'{packagename}-{l}.mo', path.join(state.subdir, l, 'LC_MESSAGES'), state.subproject, gmo_kwargs)\n            targets.append(gmotarget)\n            gmotargets.append(gmotarget)\n\n        allgmotarget = build.AliasTarget(packagename + '-gmo', gmotargets, state.subdir, state.subproject)\n        targets.append(allgmotarget)\n\n        updatepoargs = state.environment.get_build_command() + ['--internal', 'gettext', 'update_po', pkg_arg]\n        if lang_arg:\n            updatepoargs.append(lang_arg)\n        if datadirs:\n            updatepoargs.append(datadirs)\n        if extra_arg:\n            updatepoargs.append(extra_arg)\n        updatepotarget = build.RunTarget(packagename + '-update-po', updatepoargs, [], state.subdir, state.subproject)\n        targets.append(updatepotarget)\n\n        return ModuleReturnValue([gmotargets, pottarget, updatepotarget], targets)\n\ndef initialize(interp: 'Interpreter') -> I18nModule:\n    return I18nModule(interp)\n", "path": "mesonbuild/modules/i18n.py"}]}