periplus-map 0.2.1__py3-none-any.whl
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.
- periplus/__init__.py +70 -0
- periplus/checkmap.py +80 -0
- periplus/cli.py +658 -0
- periplus/contract/schema/map.schema.json +138 -0
- periplus/contract/schema/navigation.schema.json +200 -0
- periplus/contract/schema/pack-file.schema.json +1405 -0
- periplus/contract/schema/pack-manifest.schema.json +245 -0
- periplus/contract/schema/project-settings.schema.json +85 -0
- periplus/contract/spec/engine.md +151 -0
- periplus/contract/spec/rules.md +352 -0
- periplus/detect.py +228 -0
- periplus/engine/__init__.py +5 -0
- periplus/engine/check.py +481 -0
- periplus/engine/emit.py +368 -0
- periplus/engine/packload.py +2321 -0
- periplus/engine/pattern.py +27 -0
- periplus/engine/rules.py +1946 -0
- periplus/engine/select.py +491 -0
- periplus/engine/source.py +172 -0
- periplus/engine/tree.py +424 -0
- periplus/errors.py +332 -0
- periplus/init.py +358 -0
- periplus/layout.py +28 -0
- periplus/manifest.py +498 -0
- periplus/map.py +364 -0
- periplus/navigate/__init__.py +1 -0
- periplus/navigate/find.py +143 -0
- periplus/navigate/ids.py +30 -0
- periplus/navigate/listing.py +42 -0
- periplus/navigate/mapfile.py +189 -0
- periplus/navigate/path.py +175 -0
- periplus/navigate/show.py +175 -0
- periplus/navigate/types.py +83 -0
- periplus/navigate/walk.py +138 -0
- periplus/packs/advancedqueue_basic@0.0.1/pack.yaml +14 -0
- periplus/packs/advancedqueue_basic@0.0.1/queue_job_type/queue_job_type.yaml +9 -0
- periplus/packs/advancedqueue_basic@0.0.1/queue_job_type/queue_job_type_annotation.yaml +43 -0
- periplus/packs/advancedqueue_basic@0.0.1/queue_job_type/queue_job_type_attribute.yaml +43 -0
- periplus/packs/ai_basic@0.0.1/ai_agent/ai_agent.yaml +8 -0
- periplus/packs/ai_basic@0.0.1/ai_agent/ai_agent_attribute.yaml +43 -0
- periplus/packs/ai_basic@0.0.1/ai_function_call/ai_function_call.yaml +8 -0
- periplus/packs/ai_basic@0.0.1/ai_function_call/ai_function_call_attribute.yaml +43 -0
- periplus/packs/ai_basic@0.0.1/pack.yaml +15 -0
- periplus/packs/config_pages_basic@0.0.1/bundle/config_pages_bundle_config.yaml +54 -0
- periplus/packs/config_pages_basic@0.0.1/pack.yaml +11 -0
- periplus/packs/crop_basic@0.0.1/bundle/crop_bundle_config.yaml +54 -0
- periplus/packs/crop_basic@0.0.1/pack.yaml +11 -0
- periplus/packs/drupal@0.1.0/block/block_placement.yaml +25 -0
- periplus/packs/drupal@0.1.0/block/block_placement_code.yaml +58 -0
- periplus/packs/drupal@0.1.0/block/block_placement_config.yaml +53 -0
- periplus/packs/drupal@0.1.0/block/block_plugin.yaml +52 -0
- periplus/packs/drupal@0.1.0/block/block_plugin_altered.yaml +61 -0
- periplus/packs/drupal@0.1.0/block/block_plugin_annotation.yaml +69 -0
- periplus/packs/drupal@0.1.0/block/block_plugin_attribute.yaml +56 -0
- periplus/packs/drupal@0.1.0/block/block_plugin_content.yaml +46 -0
- periplus/packs/drupal@0.1.0/block/block_plugin_derived.yaml +110 -0
- periplus/packs/drupal@0.1.0/block/block_plugin_deriver.yaml +30 -0
- periplus/packs/drupal@0.1.0/block/block_type.yaml +14 -0
- periplus/packs/drupal@0.1.0/block/block_type_code.yaml +43 -0
- periplus/packs/drupal@0.1.0/block/block_type_config.yaml +45 -0
- periplus/packs/drupal@0.1.0/cache/cache.yaml +18 -0
- periplus/packs/drupal@0.1.0/cache/cache_backend.yaml +31 -0
- periplus/packs/drupal@0.1.0/component/sdc.yaml +19 -0
- periplus/packs/drupal@0.1.0/component/sdc_definition.yaml +25 -0
- periplus/packs/drupal@0.1.0/component/sdc_use.yaml +25 -0
- periplus/packs/drupal@0.1.0/config/config_object.yaml +65 -0
- periplus/packs/drupal@0.1.0/display/display.yaml +32 -0
- periplus/packs/drupal@0.1.0/display/display_code.yaml +53 -0
- periplus/packs/drupal@0.1.0/display/display_config.yaml +95 -0
- periplus/packs/drupal@0.1.0/entity/entity.yaml +33 -0
- periplus/packs/drupal@0.1.0/entity/entity_class.yaml +60 -0
- periplus/packs/drupal@0.1.0/entity/entity_save.yaml +27 -0
- periplus/packs/drupal@0.1.0/entity/entity_type_annotation.yaml +85 -0
- periplus/packs/drupal@0.1.0/entity/entity_type_attribute.yaml +76 -0
- periplus/packs/drupal@0.1.0/field/field_instance_code.yaml +40 -0
- periplus/packs/drupal@0.1.0/field/field_instance_config.yaml +58 -0
- periplus/packs/drupal@0.1.0/field/field_storage.yaml +37 -0
- periplus/packs/drupal@0.1.0/field/field_storage_code.yaml +39 -0
- periplus/packs/drupal@0.1.0/field/field_storage_config.yaml +24 -0
- periplus/packs/drupal@0.1.0/form/form.yaml +48 -0
- periplus/packs/drupal@0.1.0/form/form_class.yaml +50 -0
- periplus/packs/drupal@0.1.0/form/form_id.yaml +48 -0
- periplus/packs/drupal@0.1.0/form/form_methods.yaml +39 -0
- periplus/packs/drupal@0.1.0/hook/hook.yaml +8 -0
- periplus/packs/drupal@0.1.0/hook/hook_attribute.yaml +28 -0
- periplus/packs/drupal@0.1.0/module/module.yaml +8 -0
- periplus/packs/drupal@0.1.0/module/module_info.yaml +50 -0
- periplus/packs/drupal@0.1.0/pack.yaml +184 -0
- periplus/packs/drupal@0.1.0/plugin/plugin.yaml +17 -0
- periplus/packs/drupal@0.1.0/plugin/plugin_annotation.yaml +120 -0
- periplus/packs/drupal@0.1.0/recommendations/recommendations.yaml +14 -0
- periplus/packs/drupal@0.1.0/service/service.yaml +19 -0
- periplus/packs/drupal@0.1.0/service/service_autowire.yaml +28 -0
- periplus/packs/drupal@0.1.0/service/service_definition.yaml +24 -0
- periplus/packs/drupal@0.1.0/service/service_use.yaml +43 -0
- periplus/packs/drupal_basic@0.3.0/action/action.yaml +9 -0
- periplus/packs/drupal_basic@0.3.0/action/action_annotation.yaml +43 -0
- periplus/packs/drupal_basic@0.3.0/action/action_attribute.yaml +43 -0
- periplus/packs/drupal_basic@0.3.0/block/block_placement.yaml +16 -0
- periplus/packs/drupal_basic@0.3.0/block/block_placement_config.yaml +51 -0
- periplus/packs/drupal_basic@0.3.0/block_plugin/block_plugin.yaml +14 -0
- periplus/packs/drupal_basic@0.3.0/block_plugin/block_plugin_annotation.yaml +47 -0
- periplus/packs/drupal_basic@0.3.0/block_plugin/block_plugin_attribute.yaml +43 -0
- periplus/packs/drupal_basic@0.3.0/block_type/block_type.yaml +8 -0
- periplus/packs/drupal_basic@0.3.0/block_type/block_type_config.yaml +54 -0
- periplus/packs/drupal_basic@0.3.0/boundary/boundary_types.yaml +19 -0
- periplus/packs/drupal_basic@0.3.0/bundle/bundle.yaml +20 -0
- periplus/packs/drupal_basic@0.3.0/bundle/bundle_config.yaml +393 -0
- periplus/packs/drupal_basic@0.3.0/call/call.yaml +349 -0
- periplus/packs/drupal_basic@0.3.0/component/component.yaml +30 -0
- periplus/packs/drupal_basic@0.3.0/config/config_object.yaml +119 -0
- periplus/packs/drupal_basic@0.3.0/constraint/constraint.yaml +8 -0
- periplus/packs/drupal_basic@0.3.0/constraint/constraint_annotation.yaml +43 -0
- periplus/packs/drupal_basic@0.3.0/constraint/constraint_attribute.yaml +43 -0
- periplus/packs/drupal_basic@0.3.0/display/display.yaml +30 -0
- periplus/packs/drupal_basic@0.3.0/display/display_config.yaml +203 -0
- periplus/packs/drupal_basic@0.3.0/display/display_mode_config.yaml +60 -0
- periplus/packs/drupal_basic@0.3.0/entity_type/config_entity_type_annotation.yaml +46 -0
- periplus/packs/drupal_basic@0.3.0/entity_type/config_entity_type_attribute.yaml +43 -0
- periplus/packs/drupal_basic@0.3.0/entity_type/content_entity_type_annotation.yaml +46 -0
- periplus/packs/drupal_basic@0.3.0/entity_type/content_entity_type_attribute.yaml +43 -0
- periplus/packs/drupal_basic@0.3.0/entity_type/entity_type.yaml +16 -0
- periplus/packs/drupal_basic@0.3.0/field/field_instance_config.yaml +116 -0
- periplus/packs/drupal_basic@0.3.0/field/field_storage.yaml +21 -0
- periplus/packs/drupal_basic@0.3.0/field/field_storage_config.yaml +45 -0
- periplus/packs/drupal_basic@0.3.0/field_formatter/field_formatter.yaml +8 -0
- periplus/packs/drupal_basic@0.3.0/field_formatter/field_formatter_annotation.yaml +46 -0
- periplus/packs/drupal_basic@0.3.0/field_formatter/field_formatter_attribute.yaml +43 -0
- periplus/packs/drupal_basic@0.3.0/field_type/field_type_annotation.yaml +46 -0
- periplus/packs/drupal_basic@0.3.0/field_type/field_type_attribute.yaml +50 -0
- periplus/packs/drupal_basic@0.3.0/field_widget/field_widget_annotation.yaml +46 -0
- periplus/packs/drupal_basic@0.3.0/field_widget/field_widget_attribute.yaml +50 -0
- periplus/packs/drupal_basic@0.3.0/form/form_id.yaml +80 -0
- periplus/packs/drupal_basic@0.3.0/hook/hook.yaml +100 -0
- periplus/packs/drupal_basic@0.3.0/hook/hook_attribute.yaml +64 -0
- periplus/packs/drupal_basic@0.3.0/hook/hook_theme_include.yaml +34 -0
- periplus/packs/drupal_basic@0.3.0/library/library.yaml +12 -0
- periplus/packs/drupal_basic@0.3.0/library/library_definition.yaml +58 -0
- periplus/packs/drupal_basic@0.3.0/local_action/local_action.yaml +12 -0
- periplus/packs/drupal_basic@0.3.0/local_action/local_action_definition.yaml +49 -0
- periplus/packs/drupal_basic@0.3.0/mail/mail.yaml +8 -0
- periplus/packs/drupal_basic@0.3.0/mail/mail_attribute.yaml +43 -0
- periplus/packs/drupal_basic@0.3.0/media_source/media_source.yaml +8 -0
- periplus/packs/drupal_basic@0.3.0/media_source/media_source_annotation.yaml +43 -0
- periplus/packs/drupal_basic@0.3.0/media_source/media_source_attribute.yaml +79 -0
- periplus/packs/drupal_basic@0.3.0/menu_link/menu_link.yaml +18 -0
- periplus/packs/drupal_basic@0.3.0/menu_link/menu_link_definition.yaml +48 -0
- periplus/packs/drupal_basic@0.3.0/module/module.yaml +7 -0
- periplus/packs/drupal_basic@0.3.0/module/module_info.yaml +58 -0
- periplus/packs/drupal_basic@0.3.0/pack.yaml +528 -0
- periplus/packs/drupal_basic@0.3.0/permission/permission.yaml +7 -0
- periplus/packs/drupal_basic@0.3.0/permission/permission_definition.yaml +27 -0
- periplus/packs/drupal_basic@0.3.0/queue_worker/queue_worker.yaml +9 -0
- periplus/packs/drupal_basic@0.3.0/queue_worker/queue_worker_annotation.yaml +43 -0
- periplus/packs/drupal_basic@0.3.0/queue_worker/queue_worker_attribute.yaml +43 -0
- periplus/packs/drupal_basic@0.3.0/rest_resource/rest_resource.yaml +8 -0
- periplus/packs/drupal_basic@0.3.0/rest_resource/rest_resource_annotation.yaml +43 -0
- periplus/packs/drupal_basic@0.3.0/rest_resource/rest_resource_attribute.yaml +43 -0
- periplus/packs/drupal_basic@0.3.0/role/role.yaml +14 -0
- periplus/packs/drupal_basic@0.3.0/role/role_config.yaml +44 -0
- periplus/packs/drupal_basic@0.3.0/route/route.yaml +42 -0
- periplus/packs/drupal_basic@0.3.0/route/route_definition.yaml +113 -0
- periplus/packs/drupal_basic@0.3.0/route/route_options.yaml +55 -0
- periplus/packs/drupal_basic@0.3.0/route/route_requirements.yaml +108 -0
- periplus/packs/drupal_basic@0.3.0/service/service.yaml +56 -0
- periplus/packs/drupal_basic@0.3.0/service/service_definition.yaml +181 -0
- periplus/packs/drupal_basic@0.3.0/template/template.yaml +86 -0
- periplus/packs/drupal_basic@0.3.0/template/template_route_link.yaml +30 -0
- periplus/packs/drupal_basic@0.3.0/theme/theme.yaml +15 -0
- periplus/packs/drupal_basic@0.3.0/theme/theme_info.yaml +61 -0
- periplus/packs/drupal_basic@0.3.0/theme_hook/template_suggestion.yaml +29 -0
- periplus/packs/drupal_basic@0.3.0/theme_hook/theme_hook.yaml +87 -0
- periplus/packs/drupal_basic@0.3.0/theme_hook/theme_hook_render.yaml +20 -0
- periplus/packs/drupal_basic@0.3.0/url/url.yaml +88 -0
- periplus/packs/drupal_basic@0.3.0/views_plugin/views_field_attribute.yaml +80 -0
- periplus/packs/drupal_basic@0.3.0/views_plugin/views_filter_attribute.yaml +80 -0
- periplus/packs/drupal_basic@0.3.0/views_plugin/views_plugin.yaml +15 -0
- periplus/packs/drupal_basic@0.3.0/views_plugin/views_style_attribute.yaml +80 -0
- periplus/packs/drupal_js_basic@0.0.1/attachment/attachment.yaml +12 -0
- periplus/packs/drupal_js_basic@0.0.1/attachment/attachment_in_php.yaml +15 -0
- periplus/packs/drupal_js_basic@0.0.1/attachment/attachment_in_php_array.yaml +52 -0
- periplus/packs/drupal_js_basic@0.0.1/attachment/attachment_in_twig.yaml +26 -0
- periplus/packs/drupal_js_basic@0.0.1/attachment/php_function_holder.yaml +13 -0
- periplus/packs/drupal_js_basic@0.0.1/behavior/behavior.yaml +198 -0
- periplus/packs/drupal_js_basic@0.0.1/pack.yaml +153 -0
- periplus/packs/drupal_js_basic@0.0.1/setting/setting.yaml +13 -0
- periplus/packs/drupal_js_basic@0.0.1/setting/setting_in_js.yaml +15 -0
- periplus/packs/drupal_js_basic@0.0.1/setting/setting_in_php.yaml +92 -0
- periplus/packs/drush_basic@0.0.1/command/command.yaml +15 -0
- periplus/packs/drush_basic@0.0.1/command/command_annotation.yaml +60 -0
- periplus/packs/drush_basic@0.0.1/command/command_attribute.yaml +88 -0
- periplus/packs/drush_basic@0.0.1/pack.yaml +29 -0
- periplus/packs/eck_basic@0.0.1/bundle/eck_bundle_config.yaml +56 -0
- periplus/packs/eck_basic@0.0.1/entity_type/eck_entity_type_config.yaml +26 -0
- periplus/packs/eck_basic@0.0.1/pack.yaml +28 -0
- periplus/packs/go@0.0.2/interfaces/satisfies.yaml +47 -0
- periplus/packs/go@0.0.2/pack.yaml +51 -0
- periplus/packs/go@0.0.2/types/find_declarations.yaml +137 -0
- periplus/packs/go@0.0.2/types/node_types.yaml +36 -0
- periplus/packs/go_basic@0.0.3/pack.yaml +104 -0
- periplus/packs/go_basic@0.0.3/rules/calls.yaml +25 -0
- periplus/packs/go_basic@0.0.3/rules/declarations.yaml +40 -0
- periplus/packs/go_basic@0.0.3/rules/imports.yaml +16 -0
- periplus/packs/go_basic@0.0.3/types/node_types.yaml +15 -0
- periplus/packs/js_basic@0.0.1/function/function.yaml +68 -0
- periplus/packs/js_basic@0.0.1/pack.yaml +50 -0
- periplus/packs/laravel_basic@0.0.5/pack.yaml +313 -0
- periplus/packs/laravel_basic@0.0.5/rules/classes.yaml +42 -0
- periplus/packs/laravel_basic@0.0.5/rules/config.yaml +229 -0
- periplus/packs/laravel_basic@0.0.5/rules/routes.yaml +210 -0
- periplus/packs/laravel_basic@0.0.5/rules/types.yaml +50 -0
- periplus/packs/laravel_basic@0.0.5/rules/views.yaml +100 -0
- periplus/packs/paragraphs_basic@0.0.1/bundle/paragraph_bundle_config.yaml +54 -0
- periplus/packs/paragraphs_basic@0.0.1/pack.yaml +12 -0
- periplus/packs/php@0.1.0/edges/edge_kinds.yaml +64 -0
- periplus/packs/php@0.1.0/edges/find_calls.yaml +34 -0
- periplus/packs/php@0.1.0/edges/find_imports.yaml +18 -0
- periplus/packs/php@0.1.0/edges/find_member_access.yaml +22 -0
- periplus/packs/php@0.1.0/edges/find_structure.yaml +38 -0
- periplus/packs/php@0.1.0/embedded/embedded_regions.yaml +19 -0
- periplus/packs/php@0.1.0/imports/imports.yaml +20 -0
- periplus/packs/php@0.1.0/pack.yaml +117 -0
- periplus/packs/php@0.1.0/resolution/excluded_tokens.yaml +23 -0
- periplus/packs/php@0.1.0/resolution/resolution.yaml +35 -0
- periplus/packs/php@0.1.0/types/find_declarations.yaml +102 -0
- periplus/packs/php@0.1.0/types/node_types.yaml +55 -0
- periplus/packs/php_basic@0.2.0/edges/edge_kinds.yaml +48 -0
- periplus/packs/php_basic@0.2.0/edges/find_structure.yaml +750 -0
- periplus/packs/php_basic@0.2.0/imports/imports.yaml +19 -0
- periplus/packs/php_basic@0.2.0/pack.yaml +94 -0
- periplus/packs/php_basic@0.2.0/types/find_declarations.yaml +267 -0
- periplus/packs/php_basic@0.2.0/types/node_types.yaml +55 -0
- periplus/packs/profile_basic@0.0.1/bundle/profile_bundle_config.yaml +54 -0
- periplus/packs/profile_basic@0.0.1/pack.yaml +12 -0
- periplus/packs/salesforce_basic@0.0.1/event/salesforce_event.yaml +36 -0
- periplus/packs/salesforce_basic@0.0.1/pack.yaml +31 -0
- periplus/packs/salesforce_basic@0.0.1/salesforce_mapping/salesforce_mapping.yaml +19 -0
- periplus/packs/salesforce_basic@0.0.1/salesforce_mapping/salesforce_mapping_config.yaml +83 -0
- periplus/packs/salesforce_basic@0.0.1/salesforce_mapping_field/salesforce_mapping_field.yaml +8 -0
- periplus/packs/salesforce_basic@0.0.1/salesforce_mapping_field/salesforce_mapping_field_annotation.yaml +43 -0
- periplus/packs/twig@0.0.1/pack.yaml +26 -0
- periplus/packs/twig@0.0.1/types/template.yaml +57 -0
- periplus/packs/twig_basic@0.1.0/pack.yaml +11 -0
- periplus/packs/twig_tweak_basic@0.0.1/pack.yaml +27 -0
- periplus/packs/twig_tweak_basic@0.0.1/rules/block.yaml +20 -0
- periplus/packs/twig_tweak_basic@0.0.1/rules/entity.yaml +35 -0
- periplus/packs/twig_tweak_basic@0.0.1/rules/field.yaml +21 -0
- periplus/packs/twig_tweak_basic@0.0.1/rules/menu.yaml +21 -0
- periplus/packs/webform_basic@0.0.1/bundle/webform_submission_bundle_config.yaml +54 -0
- periplus/packs/webform_basic@0.0.1/pack.yaml +20 -0
- periplus/packs/webform_basic@0.0.1/webform_handler/webform_handler.yaml +8 -0
- periplus/packs/webform_basic@0.0.1/webform_handler/webform_handler_annotation.yaml +43 -0
- periplus/packs/yaml@0.0.1/pack.yaml +72 -0
- periplus/packs/yaml@0.0.1/types/find_mapping_entry.yaml +21 -0
- periplus/packs/yaml@0.0.1/types/yaml_types.yaml +44 -0
- periplus/packs/yaml_basic@0.1.0/pack.yaml +10 -0
- periplus/packs.py +447 -0
- periplus/preflight.py +102 -0
- periplus/py.typed +0 -0
- periplus/report.py +596 -0
- periplus/resolution.py +355 -0
- periplus/settings.py +617 -0
- periplus/settings.stub.yml +99 -0
- periplus/spec.py +774 -0
- periplus/update.py +197 -0
- periplus/validate.py +655 -0
- periplus_map-0.2.1.dist-info/METADATA +566 -0
- periplus_map-0.2.1.dist-info/RECORD +272 -0
- periplus_map-0.2.1.dist-info/WHEEL +4 -0
- periplus_map-0.2.1.dist-info/entry_points.txt +2 -0
- periplus_map-0.2.1.dist-info/licenses/LICENSE +202 -0
- periplus_map-0.2.1.dist-info/licenses/NOTICE +2 -0
periplus/update.py
ADDED
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
"""``periplus update``: move a project's pins to the rutter versions that are installed.
|
|
2
|
+
|
|
3
|
+
The installed version of a name is read off the same roots and candidates ``resolve`` builds, so
|
|
4
|
+
what this command writes is what ``map`` loads. When more than one root ships the name, the first
|
|
5
|
+
root in ``resolve_pack_roots`` order that holds it supplies the version: project, user config,
|
|
6
|
+
bundled, then ``pack_paths``. That is this module's rule, stated here; the resolver's order never
|
|
7
|
+
decides an outcome. A name the project root holds is kept, because the project copy is what is
|
|
8
|
+
installed for that project. A pin moves downward as well as upward, and the report says so, because
|
|
9
|
+
a pin nothing on the search path ships cannot be mapped at all.
|
|
10
|
+
|
|
11
|
+
``resolve`` reports a stale pin as ``PIN_UNMATCHED`` and two copies as ``PIN_DUPLICATED``. Both are
|
|
12
|
+
the cases this command serves, so neither is carried into its report. Every other resolution
|
|
13
|
+
problem is, and ends the run before the file is touched.
|
|
14
|
+
|
|
15
|
+
The file is read and written through ruamel's round-trip loader so its comments survive. That is
|
|
16
|
+
the one thing the safe loader in ``settings.py`` cannot do.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
from __future__ import annotations
|
|
20
|
+
|
|
21
|
+
import json
|
|
22
|
+
import re
|
|
23
|
+
from collections.abc import Callable, Mapping
|
|
24
|
+
from dataclasses import dataclass
|
|
25
|
+
from pathlib import Path
|
|
26
|
+
|
|
27
|
+
from ruamel.yaml import YAML
|
|
28
|
+
from ruamel.yaml.error import YAMLError
|
|
29
|
+
|
|
30
|
+
from periplus.errors import ExitCode, Problem
|
|
31
|
+
from periplus.layout import PROJECT_MARKER, SETTINGS_FILENAME
|
|
32
|
+
from periplus.packs import parse_pack_name
|
|
33
|
+
from periplus.preflight import DependencyStatus
|
|
34
|
+
from periplus.report import _escape
|
|
35
|
+
from periplus.resolution import resolve
|
|
36
|
+
|
|
37
|
+
__all__ = [
|
|
38
|
+
"RENDERERS",
|
|
39
|
+
"Change",
|
|
40
|
+
"Kept",
|
|
41
|
+
"UpdateReport",
|
|
42
|
+
"render_json",
|
|
43
|
+
"render_text",
|
|
44
|
+
"update_pins",
|
|
45
|
+
]
|
|
46
|
+
|
|
47
|
+
#: Where in the file the pin list sits, read off the text so the rewrite keeps the file's own
|
|
48
|
+
#: indentation of ``- `` rather than imposing one.
|
|
49
|
+
_FIRST_ITEM = re.compile(r"^packs:[^\n]*\n(?:[ \t]*(?:#[^\n]*)?\n)*?( *)- ", re.MULTILINE)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
@dataclass(frozen=True, slots=True)
|
|
53
|
+
class Change:
|
|
54
|
+
"""A pin moved: the rutter's name, the version it was pinned at, and the version now."""
|
|
55
|
+
|
|
56
|
+
name: str
|
|
57
|
+
old: str
|
|
58
|
+
new: str
|
|
59
|
+
also_available: tuple[str, ...]
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
@dataclass(frozen=True, slots=True)
|
|
63
|
+
class Kept:
|
|
64
|
+
"""A pin left as it was, and why."""
|
|
65
|
+
|
|
66
|
+
pin: str
|
|
67
|
+
reason: str
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
@dataclass(frozen=True, slots=True)
|
|
71
|
+
class UpdateReport:
|
|
72
|
+
changed: tuple[Change, ...]
|
|
73
|
+
kept: tuple[Kept, ...]
|
|
74
|
+
problems: tuple[Problem, ...]
|
|
75
|
+
|
|
76
|
+
@property
|
|
77
|
+
def exit_code(self) -> ExitCode:
|
|
78
|
+
"""The lowest code among the problems, or ``OK`` when there were none."""
|
|
79
|
+
return min((problem.code for problem in self.problems), default=ExitCode.OK)
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def update_pins(
|
|
83
|
+
start: Path, env: Mapping[str, str], dependencies: tuple[DependencyStatus, ...]
|
|
84
|
+
) -> UpdateReport:
|
|
85
|
+
"""Rewrite each pin whose name an installed rutter ships, and report every pin either way."""
|
|
86
|
+
resolution = resolve(start=start, env=env, dependencies=dependencies)
|
|
87
|
+
carried = tuple(
|
|
88
|
+
problem
|
|
89
|
+
for problem in resolution.problems
|
|
90
|
+
if problem.code not in (ExitCode.PIN_UNMATCHED, ExitCode.PIN_DUPLICATED)
|
|
91
|
+
)
|
|
92
|
+
path = (
|
|
93
|
+
resolution.project_root / PROJECT_MARKER / SETTINGS_FILENAME
|
|
94
|
+
if resolution.project_root is not None
|
|
95
|
+
else None
|
|
96
|
+
)
|
|
97
|
+
if carried:
|
|
98
|
+
return UpdateReport((), (), carried)
|
|
99
|
+
if path is None or not path.is_file():
|
|
100
|
+
message = f"no {PROJECT_MARKER}/{SETTINGS_FILENAME} found for this project"
|
|
101
|
+
return UpdateReport((), (), (Problem(ExitCode.NO_SETTINGS, message, {}),))
|
|
102
|
+
|
|
103
|
+
text = path.read_text(encoding="utf-8")
|
|
104
|
+
yaml = YAML(typ="rt")
|
|
105
|
+
yaml.preserve_quotes = True
|
|
106
|
+
match = _FIRST_ITEM.search(text)
|
|
107
|
+
offset = len(match.group(1)) if match else 0
|
|
108
|
+
yaml.indent(mapping=2, sequence=offset + 2, offset=offset)
|
|
109
|
+
try:
|
|
110
|
+
document = yaml.load(text)
|
|
111
|
+
except YAMLError as error:
|
|
112
|
+
problem = Problem(ExitCode.UNREADABLE_SETTINGS, f"{path} is not valid YAML: {error}", {})
|
|
113
|
+
return UpdateReport((), (), (problem,))
|
|
114
|
+
pins = document.get("packs") if hasattr(document, "get") else None
|
|
115
|
+
if not isinstance(pins, list):
|
|
116
|
+
return UpdateReport((), (), ())
|
|
117
|
+
|
|
118
|
+
changed: list[Change] = []
|
|
119
|
+
kept: list[Kept] = []
|
|
120
|
+
for index, item in enumerate(pins):
|
|
121
|
+
name = parse_pack_name(str(item))
|
|
122
|
+
holders = [
|
|
123
|
+
(candidate.root.kind, candidate.name.version)
|
|
124
|
+
for candidate in resolution.candidates
|
|
125
|
+
if candidate.status == "named"
|
|
126
|
+
and candidate.name is not None
|
|
127
|
+
and name is not None
|
|
128
|
+
and candidate.name.pack == name.pack
|
|
129
|
+
]
|
|
130
|
+
if name is None or not holders:
|
|
131
|
+
kept.append(Kept(str(item), "not shipped by any rutter on the search path"))
|
|
132
|
+
elif holders[0][0] in ("project", "configured"):
|
|
133
|
+
where = "the project's own packs" if holders[0][0] == "project" else "a pack_paths root"
|
|
134
|
+
kept.append(Kept(str(item), f"shipped from {where}"))
|
|
135
|
+
elif holders[0][1] == name.version:
|
|
136
|
+
kept.append(Kept(str(item), "already current"))
|
|
137
|
+
else:
|
|
138
|
+
new = holders[0][1]
|
|
139
|
+
pins[index] = type(item)(f"{name.pack}@{new}")
|
|
140
|
+
others = tuple(sorted({version for _, version in holders[1:] if version != new}))
|
|
141
|
+
changed.append(Change(name.pack, name.version, new, others))
|
|
142
|
+
if changed:
|
|
143
|
+
with path.open("w", encoding="utf-8") as handle:
|
|
144
|
+
yaml.dump(document, handle)
|
|
145
|
+
return UpdateReport(tuple(changed), tuple(kept), ())
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def _newer(change: Change) -> bool:
|
|
149
|
+
def numbers(version: str) -> tuple[int, ...]:
|
|
150
|
+
return tuple(int(part) for part in re.findall(r"\d+", version))
|
|
151
|
+
|
|
152
|
+
return numbers(change.new) >= numbers(change.old)
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
def render_text(report: UpdateReport) -> str:
|
|
156
|
+
"""One line per changed pin as ``name: old -> new``, one per kept pin with its reason."""
|
|
157
|
+
lines: list[str] = []
|
|
158
|
+
for change in report.changed:
|
|
159
|
+
line = f"{_escape(change.name)}: {_escape(change.old)} -> {_escape(change.new)}"
|
|
160
|
+
if not _newer(change):
|
|
161
|
+
line += " (a lower version than the pin)"
|
|
162
|
+
if change.also_available:
|
|
163
|
+
line += f" (also available: {_escape(', '.join(change.also_available))})"
|
|
164
|
+
lines.append(line)
|
|
165
|
+
lines += [f"kept {_escape(kept.pin)}: {_escape(kept.reason)}" for kept in report.kept]
|
|
166
|
+
lines += [_escape(problem.message) for problem in report.problems]
|
|
167
|
+
return "\n".join(lines) + "\n" if lines else ""
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
def render_json(report: UpdateReport) -> str:
|
|
171
|
+
"""The report as one JSON document, keys sorted, ``ensure_ascii=True``."""
|
|
172
|
+
payload = {
|
|
173
|
+
"changed": [
|
|
174
|
+
{
|
|
175
|
+
"name": change.name,
|
|
176
|
+
"old": change.old,
|
|
177
|
+
"new": change.new,
|
|
178
|
+
"downward": not _newer(change),
|
|
179
|
+
"also_available": list(change.also_available),
|
|
180
|
+
}
|
|
181
|
+
for change in report.changed
|
|
182
|
+
],
|
|
183
|
+
"kept": [{"pin": kept.pin, "reason": kept.reason} for kept in report.kept],
|
|
184
|
+
"problems": [
|
|
185
|
+
{"code": int(p.code), "message": p.message, "detail": dict(p.detail)}
|
|
186
|
+
for p in report.problems
|
|
187
|
+
],
|
|
188
|
+
}
|
|
189
|
+
return json.dumps(payload, sort_keys=True, indent=2, ensure_ascii=True) + "\n"
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
#: The formats ``update --format`` offers. ``cli.build_parser`` writes the same two names as a
|
|
193
|
+
#: literal, because ``cli`` may not import this module.
|
|
194
|
+
RENDERERS: Mapping[str, Callable[[UpdateReport], str]] = {
|
|
195
|
+
"text": render_text,
|
|
196
|
+
"json": render_json,
|
|
197
|
+
}
|