azdev 0.1.93__tar.gz → 0.1.95__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (105) hide show
  1. {azdev-0.1.93 → azdev-0.1.95}/HISTORY.rst +10 -0
  2. {azdev-0.1.93/azdev.egg-info → azdev-0.1.95}/PKG-INFO +22 -2
  3. {azdev-0.1.93 → azdev-0.1.95}/azdev/__init__.py +1 -1
  4. {azdev-0.1.93 → azdev-0.1.95}/azdev/help.py +1 -1
  5. {azdev-0.1.93 → azdev-0.1.95}/azdev/operations/breaking_change/__init__.py +24 -14
  6. {azdev-0.1.93 → azdev-0.1.95}/azdev/operations/command_change/__init__.py +4 -3
  7. {azdev-0.1.93 → azdev-0.1.95}/azdev/params.py +2 -0
  8. {azdev-0.1.93 → azdev-0.1.95}/azdev/utilities/path.py +7 -1
  9. {azdev-0.1.93 → azdev-0.1.95/azdev.egg-info}/PKG-INFO +22 -2
  10. {azdev-0.1.93 → azdev-0.1.95}/LICENSE +0 -0
  11. {azdev-0.1.93 → azdev-0.1.95}/MANIFEST.in +0 -0
  12. {azdev-0.1.93 → azdev-0.1.95}/README.md +0 -0
  13. {azdev-0.1.93 → azdev-0.1.95}/README.rst +0 -0
  14. {azdev-0.1.93 → azdev-0.1.95}/azdev/__main__.py +0 -0
  15. {azdev-0.1.93 → azdev-0.1.95}/azdev/commands.py +0 -0
  16. {azdev-0.1.93 → azdev-0.1.95}/azdev/completer.py +0 -0
  17. {azdev-0.1.93 → azdev-0.1.95}/azdev/config/__init__.py +0 -0
  18. {azdev-0.1.93 → azdev-0.1.95}/azdev/config/cli.flake8 +0 -0
  19. {azdev-0.1.93 → azdev-0.1.95}/azdev/config/cli_pylintrc +0 -0
  20. {azdev-0.1.93 → azdev-0.1.95}/azdev/config/ext.flake8 +0 -0
  21. {azdev-0.1.93 → azdev-0.1.95}/azdev/config/ext_pylintrc +0 -0
  22. {azdev-0.1.93 → azdev-0.1.95}/azdev/mod_templates/HISTORY.rst +0 -0
  23. {azdev-0.1.93 → azdev-0.1.95}/azdev/mod_templates/README.rst +0 -0
  24. {azdev-0.1.93 → azdev-0.1.95}/azdev/mod_templates/_client_factory.py +0 -0
  25. {azdev-0.1.93 → azdev-0.1.95}/azdev/mod_templates/_help.py +0 -0
  26. {azdev-0.1.93 → azdev-0.1.95}/azdev/mod_templates/_params.py +0 -0
  27. {azdev-0.1.93 → azdev-0.1.95}/azdev/mod_templates/_validators.py +0 -0
  28. {azdev-0.1.93 → azdev-0.1.95}/azdev/mod_templates/azext_metadata.json +0 -0
  29. {azdev-0.1.93 → azdev-0.1.95}/azdev/mod_templates/blank__init__.py +0 -0
  30. {azdev-0.1.93 → azdev-0.1.95}/azdev/mod_templates/commands.py +0 -0
  31. {azdev-0.1.93 → azdev-0.1.95}/azdev/mod_templates/custom.py +0 -0
  32. {azdev-0.1.93 → azdev-0.1.95}/azdev/mod_templates/module__init__.py +0 -0
  33. {azdev-0.1.93 → azdev-0.1.95}/azdev/mod_templates/pkg_declare__init__.py +0 -0
  34. {azdev-0.1.93 → azdev-0.1.95}/azdev/mod_templates/setup.cfg +0 -0
  35. {azdev-0.1.93 → azdev-0.1.95}/azdev/mod_templates/setup.py +0 -0
  36. {azdev-0.1.93 → azdev-0.1.95}/azdev/mod_templates/test_service_scenario.py +0 -0
  37. {azdev-0.1.93 → azdev-0.1.95}/azdev/operations/__init__.py +0 -0
  38. {azdev-0.1.93 → azdev-0.1.95}/azdev/operations/breaking_change/markdown_template.jinja2 +0 -0
  39. {azdev-0.1.93 → azdev-0.1.95}/azdev/operations/cmdcov/__init__.py +0 -0
  40. {azdev-0.1.93 → azdev-0.1.95}/azdev/operations/cmdcov/_macros.j2 +0 -0
  41. {azdev-0.1.93 → azdev-0.1.95}/azdev/operations/cmdcov/cmdcov.py +0 -0
  42. {azdev-0.1.93 → azdev-0.1.95}/azdev/operations/cmdcov/component.css +0 -0
  43. {azdev-0.1.93 → azdev-0.1.95}/azdev/operations/cmdcov/component.js +0 -0
  44. {azdev-0.1.93 → azdev-0.1.95}/azdev/operations/cmdcov/favicon.ico +0 -0
  45. {azdev-0.1.93 → azdev-0.1.95}/azdev/operations/cmdcov/index.j2 +0 -0
  46. {azdev-0.1.93 → azdev-0.1.95}/azdev/operations/cmdcov/index2.j2 +0 -0
  47. {azdev-0.1.93 → azdev-0.1.95}/azdev/operations/cmdcov/module.j2 +0 -0
  48. {azdev-0.1.93 → azdev-0.1.95}/azdev/operations/code_gen.py +0 -0
  49. {azdev-0.1.93 → azdev-0.1.95}/azdev/operations/command_change/custom.py +0 -0
  50. {azdev-0.1.93 → azdev-0.1.95}/azdev/operations/command_change/util.py +0 -0
  51. {azdev-0.1.93 → azdev-0.1.95}/azdev/operations/constant.py +0 -0
  52. {azdev-0.1.93 → azdev-0.1.95}/azdev/operations/extensions/__init__.py +0 -0
  53. {azdev-0.1.93 → azdev-0.1.95}/azdev/operations/extensions/util.py +0 -0
  54. {azdev-0.1.93 → azdev-0.1.95}/azdev/operations/extensions/version_upgrade.py +0 -0
  55. {azdev-0.1.93 → azdev-0.1.95}/azdev/operations/help/__init__.py +0 -0
  56. {azdev-0.1.93 → azdev-0.1.95}/azdev/operations/help/refdoc/__init__.py +0 -0
  57. {azdev-0.1.93 → azdev-0.1.95}/azdev/operations/help/refdoc/conf.py +0 -0
  58. {azdev-0.1.93 → azdev-0.1.95}/azdev/operations/legal.py +0 -0
  59. {azdev-0.1.93 → azdev-0.1.95}/azdev/operations/linter/__init__.py +0 -0
  60. {azdev-0.1.93 → azdev-0.1.95}/azdev/operations/linter/data/cmd_example_config.json +0 -0
  61. {azdev-0.1.93 → azdev-0.1.95}/azdev/operations/linter/linter.py +0 -0
  62. {azdev-0.1.93 → azdev-0.1.95}/azdev/operations/linter/pylint_checkers/__init__.py +0 -0
  63. {azdev-0.1.93 → azdev-0.1.95}/azdev/operations/linter/pylint_checkers/show_command.py +0 -0
  64. {azdev-0.1.93 → azdev-0.1.95}/azdev/operations/linter/rule_decorators.py +0 -0
  65. {azdev-0.1.93 → azdev-0.1.95}/azdev/operations/linter/rules/__init__.py +0 -0
  66. {azdev-0.1.93 → azdev-0.1.95}/azdev/operations/linter/rules/ci_exclusions.yml +0 -0
  67. {azdev-0.1.93 → azdev-0.1.95}/azdev/operations/linter/rules/command_coverage_rules.py +0 -0
  68. {azdev-0.1.93 → azdev-0.1.95}/azdev/operations/linter/rules/command_group_rules.py +0 -0
  69. {azdev-0.1.93 → azdev-0.1.95}/azdev/operations/linter/rules/command_rules.py +0 -0
  70. {azdev-0.1.93 → azdev-0.1.95}/azdev/operations/linter/rules/help_rules.py +0 -0
  71. {azdev-0.1.93 → azdev-0.1.95}/azdev/operations/linter/rules/linter_exclusions.yml +0 -0
  72. {azdev-0.1.93 → azdev-0.1.95}/azdev/operations/linter/rules/parameter_rules.py +0 -0
  73. {azdev-0.1.93 → azdev-0.1.95}/azdev/operations/linter/util.py +0 -0
  74. {azdev-0.1.93 → azdev-0.1.95}/azdev/operations/performance.py +0 -0
  75. {azdev-0.1.93 → azdev-0.1.95}/azdev/operations/pypi.py +0 -0
  76. {azdev-0.1.93 → azdev-0.1.95}/azdev/operations/python_sdk.py +0 -0
  77. {azdev-0.1.93 → azdev-0.1.95}/azdev/operations/regex.py +0 -0
  78. {azdev-0.1.93 → azdev-0.1.95}/azdev/operations/resource.py +0 -0
  79. {azdev-0.1.93 → azdev-0.1.95}/azdev/operations/secret.py +0 -0
  80. {azdev-0.1.93 → azdev-0.1.95}/azdev/operations/setup.py +0 -0
  81. {azdev-0.1.93 → azdev-0.1.95}/azdev/operations/statistics/__init__.py +0 -0
  82. {azdev-0.1.93 → azdev-0.1.95}/azdev/operations/statistics/util.py +0 -0
  83. {azdev-0.1.93 → azdev-0.1.95}/azdev/operations/style.py +0 -0
  84. {azdev-0.1.93 → azdev-0.1.95}/azdev/operations/testtool/__init__.py +0 -0
  85. {azdev-0.1.93 → azdev-0.1.95}/azdev/operations/testtool/incremental_strategy.py +0 -0
  86. {azdev-0.1.93 → azdev-0.1.95}/azdev/operations/testtool/profile_context.py +0 -0
  87. {azdev-0.1.93 → azdev-0.1.95}/azdev/operations/testtool/pytest_runner.py +0 -0
  88. {azdev-0.1.93 → azdev-0.1.95}/azdev/transformers.py +0 -0
  89. {azdev-0.1.93 → azdev-0.1.95}/azdev/utilities/__init__.py +0 -0
  90. {azdev-0.1.93 → azdev-0.1.95}/azdev/utilities/command.py +0 -0
  91. {azdev-0.1.93 → azdev-0.1.95}/azdev/utilities/config.py +0 -0
  92. {azdev-0.1.93 → azdev-0.1.95}/azdev/utilities/const.py +0 -0
  93. {azdev-0.1.93 → azdev-0.1.95}/azdev/utilities/display.py +0 -0
  94. {azdev-0.1.93 → azdev-0.1.95}/azdev/utilities/git_util.py +0 -0
  95. {azdev-0.1.93 → azdev-0.1.95}/azdev/utilities/pypi.py +0 -0
  96. {azdev-0.1.93 → azdev-0.1.95}/azdev/utilities/testing.py +0 -0
  97. {azdev-0.1.93 → azdev-0.1.95}/azdev/utilities/tools.py +0 -0
  98. {azdev-0.1.93 → azdev-0.1.95}/azdev.egg-info/SOURCES.txt +0 -0
  99. {azdev-0.1.93 → azdev-0.1.95}/azdev.egg-info/dependency_links.txt +0 -0
  100. {azdev-0.1.93 → azdev-0.1.95}/azdev.egg-info/entry_points.txt +0 -0
  101. {azdev-0.1.93 → azdev-0.1.95}/azdev.egg-info/requires.txt +0 -0
  102. {azdev-0.1.93 → azdev-0.1.95}/azdev.egg-info/top_level.txt +0 -0
  103. {azdev-0.1.93 → azdev-0.1.95}/pyproject.toml +0 -0
  104. {azdev-0.1.93 → azdev-0.1.95}/setup.cfg +0 -0
  105. {azdev-0.1.93 → azdev-0.1.95}/setup.py +0 -0
@@ -2,6 +2,16 @@
2
2
 
3
3
  Release History
4
4
  ===============
5
+ 0.1.95
6
+ ++++++
7
+ * `azdev generate-breaking-change-report`: Extracts upcoming breaking changes in extensions, regardless of the target version set
8
+ * `azdev generate-breaking-change-report`: Fix collecting announcement starting with `az`
9
+
10
+
11
+ 0.1.94
12
+ ++++++
13
+ * `azdev command-change meta-export`: Enable meta exporting for extension installed using `.whl` package by `include_whl_extensions`
14
+
5
15
  0.1.93
6
16
  ++++++
7
17
  * `azdev linter`: Fix `None` path for added files in `git diff` for `missing_command_example` rule
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: azdev
3
- Version: 0.1.93
3
+ Version: 0.1.95
4
4
  Summary: Microsoft Azure CLI Developer Tools
5
5
  Home-page: https://github.com/Azure/azure-cli-dev-tools
6
6
  Author: Microsoft Corporation
@@ -41,6 +41,16 @@ Requires-Dist: packaging
41
41
  Requires-Dist: tqdm
42
42
  Requires-Dist: wheel==0.30.0
43
43
  Requires-Dist: microsoft-security-utilities-secret-masker~=1.0.0b2
44
+ Dynamic: author
45
+ Dynamic: author-email
46
+ Dynamic: classifier
47
+ Dynamic: description
48
+ Dynamic: home-page
49
+ Dynamic: keywords
50
+ Dynamic: license
51
+ Dynamic: requires-dist
52
+ Dynamic: requires-python
53
+ Dynamic: summary
44
54
 
45
55
  Microsoft Azure CLI Dev Tools (azdev)
46
56
  =====================================
@@ -148,6 +158,16 @@ License
148
158
 
149
159
  Release History
150
160
  ===============
161
+ 0.1.95
162
+ ++++++
163
+ * `azdev generate-breaking-change-report`: Extracts upcoming breaking changes in extensions, regardless of the target version set
164
+ * `azdev generate-breaking-change-report`: Fix collecting announcement starting with `az`
165
+
166
+
167
+ 0.1.94
168
+ ++++++
169
+ * `azdev command-change meta-export`: Enable meta exporting for extension installed using `.whl` package by `include_whl_extensions`
170
+
151
171
  0.1.93
152
172
  ++++++
153
173
  * `azdev linter`: Fix `None` path for added files in `git diff` for `missing_command_example` rule
@@ -4,4 +4,4 @@
4
4
  # license information.
5
5
  # -----------------------------------------------------------------------------
6
6
 
7
- __VERSION__ = '0.1.93'
7
+ __VERSION__ = '0.1.95'
@@ -243,7 +243,7 @@ helps['command-change meta-diff'] = """
243
243
  short-summary: Diff the command meta between provided meta files.
244
244
  examples:
245
245
  - name: Diff the command meta change from fileA to fileB
246
- text: azdev statistics meta-diff --base-meta-file fileA --diff-meta-file fileB --only-break
246
+ text: azdev command-change meta-diff --base-meta-file fileA --diff-meta-file fileB --only-break
247
247
  """
248
248
 
249
249
  helps['command-change tree-export'] = """
@@ -13,6 +13,7 @@ from knack.log import get_logger
13
13
 
14
14
  from azdev.operations.statistics import _create_invoker_and_load_cmds # pylint: disable=protected-access
15
15
  from azdev.utilities import require_azure_cli, display, heading, output, calc_selected_mod_names
16
+ from azdev.utilities.path import calc_selected_modules
16
17
 
17
18
  # pylint: disable=no-else-return
18
19
 
@@ -68,8 +69,9 @@ def _handle_custom_breaking_changes(module, command):
68
69
  """
69
70
  from azure.cli.core.breaking_change import upcoming_breaking_changes
70
71
  yield from _handle_custom_breaking_change(module, command, upcoming_breaking_changes.get(command))
72
+ yield from _handle_custom_breaking_change(module, command, upcoming_breaking_changes.get(f'az {command}'))
71
73
  for key in upcoming_breaking_changes:
72
- if key.startswith(command + '.'):
74
+ if key.startswith(command + '.') or key.startswith(f'az {command}.'):
73
75
  yield from _handle_custom_breaking_change(module, command, upcoming_breaking_changes[key])
74
76
 
75
77
 
@@ -249,9 +251,7 @@ def _handle_core(source):
249
251
  display('Core finished loaded in {} sec'.format(stop - start))
250
252
 
251
253
 
252
- def _handle_upcoming_breaking_changes(selected_mod_names, source):
253
- command_loader = _load_commands()
254
-
254
+ def _handle_upcoming_breaking_changes(command_loader, selected_mod_names, source):
255
255
  if 'core' in selected_mod_names or 'azure-cli-core' in selected_mod_names:
256
256
  yield from _handle_core(source)
257
257
 
@@ -285,13 +285,13 @@ def _filter_breaking_changes(iterator, max_version=None):
285
285
  # pylint: disable=unnecessary-lambda-assignment
286
286
  def _group_breaking_change_items(iterator, group_by_version=False):
287
287
  if group_by_version:
288
- upcoming_breaking_changes = defaultdict( # module to command
289
- lambda: defaultdict( # command to version
290
- lambda: {'group_ref': None, 'items': defaultdict( # version to list of breaking changes
288
+ upcoming_breaking_changes = defaultdict( # module to command
289
+ lambda: defaultdict( # command to version
290
+ lambda: {'group_ref': None, 'items': defaultdict( # version to list of breaking changes
291
291
  lambda: [])}))
292
292
  else:
293
- upcoming_breaking_changes = defaultdict( # module to command
294
- lambda: defaultdict( # command to list of breaking changes
293
+ upcoming_breaking_changes = defaultdict( # module to command
294
+ lambda: defaultdict( # command to list of breaking changes
295
295
  lambda: {'group_ref': None, 'items': []}))
296
296
  for item in iterator:
297
297
  version = item.target_version if item.target_version else 'Unspecific'
@@ -313,14 +313,24 @@ def collect_upcoming_breaking_changes(modules=None, target_version='NextWindow',
313
313
 
314
314
  require_azure_cli()
315
315
 
316
- selected_mod_names = calc_selected_mod_names(modules)
316
+ selected_modules = calc_selected_modules(modules)
317
+ cli_mod_names = list(selected_modules['core'].keys()) + list(selected_modules['mod'].keys())
318
+ ext_mod_names = list(selected_modules['ext'].keys())
317
319
 
318
- if selected_mod_names:
319
- display('Modules selected: {}\n'.format(', '.join(selected_mod_names)))
320
+ if cli_mod_names or ext_mod_names:
321
+ display('Modules selected: {}\n'.format(', '.join(cli_mod_names + ext_mod_names)))
322
+
323
+ command_loader = _load_commands()
320
324
 
321
325
  heading('Collecting Breaking Change Pre-announcement')
322
- breaking_changes = _handle_upcoming_breaking_changes(selected_mod_names, source)
323
- breaking_changes = _filter_breaking_changes(breaking_changes, target_version)
326
+ breaking_changes = []
327
+ if cli_mod_names:
328
+ cli_breaking_changes = _handle_upcoming_breaking_changes(command_loader, cli_mod_names, source)
329
+ cli_breaking_changes = _filter_breaking_changes(cli_breaking_changes, target_version)
330
+ breaking_changes.extend(cli_breaking_changes)
331
+ if ext_mod_names:
332
+ ext_breaking_changes = _handle_upcoming_breaking_changes(command_loader, ext_mod_names, 'pre_announce')
333
+ breaking_changes.extend(ext_breaking_changes)
324
334
  breaking_changes = _group_breaking_change_items(breaking_changes, group_by_version)
325
335
  if output_format == 'structure':
326
336
  return breaking_changes
@@ -28,7 +28,7 @@ def diff_export_format_choices():
28
28
 
29
29
  # pylint: disable=too-many-statements
30
30
  def export_command_meta(modules=None, git_source=None, git_target=None, git_repo=None,
31
- with_help=False, with_example=False,
31
+ with_help=False, with_example=False, include_whl_extensions=False,
32
32
  meta_output_path=None):
33
33
  require_azure_cli()
34
34
 
@@ -38,7 +38,7 @@ def export_command_meta(modules=None, git_source=None, git_target=None, git_repo
38
38
  if cli_only or ext_only:
39
39
  modules = None
40
40
 
41
- selected_modules = get_path_table(include_only=modules)
41
+ selected_modules = get_path_table(include_only=modules, include_whl_extensions=include_whl_extensions)
42
42
 
43
43
  if cli_only:
44
44
  selected_modules['ext'] = {}
@@ -84,7 +84,8 @@ def export_command_meta(modules=None, git_source=None, git_target=None, git_repo
84
84
  help_info[help_item.command] = help_item
85
85
 
86
86
  # trim command table to selected_modules
87
- command_loader = filter_modules(command_loader, modules=selected_mod_names)
87
+ command_loader = filter_modules(command_loader, modules=selected_mod_names,
88
+ include_whl_extensions=include_whl_extensions)
88
89
 
89
90
  if not command_loader.command_table:
90
91
  logger.warning('No commands selected to check.')
@@ -165,6 +165,8 @@ def load_arguments(self, _):
165
165
  c.argument('with_help', action="store_true", help="State whether to include help message")
166
166
  c.argument('with_example', action="store_true", help="State whether to include examples")
167
167
  c.argument('meta_output_path', help='command meta json file path to store')
168
+ c.argument('include_whl_extensions', action='store_true',
169
+ help="Allow running cmd loader on extensions installed by `az extension add --source xxx.whl`.")
168
170
 
169
171
  with ArgumentsContext(self, 'command-change meta-diff') as c:
170
172
  c.argument('base_meta_file', required=True, help='command meta json file')
@@ -265,7 +265,7 @@ def get_path_table(include_only=None, include_whl_extensions=False):
265
265
  return table
266
266
 
267
267
 
268
- def calc_selected_mod_names(modules=None):
268
+ def calc_selected_modules(modules=None):
269
269
  # allow user to run only on CLI or extensions
270
270
  cli_only = modules == ['CLI']
271
271
  ext_only = modules == ['EXT']
@@ -280,6 +280,12 @@ def calc_selected_mod_names(modules=None):
280
280
  selected_modules['core'] = {}
281
281
  selected_modules['mod'] = {}
282
282
 
283
+ return selected_modules
284
+
285
+
286
+ def calc_selected_mod_names(modules=None):
287
+ selected_modules = calc_selected_modules(modules)
288
+
283
289
  if not any(selected_modules.values()):
284
290
  logger.warning('No commands selected to check.')
285
291
 
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: azdev
3
- Version: 0.1.93
3
+ Version: 0.1.95
4
4
  Summary: Microsoft Azure CLI Developer Tools
5
5
  Home-page: https://github.com/Azure/azure-cli-dev-tools
6
6
  Author: Microsoft Corporation
@@ -41,6 +41,16 @@ Requires-Dist: packaging
41
41
  Requires-Dist: tqdm
42
42
  Requires-Dist: wheel==0.30.0
43
43
  Requires-Dist: microsoft-security-utilities-secret-masker~=1.0.0b2
44
+ Dynamic: author
45
+ Dynamic: author-email
46
+ Dynamic: classifier
47
+ Dynamic: description
48
+ Dynamic: home-page
49
+ Dynamic: keywords
50
+ Dynamic: license
51
+ Dynamic: requires-dist
52
+ Dynamic: requires-python
53
+ Dynamic: summary
44
54
 
45
55
  Microsoft Azure CLI Dev Tools (azdev)
46
56
  =====================================
@@ -148,6 +158,16 @@ License
148
158
 
149
159
  Release History
150
160
  ===============
161
+ 0.1.95
162
+ ++++++
163
+ * `azdev generate-breaking-change-report`: Extracts upcoming breaking changes in extensions, regardless of the target version set
164
+ * `azdev generate-breaking-change-report`: Fix collecting announcement starting with `az`
165
+
166
+
167
+ 0.1.94
168
+ ++++++
169
+ * `azdev command-change meta-export`: Enable meta exporting for extension installed using `.whl` package by `include_whl_extensions`
170
+
151
171
  0.1.93
152
172
  ++++++
153
173
  * `azdev linter`: Fix `None` path for added files in `git diff` for `missing_command_example` rule
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes