diff --git a/.github/validate_customizations.py b/.github/validate_customizations.py deleted file mode 100644 index 502a8257..00000000 --- a/.github/validate_customizations.py +++ /dev/null @@ -1,166 +0,0 @@ -import json -import pathlib -import sys - - -def scrub(txt: str) -> str: - """Returns sluggified string. e.g. `Sales Order` becomes `sales_order`.""" - return txt.replace(" ", "_").replace("-", "_").lower() - - -def unscrub(txt: str) -> str: - """Returns titlified string. e.g. `sales_order` becomes `Sales Order`.""" - return txt.replace("_", " ").replace("-", " ").title() - - -def get_customized_doctypes(): - apps_dir = pathlib.Path(__file__).resolve().parent.parent.parent - apps_order = pathlib.Path(__file__).resolve().parent.parent.parent.parent / "sites" / "apps.txt" - apps_order = apps_order.read_text().split("\n") - customized_doctypes = {} - for _app_dir in apps_order: - app_dir = (apps_dir / _app_dir).resolve() - if not app_dir.is_dir(): - continue - modules = (app_dir / _app_dir / "modules.txt").read_text().split("\n") - for module in modules: - if not (app_dir / _app_dir / scrub(module) / "custom").exists(): - continue - for custom_file in list((app_dir / _app_dir / scrub(module) / "custom").glob("**/*.json")): - if custom_file.stem in customized_doctypes: - customized_doctypes[custom_file.stem].append(custom_file.resolve()) - else: - customized_doctypes[custom_file.stem] = [custom_file.resolve()] - - return dict(sorted(customized_doctypes.items())) - - -def validate_module(customized_doctypes, set_module=False): - exceptions = [] - app_dir = pathlib.Path(__file__).resolve().parent.parent - this_app = app_dir.stem - for doctype, customize_files in customized_doctypes.items(): - for customize_file in customize_files: - if not this_app == customize_file.parent.parent.parent.parent.stem: - continue - module = customize_file.parent.parent.stem - file_contents = json.loads(customize_file.read_text()) - if file_contents.get("custom_fields"): - for custom_field in file_contents.get("custom_fields"): - if set_module: - custom_field["module"] = unscrub(module) - continue - if not custom_field.get("module"): - exceptions.append( - f"Custom Field for {custom_field.get('dt')} in {this_app} '{custom_field.get('fieldname')}' does not have a module key" - ) - continue - elif custom_field.get("module") != unscrub(module): - exceptions.append( - f"Custom Field for {custom_field.get('dt')} in {this_app} '{custom_field.get('fieldname')}' has module key ({custom_field.get('module')}) associated with another app" - ) - continue - if file_contents.get("property_setters"): - for ps in file_contents.get("property_setters"): - if set_module: - ps["module"] = unscrub(module) - continue - if not ps.get("module"): - exceptions.append( - f"Property Setter for {ps.get('doc_type')} in {this_app} '{ps.get('property')}' on {ps.get('field_name')} does not have a module key" - ) - continue - elif ps.get("module") != unscrub(module): - exceptions.append( - f"Property Setter for {ps.get('doc_type')} in {this_app} '{ps.get('property')}' on {ps.get('field_name')} has module key ({ps.get('module')}) associated with another app" - ) - continue - if set_module: - with customize_file.open("w", encoding="UTF-8") as target: - json.dump(file_contents, target, sort_keys=True, indent=2) - - return exceptions - - -def validate_no_custom_perms(customized_doctypes): - exceptions = [] - this_app = pathlib.Path(__file__).resolve().parent.parent.stem - for doctype, customize_files in customized_doctypes.items(): - for customize_file in customize_files: - if not this_app == customize_file.parent.parent.parent.parent.stem: - continue - file_contents = json.loads(customize_file.read_text()) - if file_contents.get("custom_perms"): - exceptions.append(f"Customization for {doctype} in {this_app} contains custom permissions") - return exceptions - - -def validate_duplicate_customizations(customized_doctypes): - exceptions = [] - common_fields = {} - common_property_setters = {} - app_dir = pathlib.Path(__file__).resolve().parent.parent - this_app = app_dir.stem - for doctype, customize_files in customized_doctypes.items(): - if len(customize_files) == 1: - continue - common_fields[doctype] = {} - common_property_setters[doctype] = {} - for customize_file in customize_files: - module = customize_file.parent.parent.stem - app = customize_file.parent.parent.parent.parent.stem - file_contents = json.loads(customize_file.read_text()) - if file_contents.get("custom_fields"): - fields = [cf.get("fieldname") for cf in file_contents.get("custom_fields")] - common_fields[doctype][module] = fields - if file_contents.get("property_setters"): - ps = [ps.get("name") for ps in file_contents.get("property_setters")] - common_property_setters[doctype][module] = ps - - for doctype, module_and_fields in common_fields.items(): - if this_app not in module_and_fields.keys(): - continue - this_modules_fields = module_and_fields.pop(this_app) - for module, fields in module_and_fields.items(): - for field in fields: - if field in this_modules_fields: - exceptions.append( - f"Custom Field for {unscrub(doctype)} in {this_app} '{field}' also appears in customizations for {module}" - ) - - for doctype, module_and_ps in common_property_setters.items(): - if this_app not in module_and_ps.keys(): - continue - this_modules_ps = module_and_ps.pop(this_app) - for module, ps in module_and_ps.items(): - for p in ps: - if p in this_modules_ps: - exceptions.append( - f"Property Setter for {unscrub(doctype)} in {this_app} on '{p}' also appears in customizations for {module}" - ) - - return exceptions - - -def validate_customizations(set_module): - customized_doctypes = get_customized_doctypes() - exceptions = validate_no_custom_perms(customized_doctypes) - exceptions += validate_module(customized_doctypes, set_module) - exceptions += validate_duplicate_customizations(customized_doctypes) - - return exceptions - - -if __name__ == "__main__": - exceptions = [] - set_module = False - for arg in sys.argv: - if arg == "--set-module": - set_module = True - exceptions.append(validate_customizations(set_module)) - - if exceptions: - for exception in exceptions: - [print(e) for e in exception] # TODO: colorize - - sys.exit(1) if all(exceptions) else sys.exit(0) diff --git a/.github/workflows/print_format_diff.yml b/.github/workflows/print_format_diff.yml index 28500ed5..2e9a308c 100644 --- a/.github/workflows/print_format_diff.yml +++ b/.github/workflows/print_format_diff.yml @@ -1,4 +1,4 @@ -name: Print Format Diff +name: Diff Print Formats on: pull_request: @@ -9,14 +9,9 @@ on: jobs: diff_print_format: runs-on: ubuntu-latest - name: Print Format Diff + name: Diff Print Formats steps: - - name: Checkout the code - uses: actions/checkout@v3 + - name: Diff Print Formats + uses: agritheory/test_utils/actions/diff_print_format@main with: - fetch-depth: 0 - - - name: Print Format Diff - uses: diamorafaela/diff-print-format@main - with: - github-token: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file + github-token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 8c61e732..3290d2f5 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -4,7 +4,7 @@ fail_fast: false repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v5.0.0 + rev: v6.0.0 hooks: - id: trailing-whitespace files: 'check_run.*' @@ -45,7 +45,7 @@ repos: additional_dependencies: ['flake8-bugbear'] - repo: https://github.com/agritheory/test_utils - rev: v1.15.4 + rev: v1.16.0 hooks: - id: update_pre_commit_config - id: validate_frappe_project @@ -61,6 +61,8 @@ repos: args: ['--app', 'check_run'] - id: track_overrides args: ['--directory', '.', '--app', 'check_run', '--base-branch', 'version-15'] + - id: check_code_duplication + args: ['--max-clones', '60', '--max-percentage', '5.0'] - repo: https://github.com/pre-commit/mirrors-prettier rev: v3.1.0 diff --git a/CHANGELOG.md b/CHANGELOG.md index ca5490ce..32e2eb47 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1465,3 +1465,7 @@ Co-authored-by: fproldan <fproldan@users.noreply.github.com> ([`a698431`]( * look up party on PE submission to avoid renaming problems ([#67](https://github.com/agritheory/check_run/issues/67)) ([4cdf7de](https://github.com/agritheory/check_run/commit/4cdf7de5d648bcd37cb19ce67d899804f7107ad3)) * split checks by address ([f091550](https://github.com/agritheory/check_run/commit/f09155050ea8a64ee7fdb3ba8f3596eb936fd871)) * validate docstatus of selected invoices in Check Run still saved/submitted ([9bf5605](https://github.com/agritheory/check_run/commit/9bf56054041c341fc23c4cdf0a9449ca32ef8ba5)) + + + + diff --git a/check_run/public/js/check_run/check_run_quick_entry.js b/check_run/public/js/check_run/check_run_quick_entry.js index 1a4d1b48..ca170745 100644 --- a/check_run/public/js/check_run/check_run_quick_entry.js +++ b/check_run/public/js/check_run/check_run_quick_entry.js @@ -5,6 +5,7 @@ frappe.provide('check_run') frappe.provide('frappe.ui.form') frappe.ui.form.CheckRunQuickEntryForm = class CheckRunQuickEntryForm extends frappe.ui.form.QuickEntryForm { + /* jscpd:ignore-start */ constructor(doctype, after_insert, init_callback, doc, force) { super(doctype, after_insert, init_callback, doc, force) } @@ -75,6 +76,7 @@ frappe.ui.form.CheckRunQuickEntryForm = class CheckRunQuickEntryForm extends fra }) } } + /* jscpd:ignore-end */ register_primary_action() { const me = this this.dialog.set_primary_action(__('Start Check Run'), () => { diff --git a/check_run/public/js/check_run/check_run_settings_quick_entry.js b/check_run/public/js/check_run/check_run_settings_quick_entry.js index 8688b779..1bcc6061 100644 --- a/check_run/public/js/check_run/check_run_settings_quick_entry.js +++ b/check_run/public/js/check_run/check_run_settings_quick_entry.js @@ -4,7 +4,10 @@ frappe.provide('check_run') frappe.provide('frappe.ui.form') -frappe.ui.form.CheckRunSettingsQuickEntryForm = class CheckRunQuickEntryForm extends frappe.ui.form.QuickEntryForm { +frappe.ui.form.CheckRunSettingsQuickEntryForm = class CheckRunSettingsQuickEntryForm extends ( + frappe.ui.form.QuickEntryForm +) { + /* jscpd:ignore-start */ constructor(doctype, after_insert, init_callback, doc, force) { super(doctype, after_insert, init_callback, doc, force) } @@ -75,4 +78,5 @@ frappe.ui.form.CheckRunSettingsQuickEntryForm = class CheckRunQuickEntryForm ext }) } } + /* jscpd:ignore-end */ }