diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index 4faece896a..f02694846d 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -10,3 +10,6 @@ # Replace use of Class.extend with native JS class fe20515c23a3ac41f1092bf0eaf0a0a452ec2e85 + +# Updating license headers +34460265554242a8d05fb09f049033b1117e1a2b diff --git a/.github/helper/install.sh b/.github/helper/install.sh index f6f0cad31a..93189d2b1f 100644 --- a/.github/helper/install.sh +++ b/.github/helper/install.sh @@ -17,6 +17,7 @@ if [ "$TYPE" == "server" ]; then fi if [ "$DB" == "mariadb" ];then + sudo apt install mariadb-client-10.3 mysql --host 127.0.0.1 --port 3306 -u root -e "SET GLOBAL character_set_server = 'utf8mb4'"; mysql --host 127.0.0.1 --port 3306 -u root -e "SET GLOBAL collation_server = 'utf8mb4_unicode_ci'"; @@ -58,4 +59,4 @@ cd ../.. bench start & bench --site test_site reinstall --yes if [ "$TYPE" == "server" ]; then bench --site test_site_producer reinstall --yes; fi -bench build --app frappe \ No newline at end of file +bench build --app frappe diff --git a/.github/workflows/docs-checker.yml b/.github/workflows/docs-checker.yml index 90453cd1b4..02a01bf4e4 100644 --- a/.github/workflows/docs-checker.yml +++ b/.github/workflows/docs-checker.yml @@ -12,7 +12,7 @@ jobs: - name: 'Setup Environment' uses: actions/setup-python@v2 with: - python-version: 3.6 + python-version: 3.7 - name: 'Clone repo' uses: actions/checkout@v2 diff --git a/.github/workflows/patch-mariadb-tests.yml b/.github/workflows/patch-mariadb-tests.yml index 0dd4cd51d8..3ac5cfa349 100644 --- a/.github/workflows/patch-mariadb-tests.yml +++ b/.github/workflows/patch-mariadb-tests.yml @@ -9,7 +9,7 @@ concurrency: jobs: test: - runs-on: ubuntu-18.04 + runs-on: ubuntu-latest name: Patch Test diff --git a/.github/workflows/publish-assets-develop.yml b/.github/workflows/publish-assets-develop.yml index a23885b508..85f3f7c3b0 100644 --- a/.github/workflows/publish-assets-develop.yml +++ b/.github/workflows/publish-assets-develop.yml @@ -18,7 +18,7 @@ jobs: node-version: 14 - uses: actions/setup-python@v2 with: - python-version: '3.6' + python-version: '3.7' - name: Set up bench and build assets run: | npm install -g yarn diff --git a/.github/workflows/publish-assets-releases.yml b/.github/workflows/publish-assets-releases.yml index a697517c23..a5cc1f8872 100644 --- a/.github/workflows/publish-assets-releases.yml +++ b/.github/workflows/publish-assets-releases.yml @@ -21,7 +21,7 @@ jobs: python-version: '12.x' - uses: actions/setup-python@v2 with: - python-version: '3.6' + python-version: '3.7' - name: Set up bench and build assets run: | npm install -g yarn diff --git a/.github/workflows/server-mariadb-tests.yml b/.github/workflows/server-mariadb-tests.yml index 57a7fa304d..0b187fc44c 100644 --- a/.github/workflows/server-mariadb-tests.yml +++ b/.github/workflows/server-mariadb-tests.yml @@ -13,7 +13,7 @@ concurrency: jobs: test: - runs-on: ubuntu-18.04 + runs-on: ubuntu-latest strategy: fail-fast: false @@ -121,9 +121,10 @@ jobs: ORCHESTRATOR_URL: http://test-orchestrator.frappe.io - name: Upload coverage data + if: ${{ steps.check-build.outputs.build == 'strawberry' }} uses: codecov/codecov-action@v2 with: name: MariaDB fail_ci_if_error: true files: /home/runner/frappe-bench/sites/coverage.xml - verbose: true + verbose: true \ No newline at end of file diff --git a/.github/workflows/server-postgres-tests.yml b/.github/workflows/server-postgres-tests.yml index 57ac9c6c60..a5630121a4 100644 --- a/.github/workflows/server-postgres-tests.yml +++ b/.github/workflows/server-postgres-tests.yml @@ -12,7 +12,7 @@ concurrency: jobs: test: - runs-on: ubuntu-18.04 + runs-on: ubuntu-latest strategy: fail-fast: false @@ -124,6 +124,7 @@ jobs: ORCHESTRATOR_URL: http://test-orchestrator.frappe.io - name: Upload coverage data + if: ${{ steps.check-build.outputs.build == 'strawberry' }} uses: codecov/codecov-action@v2 with: name: Postgres diff --git a/.github/workflows/translation_linter.yml b/.github/workflows/translation_linter.yml deleted file mode 100644 index 4becaebd6b..0000000000 --- a/.github/workflows/translation_linter.yml +++ /dev/null @@ -1,22 +0,0 @@ -name: Frappe Linter -on: - pull_request: - branches: - - develop - - version-12-hotfix - - version-11-hotfix -jobs: - check_translation: - name: Translation Syntax Check - runs-on: ubuntu-18.04 - steps: - - uses: actions/checkout@v2 - - name: Setup python3 - uses: actions/setup-python@v1 - with: - python-version: 3.6 - - name: Validating Translation Syntax - run: | - git fetch origin $GITHUB_BASE_REF:$GITHUB_BASE_REF -q - files=$(git diff --name-only --diff-filter=d $GITHUB_BASE_REF) - python $GITHUB_WORKSPACE/.github/helper/translation.py $files diff --git a/.github/workflows/ui-tests.yml b/.github/workflows/ui-tests.yml index 2a55546ec4..0727b06043 100644 --- a/.github/workflows/ui-tests.yml +++ b/.github/workflows/ui-tests.yml @@ -12,7 +12,7 @@ concurrency: jobs: test: - runs-on: ubuntu-18.04 + runs-on: ubuntu-latest strategy: fail-fast: false diff --git a/LICENSE b/LICENSE index 5dfc0fd5bd..6919960f8b 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License -Copyright (c) 2016-2018 Frappe Technologies Pvt. Ltd. +Copyright (c) 2016-2021 Frappe Technologies Pvt. Ltd. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/codecov.yml b/codecov.yml index eb81252b61..41b22001a5 100644 --- a/codecov.yml +++ b/codecov.yml @@ -1,9 +1,13 @@ codecov: require_ci_to_pass: yes + +coverage: status: project: default: + target: auto threshold: 0.5% + comment: - layout: "diff, flags, files" + layout: "diff" require_changes: true diff --git a/cypress/fixtures/doctype_with_tab_break.js b/cypress/fixtures/doctype_with_tab_break.js new file mode 100644 index 0000000000..bc346e8fb8 --- /dev/null +++ b/cypress/fixtures/doctype_with_tab_break.js @@ -0,0 +1,59 @@ +export default { + name: 'Form With Tab Break', + custom: 1, + actions: [], + doctype: 'DocType', + engine: 'InnoDB', + fields: [ + { + fieldname: 'username', + fieldtype: 'Data', + label: 'Name', + options: 'Name' + }, + { + fieldname: 'tab', + fieldtype: 'Tab Break', + label: 'Tab 2', + }, + { + fieldname: 'Phone', + fieldtype: 'Data', + label: 'Phone', + options: 'Phone', + reqd: 1 + }, + ], + links: [ + { + "group": "Profile", + "link_doctype": "Contact", + "link_fieldname": "user" + }, + { + "group": "Profile", + "link_doctype": "Chat Profile", + "link_fieldname": "user" + }, + ], + modified_by: 'Administrator', + module: 'Custom', + owner: 'Administrator', + permissions: [ + { + create: 1, + delete: 1, + email: 1, + print: 1, + read: 1, + role: 'System Manager', + share: 1, + write: 1 + } + ], + quick_entry: 1, + autoname: "format: Test-{####}", + sort_field: 'modified', + sort_order: 'ASC', + track_changes: 1 +}; diff --git a/cypress/integration/api.js b/cypress/integration/api.js index 7a5b1611b0..e8c39e6e25 100644 --- a/cypress/integration/api.js +++ b/cypress/integration/api.js @@ -31,8 +31,13 @@ context('API Resources', () => { }); it('Removes the Comments', () => { - cy.get_list('Comment').then(body => body.data.forEach(comment => { - cy.remove_doc('Comment', comment.name); - })); + cy.get_list('Comment').then(body => { + let comment_names = []; + body.data.map(comment => comment_names.push(comment.name)); + comment_names = [...new Set(comment_names)]; // remove duplicates + comment_names.forEach((comment_name) => { + cy.remove_doc('Comment', comment_name); + }); + }); }); }); diff --git a/cypress/integration/control_float.js b/cypress/integration/control_float.js new file mode 100644 index 0000000000..670d1fe73e --- /dev/null +++ b/cypress/integration/control_float.js @@ -0,0 +1,93 @@ +context("Control Float", () => { + before(() => { + cy.login(); + cy.visit("/app/website"); + }); + + function get_dialog_with_float() { + return cy.dialog({ + title: "Float Check", + fields: [ + { + fieldname: "float_number", + fieldtype: "Float", + Label: "Float" + } + ] + }); + } + + it("check value changes", () => { + get_dialog_with_float().as("dialog"); + + let data = get_data(); + data.forEach(x => { + cy.window() + .its("frappe") + .then(frappe => { + frappe.boot.sysdefaults.number_format = x.number_format; + }); + x.values.forEach(d => { + cy.get_field("float_number", "Float").clear(); + cy.fill_field("float_number", d.input, "Float").blur(); + cy.get_field("float_number", "Float").should( + "have.value", + d.blur_expected + ); + + cy.get_field("float_number", "Float").focus(); + cy.get_field("float_number", "Float").blur(); + cy.get_field("float_number", "Float").focus(); + cy.get_field("float_number", "Float").should( + "have.value", + d.focus_expected + ); + }); + }); + }); + + function get_data() { + return [ + { + number_format: "#.###,##", + values: [ + { + input: "364.87,334", + blur_expected: "36.487,334", + focus_expected: "36487.334" + }, + { + input: "36487,334", + blur_expected: "36.487,334", + focus_expected: "36487.334" + }, + { + input: "100", + blur_expected: "100,000", + focus_expected: "100" + } + ] + }, + { + number_format: "#,###.##", + values: [ + { + input: "364,87.334", + blur_expected: "36,487.334", + focus_expected: "36487.334" + }, + { + input: "36487.334", + blur_expected: "36,487.334", + focus_expected: "36487.334" + }, + { + input: "100", + blur_expected: "100.000", + focus_expected: "100" + } + ] + } + ]; + } +}); diff --git a/cypress/integration/datetime_field_form_validation.js b/cypress/integration/datetime_field_form_validation.js index 66fdde6863..ef47a0fbf7 100644 --- a/cypress/integration/datetime_field_form_validation.js +++ b/cypress/integration/datetime_field_form_validation.js @@ -1,19 +1,19 @@ -context('Datetime Field Validation', () => { - before(() => { - cy.login(); - cy.visit('/app/communication'); - cy.window().its('frappe').then(frappe => { - frappe.call("frappe.tests.ui_test_helpers.create_communication_records"); - }); - }); +// TODO: Enable this again +// currently this is flaky possibly because of different timezone in CI - // validating datetime field value when value is set from backend and get validated on form load. - it('datetime field form validation', () => { - cy.visit('/app/communication'); - cy.get('a[title="Test Form Communication 1"]').invoke('attr', 'data-name') - .then((name) => { - cy.visit(`/app/communication/${name}`); - cy.get('.indicator-pill').should('contain', 'Open').should('have.class', 'red'); - }); - }); -}); \ No newline at end of file +// context('Datetime Field Validation', () => { +// before(() => { +// cy.login(); +// cy.visit('/app/communication'); +// }); + +// it('datetime field form validation', () => { +// // validating datetime field value when value is set from backend and get validated on form load. +// cy.window().its('frappe').then(frappe => { +// return frappe.xcall("frappe.tests.ui_test_helpers.create_communication_record"); +// }).then(doc => { +// cy.visit(`/app/communication/${doc.name}`); +// cy.get('.indicator-pill').should('contain', 'Open').should('have.class', 'red'); +// }); +// }); +// }); \ No newline at end of file diff --git a/cypress/integration/form_tab_break.js b/cypress/integration/form_tab_break.js new file mode 100644 index 0000000000..45c3c92084 --- /dev/null +++ b/cypress/integration/form_tab_break.js @@ -0,0 +1,31 @@ +import doctype_with_tab_break from '../fixtures/doctype_with_tab_break'; +const doctype_name = doctype_with_tab_break.name; +context("Form Tab Break", () => { + before(() => { + cy.login(); + cy.visit('/app/website'); + return cy.insert_doc('DocType', doctype_with_tab_break, true); + }); + it("Should switch tab and open correct tabs on validation error", () => { + cy.new_form(doctype_name); + // test tab switch + cy.findByRole("tab", {name: "Tab 2"}).click(); + cy.findByText("Phone"); + cy.findByRole("tab", {name: "Details"}).click(); + cy.findByText("Name"); + + // form should switch to the tab with un-filled mandatory field + cy.fill_field("username", "Test"); + cy.findByRole("button", {name: "Save"}).click(); + cy.findByText("Missing Fields"); + cy.hide_dialog(); + cy.findByText("Phone"); + cy.fill_field("phone", "12345678"); + cy.findByRole("button", {name: "Save"}).click(); + + // After save, first tab should have dashboard + cy.get(".form-tabs > .nav-item").eq(0).click(); + cy.findByText("Connections"); + + }); +}); \ No newline at end of file diff --git a/cypress/integration/list_view.js b/cypress/integration/list_view.js index 633d1335ab..2e865e6a57 100644 --- a/cypress/integration/list_view.js +++ b/cypress/integration/list_view.js @@ -6,12 +6,34 @@ context('List View', () => { return frappe.xcall("frappe.tests.ui_test_helpers.setup_workflow"); }); }); + + it('Keep checkbox checked after Bulk Update', () => { + cy.go_to_list('ToDo'); + cy.get('.list-row-container .list-row-checkbox').click({ multiple: true, force: true }); + cy.get('.actions-btn-group button').contains('Actions').should('be.visible').click(); + cy.get('.dropdown-menu li:visible .dropdown-item .menu-item-label[data-label="Edit"]').click(); + + cy.get('.modal-body .form-control[data-fieldname="field"]').first().select('Due Date').wait(200); + cy.get('.modal-body .frappe-control[data-fieldname="value"] input:visible').first().focus(); + cy.get('.datepickers-container .datepicker.active').should('be.visible'); + + cy.get('.datepickers-container .datepicker.active .datepicker--cell-day.-current-').click({force: true}); + cy.get('.modal-body .frappe-control[data-fieldname="value"] input:visible').first().focus(); + cy.get('.datepickers-container .datepicker.active .datepicker--cell-day.-current-').click({force: true}); + + cy.get('.modal-footer .standard-actions .btn-primary').click(); + cy.wait(500); + + cy.get('.actions-btn-group button').contains('Actions').should('be.visible').click(); + cy.get('.list-row-container .list-row-checkbox:checked').should('be.visible'); + }); + it('enables "Actions" button', () => { - const actions = ['Approve', 'Reject', 'Edit', 'Assign To', 'Apply Assignment Rule', 'Add Tags', 'Print', 'Delete']; + const actions = ['Approve', 'Reject', 'Edit', 'Export', 'Assign To', 'Apply Assignment Rule', 'Add Tags', 'Print', 'Delete']; cy.go_to_list('ToDo'); cy.get('.list-row-container:contains("Pending") .list-row-checkbox').click({ multiple: true, force: true }); cy.get('.actions-btn-group button').contains('Actions').should('be.visible').click(); - cy.get('.dropdown-menu li:visible .dropdown-item').should('have.length', 8).each((el, index) => { + cy.get('.dropdown-menu li:visible .dropdown-item').should('have.length', 9).each((el, index) => { cy.wrap(el).contains(actions[index]); }).then((elements) => { cy.intercept({ @@ -30,4 +52,3 @@ context('List View', () => { }); }); }); - diff --git a/cypress/integration/multi_select_dialog.js b/cypress/integration/multi_select_dialog.js new file mode 100644 index 0000000000..a45fba8d32 --- /dev/null +++ b/cypress/integration/multi_select_dialog.js @@ -0,0 +1,58 @@ +context('MultiSelectDialog', () => { + before(() => { + cy.login(); + cy.visit('/app'); + }); + + function open_multi_select_dialog() { + cy.window().its('frappe').then(frappe => { + new frappe.ui.form.MultiSelectDialog({ + doctype: "Assignment Rule", + target: {}, + setters: { + document_type: null, + priority: null + }, + add_filters_group: 1, + allow_child_item_selection: 1, + child_fieldname: "assignment_days", + child_columns: ["day"] + }); + }); + } + + it('multi select dialog api works', () => { + open_multi_select_dialog(); + cy.get_open_dialog().should('contain', 'Select Assignment Rules'); + }); + + it('checks for filters', () => { + ['search_term', 'document_type', 'priority'].forEach(fieldname => { + cy.get_open_dialog().get(`.frappe-control[data-fieldname="${fieldname}"]`).should('exist'); + }); + + // add_filters_group: 1 should add a filter group + cy.get_open_dialog().get(`.frappe-control[data-fieldname="filter_area"]`).should('exist'); + + }); + + it('checks for child item selection', () => { + cy.get_open_dialog() + .get(`.dt-row-header`).should('not.exist'); + + cy.get_open_dialog() + .get(`.frappe-control[data-fieldname="allow_child_item_selection"]`) + .should('exist') + .click(); + + cy.get_open_dialog() + .get(`.frappe-control[data-fieldname="child_selection_area"]`) + .should('exist'); + + cy.get_open_dialog() + .get(`.dt-row-header`).should('contain', 'Assignment Rule'); + + cy.get_open_dialog() + .get(`.dt-row-header`).should('contain', 'Day'); + }); +}); \ No newline at end of file diff --git a/cypress/integration/navigation.js b/cypress/integration/navigation.js index 7e1426aa46..ba45137cbd 100644 --- a/cypress/integration/navigation.js +++ b/cypress/integration/navigation.js @@ -1,7 +1,6 @@ context('Navigation', () => { before(() => { cy.login(); - cy.visit('/app/website'); }); it('Navigate to route with hash in document name', () => { cy.insert_doc('ToDo', {'__newname': 'ABC#123', 'description': 'Test this', 'ignore_duplicate': true}); @@ -11,4 +10,15 @@ context('Navigation', () => { cy.go('back'); cy.title().should('eq', 'Website'); }); + + it.only('Navigate to previous page after login', () => { + cy.visit('/app/todo'); + cy.request('/api/method/logout'); + cy.reload(); + cy.get('.btn-primary').contains('Login').click(); + cy.location('pathname').should('eq', '/login'); + cy.login(); + cy.visit('/app'); + cy.location('pathname').should('eq', '/app/todo'); + }); }); diff --git a/cypress/integration/sidebar.js b/cypress/integration/sidebar.js index e05f1877bf..cd771430c6 100644 --- a/cypress/integration/sidebar.js +++ b/cypress/integration/sidebar.js @@ -6,12 +6,12 @@ context('Sidebar', () => { }); it('Test for checking "Assigned To" counter value, adding filter and adding & removing an assignment', () => { - cy.click_sidebar_button(0); + cy.click_sidebar_button("Assigned To"); //To check if no filter is available in "Assigned To" dropdown cy.get('.empty-state').should('contain', 'No filters found'); - cy.click_sidebar_button(1); + cy.click_sidebar_button("Created By"); //To check if "Created By" dropdown contains filter cy.get('.group-by-item > .dropdown-item').should('contain', 'Me'); @@ -22,7 +22,7 @@ context('Sidebar', () => { cy.get_field('assign_to_me', 'Check').click(); cy.get('.modal-footer > .standard-actions > .btn-primary').click(); cy.visit('/app/doctype'); - cy.click_sidebar_button(0); + cy.click_sidebar_button("Assigned To"); //To check if filter is added in "Assigned To" dropdown after assignment cy.get('.group-by-field.show > .dropdown-menu > .group-by-item > .dropdown-item').should('contain', '1'); @@ -38,20 +38,19 @@ context('Sidebar', () => { cy.get('.fieldname-select-area > .awesomplete > .form-control').should('have.value', 'Assigned To'); cy.get('.condition').should('have.value', 'like'); cy.get('.filter-field > .form-group > .input-with-feedback').should('have.value', '%Administrator%'); + cy.click_filter_button(); //To remove the applied filter - cy.get('.filter-action-buttons > div > .btn-secondary').contains('Clear Filters').click(); - cy.click_filter_button(); - cy.get('.filter-selector > .btn').should('contain', 'Filter'); + cy.clear_filters(); //To remove the assignment cy.visit('/app/doctype'); cy.click_listview_row_item(0); cy.get('.assignments > .avatar-group > .avatar > .avatar-frame').click(); cy.get('.remove-btn').click({force: true}); - cy.get('.modal.show > .modal-dialog > .modal-content > .modal-header > .modal-actions > .btn-modal-close').click(); + cy.hide_dialog(); cy.visit('/app/doctype'); - cy.click_sidebar_button(0); + cy.click_sidebar_button("Assigned To"); cy.get('.empty-state').should('contain', 'No filters found'); }); }); \ No newline at end of file diff --git a/cypress/integration/timeline.js b/cypress/integration/timeline.js index 7a8f3a159b..6387485220 100644 --- a/cypress/integration/timeline.js +++ b/cypress/integration/timeline.js @@ -4,11 +4,11 @@ context('Timeline', () => { before(() => { cy.visit('/login'); cy.login(); - cy.visit('/app/todo'); }); it('Adding new ToDo, adding new comment, verifying comment addition & deletion and deleting ToDo', () => { //Adding new ToDo + cy.visit('/app/todo'); cy.click_listview_primary_button('Add ToDo'); cy.findByRole('button', {name: 'Edit in full page'}).click(); cy.get('[data-fieldname="description"] .ql-editor').eq(0).type('Test ToDo', {force: true}); @@ -28,15 +28,15 @@ context('Timeline', () => { cy.get('.timeline-content').should('contain', 'Testing Timeline'); //Editing comment - cy.click_timeline_action_btn(0); + cy.click_timeline_action_btn("Edit"); cy.get('.timeline-content [data-fieldname="comment"] .ql-editor').first().type(' 123'); - cy.click_timeline_action_btn(0); + cy.click_timeline_action_btn("Save"); //To check if the edited comment text is visible in timeline content cy.get('.timeline-content').should('contain', 'Testing Timeline 123'); //Discarding comment - cy.click_timeline_action_btn(0); + cy.click_timeline_action_btn("Edit"); cy.findByRole('button', {name: 'Dismiss'}).click(); //To check if after discarding the timeline content is same as previous @@ -81,7 +81,7 @@ context('Timeline', () => { cy.visit('/app/custom-submittable-doctype'); cy.get('.list-subject > .select-like > .list-row-checkbox').eq(0).click(); cy.findByRole('button', {name: 'Actions'}).click(); - cy.get('.actions-btn-group > .dropdown-menu > li > .grey-link').eq(7).click(); + cy.get('.actions-btn-group > .dropdown-menu > li > .dropdown-item').contains("Delete").click(); cy.click_modal_primary_button('Yes', {force: true, delay: 700}); //Deleting the custom doctype diff --git a/cypress/support/commands.js b/cypress/support/commands.js index c941652487..47c37a56a0 100644 --- a/cypress/support/commands.js +++ b/cypress/support/commands.js @@ -187,7 +187,7 @@ Cypress.Commands.add('fill_field', (fieldname, value, fieldtype = 'Data') => { if (fieldtype === 'Select') { cy.get('@input').select(value); } else { - cy.get('@input').type(value, {waitForAnimations: false, force: true}); + cy.get('@input').type(value, {waitForAnimations: false, force: true, delay: 100}); } return cy.get('@input'); }); @@ -252,7 +252,8 @@ Cypress.Commands.add('new_form', doctype => { }); Cypress.Commands.add('go_to_list', doctype => { - cy.visit(`/app/list/${doctype}/list`); + let dt_in_route = doctype.toLowerCase().replace(/ /g, '-'); + cy.visit(`/app/${dt_in_route}`); }); Cypress.Commands.add('clear_cache', () => { @@ -316,7 +317,11 @@ Cypress.Commands.add('add_filter', () => { }); Cypress.Commands.add('clear_filters', () => { - cy.get('.filter-section .filter-button').click(); + cy.intercept({ + method: 'POST', + url: 'api/method/frappe.model.utils.user_settings.save' + }).as('filter-saved'); + cy.get('.filter-section .filter-button').click({force: true}); cy.wait(300); cy.get('.filter-popover').should('exist'); cy.get('.filter-popover').find('.clear-filters').click(); @@ -324,16 +329,15 @@ Cypress.Commands.add('clear_filters', () => { cy.window().its('cur_list').then(cur_list => { cur_list && cur_list.filter_area && cur_list.filter_area.clear(); }); - - + cy.wait('@filter-saved'); }); Cypress.Commands.add('click_modal_primary_button', (btn_name) => { cy.get('.modal-footer > .standard-actions > .btn-primary').contains(btn_name).trigger('click', {force: true}); }); -Cypress.Commands.add('click_sidebar_button', (btn_no) => { - cy.get('.list-group-by-fields > .group-by-field > .btn').eq(btn_no).click(); +Cypress.Commands.add('click_sidebar_button', (btn_name) => { + cy.get('.list-group-by-fields .list-link > a').contains(btn_name).click({force: true}); }); Cypress.Commands.add('click_listview_row_item', (row_no) => { @@ -348,6 +352,6 @@ Cypress.Commands.add('click_listview_primary_button', (btn_name) => { cy.get('.primary-action').contains(btn_name).click({force: true}); }); -Cypress.Commands.add('click_timeline_action_btn', (btn_no) => { - cy.get('.timeline-content > .timeline-message-box > .justify-between > .actions > .btn').eq(btn_no).first().click(); +Cypress.Commands.add('click_timeline_action_btn', (btn_name) => { + cy.get('.timeline-content > .timeline-message-box > .justify-between > .actions > .btn').contains(btn_name).click(); }); \ No newline at end of file diff --git a/frappe/__init__.py b/frappe/__init__.py index ea983e7f02..64e445973f 100644 --- a/frappe/__init__.py +++ b/frappe/__init__.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE """ Frappe - Low Code Open Source Framework in Python and JS @@ -235,12 +235,13 @@ def connect_replica(): from frappe.database import get_db user = local.conf.db_name password = local.conf.db_password + port = local.conf.replica_db_port if local.conf.different_credentials_for_replica: user = local.conf.replica_db_name password = local.conf.replica_db_password - local.replica_db = get_db(host=local.conf.replica_host, user=user, password=password) + local.replica_db = get_db(host=local.conf.replica_host, user=user, password=password, port=port) # swap db connections local.primary_db = local.db @@ -618,8 +619,6 @@ def read_only(): try: retval = fn(*args, **get_newargs(fn, kwargs)) - except: - raise finally: if local and hasattr(local, 'primary_db'): local.db.close() @@ -629,6 +628,29 @@ def read_only(): return wrapper_fn return innfn +def write_only(): + # if replica connection exists, we have to replace it momentarily with the primary connection + def innfn(fn): + def wrapper_fn(*args, **kwargs): + primary_db = getattr(local, "primary_db", None) + replica_db = getattr(local, "replica_db", None) + in_read_only = getattr(local, "db", None) != primary_db + + # switch to primary connection + if in_read_only and primary_db: + local.db = local.primary_db + + try: + retval = fn(*args, **get_newargs(fn, kwargs)) + finally: + # switch back to replica connection + if in_read_only and replica_db: + local.db = replica_db + + return retval + return wrapper_fn + return innfn + def only_for(roles, message=False): """Raise `frappe.PermissionError` if the user does not have any of the given **Roles**. diff --git a/frappe/api.py b/frappe/api.py index 636c6b2888..b061761d10 100644 --- a/frappe/api.py +++ b/frappe/api.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import base64 import binascii import json diff --git a/frappe/app.py b/frappe/app.py index 920628dda4..8e1534e7ef 100644 --- a/frappe/app.py +++ b/frappe/app.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import os import logging diff --git a/frappe/automation/doctype/assignment_rule/assignment_rule.py b/frappe/automation/doctype/assignment_rule/assignment_rule.py index ef579aca01..a3e27d4da5 100644 --- a/frappe/automation/doctype/assignment_rule/assignment_rule.py +++ b/frappe/automation/doctype/assignment_rule/assignment_rule.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe from frappe.model.document import Document diff --git a/frappe/automation/doctype/assignment_rule/test_assignment_rule.py b/frappe/automation/doctype/assignment_rule/test_assignment_rule.py index dfefd091fb..1c9e177f94 100644 --- a/frappe/automation/doctype/assignment_rule/test_assignment_rule.py +++ b/frappe/automation/doctype/assignment_rule/test_assignment_rule.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE import frappe import unittest from frappe.utils import random_string diff --git a/frappe/automation/doctype/assignment_rule_day/assignment_rule_day.py b/frappe/automation/doctype/assignment_rule_day/assignment_rule_day.py index c734495c39..836ae3d453 100644 --- a/frappe/automation/doctype/assignment_rule_day/assignment_rule_day.py +++ b/frappe/automation/doctype/assignment_rule_day/assignment_rule_day.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE # import frappe from frappe.model.document import Document diff --git a/frappe/automation/doctype/assignment_rule_user/assignment_rule_user.py b/frappe/automation/doctype/assignment_rule_user/assignment_rule_user.py index 4d65efd5c1..1bb8953a7a 100644 --- a/frappe/automation/doctype/assignment_rule_user/assignment_rule_user.py +++ b/frappe/automation/doctype/assignment_rule_user/assignment_rule_user.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE # import frappe from frappe.model.document import Document diff --git a/frappe/automation/doctype/auto_repeat/auto_repeat.py b/frappe/automation/doctype/auto_repeat/auto_repeat.py index d2afda1553..5ab6c86c00 100644 --- a/frappe/automation/doctype/auto_repeat/auto_repeat.py +++ b/frappe/automation/doctype/auto_repeat/auto_repeat.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe from frappe import _ diff --git a/frappe/automation/doctype/auto_repeat/test_auto_repeat.py b/frappe/automation/doctype/auto_repeat/test_auto_repeat.py index 567c1161af..30a0310a92 100644 --- a/frappe/automation/doctype/auto_repeat/test_auto_repeat.py +++ b/frappe/automation/doctype/auto_repeat/test_auto_repeat.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2018, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE import unittest import frappe diff --git a/frappe/automation/doctype/auto_repeat_day/auto_repeat_day.py b/frappe/automation/doctype/auto_repeat_day/auto_repeat_day.py index 8af3284cde..54fc0d14e9 100644 --- a/frappe/automation/doctype/auto_repeat_day/auto_repeat_day.py +++ b/frappe/automation/doctype/auto_repeat_day/auto_repeat_day.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE # import frappe from frappe.model.document import Document diff --git a/frappe/automation/doctype/milestone/milestone.py b/frappe/automation/doctype/milestone/milestone.py index 6ea6d7544a..eff65571fd 100644 --- a/frappe/automation/doctype/milestone/milestone.py +++ b/frappe/automation/doctype/milestone/milestone.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe from frappe.model.document import Document diff --git a/frappe/automation/doctype/milestone/test_milestone.py b/frappe/automation/doctype/milestone/test_milestone.py index 175c56e552..f8fb910072 100644 --- a/frappe/automation/doctype/milestone/test_milestone.py +++ b/frappe/automation/doctype/milestone/test_milestone.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE #import frappe import unittest diff --git a/frappe/automation/doctype/milestone_tracker/milestone_tracker.py b/frappe/automation/doctype/milestone_tracker/milestone_tracker.py index 125cad7fa8..042e7b0391 100644 --- a/frappe/automation/doctype/milestone_tracker/milestone_tracker.py +++ b/frappe/automation/doctype/milestone_tracker/milestone_tracker.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe from frappe.model.document import Document diff --git a/frappe/automation/doctype/milestone_tracker/test_milestone_tracker.py b/frappe/automation/doctype/milestone_tracker/test_milestone_tracker.py index 1683e94827..f4d5f00d83 100644 --- a/frappe/automation/doctype/milestone_tracker/test_milestone_tracker.py +++ b/frappe/automation/doctype/milestone_tracker/test_milestone_tracker.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE import frappe import frappe.cache_manager import unittest diff --git a/frappe/boot.py b/frappe/boot.py index c46709d3d7..cf2b914436 100644 --- a/frappe/boot.py +++ b/frappe/boot.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE """ bootstrap client session """ diff --git a/frappe/build.py b/frappe/build.py index ed19574cfd..879d5ec432 100644 --- a/frappe/build.py +++ b/frappe/build.py @@ -1,10 +1,11 @@ -# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors +# License: MIT. See LICENSE import os import re import json import shutil import subprocess +from subprocess import getoutput from io import StringIO from tempfile import mkdtemp, mktemp from distutils.spawn import find_executable @@ -17,6 +18,8 @@ import psutil from urllib.parse import urlparse from simple_chalk import green from semantic_version import Version +from requests import head +from requests.exceptions import HTTPError timestamps = {} @@ -24,6 +27,12 @@ app_paths = None sites_path = os.path.abspath(os.getcwd()) +class AssetsNotDownloadedError(Exception): + pass + +class AssetsDontExistError(HTTPError): + pass + def download_file(url, prefix): from requests import get @@ -70,81 +79,94 @@ def build_missing_files(): bundle(build_mode, apps="frappe") -def get_assets_link(frappe_head): - from subprocess import getoutput - from requests import head - +def get_assets_link(frappe_head) -> str: tag = getoutput( - r"cd ../apps/frappe && git show-ref --tags -d | grep %s | sed -e 's,.*" - r" refs/tags/,,' -e 's/\^{}//'" - % frappe_head - ) + r"cd ../apps/frappe && git show-ref --tags -d | grep %s | sed -e 's,.*" + r" refs/tags/,,' -e 's/\^{}//'" + % frappe_head + ) if tag: # if tag exists, download assets from github release - url = "https://github.com/frappe/frappe/releases/download/{0}/assets.tar.gz".format(tag) + url = f"https://github.com/frappe/frappe/releases/download/{tag}/assets.tar.gz" else: - url = "http://assets.frappeframework.com/{0}.tar.gz".format(frappe_head) + url = f"http://assets.frappeframework.com/{frappe_head}.tar.gz" if not head(url): - raise ValueError("URL {0} doesn't exist".format(url)) + reference = f"Release {tag}" if tag else f"Commit {frappe_head}" + raise AssetsDontExistError(f"Assets for {reference} don't exist") return url +def fetch_assets(url, frappe_head): + click.secho("Retrieving assets...", fg="yellow") + + prefix = mkdtemp(prefix="frappe-assets-", suffix=frappe_head) + assets_archive = download_file(url, prefix) + + if not assets_archive: + raise AssetsNotDownloadedError(f"Assets could not be retrived from {url}") + + print(f"\n{green('✔')} Downloaded Frappe assets from {url}") + + return assets_archive + + +def setup_assets(assets_archive): + import tarfile + directories_created = set() + + click.secho("\nExtracting assets...\n", fg="yellow") + with tarfile.open(assets_archive) as tar: + for file in tar: + if not file.isdir(): + dest = "." + file.name.replace("./frappe-bench/sites", "") + asset_directory = os.path.dirname(dest) + show = dest.replace("./assets/", "") + + if asset_directory not in directories_created: + if not os.path.exists(asset_directory): + os.makedirs(asset_directory, exist_ok=True) + directories_created.add(asset_directory) + + tar.makefile(file, dest) + print("{0} Restored {1}".format(green('✔'), show)) + + return directories_created + + def download_frappe_assets(verbose=True): """Downloads and sets up Frappe assets if they exist based on the current commit HEAD. Returns True if correctly setup else returns False. """ - from subprocess import getoutput - - assets_setup = False frappe_head = getoutput("cd ../apps/frappe && git rev-parse HEAD") - if frappe_head: + if not frappe_head: + return False + + try: + url = get_assets_link(frappe_head) + assets_archive = fetch_assets(url, frappe_head) + setup_assets(assets_archive) + build_missing_files() + return True + + except AssetsDontExistError as e: + click.secho(str(e), fg="yellow") + + except Exception as e: + # TODO: log traceback in bench.log + click.secho(str(e), fg="red") + + finally: try: - url = get_assets_link(frappe_head) - click.secho("Retrieving assets...", fg="yellow") - prefix = mkdtemp(prefix="frappe-assets-", suffix=frappe_head) - assets_archive = download_file(url, prefix) - print("\n{0} Downloaded Frappe assets from {1}".format(green('✔'), url)) - - if assets_archive: - import tarfile - directories_created = set() - - click.secho("\nExtracting assets...\n", fg="yellow") - with tarfile.open(assets_archive) as tar: - for file in tar: - if not file.isdir(): - dest = "." + file.name.replace("./frappe-bench/sites", "") - asset_directory = os.path.dirname(dest) - show = dest.replace("./assets/", "") - - if asset_directory not in directories_created: - if not os.path.exists(asset_directory): - os.makedirs(asset_directory, exist_ok=True) - directories_created.add(asset_directory) - - tar.makefile(file, dest) - print("{0} Restored {1}".format(green('✔'), show)) - - build_missing_files() - return True - else: - raise + shutil.rmtree(os.path.dirname(assets_archive)) except Exception: - # TODO: log traceback in bench.log - click.secho("An Error occurred while downloading assets...", fg="red") - assets_setup = False - finally: - try: - shutil.rmtree(os.path.dirname(assets_archive)) - except Exception: - pass - - return assets_setup + pass + + return False def symlink(target, link_name, overwrite=False): diff --git a/frappe/cache_manager.py b/frappe/cache_manager.py index 2ee3b46b7c..0df8878da4 100644 --- a/frappe/cache_manager.py +++ b/frappe/cache_manager.py @@ -1,5 +1,5 @@ # Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import frappe, json from frappe.model.document import Document diff --git a/frappe/chat/doctype/chat_token/chat_token.py b/frappe/chat/doctype/chat_token/chat_token.py index 63d69a58be..0be51b6081 100644 --- a/frappe/chat/doctype/chat_token/chat_token.py +++ b/frappe/chat/doctype/chat_token/chat_token.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2018, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe from frappe.model.document import Document diff --git a/frappe/client.py b/frappe/client.py index 66c457e893..21d10e8271 100644 --- a/frappe/client.py +++ b/frappe/client.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import frappe from frappe import _ import frappe.model diff --git a/frappe/commands/__init__.py b/frappe/commands/__init__.py index 9ed333d034..82a71ce7b4 100644 --- a/frappe/commands/__init__.py +++ b/frappe/commands/__init__.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Web Notes Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import sys import click @@ -102,9 +102,24 @@ def get_commands(): from .site import commands as site_commands from .translate import commands as translate_commands from .utils import commands as utils_commands - from .redis import commands as redis_commands + from .redis_utils import commands as redis_commands + + clickable_link = ( + "\x1b]8;;https://frappeframework.com/docs\afrappeframework.com\x1b]8;;\a" + ) + all_commands = ( + scheduler_commands + + site_commands + + translate_commands + + utils_commands + + redis_commands + ) + + for command in all_commands: + if not command.help: + command.help = f"Refer to {clickable_link}" + + return all_commands - all_commands = scheduler_commands + site_commands + translate_commands + utils_commands + redis_commands - return list(set(all_commands)) commands = get_commands() diff --git a/frappe/commands/redis.py b/frappe/commands/redis_utils.py similarity index 97% rename from frappe/commands/redis.py rename to frappe/commands/redis_utils.py index 38a46c2142..3556050782 100644 --- a/frappe/commands/redis.py +++ b/frappe/commands/redis_utils.py @@ -3,7 +3,7 @@ import os import click import frappe -from frappe.utils.rq import RedisQueue +from frappe.utils.redis_queue import RedisQueue from frappe.installer import update_site_config @click.command('create-rq-users') diff --git a/frappe/commands/site.py b/frappe/commands/site.py index 9098e31738..2bd3110481 100755 --- a/frappe/commands/site.py +++ b/frappe/commands/site.py @@ -67,6 +67,9 @@ def restore(context, sql_file_path, mariadb_root_username=None, mariadb_root_pas validate_database_sql ) + site = get_site(context) + frappe.init(site=site) + force = context.force or force decompressed_file_name = extract_sql_from_archive(sql_file_path) @@ -85,9 +88,6 @@ def restore(context, sql_file_path, mariadb_root_username=None, mariadb_root_pas # check if valid SQL file validate_database_sql(decompressed_file_name, _raise=not force) - site = get_site(context) - frappe.init(site=site) - # dont allow downgrading to older versions of frappe without force if not force and is_downgrade(decompressed_file_name, verbose=True): warn_message = ( @@ -474,7 +474,7 @@ def remove_from_installed_apps(context, app): @click.command('uninstall-app') @click.argument('app') -@click.option('--yes', '-y', help='To bypass confirmation prompt for uninstalling the app', is_flag=True, default=False, multiple=True) +@click.option('--yes', '-y', help='To bypass confirmation prompt for uninstalling the app', is_flag=True, default=False) @click.option('--dry-run', help='List all doctypes that will be deleted', is_flag=True, default=False) @click.option('--no-backup', help='Do not backup the site', is_flag=True, default=False) @click.option('--force', help='Force remove app from site', is_flag=True, default=False) @@ -738,6 +738,131 @@ def build_search_index(context): finally: frappe.destroy() +@click.command('trim-database') +@click.option('--dry-run', is_flag=True, default=False, help='Show what would be deleted') +@click.option('--format', '-f', default='text', type=click.Choice(['json', 'text']), help='Output format') +@click.option('--no-backup', is_flag=True, default=False, help='Do not backup the site') +@pass_context +def trim_database(context, dry_run, format, no_backup): + if not context.sites: + raise SiteNotSpecifiedError + + from frappe.utils.backups import scheduled_backup + + ALL_DATA = {} + + for site in context.sites: + frappe.init(site=site) + frappe.connect() + + TABLES_TO_DROP = [] + STANDARD_TABLES = get_standard_tables() + information_schema = frappe.qb.Schema("information_schema") + table_name = frappe.qb.Field("table_name").as_("name") + + queried_result = frappe.qb.from_( + information_schema.tables + ).select(table_name).where( + information_schema.tables.table_schema == frappe.conf.db_name + ).run() + + database_tables = [x[0] for x in queried_result] + doctype_tables = frappe.get_all("DocType", pluck="name") + + for x in database_tables: + doctype = x.lstrip("tab") + if not (doctype in doctype_tables or x.startswith("__") or x in STANDARD_TABLES): + TABLES_TO_DROP.append(x) + + if not TABLES_TO_DROP: + if format == "text": + click.secho(f"No ghost tables found in {frappe.local.site}...Great!", fg="green") + else: + if not (no_backup or dry_run): + if format == "text": + print(f"Backing Up Tables: {', '.join(TABLES_TO_DROP)}") + + odb = scheduled_backup( + ignore_conf=False, + include_doctypes=",".join(x.lstrip("tab") for x in TABLES_TO_DROP), + ignore_files=True, + force=True, + ) + if format == "text": + odb.print_summary() + print("\nTrimming Database") + + for table in TABLES_TO_DROP: + if format == "text": + print(f"* Dropping Table '{table}'...") + if not dry_run: + frappe.db.sql_ddl(f"drop table `{table}`") + + ALL_DATA[frappe.local.site] = TABLES_TO_DROP + frappe.destroy() + + if format == "json": + import json + print(json.dumps(ALL_DATA, indent=1)) + + +def get_standard_tables(): + import re + + tables = [] + sql_file = os.path.join( + "..", "apps", "frappe", "frappe", "database", frappe.conf.db_type, f'framework_{frappe.conf.db_type}.sql' + ) + content = open(sql_file).read().splitlines() + + for line in content: + table_found = re.search(r"""CREATE TABLE ("|`)(.*)?("|`) \(""", line) + if table_found: + tables.append(table_found.group(2)) + + return tables + +@click.command('trim-tables') +@click.option('--dry-run', is_flag=True, default=False, help='Show what would be deleted') +@click.option('--format', '-f', default='table', type=click.Choice(['json', 'table']), help='Output format') +@click.option('--no-backup', is_flag=True, default=False, help='Do not backup the site') +@pass_context +def trim_tables(context, dry_run, format, no_backup): + if not context.sites: + raise SiteNotSpecifiedError + + from frappe.model.meta import trim_tables + from frappe.utils.backups import scheduled_backup + + for site in context.sites: + frappe.init(site=site) + frappe.connect() + + if not (no_backup or dry_run): + click.secho(f"Taking backup for {frappe.local.site}", fg="green") + odb = scheduled_backup(ignore_files=False, force=True) + odb.print_summary() + + try: + trimmed_data = trim_tables(dry_run=dry_run, quiet=format == 'json') + + if format == 'table' and not dry_run: + click.secho(f"The following data have been removed from {frappe.local.site}", fg='green') + + handle_data(trimmed_data, format=format) + finally: + frappe.destroy() + +def handle_data(data: dict, format='json'): + if format == 'json': + import json + print(json.dumps({frappe.local.site: data}, indent=1, sort_keys=True)) + else: + from frappe.utils.commands import render_table + data = [["DocType", "Fields"]] + [[table, ", ".join(columns)] for table, columns in data.items()] + render_table(data) + + commands = [ add_system_manager, backup, @@ -766,5 +891,7 @@ commands = [ add_to_hosts, start_ngrok, build_search_index, - partial_restore + partial_restore, + trim_tables, + trim_database, ] diff --git a/frappe/commands/utils.py b/frappe/commands/utils.py index b0151106db..90cd60c6ec 100644 --- a/frappe/commands/utils.py +++ b/frappe/commands/utils.py @@ -408,20 +408,47 @@ def bulk_rename(context, doctype, path): frappe.destroy() +@click.command('db-console') +@pass_context +def database(context): + """ + Enter into the Database console for given site. + """ + site = get_site(context) + if not site: + raise SiteNotSpecifiedError + frappe.init(site=site) + if not frappe.conf.db_type or frappe.conf.db_type == "mariadb": + _mariadb() + elif frappe.conf.db_type == "postgres": + _psql() + + @click.command('mariadb') @pass_context def mariadb(context): """ Enter into mariadb console for a given site. """ - import os - site = get_site(context) if not site: raise SiteNotSpecifiedError frappe.init(site=site) + _mariadb() + + +@click.command('postgres') +@pass_context +def postgres(context): + """ + Enter into postgres console for a given site. + """ + site = get_site(context) + frappe.init(site=site) + _psql() - # This is assuming you're within the bench instance. + +def _mariadb(): mysql = find_executable('mysql') os.execv(mysql, [ mysql, @@ -434,15 +461,7 @@ def mariadb(context): "-A"]) -@click.command('postgres') -@pass_context -def postgres(context): - """ - Enter into postgres console for a given site. - """ - site = get_site(context) - frappe.init(site=site) - # This is assuming you're within the bench instance. +def _psql(): psql = find_executable('psql') subprocess.run([ psql, '-d', frappe.conf.db_name]) @@ -525,6 +544,74 @@ def console(context, autoreload=False): terminal() +@click.command('transform-database', help="Change tables' internal settings changing engine and row formats") +@click.option('--table', required=True, help="Comma separated name of tables to convert. To convert all tables, pass 'all'") +@click.option('--engine', default=None, type=click.Choice(["InnoDB", "MyISAM"]), help="Choice of storage engine for said table(s)") +@click.option('--row_format', default=None, type=click.Choice(["DYNAMIC", "COMPACT", "REDUNDANT", "COMPRESSED"]), help="Set ROW_FORMAT parameter for said table(s)") +@click.option('--failfast', is_flag=True, default=False, help="Exit on first failure occurred") +@pass_context +def transform_database(context, table, engine, row_format, failfast): + "Transform site database through given parameters" + site = get_site(context) + check_table = [] + add_line = False + skipped = 0 + frappe.init(site=site) + + if frappe.conf.db_type and frappe.conf.db_type != "mariadb": + click.secho("This command only has support for MariaDB databases at this point", fg="yellow") + sys.exit(1) + + if not (engine or row_format): + click.secho("Values for `--engine` or `--row_format` must be set") + sys.exit(1) + + frappe.connect() + + if table == "all": + information_schema = frappe.qb.Schema("information_schema") + queried_tables = frappe.qb.from_( + information_schema.tables + ).select("table_name").where( + (information_schema.tables.row_format != row_format) + & (information_schema.tables.table_schema == frappe.conf.db_name) + ).run() + tables = [x[0] for x in queried_tables] + else: + tables = [x.strip() for x in table.split(",")] + + total = len(tables) + + for current, table in enumerate(tables): + values_to_set = "" + if engine: + values_to_set += f" ENGINE={engine}" + if row_format: + values_to_set += f" ROW_FORMAT={row_format}" + + try: + frappe.db.sql(f"ALTER TABLE `{table}`{values_to_set}") + update_progress_bar("Updating table schema", current - skipped, total) + add_line = True + + except Exception as e: + check_table.append([table, e.args]) + skipped += 1 + + if failfast: + break + + if add_line: + print() + + for errored_table in check_table: + table, err = errored_table + err_msg = f"{table}: ERROR {err[0]}: {err[1]}" + click.secho(err_msg, fg="yellow") + + frappe.destroy() + + @click.command('run-tests') @click.option('--app', help="For App") @click.option('--doctype', help="For DocType") @@ -811,6 +898,8 @@ commands = [ build, clear_cache, clear_website_cache, + database, + transform_database, jupyter, console, destroy_all_sessions, diff --git a/frappe/contacts/address_and_contact.py b/frappe/contacts/address_and_contact.py index 77305168c1..6b71ec50f9 100644 --- a/frappe/contacts/address_and_contact.py +++ b/frappe/contacts/address_and_contact.py @@ -1,5 +1,5 @@ -# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt +# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors +# License: MIT. See LICENSE import frappe diff --git a/frappe/contacts/doctype/address/address.py b/frappe/contacts/doctype/address/address.py index 755bc63064..5d0ed18d5f 100644 --- a/frappe/contacts/doctype/address/address.py +++ b/frappe/contacts/doctype/address/address.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe @@ -65,7 +65,7 @@ class Address(Document): def has_link(self, doctype, name): for link in self.links: - if link.link_doctype==doctype and link.link_name== name: + if link.link_doctype == doctype and link.link_name == name: return True def has_common_link(self, doc): diff --git a/frappe/contacts/doctype/address/test_address.py b/frappe/contacts/doctype/address/test_address.py index ed61b6f0ee..dd6cd1ca83 100644 --- a/frappe/contacts/doctype/address/test_address.py +++ b/frappe/contacts/doctype/address/test_address.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE import frappe, unittest from frappe.contacts.doctype.address.address import get_address_display diff --git a/frappe/contacts/doctype/address_template/address_template.py b/frappe/contacts/doctype/address_template/address_template.py index 2d69a792ab..005f414303 100644 --- a/frappe/contacts/doctype/address_template/address_template.py +++ b/frappe/contacts/doctype/address_template/address_template.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe from frappe.model.document import Document diff --git a/frappe/contacts/doctype/address_template/test_address_template.py b/frappe/contacts/doctype/address_template/test_address_template.py index 6b519a3bb7..b86623b548 100644 --- a/frappe/contacts/doctype/address_template/test_address_template.py +++ b/frappe/contacts/doctype/address_template/test_address_template.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE import frappe, unittest class TestAddressTemplate(unittest.TestCase): diff --git a/frappe/contacts/doctype/contact/contact.py b/frappe/contacts/doctype/contact/contact.py index d1dd1f1010..dfb9ff2973 100644 --- a/frappe/contacts/doctype/contact/contact.py +++ b/frappe/contacts/doctype/contact/contact.py @@ -1,5 +1,5 @@ -# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt +# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors +# License: MIT. See LICENSE import frappe from frappe.utils import cstr, has_gravatar from frappe import _ @@ -47,14 +47,14 @@ class Contact(Document): def get_link_for(self, link_doctype): '''Return the link name, if exists for the given link DocType''' for link in self.links: - if link.link_doctype==link_doctype: + if link.link_doctype == link_doctype: return link.link_name return None def has_link(self, doctype, name): for link in self.links: - if link.link_doctype==doctype and link.link_name== name: + if link.link_doctype == doctype and link.link_name == name: return True def has_common_link(self, doc): diff --git a/frappe/contacts/doctype/contact/test_contact.py b/frappe/contacts/doctype/contact/test_contact.py index 6c6089edeb..1170ba843a 100644 --- a/frappe/contacts/doctype/contact/test_contact.py +++ b/frappe/contacts/doctype/contact/test_contact.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE import frappe import unittest diff --git a/frappe/contacts/doctype/contact_email/contact_email.py b/frappe/contacts/doctype/contact_email/contact_email.py index 5fc2fef316..58d37376b8 100644 --- a/frappe/contacts/doctype/contact_email/contact_email.py +++ b/frappe/contacts/doctype/contact_email/contact_email.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE # import frappe from frappe.model.document import Document diff --git a/frappe/contacts/doctype/contact_phone/contact_phone.py b/frappe/contacts/doctype/contact_phone/contact_phone.py index 63f5f73cf1..ed7d3b9911 100644 --- a/frappe/contacts/doctype/contact_phone/contact_phone.py +++ b/frappe/contacts/doctype/contact_phone/contact_phone.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE # import frappe from frappe.model.document import Document diff --git a/frappe/contacts/doctype/gender/gender.py b/frappe/contacts/doctype/gender/gender.py index 319800de7e..b4efcb64b9 100644 --- a/frappe/contacts/doctype/gender/gender.py +++ b/frappe/contacts/doctype/gender/gender.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE from frappe.model.document import Document diff --git a/frappe/contacts/doctype/gender/test_gender.py b/frappe/contacts/doctype/gender/test_gender.py index 071ed47df0..8549cc2130 100644 --- a/frappe/contacts/doctype/gender/test_gender.py +++ b/frappe/contacts/doctype/gender/test_gender.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE import unittest class TestGender(unittest.TestCase): diff --git a/frappe/contacts/doctype/salutation/salutation.py b/frappe/contacts/doctype/salutation/salutation.py index d79ad66845..380af6de28 100644 --- a/frappe/contacts/doctype/salutation/salutation.py +++ b/frappe/contacts/doctype/salutation/salutation.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE from frappe.model.document import Document diff --git a/frappe/contacts/doctype/salutation/test_salutation.py b/frappe/contacts/doctype/salutation/test_salutation.py index e2e9075855..59333fb61e 100644 --- a/frappe/contacts/doctype/salutation/test_salutation.py +++ b/frappe/contacts/doctype/salutation/test_salutation.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE import unittest class TestSalutation(unittest.TestCase): diff --git a/frappe/contacts/report/addresses_and_contacts/addresses_and_contacts.py b/frappe/contacts/report/addresses_and_contacts/addresses_and_contacts.py index bf48b6b185..671e1c6bc8 100644 --- a/frappe/contacts/report/addresses_and_contacts/addresses_and_contacts.py +++ b/frappe/contacts/report/addresses_and_contacts/addresses_and_contacts.py @@ -1,5 +1,5 @@ # Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe from frappe import _ diff --git a/frappe/core/__init__.py b/frappe/core/__init__.py index f064a66c17..98029dd956 100644 --- a/frappe/core/__init__.py +++ b/frappe/core/__init__.py @@ -1,2 +1,2 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE diff --git a/frappe/core/doctype/__init__.py b/frappe/core/doctype/__init__.py index 0e57cb68c3..eb5ba62e5c 100644 --- a/frappe/core/doctype/__init__.py +++ b/frappe/core/doctype/__init__.py @@ -1,3 +1,3 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE diff --git a/frappe/core/doctype/access_log/access_log.py b/frappe/core/doctype/access_log/access_log.py index 82db450b4a..f631353d56 100644 --- a/frappe/core/doctype/access_log/access_log.py +++ b/frappe/core/doctype/access_log/access_log.py @@ -1,6 +1,7 @@ -# Copyright (c) 2019, Frappe Technologies and contributors -# For license information, please see license.txt +# Copyright (c) 2021, Frappe Technologies and contributors +# License: MIT. See LICENSE import frappe +from tenacity import retry, retry_if_exception_type, stop_after_attempt from frappe.model.document import Document @@ -9,25 +10,41 @@ class AccessLog(Document): @frappe.whitelist() -def make_access_log(doctype=None, document=None, method=None, file_type=None, - report_name=None, filters=None, page=None, columns=None): +@frappe.write_only() +@retry( + stop=stop_after_attempt(3), retry=retry_if_exception_type(frappe.DuplicateEntryError) +) +def make_access_log( + doctype=None, + document=None, + method=None, + file_type=None, + report_name=None, + filters=None, + page=None, + columns=None, +): user = frappe.session.user + in_request = frappe.request and frappe.request.method == "GET" - doc = frappe.get_doc({ - 'doctype': 'Access Log', - 'user': user, - 'export_from': doctype, - 'reference_document': document, - 'file_type': file_type, - 'report_name': report_name, - 'page': page, - 'method': method, - 'filters': frappe.utils.cstr(filters) if filters else None, - 'columns': columns - }) + doc = frappe.get_doc( + { + "doctype": "Access Log", + "user": user, + "export_from": doctype, + "reference_document": document, + "file_type": file_type, + "report_name": report_name, + "page": page, + "method": method, + "filters": frappe.utils.cstr(filters) if filters else None, + "columns": columns, + } + ) doc.insert(ignore_permissions=True) # `frappe.db.commit` added because insert doesnt `commit` when called in GET requests like `printview` - if frappe.request and frappe.request.method == 'GET': + # dont commit in test mode + if not frappe.flags.in_test or in_request: frappe.db.commit() diff --git a/frappe/core/doctype/access_log/test_access_log.py b/frappe/core/doctype/access_log/test_access_log.py index 9830507423..42878d0eb4 100644 --- a/frappe/core/doctype/access_log/test_access_log.py +++ b/frappe/core/doctype/access_log/test_access_log.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE # imports - standard imports import unittest diff --git a/frappe/core/doctype/activity_log/activity_log.py b/frappe/core/doctype/activity_log/activity_log.py index efec0dc217..183a1c264c 100644 --- a/frappe/core/doctype/activity_log/activity_log.py +++ b/frappe/core/doctype/activity_log/activity_log.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE from frappe import _ from frappe.utils import get_fullname, now diff --git a/frappe/core/doctype/activity_log/feed.py b/frappe/core/doctype/activity_log/feed.py index 19d7b77184..358272ac63 100644 --- a/frappe/core/doctype/activity_log/feed.py +++ b/frappe/core/doctype/activity_log/feed.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# License: See license.txt +# License: MIT. See LICENSE import frappe import frappe.permissions diff --git a/frappe/core/doctype/activity_log/test_activity_log.py b/frappe/core/doctype/activity_log/test_activity_log.py index ed7b70cca1..87d3538cc7 100644 --- a/frappe/core/doctype/activity_log/test_activity_log.py +++ b/frappe/core/doctype/activity_log/test_activity_log.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE import frappe import unittest import time diff --git a/frappe/core/doctype/block_module/block_module.py b/frappe/core/doctype/block_module/block_module.py index d9723f9170..cc6c222a04 100644 --- a/frappe/core/doctype/block_module/block_module.py +++ b/frappe/core/doctype/block_module/block_module.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe from frappe.model.document import Document diff --git a/frappe/core/doctype/comment/comment.py b/frappe/core/doctype/comment/comment.py index 2706ab1c30..e28d350d04 100644 --- a/frappe/core/doctype/comment/comment.py +++ b/frappe/core/doctype/comment/comment.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe from frappe import _ import json diff --git a/frappe/core/doctype/comment/test_comment.py b/frappe/core/doctype/comment/test_comment.py index 12fe027fba..99bd19c106 100644 --- a/frappe/core/doctype/comment/test_comment.py +++ b/frappe/core/doctype/comment/test_comment.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE import frappe, json import unittest diff --git a/frappe/core/doctype/communication/__init__.py b/frappe/core/doctype/communication/__init__.py index 0e57cb68c3..eb5ba62e5c 100644 --- a/frappe/core/doctype/communication/__init__.py +++ b/frappe/core/doctype/communication/__init__.py @@ -1,3 +1,3 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE diff --git a/frappe/core/doctype/communication/communication.py b/frappe/core/doctype/communication/communication.py index 17b1290776..66bb3909da 100644 --- a/frappe/core/doctype/communication/communication.py +++ b/frappe/core/doctype/communication/communication.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE from collections import Counter import frappe diff --git a/frappe/core/doctype/communication/email.py b/frappe/core/doctype/communication/email.py index 7ffbe6781d..4d22075b78 100755 --- a/frappe/core/doctype/communication/email.py +++ b/frappe/core/doctype/communication/email.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import frappe import json diff --git a/frappe/core/doctype/communication/test_communication.py b/frappe/core/doctype/communication/test_communication.py index d50a4db88a..b0c8e1fcee 100644 --- a/frappe/core/doctype/communication/test_communication.py +++ b/frappe/core/doctype/communication/test_communication.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# See license.txt +# License: MIT. See LICENSE import unittest from urllib.parse import quote diff --git a/frappe/core/doctype/communication_link/communication_link.py b/frappe/core/doctype/communication_link/communication_link.py index d3307d1d32..a895ad3df5 100644 --- a/frappe/core/doctype/communication_link/communication_link.py +++ b/frappe/core/doctype/communication_link/communication_link.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe from frappe.model.document import Document diff --git a/frappe/core/doctype/custom_docperm/custom_docperm.py b/frappe/core/doctype/custom_docperm/custom_docperm.py index 225f5db79b..1790344776 100644 --- a/frappe/core/doctype/custom_docperm/custom_docperm.py +++ b/frappe/core/doctype/custom_docperm/custom_docperm.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe from frappe.model.document import Document diff --git a/frappe/core/doctype/custom_docperm/test_custom_docperm.py b/frappe/core/doctype/custom_docperm/test_custom_docperm.py index 6e0c82d1db..422b711e5b 100644 --- a/frappe/core/doctype/custom_docperm/test_custom_docperm.py +++ b/frappe/core/doctype/custom_docperm/test_custom_docperm.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE import frappe import unittest diff --git a/frappe/core/doctype/custom_role/custom_role.py b/frappe/core/doctype/custom_role/custom_role.py index 89e478dd38..c6630baf6d 100644 --- a/frappe/core/doctype/custom_role/custom_role.py +++ b/frappe/core/doctype/custom_role/custom_role.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe from frappe.model.document import Document diff --git a/frappe/core/doctype/custom_role/test_custom_role.py b/frappe/core/doctype/custom_role/test_custom_role.py index 0ad77524fa..21511a7408 100644 --- a/frappe/core/doctype/custom_role/test_custom_role.py +++ b/frappe/core/doctype/custom_role/test_custom_role.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE import frappe import unittest diff --git a/frappe/core/doctype/data_export/data_export.py b/frappe/core/doctype/data_export/data_export.py index c376b25230..46fe3570a1 100644 --- a/frappe/core/doctype/data_export/data_export.py +++ b/frappe/core/doctype/data_export/data_export.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE from frappe.model.document import Document diff --git a/frappe/core/doctype/data_export/exporter.py b/frappe/core/doctype/data_export/exporter.py index ffd828bfdb..7c660c7180 100644 --- a/frappe/core/doctype/data_export/exporter.py +++ b/frappe/core/doctype/data_export/exporter.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import frappe from frappe import _ diff --git a/frappe/core/doctype/data_import/data_import.py b/frappe/core/doctype/data_import/data_import.py index 50469eeb4d..5935ddc4ba 100644 --- a/frappe/core/doctype/data_import/data_import.py +++ b/frappe/core/doctype/data_import/data_import.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import os diff --git a/frappe/core/doctype/data_import/exporter.py b/frappe/core/doctype/data_import/exporter.py index acaa294a6f..684328a4c7 100644 --- a/frappe/core/doctype/data_import/exporter.py +++ b/frappe/core/doctype/data_import/exporter.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import typing diff --git a/frappe/core/doctype/data_import/importer.py b/frappe/core/doctype/data_import/importer.py index bb922f1f5d..ef2bb02398 100644 --- a/frappe/core/doctype/data_import/importer.py +++ b/frappe/core/doctype/data_import/importer.py @@ -1,5 +1,5 @@ # Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import os import io diff --git a/frappe/core/doctype/data_import/test_data_import.py b/frappe/core/doctype/data_import/test_data_import.py index c9366a97ba..c0e4f50d6d 100644 --- a/frappe/core/doctype/data_import/test_data_import.py +++ b/frappe/core/doctype/data_import/test_data_import.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE # import frappe import unittest diff --git a/frappe/core/doctype/data_import/test_exporter.py b/frappe/core/doctype/data_import/test_exporter.py index dfe9926906..cb9461451f 100644 --- a/frappe/core/doctype/data_import/test_exporter.py +++ b/frappe/core/doctype/data_import/test_exporter.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE import unittest import frappe from frappe.core.doctype.data_import.exporter import Exporter diff --git a/frappe/core/doctype/data_import/test_importer.py b/frappe/core/doctype/data_import/test_importer.py index 7a4d185d8f..e1bc0e7ca5 100644 --- a/frappe/core/doctype/data_import/test_importer.py +++ b/frappe/core/doctype/data_import/test_importer.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE import unittest import frappe from frappe.core.doctype.data_import.importer import Importer diff --git a/frappe/core/doctype/defaultvalue/__init__.py b/frappe/core/doctype/defaultvalue/__init__.py index 0e57cb68c3..eb5ba62e5c 100644 --- a/frappe/core/doctype/defaultvalue/__init__.py +++ b/frappe/core/doctype/defaultvalue/__init__.py @@ -1,3 +1,3 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE diff --git a/frappe/core/doctype/defaultvalue/defaultvalue.py b/frappe/core/doctype/defaultvalue/defaultvalue.py index 0ae088ee96..1d597c7fc4 100644 --- a/frappe/core/doctype/defaultvalue/defaultvalue.py +++ b/frappe/core/doctype/defaultvalue/defaultvalue.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import frappe diff --git a/frappe/core/doctype/deleted_document/deleted_document.py b/frappe/core/doctype/deleted_document/deleted_document.py index f4109c8197..b398ec5410 100644 --- a/frappe/core/doctype/deleted_document/deleted_document.py +++ b/frappe/core/doctype/deleted_document/deleted_document.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe import json diff --git a/frappe/core/doctype/deleted_document/test_deleted_document.py b/frappe/core/doctype/deleted_document/test_deleted_document.py index d9dc2bb2d1..fb2376de90 100644 --- a/frappe/core/doctype/deleted_document/test_deleted_document.py +++ b/frappe/core/doctype/deleted_document/test_deleted_document.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE import frappe import unittest diff --git a/frappe/core/doctype/docfield/__init__.py b/frappe/core/doctype/docfield/__init__.py index 0e57cb68c3..eb5ba62e5c 100644 --- a/frappe/core/doctype/docfield/__init__.py +++ b/frappe/core/doctype/docfield/__init__.py @@ -1,3 +1,3 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE diff --git a/frappe/core/doctype/docfield/docfield.json b/frappe/core/doctype/docfield/docfield.json index ce62adc8be..6910d615d3 100644 --- a/frappe/core/doctype/docfield/docfield.json +++ b/frappe/core/doctype/docfield/docfield.json @@ -1,498 +1,543 @@ { - "actions": [], - "autoname": "hash", - "creation": "2013-02-22 01:27:33", - "doctype": "DocType", - "document_type": "Setup", - "editable_grid": 1, - "engine": "InnoDB", - "field_order": [ - "label_and_type", - "label", - "fieldtype", - "fieldname", - "precision", - "length", - "non_negative", - "hide_days", - "hide_seconds", - "reqd", - "search_index", - "in_list_view", - "in_standard_filter", - "in_global_search", - "in_preview", - "allow_in_quick_entry", - "bold", - "translatable", - "collapsible", - "collapsible_depends_on", - "column_break_6", - "options", - "default", - "fetch_from", - "fetch_if_empty", - "permissions", - "depends_on", - "hidden", - "read_only", - "unique", - "set_only_once", - "allow_bulk_edit", - "column_break_13", - "permlevel", - "ignore_user_permissions", - "allow_on_submit", - "report_hide", - "remember_last_selected_value", - "ignore_xss_filter", - "hide_border", - "property_depends_on_section", - "mandatory_depends_on", - "column_break_38", - "read_only_depends_on", - "display", - "in_filter", - "no_copy", - "print_hide", - "print_hide_if_no_value", - "print_width", - "width", - "columns", - "column_break_22", - "description", - "oldfieldname", - "oldfieldtype" - ], - "fields": [ - { - "fieldname": "label_and_type", - "fieldtype": "Section Break" - }, - { - "bold": 1, - "fieldname": "label", - "fieldtype": "Data", - "in_list_view": 1, - "label": "Label", - "oldfieldname": "label", - "oldfieldtype": "Data", - "print_width": "163", - "search_index": 1, - "width": "163" - }, - { - "bold": 1, - "default": "Data", - "fieldname": "fieldtype", - "fieldtype": "Select", - "in_list_view": 1, - "label": "Type", - "oldfieldname": "fieldtype", - "oldfieldtype": "Select", - "options": "Attach\nAttach Image\nBarcode\nButton\nCheck\nCode\nColor\nColumn Break\nCurrency\nData\nDate\nDatetime\nDuration\nDynamic Link\nFloat\nFold\nGeolocation\nHeading\nHTML\nHTML Editor\nIcon\nImage\nInt\nLink\nLong Text\nMarkdown Editor\nPassword\nPercent\nRead Only\nRating\nSection Break\nSelect\nSmall Text\nTable\nTable MultiSelect\nText\nText Editor\nTime\nSignature", - "reqd": 1, - "search_index": 1 - }, - { - "bold": 1, - "fieldname": "fieldname", - "fieldtype": "Data", - "in_list_view": 1, - "label": "Name", - "oldfieldname": "fieldname", - "oldfieldtype": "Data", - "search_index": 1 - }, - { - "default": "0", - "depends_on": "eval:!in_list([\"Section Break\", \"Column Break\", \"Button\", \"HTML\"], doc.fieldtype)", - "fieldname": "reqd", - "fieldtype": "Check", - "in_list_view": 1, - "label": "Mandatory", - "oldfieldname": "reqd", - "oldfieldtype": "Check", - "print_width": "50px", - "width": "50px" - }, - { - "depends_on": "eval:in_list([\"Float\", \"Currency\", \"Percent\"], doc.fieldtype)", - "description": "Set non-standard precision for a Float or Currency field", - "fieldname": "precision", - "fieldtype": "Select", - "label": "Precision", - "options": "\n0\n1\n2\n3\n4\n5\n6\n7\n8\n9", - "print_hide": 1 - }, - { - "depends_on": "eval:in_list(['Data', 'Link', 'Dynamic Link', 'Password', 'Select', 'Read Only', 'Attach', 'Attach Image', 'Int'], doc.fieldtype)", - "fieldname": "length", - "fieldtype": "Int", - "label": "Length" - }, - { - "default": "0", - "fieldname": "search_index", - "fieldtype": "Check", - "label": "Index", - "oldfieldname": "search_index", - "oldfieldtype": "Check", - "print_width": "50px", - "width": "50px" - }, - { - "default": "0", - "fieldname": "in_list_view", - "fieldtype": "Check", - "label": "In List View", - "print_width": "70px", - "width": "70px" - }, - { - "default": "0", - "fieldname": "in_standard_filter", - "fieldtype": "Check", - "label": "In Standard Filter" - }, - { - "default": "0", - "depends_on": "eval:([\"Data\", \"Select\", \"Table\", \"Text\", \"Text Editor\", \"Link\", \"Small Text\", \"Long Text\", \"Read Only\", \"Heading\", \"Dynamic Link\"].indexOf(doc.fieldtype) !== -1)", - "fieldname": "in_global_search", - "fieldtype": "Check", - "label": "In Global Search" - }, - { - "default": "0", - "depends_on": "eval:!in_list(['Table', 'Table MultiSelect'], doc.fieldtype);", - "fieldname": "in_preview", - "fieldtype": "Check", - "label": "In Preview" - }, - { - "default": "0", - "fieldname": "allow_in_quick_entry", - "fieldtype": "Check", - "label": "Allow in Quick Entry" - }, - { - "default": "0", - "fieldname": "bold", - "fieldtype": "Check", - "label": "Bold" - }, - { - "default": "0", - "depends_on": "eval:['Data', 'Select', 'Text', 'Small Text', 'Text Editor'].includes(doc.fieldtype)", - "fieldname": "translatable", - "fieldtype": "Check", - "label": "Translatable" - }, - { - "default": "0", - "depends_on": "eval:doc.fieldtype===\"Section Break\"", - "fieldname": "collapsible", - "fieldtype": "Check", - "label": "Collapsible", - "length": 255 - }, - { - "depends_on": "eval:doc.fieldtype==\"Section Break\"", - "fieldname": "collapsible_depends_on", - "fieldtype": "Code", - "label": "Collapsible Depends On", - "options": "JS" - }, - { - "fieldname": "column_break_6", - "fieldtype": "Column Break" - }, - { - "description": "For Links, enter the DocType as range.\nFor Select, enter list of Options, each on a new line.", - "fieldname": "options", - "fieldtype": "Small Text", - "in_list_view": 1, - "label": "Options", - "oldfieldname": "options", - "oldfieldtype": "Text" - }, - { - "fieldname": "default", - "fieldtype": "Small Text", - "label": "Default", - "oldfieldname": "default", - "oldfieldtype": "Text" - }, - { - "fieldname": "fetch_from", - "fieldtype": "Small Text", - "label": "Fetch From" - }, - { - "default": "0", - "description": "If checked, this field will be not overwritten based on Fetch From if a value already exists.", - "fieldname": "fetch_if_empty", - "fieldtype": "Check", - "label": "Fetch If Empty" - }, - { - "fieldname": "permissions", - "fieldtype": "Section Break", - "label": "Permissions" - }, - { - "fieldname": "depends_on", - "fieldtype": "Code", - "label": "Display Depends On", - "length": 255, - "oldfieldname": "depends_on", - "oldfieldtype": "Data", - "options": "JS" - }, - { - "default": "0", - "fieldname": "hidden", - "fieldtype": "Check", - "label": "Hidden", - "oldfieldname": "hidden", - "oldfieldtype": "Check", - "print_width": "50px", - "width": "50px" - }, - { - "default": "0", - "fieldname": "read_only", - "fieldtype": "Check", - "label": "Read Only", - "print_width": "50px", - "width": "50px" - }, - { - "default": "0", - "fieldname": "unique", - "fieldtype": "Check", - "label": "Unique" - }, - { - "default": "0", - "description": "Do not allow user to change after set the first time", - "fieldname": "set_only_once", - "fieldtype": "Check", - "label": "Set Only Once" - }, - { - "default": "0", - "depends_on": "eval: doc.fieldtype == \"Table\"", - "fieldname": "allow_bulk_edit", - "fieldtype": "Check", - "label": "Allow Bulk Edit" - }, - { - "fieldname": "column_break_13", - "fieldtype": "Column Break" - }, - { - "default": "0", - "fieldname": "permlevel", - "fieldtype": "Int", - "label": "Perm Level", - "oldfieldname": "permlevel", - "oldfieldtype": "Int", - "print_width": "50px", - "width": "50px" - }, - { - "default": "0", - "description": "User permissions should not apply for this Link", - "fieldname": "ignore_user_permissions", - "fieldtype": "Check", - "label": "Ignore User Permissions" - }, - { - "default": "0", - "depends_on": "eval: parent.is_submittable", - "fieldname": "allow_on_submit", - "fieldtype": "Check", - "label": "Allow on Submit", - "oldfieldname": "allow_on_submit", - "oldfieldtype": "Check", - "print_width": "50px", - "width": "50px" - }, - { - "default": "0", - "fieldname": "report_hide", - "fieldtype": "Check", - "label": "Report Hide", - "oldfieldname": "report_hide", - "oldfieldtype": "Check", - "print_width": "50px", - "width": "50px" - }, - { - "default": "0", - "depends_on": "eval:(doc.fieldtype == 'Link')", - "fieldname": "remember_last_selected_value", - "fieldtype": "Check", - "label": "Remember Last Selected Value" - }, - { - "default": "0", - "description": "Don't HTML Encode HTML tags like <script> or just characters like < or >, as they could be intentionally used in this field", - "fieldname": "ignore_xss_filter", - "fieldtype": "Check", - "label": "Ignore XSS Filter" - }, - { - "fieldname": "display", - "fieldtype": "Section Break", - "label": "Display" - }, - { - "default": "0", - "fieldname": "in_filter", - "fieldtype": "Check", - "label": "In Filter", - "oldfieldname": "in_filter", - "oldfieldtype": "Check", - "print_width": "50px", - "width": "50px" - }, - { - "default": "0", - "fieldname": "no_copy", - "fieldtype": "Check", - "label": "No Copy", - "oldfieldname": "no_copy", - "oldfieldtype": "Check", - "print_width": "50px", - "width": "50px" - }, - { - "default": "0", - "fieldname": "print_hide", - "fieldtype": "Check", - "label": "Print Hide", - "oldfieldname": "print_hide", - "oldfieldtype": "Check", - "print_width": "50px", - "width": "50px" - }, - { - "default": "0", - "depends_on": "eval:[\"Int\", \"Float\", \"Currency\", \"Percent\"].indexOf(doc.fieldtype)!==-1", - "fieldname": "print_hide_if_no_value", - "fieldtype": "Check", - "label": "Print Hide If No Value" - }, - { - "fieldname": "print_width", - "fieldtype": "Data", - "label": "Print Width" - }, - { - "fieldname": "width", - "fieldtype": "Data", - "label": "Width", - "oldfieldname": "width", - "oldfieldtype": "Data", - "print_width": "50px", - "width": "50px" - }, - { - "description": "Number of columns for a field in a List View or a Grid (Total Columns should be less than 11)", - "fieldname": "columns", - "fieldtype": "Int", - "label": "Columns" - }, - { - "fieldname": "column_break_22", - "fieldtype": "Column Break" - }, - { - "fieldname": "description", - "fieldtype": "Small Text", - "in_list_view": 1, - "label": "Description", - "oldfieldname": "description", - "oldfieldtype": "Text", - "print_width": "300px", - "width": "300px" - }, - { - "fieldname": "oldfieldname", - "fieldtype": "Data", - "hidden": 1, - "oldfieldname": "oldfieldname", - "oldfieldtype": "Data" - }, - { - "fieldname": "oldfieldtype", - "fieldtype": "Data", - "hidden": 1, - "oldfieldname": "oldfieldtype", - "oldfieldtype": "Data" - }, - { - "fieldname": "mandatory_depends_on", - "fieldtype": "Code", - "label": "Mandatory Depends On", - "options": "JS" - }, - { - "fieldname": "read_only_depends_on", - "fieldtype": "Code", - "label": "Read Only Depends On", - "options": "JS" - }, - { - "fieldname": "property_depends_on_section", - "fieldtype": "Section Break", - "label": "Property Depends On" - }, - { - "fieldname": "column_break_38", - "fieldtype": "Column Break" - }, - { - "default": "0", - "depends_on": "eval:doc.fieldtype=='Duration'", - "fieldname": "hide_days", - "fieldtype": "Check", - "label": "Hide Days" - }, - { - "default": "0", - "depends_on": "eval:doc.fieldtype=='Duration'", - "fieldname": "hide_seconds", - "fieldtype": "Check", - "label": "Hide Seconds" - }, - { - "default": "0", - "depends_on": "eval:doc.fieldtype=='Section Break'", - "fieldname": "hide_border", - "fieldtype": "Check", - "label": "Hide Border" - }, - { - "default": "0", - "depends_on": "eval:in_list([\"Int\", \"Float\", \"Currency\"], doc.fieldtype)", - "fieldname": "non_negative", - "fieldtype": "Check", - "label": "Non Negative" - } - ], - "idx": 1, - "index_web_pages_for_search": 1, - "istable": 1, - "links": [], - "modified": "2021-07-10 21:56:04.167745", - "modified_by": "Administrator", - "module": "Core", - "name": "DocField", - "owner": "Administrator", - "permissions": [], - "sort_field": "modified", - "sort_order": "ASC" + "actions": [], + "autoname": "hash", + "creation": "2013-02-22 01:27:33", + "doctype": "DocType", + "document_type": "Setup", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "label_and_type", + "label", + "fieldtype", + "fieldname", + "precision", + "length", + "non_negative", + "hide_days", + "hide_seconds", + "reqd", + "search_index", + "column_break_18", + "options", + "defaults_section", + "default", + "column_break_6", + "fetch_from", + "fetch_if_empty", + "visibility_section", + "hidden", + "bold", + "allow_in_quick_entry", + "translatable", + "print_hide", + "print_hide_if_no_value", + "report_hide", + "column_break_28", + "depends_on", + "collapsible", + "collapsible_depends_on", + "hide_border", + "list__search_settings_section", + "in_list_view", + "in_standard_filter", + "in_preview", + "column_break_35", + "in_filter", + "in_global_search", + "permissions", + "read_only", + "allow_on_submit", + "ignore_user_permissions", + "allow_bulk_edit", + "column_break_13", + "permlevel", + "ignore_xss_filter", + "constraints_section", + "unique", + "no_copy", + "set_only_once", + "remember_last_selected_value", + "column_break_38", + "mandatory_depends_on", + "read_only_depends_on", + "display", + "print_width", + "width", + "max_height", + "columns", + "column_break_22", + "description", + "oldfieldname", + "oldfieldtype" + ], + "fields": [{ + "fieldname": "label_and_type", + "fieldtype": "Section Break" + }, + { + "bold": 1, + "fieldname": "label", + "fieldtype": "Data", + "in_list_view": 1, + "label": "Label", + "oldfieldname": "label", + "oldfieldtype": "Data", + "print_width": "163", + "search_index": 1, + "width": "163" + }, + { + "bold": 1, + "default": "Data", + "fieldname": "fieldtype", + "fieldtype": "Select", + "in_list_view": 1, + "label": "Type", + "oldfieldname": "fieldtype", + "oldfieldtype": "Select", + "options": "Attach\nAttach Image\nBarcode\nButton\nCheck\nCode\nColor\nColumn Break\nCurrency\nData\nDate\nDatetime\nDuration\nDynamic Link\nFloat\nFold\nGeolocation\nHeading\nHTML\nHTML Editor\nIcon\nImage\nInt\nLink\nLong Text\nMarkdown Editor\nPassword\nPercent\nRead Only\nRating\nSection Break\nSelect\nSmall Text\nTable\nTable MultiSelect\nText\nText Editor\nTime\nSignature\nTab Break", + "reqd": 1, + "search_index": 1 + }, + { + "bold": 1, + "fieldname": "fieldname", + "fieldtype": "Data", + "in_list_view": 1, + "label": "Name", + "oldfieldname": "fieldname", + "oldfieldtype": "Data", + "search_index": 1 + }, + { + "default": "0", + "depends_on": "eval:!in_list([\"Section Break\", \"Column Break\", \"Button\", \"HTML\"], doc.fieldtype)", + "fieldname": "reqd", + "fieldtype": "Check", + "in_list_view": 1, + "label": "Mandatory", + "oldfieldname": "reqd", + "oldfieldtype": "Check", + "print_width": "50px", + "width": "50px" + }, + { + "depends_on": "eval:in_list([\"Float\", \"Currency\", \"Percent\"], doc.fieldtype)", + "description": "Set non-standard precision for a Float or Currency field", + "fieldname": "precision", + "fieldtype": "Select", + "label": "Precision", + "options": "\n0\n1\n2\n3\n4\n5\n6\n7\n8\n9", + "print_hide": 1 + }, + { + "depends_on": "eval:in_list(['Data', 'Link', 'Dynamic Link', 'Password', 'Select', 'Read Only', 'Attach', 'Attach Image', 'Int'], doc.fieldtype)", + "fieldname": "length", + "fieldtype": "Int", + "label": "Length" + }, + { + "default": "0", + "fieldname": "search_index", + "fieldtype": "Check", + "label": "Index", + "oldfieldname": "search_index", + "oldfieldtype": "Check", + "print_width": "50px", + "width": "50px" + }, + { + "default": "0", + "fieldname": "in_list_view", + "fieldtype": "Check", + "label": "In List View", + "print_width": "70px", + "width": "70px" + }, + { + "default": "0", + "fieldname": "in_standard_filter", + "fieldtype": "Check", + "label": "In List Filter" + }, + { + "default": "0", + "depends_on": "eval:([\"Data\", \"Select\", \"Table\", \"Text\", \"Text Editor\", \"Link\", \"Small Text\", \"Long Text\", \"Read Only\", \"Heading\", \"Dynamic Link\"].indexOf(doc.fieldtype) !== -1)", + "fieldname": "in_global_search", + "fieldtype": "Check", + "label": "In Global Search" + }, + { + "default": "0", + "depends_on": "eval:!in_list(['Table', 'Table MultiSelect'], doc.fieldtype);", + "fieldname": "in_preview", + "fieldtype": "Check", + "label": "In Preview" + }, + { + "default": "0", + "fieldname": "allow_in_quick_entry", + "fieldtype": "Check", + "label": "Allow in Quick Entry" + }, + { + "default": "0", + "fieldname": "bold", + "fieldtype": "Check", + "label": "Bold" + }, + { + "default": "0", + "depends_on": "eval:['Data', 'Select', 'Text', 'Small Text', 'Text Editor'].includes(doc.fieldtype)", + "fieldname": "translatable", + "fieldtype": "Check", + "label": "Translatable" + }, + { + "default": "0", + "depends_on": "eval:doc.fieldtype===\"Section Break\"", + "fieldname": "collapsible", + "fieldtype": "Check", + "label": "Collapsible", + "length": 255 + }, + { + "depends_on": "eval:doc.fieldtype==\"Section Break\" && doc.collapsible", + "fieldname": "collapsible_depends_on", + "fieldtype": "Code", + "label": "Collapsible Depends On (JS)", + "max_height": "3rem", + "options": "JS" + }, + { + "fieldname": "column_break_6", + "fieldtype": "Column Break" + }, + { + "description": "For Links, enter the DocType as range.\nFor Select, enter list of Options, each on a new line.", + "fieldname": "options", + "fieldtype": "Small Text", + "in_list_view": 1, + "label": "Options", + "oldfieldname": "options", + "oldfieldtype": "Text" + }, + { + "fieldname": "default", + "fieldtype": "Small Text", + "label": "Default", + "max_height": "3rem", + "oldfieldname": "default", + "oldfieldtype": "Text" + }, + { + "fieldname": "fetch_from", + "fieldtype": "Small Text", + "label": "Fetch From" + }, + { + "default": "0", + "fieldname": "fetch_if_empty", + "fieldtype": "Check", + "label": "Fetch only if value is not set" + }, + { + "fieldname": "permissions", + "fieldtype": "Section Break", + "label": "Permissions" + }, + { + "fieldname": "depends_on", + "fieldtype": "Code", + "label": "Display Depends On (JS)", + "length": 255, + "max_height": "3rem", + "oldfieldname": "depends_on", + "oldfieldtype": "Data", + "options": "JS" + }, + { + "default": "0", + "fieldname": "hidden", + "fieldtype": "Check", + "label": "Hidden", + "oldfieldname": "hidden", + "oldfieldtype": "Check", + "print_width": "50px", + "width": "50px" + }, + { + "default": "0", + "fieldname": "read_only", + "fieldtype": "Check", + "label": "Read Only", + "print_width": "50px", + "width": "50px" + }, + { + "default": "0", + "fieldname": "unique", + "fieldtype": "Check", + "label": "Unique" + }, + { + "default": "0", + "fieldname": "set_only_once", + "fieldtype": "Check", + "label": "Set only once" + }, + { + "default": "0", + "depends_on": "eval: doc.fieldtype == \"Table\"", + "fieldname": "allow_bulk_edit", + "fieldtype": "Check", + "label": "Allow Bulk Edit" + }, + { + "fieldname": "column_break_13", + "fieldtype": "Column Break" + }, + { + "default": "0", + "fieldname": "permlevel", + "fieldtype": "Int", + "label": "Perm Level", + "oldfieldname": "permlevel", + "oldfieldtype": "Int", + "print_width": "50px", + "width": "50px" + }, + { + "default": "0", + "fieldname": "ignore_user_permissions", + "fieldtype": "Check", + "label": "Ignore User Permissions" + }, + { + "default": "0", + "depends_on": "eval: parent.is_submittable", + "fieldname": "allow_on_submit", + "fieldtype": "Check", + "label": "Allow on Submit", + "oldfieldname": "allow_on_submit", + "oldfieldtype": "Check", + "print_width": "50px", + "width": "50px" + }, + { + "default": "0", + "fieldname": "report_hide", + "fieldtype": "Check", + "label": "Report Hide", + "oldfieldname": "report_hide", + "oldfieldtype": "Check", + "print_width": "50px", + "width": "50px" + }, + { + "default": "0", + "depends_on": "eval:(doc.fieldtype == 'Link')", + "fieldname": "remember_last_selected_value", + "fieldtype": "Check", + "label": "Remember Last Selected Value" + }, + { + "default": "0", + "description": "Don't HTML Encode HTML tags like <script> or just characters like < or >, as they could be intentionally used in this field", + "fieldname": "ignore_xss_filter", + "fieldtype": "Check", + "label": "Ignore XSS Filter" + }, + { + "fieldname": "display", + "fieldtype": "Section Break", + "label": "Display" + }, + { + "default": "0", + "fieldname": "in_filter", + "fieldtype": "Check", + "label": "In Filter", + "oldfieldname": "in_filter", + "oldfieldtype": "Check", + "print_width": "50px", + "width": "50px" + }, + { + "default": "0", + "fieldname": "no_copy", + "fieldtype": "Check", + "label": "No Copy", + "oldfieldname": "no_copy", + "oldfieldtype": "Check", + "print_width": "50px", + "width": "50px" + }, + { + "default": "0", + "fieldname": "print_hide", + "fieldtype": "Check", + "label": "Print Hide", + "oldfieldname": "print_hide", + "oldfieldtype": "Check", + "print_width": "50px", + "width": "50px" + }, + { + "default": "0", + "depends_on": "eval:[\"Int\", \"Float\", \"Currency\", \"Percent\"].indexOf(doc.fieldtype)!==-1", + "fieldname": "print_hide_if_no_value", + "fieldtype": "Check", + "label": "Print Hide If No Value" + }, + { + "fieldname": "print_width", + "fieldtype": "Data", + "label": "Print Width", + "length": 10 + }, + { + "fieldname": "width", + "fieldtype": "Data", + "label": "Width", + "length": 10, + "oldfieldname": "width", + "oldfieldtype": "Data", + "print_width": "50px", + "width": "50px" + }, + { + "description": "Number of columns for a field in a List View or a Grid (Total Columns should be less than 11)", + "fieldname": "columns", + "fieldtype": "Int", + "label": "Columns" + }, + { + "fieldname": "column_break_22", + "fieldtype": "Column Break" + }, + { + "fieldname": "description", + "fieldtype": "Small Text", + "in_list_view": 1, + "label": "Description", + "oldfieldname": "description", + "oldfieldtype": "Text", + "print_width": "300px", + "width": "300px" + }, + { + "fieldname": "oldfieldname", + "fieldtype": "Data", + "hidden": 1, + "oldfieldname": "oldfieldname", + "oldfieldtype": "Data" + }, + { + "fieldname": "oldfieldtype", + "fieldtype": "Data", + "hidden": 1, + "oldfieldname": "oldfieldtype", + "oldfieldtype": "Data" + }, + { + "fieldname": "mandatory_depends_on", + "fieldtype": "Code", + "label": "Mandatory Depends On (JS)", + "max_height": "3rem", + "options": "JS" + }, + { + "fieldname": "read_only_depends_on", + "fieldtype": "Code", + "label": "Read Only Depends On (JS)", + "max_height": "3rem", + "options": "JS" + }, + { + "fieldname": "column_break_38", + "fieldtype": "Column Break" + }, + { + "default": "0", + "depends_on": "eval:doc.fieldtype=='Duration'", + "fieldname": "hide_days", + "fieldtype": "Check", + "label": "Hide Days" + }, + { + "default": "0", + "depends_on": "eval:doc.fieldtype=='Duration'", + "fieldname": "hide_seconds", + "fieldtype": "Check", + "label": "Hide Seconds" + }, + { + "default": "0", + "depends_on": "eval:doc.fieldtype=='Section Break'", + "fieldname": "hide_border", + "fieldtype": "Check", + "label": "Hide Border" + }, + { + "default": "0", + "depends_on": "eval:in_list([\"Int\", \"Float\", \"Currency\"], doc.fieldtype)", + "fieldname": "non_negative", + "fieldtype": "Check", + "label": "Non Negative" + }, + { + "fieldname": "column_break_18", + "fieldtype": "Column Break" + }, + { + "fieldname": "defaults_section", + "fieldtype": "Section Break", + "label": "Defaults", + "max_height": "2rem" + }, + { + "fieldname": "visibility_section", + "fieldtype": "Section Break", + "label": "Visibility" + }, + { + "fieldname": "column_break_28", + "fieldtype": "Column Break" + }, + { + "fieldname": "constraints_section", + "fieldtype": "Section Break", + "label": "Constraints" + }, + { + "fieldname": "max_height", + "fieldtype": "Data", + "label": "Max Height", + "length": 10 + }, + { + "fieldname": "list__search_settings_section", + "fieldtype": "Section Break", + "label": "List / Search Settings" + }, + { + "fieldname": "column_break_35", + "fieldtype": "Column Break" + } + ], + "idx": 1, + "index_web_pages_for_search": 1, + "istable": 1, + "links": [], + "modified": "2021-09-04 19:41:23.684094", + "modified_by": "Administrator", + "module": "Core", + "name": "DocField", + "naming_rule": "Random", + "owner": "Administrator", + "permissions": [], + "sort_field": "modified", + "sort_order": "ASC" } \ No newline at end of file diff --git a/frappe/core/doctype/docfield/docfield.py b/frappe/core/doctype/docfield/docfield.py index 175cba3c7c..4dd49631ae 100644 --- a/frappe/core/doctype/docfield/docfield.py +++ b/frappe/core/doctype/docfield/docfield.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import frappe from frappe.model.document import Document diff --git a/frappe/core/doctype/docperm/__init__.py b/frappe/core/doctype/docperm/__init__.py index 0e57cb68c3..eb5ba62e5c 100644 --- a/frappe/core/doctype/docperm/__init__.py +++ b/frappe/core/doctype/docperm/__init__.py @@ -1,3 +1,3 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE diff --git a/frappe/core/doctype/docperm/docperm.py b/frappe/core/doctype/docperm/docperm.py index 9732cde920..4751816dc5 100644 --- a/frappe/core/doctype/docperm/docperm.py +++ b/frappe/core/doctype/docperm/docperm.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import frappe diff --git a/frappe/core/doctype/docshare/docshare.py b/frappe/core/doctype/docshare/docshare.py index 2d7b6b9e48..6320fba60b 100644 --- a/frappe/core/doctype/docshare/docshare.py +++ b/frappe/core/doctype/docshare/docshare.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe from frappe.model.document import Document diff --git a/frappe/core/doctype/docshare/test_docshare.py b/frappe/core/doctype/docshare/test_docshare.py index 6551dabbea..cbdaa8ebaf 100644 --- a/frappe/core/doctype/docshare/test_docshare.py +++ b/frappe/core/doctype/docshare/test_docshare.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# See license.txt +# License: MIT. See LICENSE import frappe import frappe.share diff --git a/frappe/core/doctype/doctype/__init__.py b/frappe/core/doctype/doctype/__init__.py index 0e57cb68c3..eb5ba62e5c 100644 --- a/frappe/core/doctype/doctype/__init__.py +++ b/frappe/core/doctype/doctype/__init__.py @@ -1,3 +1,3 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE diff --git a/frappe/core/doctype/doctype/doctype.js b/frappe/core/doctype/doctype/doctype.js index 3f1b5bb7ad..262a6efd90 100644 --- a/frappe/core/doctype/doctype/doctype.js +++ b/frappe/core/doctype/doctype/doctype.js @@ -61,9 +61,73 @@ frappe.ui.form.on('DocType', { __('In Grid View') : __('In List View'); frm.events.autoname(frm); + frm.events.set_naming_rule_description(frm); + }, + + naming_rule: function(frm) { + // set the "autoname" property based on naming_rule + if (frm.doc.naming_rule && !frm.__from_autoname) { + + // flag to avoid recursion + frm.__from_naming_rule = true; + + if (frm.doc.naming_rule=='Set by user') { + frm.set_value('autoname', 'Prompt'); + } else if (frm.doc.naming_rule=='By fieldname') { + frm.set_value('autoname', 'field:'); + } else if (frm.doc.naming_rule=='By "Naming Series" field') { + frm.set_value('autoname', 'naming_series:'); + } else if (frm.doc.naming_rule=='Expression') { + frm.set_value('autoname', 'format:'); + } else if (frm.doc.naming_rule=='Expression (old style)') { + // pass + } else if (frm.doc.naming_rule=='Random') { + frm.set_value('autoname', 'hash'); + } + setTimeout(() =>frm.__from_naming_rule = false, 500); + + frm.events.set_naming_rule_description(frm); + } + + }, + + set_naming_rule_description(frm) { + let naming_rule_description = { + 'Set by user': '', + 'By fieldname': 'Format: field:[fieldname]. Valid fieldname must exist', + 'By "Naming Series" field': 'Format: naming_series:[fieldname]. Fieldname called naming_series must exist', + 'Expression': 'Format: format:EXAMPLE-{MM}morewords{fieldname1}-{fieldname2}-{#####} - Replace all braced words (fieldnames, date words (DD, MM, YY), series) with their value. Outside braces, any characters can be used.', + 'Expression (old style)': 'Format: EXAMPLE-.##### Series by prefix (separated by a dot)', + 'Random': '', + 'By script': '' + }; + + if (frm.doc.naming_rule) { + frm.get_field('autoname').set_description(naming_rule_description[frm.doc.naming_rule]); + } }, autoname: function(frm) { + // set naming_rule based on autoname (for old doctypes where its not been set) + if (frm.doc.autoname && !frm.doc.naming_rule && !frm.__from_naming_rule) { + // flag to avoid recursion + frm.__from_autoname = true; + if (frm.doc.autoname.toLowerCase() === 'prompt') { + frm.set_value('naming_rule', 'Set by user'); + } else if (frm.doc.autoname.startsWith('field:')) { + frm.set_value('naming_rule', 'By fieldname'); + } else if (frm.doc.autoname.startsWith('naming_series:')) { + frm.set_value('naming_rule', 'By "Naming Series" field'); + } else if (frm.doc.autoname.startsWith('format:')) { + frm.set_value('naming_rule', 'Expression'); + } else if (frm.doc.autoname.toLowerCase() === 'hash') { + frm.set_value('naming_rule', 'Random'); + } else { + frm.set_value('naming_rule', 'Expression (old style)'); + } + setTimeout(() => frm.__from_autoname = false, 500); + } + frm.set_df_property('fields', 'reqd', frm.doc.autoname !== 'Prompt'); } }); diff --git a/frappe/core/doctype/doctype/doctype.json b/frappe/core/doctype/doctype/doctype.json index 63e0426eb3..18435f8873 100644 --- a/frappe/core/doctype/doctype/doctype.json +++ b/frappe/core/doctype/doctype/doctype.json @@ -26,6 +26,7 @@ "fields_section_break", "fields", "sb1", + "naming_rule", "autoname", "name_case", "allow_rename", @@ -554,6 +555,13 @@ "fieldname": "website_search_field", "fieldtype": "Data", "label": "Website Search Field" + }, + { + "fieldname": "naming_rule", + "fieldtype": "Select", + "label": "Naming Rule", + "length": 40, + "options": "\nSet by user\nBy fieldname\nBy \"Naming Series\" field\nExpression\nExpression (old style)\nRandom\nBy script" } ], "icon": "fa fa-bolt", @@ -635,7 +643,7 @@ "link_fieldname": "reference_doctype" } ], - "modified": "2021-08-31 15:26:19.077164", + "modified": "2021-09-05 15:39:13.233403", "modified_by": "Administrator", "module": "Core", "name": "DocType", diff --git a/frappe/core/doctype/doctype/doctype.py b/frappe/core/doctype/doctype/doctype.py index a7f4dd9def..8f8a8ed287 100644 --- a/frappe/core/doctype/doctype/doctype.py +++ b/frappe/core/doctype/doctype/doctype.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE # imports - standard imports import re, copy, os, shutil @@ -274,6 +274,8 @@ class DocType(Document): d.fieldname = d.fieldname + '_section' elif d.fieldtype=='Column Break': d.fieldname = d.fieldname + '_column' + elif d.fieldtype=='Tab Break': + d.fieldname = d.fieldname + '_tab' else: d.fieldname = d.fieldtype.lower().replace(" ","_") + "_" + str(d.idx) else: @@ -493,6 +495,9 @@ class DocType(Document): # retain order of 'fields' table and change order in 'field_order' docdict["field_order"] = [f.fieldname for f in self.fields] + if self.custom: + return + path = get_file_path(self.module, "DocType", self.name) if os.path.exists(path): try: @@ -719,20 +724,20 @@ def validate_links_table_fieldnames(meta): for index, link in enumerate(meta.links): link_meta = frappe.get_meta(link.link_doctype) if not link_meta.get_field(link.link_fieldname): - message = _("Row #{0}: Could not find field {1} in {2} DocType").format(index+1, frappe.bold(link.link_fieldname), frappe.bold(link.link_doctype)) + message = _("Document Links Row #{0}: Could not find field {1} in {2} DocType").format(index+1, frappe.bold(link.link_fieldname), frappe.bold(link.link_doctype)) frappe.throw(message, InvalidFieldNameError, _("Invalid Fieldname")) if link.is_child_table and not meta.get_field(link.table_fieldname): - message = _("Row #{0}: Could not find field {1} in {2} DocType").format(index+1, frappe.bold(link.table_fieldname), frappe.bold(meta.name)) + message = _("Document Links Row #{0}: Could not find field {1} in {2} DocType").format(index+1, frappe.bold(link.table_fieldname), frappe.bold(meta.name)) frappe.throw(message, frappe.ValidationError, _("Invalid Table Fieldname")) if link.is_child_table: if not link.parent_doctype: - message = _("Row #{0}: Parent DocType is mandatory for internal links").format(index+1) + message = _("Document Links Row #{0}: Parent DocType is mandatory for internal links").format(index+1) frappe.throw(message, frappe.ValidationError, _("Parent Missing")) if not link.table_fieldname: - message = _("Row #{0}: Table Fieldname is mandatory for internal links").format(index+1) + message = _("Document Links Row #{0}: Table Fieldname is mandatory for internal links").format(index+1) frappe.throw(message, frappe.ValidationError, _("Table Fieldname Missing")) def validate_fields_for_doctype(doctype): @@ -1027,6 +1032,9 @@ def validate_fields(meta): frappe.throw(_('Option {0} for field {1} is not a child table') .format(frappe.bold(doctype), frappe.bold(docfield.fieldname)), title=_("Invalid Option")) + def check_max_height(docfield): + if getattr(docfield, 'max_height', None) and (docfield.max_height[-2:] not in ('px', 'em')): + frappe.throw('Max for {} height must be in px, em, rem'.format(frappe.bold(docfield.fieldname))) fields = meta.get("fields") fieldname_list = [d.fieldname for d in fields] @@ -1060,6 +1068,7 @@ def validate_fields(meta): scrub_options_in_select(d) scrub_fetch_from(d) validate_data_field_type(d) + check_max_height(d) check_fold(fields) check_search_fields(meta, fields) @@ -1216,8 +1225,14 @@ def make_module_and_roles(doc, perm_fieldname="permissions"): if ("tabModule Def" in frappe.db.get_tables() and not frappe.db.exists("Module Def", doc.module)): m = frappe.get_doc({"doctype": "Module Def", "module_name": doc.module}) - m.app_name = frappe.local.module_app[frappe.scrub(doc.module)] + if frappe.scrub(doc.module) in frappe.local.module_app: + m.app_name = frappe.local.module_app[frappe.scrub(doc.module)] + else: + m.app_name = 'frappe' m.flags.ignore_mandatory = m.flags.ignore_permissions = True + if frappe.flags.package: + m.package = frappe.flags.package.name + m.custom = 1 m.insert() default_roles = ["Administrator", "Guest", "All"] diff --git a/frappe/core/doctype/doctype/test_doctype.py b/frappe/core/doctype/doctype/test_doctype.py index 9aaaf5a1ac..4362a52c34 100644 --- a/frappe/core/doctype/doctype/test_doctype.py +++ b/frappe/core/doctype/doctype/test_doctype.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# See license.txt +# License: MIT. See LICENSE import frappe import unittest from frappe.core.doctype.doctype.doctype import (UniqueFieldnameError, diff --git a/frappe/core/doctype/doctype_action/doctype_action.py b/frappe/core/doctype/doctype_action/doctype_action.py index 203b06ec1b..807d1bf0b1 100644 --- a/frappe/core/doctype/doctype_action/doctype_action.py +++ b/frappe/core/doctype/doctype_action/doctype_action.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE # import frappe from frappe.model.document import Document diff --git a/frappe/core/doctype/doctype_link/doctype_link.py b/frappe/core/doctype/doctype_link/doctype_link.py index 07e0efdace..ca2c4efa16 100644 --- a/frappe/core/doctype/doctype_link/doctype_link.py +++ b/frappe/core/doctype/doctype_link/doctype_link.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE # import frappe from frappe.model.document import Document diff --git a/frappe/core/doctype/document_naming_rule/document_naming_rule.json b/frappe/core/doctype/document_naming_rule/document_naming_rule.json index 4a88e3be6e..4e6f3f3fd1 100644 --- a/frappe/core/doctype/document_naming_rule/document_naming_rule.json +++ b/frappe/core/doctype/document_naming_rule/document_naming_rule.json @@ -41,6 +41,7 @@ "fieldname": "counter", "fieldtype": "Int", "label": "Counter", + "no_copy": 1, "read_only": 1 }, { @@ -79,7 +80,7 @@ ], "index_web_pages_for_search": 1, "links": [], - "modified": "2020-11-04 14:38:14.836056", + "modified": "2021-09-13 20:07:47.617615", "modified_by": "Administrator", "module": "Core", "name": "Document Naming Rule", diff --git a/frappe/core/doctype/document_naming_rule/document_naming_rule.py b/frappe/core/doctype/document_naming_rule/document_naming_rule.py index 10099bd19a..8013f9df6f 100644 --- a/frappe/core/doctype/document_naming_rule/document_naming_rule.py +++ b/frappe/core/doctype/document_naming_rule/document_naming_rule.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe from frappe.model.document import Document diff --git a/frappe/core/doctype/document_naming_rule/test_document_naming_rule.py b/frappe/core/doctype/document_naming_rule/test_document_naming_rule.py index 2206d173d7..50f1386758 100644 --- a/frappe/core/doctype/document_naming_rule/test_document_naming_rule.py +++ b/frappe/core/doctype/document_naming_rule/test_document_naming_rule.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE import frappe import unittest diff --git a/frappe/core/doctype/document_naming_rule_condition/document_naming_rule_condition.py b/frappe/core/doctype/document_naming_rule_condition/document_naming_rule_condition.py index dfca052d95..4706492cea 100644 --- a/frappe/core/doctype/document_naming_rule_condition/document_naming_rule_condition.py +++ b/frappe/core/doctype/document_naming_rule_condition/document_naming_rule_condition.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE # import frappe from frappe.model.document import Document diff --git a/frappe/core/doctype/document_naming_rule_condition/test_document_naming_rule_condition.py b/frappe/core/doctype/document_naming_rule_condition/test_document_naming_rule_condition.py index 643e963bd7..3d0565234c 100644 --- a/frappe/core/doctype/document_naming_rule_condition/test_document_naming_rule_condition.py +++ b/frappe/core/doctype/document_naming_rule_condition/test_document_naming_rule_condition.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE # import frappe import unittest diff --git a/frappe/core/doctype/domain/domain.py b/frappe/core/doctype/domain/domain.py index bbd20f3b70..ebd6e3ac9e 100644 --- a/frappe/core/doctype/domain/domain.py +++ b/frappe/core/doctype/domain/domain.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe diff --git a/frappe/core/doctype/domain/test_domain.py b/frappe/core/doctype/domain/test_domain.py index c2686a7566..d7924ebc90 100644 --- a/frappe/core/doctype/domain/test_domain.py +++ b/frappe/core/doctype/domain/test_domain.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE import frappe import unittest diff --git a/frappe/core/doctype/domain_settings/domain_settings.py b/frappe/core/doctype/domain_settings/domain_settings.py index a8c7c6a747..276411c2ab 100644 --- a/frappe/core/doctype/domain_settings/domain_settings.py +++ b/frappe/core/doctype/domain_settings/domain_settings.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe from frappe.model.document import Document diff --git a/frappe/core/doctype/dynamic_link/dynamic_link.py b/frappe/core/doctype/dynamic_link/dynamic_link.py index a7adb9ae72..c0502824c6 100644 --- a/frappe/core/doctype/dynamic_link/dynamic_link.py +++ b/frappe/core/doctype/dynamic_link/dynamic_link.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe from frappe.model.document import Document diff --git a/frappe/core/doctype/error_log/error_log.py b/frappe/core/doctype/error_log/error_log.py index 3d66253b08..39c307520f 100644 --- a/frappe/core/doctype/error_log/error_log.py +++ b/frappe/core/doctype/error_log/error_log.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe from frappe.model.document import Document diff --git a/frappe/core/doctype/error_log/test_error_log.py b/frappe/core/doctype/error_log/test_error_log.py index d7444ab2a7..54a41cd4a9 100644 --- a/frappe/core/doctype/error_log/test_error_log.py +++ b/frappe/core/doctype/error_log/test_error_log.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE import frappe import unittest diff --git a/frappe/core/doctype/error_snapshot/error_snapshot.py b/frappe/core/doctype/error_snapshot/error_snapshot.py index 247a796a6b..85143b5aa6 100644 --- a/frappe/core/doctype/error_snapshot/error_snapshot.py +++ b/frappe/core/doctype/error_snapshot/error_snapshot.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe from frappe.model.document import Document diff --git a/frappe/core/doctype/error_snapshot/test_error_snapshot.py b/frappe/core/doctype/error_snapshot/test_error_snapshot.py index 135136294a..86928db9cc 100644 --- a/frappe/core/doctype/error_snapshot/test_error_snapshot.py +++ b/frappe/core/doctype/error_snapshot/test_error_snapshot.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# See license.txt +# License: MIT. See LICENSE import frappe import unittest diff --git a/frappe/core/doctype/feedback/feedback.py b/frappe/core/doctype/feedback/feedback.py index 655bed6eb1..3704ee66e0 100644 --- a/frappe/core/doctype/feedback/feedback.py +++ b/frappe/core/doctype/feedback/feedback.py @@ -1,5 +1,5 @@ # Copyright (c) 2021, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE # import frappe from frappe.model.document import Document diff --git a/frappe/core/doctype/feedback/test_feedback.py b/frappe/core/doctype/feedback/test_feedback.py index c7551420c3..7a722ae0d1 100644 --- a/frappe/core/doctype/feedback/test_feedback.py +++ b/frappe/core/doctype/feedback/test_feedback.py @@ -1,5 +1,5 @@ # Copyright (c) 2021, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE import frappe import unittest diff --git a/frappe/core/doctype/file/file.py b/frappe/core/doctype/file/file.py index 36ff67ce7c..d9ecd85533 100755 --- a/frappe/core/doctype/file/file.py +++ b/frappe/core/doctype/file/file.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE """ record of files @@ -254,10 +254,11 @@ class File(Document): return file_name = self.file_url.split('/')[-1] try: - with open(get_files_path(file_name, is_private=self.is_private), "rb") as f: + file_path = get_files_path(file_name, is_private=self.is_private) + with open(file_path, "rb") as f: self.content_hash = get_content_hash(f.read()) except IOError: - frappe.throw(_("File {0} does not exist").format(self.file_url)) + frappe.throw(_("File {0} does not exist").format(file_path)) def on_trash(self): if self.is_home_folder or self.is_attachments_folder: diff --git a/frappe/core/doctype/file/test_file.py b/frappe/core/doctype/file/test_file.py index 18ad95eeba..4538ffb6bb 100644 --- a/frappe/core/doctype/file/test_file.py +++ b/frappe/core/doctype/file/test_file.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# See license.txt +# License: MIT. See LICENSE import base64 import json import frappe diff --git a/frappe/core/doctype/has_domain/has_domain.py b/frappe/core/doctype/has_domain/has_domain.py index 2220656a2e..640cdb3dce 100644 --- a/frappe/core/doctype/has_domain/has_domain.py +++ b/frappe/core/doctype/has_domain/has_domain.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe from frappe.model.document import Document diff --git a/frappe/core/doctype/has_role/has_role.py b/frappe/core/doctype/has_role/has_role.py index 51d86c7b0a..1e6fa7ff60 100644 --- a/frappe/core/doctype/has_role/has_role.py +++ b/frappe/core/doctype/has_role/has_role.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe from frappe.model.document import Document diff --git a/frappe/core/doctype/installed_application/installed_application.py b/frappe/core/doctype/installed_application/installed_application.py index f53a6424eb..81c806642f 100644 --- a/frappe/core/doctype/installed_application/installed_application.py +++ b/frappe/core/doctype/installed_application/installed_application.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE # import frappe from frappe.model.document import Document diff --git a/frappe/core/doctype/installed_applications/installed_applications.py b/frappe/core/doctype/installed_applications/installed_applications.py index b61555f57e..621e44d856 100644 --- a/frappe/core/doctype/installed_applications/installed_applications.py +++ b/frappe/core/doctype/installed_applications/installed_applications.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe from frappe.model.document import Document diff --git a/frappe/core/doctype/installed_applications/test_installed_applications.py b/frappe/core/doctype/installed_applications/test_installed_applications.py index 1d57fd2cd8..ab2f2566ef 100644 --- a/frappe/core/doctype/installed_applications/test_installed_applications.py +++ b/frappe/core/doctype/installed_applications/test_installed_applications.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE # import frappe import unittest diff --git a/frappe/core/doctype/language/language.py b/frappe/core/doctype/language/language.py index 01c8553e10..511c8ddeb6 100644 --- a/frappe/core/doctype/language/language.py +++ b/frappe/core/doctype/language/language.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe, json, re from frappe import _ diff --git a/frappe/core/doctype/language/test_language.py b/frappe/core/doctype/language/test_language.py index 837594247f..d9813afa85 100644 --- a/frappe/core/doctype/language/test_language.py +++ b/frappe/core/doctype/language/test_language.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE import frappe import unittest diff --git a/frappe/core/doctype/log_setting_user/log_setting_user.py b/frappe/core/doctype/log_setting_user/log_setting_user.py index 64728b2c2b..40914cfef8 100644 --- a/frappe/core/doctype/log_setting_user/log_setting_user.py +++ b/frappe/core/doctype/log_setting_user/log_setting_user.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE # import frappe from frappe.model.document import Document diff --git a/frappe/core/doctype/log_setting_user/test_log_setting_user.py b/frappe/core/doctype/log_setting_user/test_log_setting_user.py index c58b8faa66..45f7b61158 100644 --- a/frappe/core/doctype/log_setting_user/test_log_setting_user.py +++ b/frappe/core/doctype/log_setting_user/test_log_setting_user.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE # import frappe import unittest diff --git a/frappe/core/doctype/log_settings/log_settings.py b/frappe/core/doctype/log_settings/log_settings.py index e73aa8dac1..8a471b9173 100644 --- a/frappe/core/doctype/log_settings/log_settings.py +++ b/frappe/core/doctype/log_settings/log_settings.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe from frappe import _ diff --git a/frappe/core/doctype/log_settings/test_log_settings.py b/frappe/core/doctype/log_settings/test_log_settings.py index 8e0c9c3f23..40287948fd 100644 --- a/frappe/core/doctype/log_settings/test_log_settings.py +++ b/frappe/core/doctype/log_settings/test_log_settings.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE # import frappe import unittest diff --git a/frappe/core/doctype/module_def/__init__.py b/frappe/core/doctype/module_def/__init__.py index 0e57cb68c3..eb5ba62e5c 100644 --- a/frappe/core/doctype/module_def/__init__.py +++ b/frappe/core/doctype/module_def/__init__.py @@ -1,3 +1,3 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE diff --git a/frappe/core/doctype/module_def/module_def.js b/frappe/core/doctype/module_def/module_def.js index c7a6cf85f9..73d2d6562c 100644 --- a/frappe/core/doctype/module_def/module_def.js +++ b/frappe/core/doctype/module_def/module_def.js @@ -5,6 +5,9 @@ frappe.ui.form.on('Module Def', { refresh: function(frm) { frappe.xcall('frappe.core.doctype.module_def.module_def.get_installed_apps').then(r => { frm.set_df_property('app_name', 'options', JSON.parse(r)); + if (!frm.doc.app_name) { + frm.set_value('app_name', 'frappe'); + } }); } }); diff --git a/frappe/core/doctype/module_def/module_def.json b/frappe/core/doctype/module_def/module_def.json index 4de046bbb6..7ddc55fce5 100644 --- a/frappe/core/doctype/module_def/module_def.json +++ b/frappe/core/doctype/module_def/module_def.json @@ -8,6 +8,7 @@ "field_order": [ "module_name", "custom", + "package", "app_name", "restrict_to_domain" ], @@ -23,6 +24,7 @@ "unique": 1 }, { + "depends_on": "eval:!doc.custom", "fieldname": "app_name", "fieldtype": "Select", "in_list_view": 1, @@ -41,24 +43,84 @@ "fieldname": "custom", "fieldtype": "Check", "label": "Custom" + }, + { + "depends_on": "custom", + "fieldname": "package", + "fieldtype": "Link", + "label": "Package", + "options": "Package" } ], "icon": "fa fa-sitemap", "idx": 1, "links": [ { + "group": "DocType", "link_doctype": "DocType", "link_fieldname": "module" }, { + "group": "DocType", + "link_doctype": "Client Script", + "link_fieldname": "module" + }, + { + "group": "DocType", + "link_doctype": "Server Script", + "link_fieldname": "module" + }, + { + "group": "Website", + "link_doctype": "Web Page", + "link_fieldname": "module" + }, + { + "group": "Website", + "link_doctype": "Web Template", + "link_fieldname": "module" + }, + { + "group": "Website", + "link_doctype": "Website Theme", + "link_fieldname": "module" + }, + { + "group": "Website", + "link_doctype": "Web Form", + "link_fieldname": "module" + }, + { + "group": "Customization", "link_doctype": "Workspace", "link_fieldname": "module" + }, + { + "group": "Customization", + "link_doctype": "Custom Field", + "link_fieldname": "module" + }, + { + "group": "Customization", + "link_doctype": "Property Setter", + "link_fieldname": "module" + }, + { + "group": "Customization", + "link_doctype": "Print Format", + "link_fieldname": "module" + }, + { + "group": "Customization", + "link_doctype": "Notification", + "link_fieldname": "module" } ], - "modified": "2021-06-02 13:04:53.118716", + "modified": "2021-09-05 21:58:40.253909", "modified_by": "Administrator", "module": "Core", "name": "Module Def", + "naming_rule": "By fieldname", "owner": "Administrator", "permissions": [ { diff --git a/frappe/core/doctype/module_def/module_def.py b/frappe/core/doctype/module_def/module_def.py index 68025c83bb..6b420430b8 100644 --- a/frappe/core/doctype/module_def/module_def.py +++ b/frappe/core/doctype/module_def/module_def.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import frappe, os, json diff --git a/frappe/core/doctype/module_def/test_module_def.py b/frappe/core/doctype/module_def/test_module_def.py index 3a3ceb4b57..69a114d765 100644 --- a/frappe/core/doctype/module_def/test_module_def.py +++ b/frappe/core/doctype/module_def/test_module_def.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# See license.txt +# License: MIT. See LICENSE import frappe import unittest diff --git a/frappe/core/doctype/module_profile/module_profile.py b/frappe/core/doctype/module_profile/module_profile.py index 373e5078d0..930c3879b6 100644 --- a/frappe/core/doctype/module_profile/module_profile.py +++ b/frappe/core/doctype/module_profile/module_profile.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE from frappe.model.document import Document diff --git a/frappe/core/doctype/module_profile/test_module_profile.py b/frappe/core/doctype/module_profile/test_module_profile.py index e0d9c13371..e676767db6 100644 --- a/frappe/core/doctype/module_profile/test_module_profile.py +++ b/frappe/core/doctype/module_profile/test_module_profile.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE import frappe import unittest diff --git a/frappe/core/doctype/navbar_item/navbar_item.py b/frappe/core/doctype/navbar_item/navbar_item.py index a8fa611374..d4952a75f2 100644 --- a/frappe/core/doctype/navbar_item/navbar_item.py +++ b/frappe/core/doctype/navbar_item/navbar_item.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE # import frappe from frappe.model.document import Document diff --git a/frappe/core/doctype/navbar_item/test_navbar_item.py b/frappe/core/doctype/navbar_item/test_navbar_item.py index 85852a45e8..bb4b2a837a 100644 --- a/frappe/core/doctype/navbar_item/test_navbar_item.py +++ b/frappe/core/doctype/navbar_item/test_navbar_item.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE # import frappe import unittest diff --git a/frappe/core/doctype/navbar_settings/navbar_settings.py b/frappe/core/doctype/navbar_settings/navbar_settings.py index 60aec67a00..fd8db31d10 100644 --- a/frappe/core/doctype/navbar_settings/navbar_settings.py +++ b/frappe/core/doctype/navbar_settings/navbar_settings.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe from frappe.model.document import Document diff --git a/frappe/core/doctype/navbar_settings/test_navbar_settings.py b/frappe/core/doctype/navbar_settings/test_navbar_settings.py index 4d1ee72815..01497d9035 100644 --- a/frappe/core/doctype/navbar_settings/test_navbar_settings.py +++ b/frappe/core/doctype/navbar_settings/test_navbar_settings.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE # import frappe import unittest diff --git a/frappe/core/doctype/package/__init__.py b/frappe/core/doctype/package/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/frappe/core/doctype/package/licenses/GNU Affero General Public License.md b/frappe/core/doctype/package/licenses/GNU Affero General Public License.md new file mode 100644 index 0000000000..c7f159aed8 --- /dev/null +++ b/frappe/core/doctype/package/licenses/GNU Affero General Public License.md @@ -0,0 +1,614 @@ +### GNU AFFERO GENERAL PUBLIC LICENSE + +Version 3, 19 November 2007 + +Copyright (C) 2007 Free Software Foundation, Inc. + + +Everyone is permitted to copy and distribute verbatim copies of this +license document, but changing it is not allowed. + +### Preamble + +The GNU Affero General Public License is a free, copyleft license for +software and other kinds of works, specifically designed to ensure +cooperation with the community in the case of network server software. + +The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +our General Public Licenses are intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains +free software for all its users. + +When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + +Developers that use our General Public Licenses protect your rights +with two steps: (1) assert copyright on the software, and (2) offer +you this License which gives you legal permission to copy, distribute +and/or modify the software. + +A secondary benefit of defending all users' freedom is that +improvements made in alternate versions of the program, if they +receive widespread use, become available for other developers to +incorporate. Many developers of free software are heartened and +encouraged by the resulting cooperation. However, in the case of +software used on network servers, this result may fail to come about. +The GNU General Public License permits making a modified version and +letting the public access it on a server without ever releasing its +source code to the public. + +The GNU Affero General Public License is designed specifically to +ensure that, in such cases, the modified source code becomes available +to the community. It requires the operator of a network server to +provide the source code of the modified version running there to the +users of that server. Therefore, public use of a modified version, on +a publicly accessible server, gives the public access to the source +code of the modified version. + +An older license, called the Affero General Public License and +published by Affero, was designed to accomplish similar goals. This is +a different license, not a version of the Affero GPL, but Affero has +released a new version of the Affero GPL which permits relicensing +under this license. + +The precise terms and conditions for copying, distribution and +modification follow. + +### TERMS AND CONDITIONS + +#### 0. Definitions. + +"This License" refers to version 3 of the GNU Affero General Public +License. + +"Copyright" also means copyright-like laws that apply to other kinds +of works, such as semiconductor masks. + +"The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + +To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of +an exact copy. The resulting work is called a "modified version" of +the earlier work or a work "based on" the earlier work. + +A "covered work" means either the unmodified Program or a work based +on the Program. + +To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + +To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user +through a computer network, with no transfer of a copy, is not +conveying. + +An interactive user interface displays "Appropriate Legal Notices" to +the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + +#### 1. Source Code. + +The "source code" for a work means the preferred form of the work for +making modifications to it. "Object code" means any non-source form of +a work. + +A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + +The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + +The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + +The Corresponding Source need not include anything that users can +regenerate automatically from other parts of the Corresponding Source. + +The Corresponding Source for a work in source code form is that same +work. + +#### 2. Basic Permissions. + +All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + +You may make, run and propagate covered works that you do not convey, +without conditions so long as your license otherwise remains in force. +You may convey covered works to others for the sole purpose of having +them make modifications exclusively for you, or provide you with +facilities for running those works, provided that you comply with the +terms of this License in conveying all material for which you do not +control copyright. Those thus making or running the covered works for +you must do so exclusively on your behalf, under your direction and +control, on terms that prohibit them from making any copies of your +copyrighted material outside their relationship with you. + +Conveying under any other circumstances is permitted solely under the +conditions stated below. Sublicensing is not allowed; section 10 makes +it unnecessary. + +#### 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + +No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + +When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such +circumvention is effected by exercising rights under this License with +respect to the covered work, and you disclaim any intention to limit +operation or modification of the work as a means of enforcing, against +the work's users, your or third parties' legal rights to forbid +circumvention of technological measures. + +#### 4. Conveying Verbatim Copies. + +You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + +You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + +#### 5. Conveying Modified Source Versions. + +You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these +conditions: + +- a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. +- b) The work must carry prominent notices stating that it is + released under this License and any conditions added under + section 7. This requirement modifies the requirement in section 4 + to "keep intact all notices". +- c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. +- d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + +A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + +#### 6. Conveying Non-Source Forms. + +You may convey a covered work in object code form under the terms of +sections 4 and 5, provided that you also convey the machine-readable +Corresponding Source under the terms of this License, in one of these +ways: + +- a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. +- b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the Corresponding + Source from a network server at no charge. +- c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. +- d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. +- e) Convey the object code using peer-to-peer transmission, + provided you inform other peers where the object code and + Corresponding Source of the work are being offered to the general + public at no charge under subsection 6d. + +A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + +A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, +family, or household purposes, or (2) anything designed or sold for +incorporation into a dwelling. In determining whether a product is a +consumer product, doubtful cases shall be resolved in favor of +coverage. For a particular product received by a particular user, +"normally used" refers to a typical or common use of that class of +product, regardless of the status of the particular user or of the way +in which the particular user actually uses, or expects or is expected +to use, the product. A product is a consumer product regardless of +whether the product has substantial commercial, industrial or +non-consumer uses, unless such uses represent the only significant +mode of use of the product. + +"Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to +install and execute modified versions of a covered work in that User +Product from a modified version of its Corresponding Source. The +information must suffice to ensure that the continued functioning of +the modified object code is in no case prevented or interfered with +solely because modification has been made. + +If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + +The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or +updates for a work that has been modified or installed by the +recipient, or for the User Product in which it has been modified or +installed. Access to a network may be denied when the modification +itself materially and adversely affects the operation of the network +or violates the rules and protocols for communication across the +network. + +Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + +#### 7. Additional Terms. + +"Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + +When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + +Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders +of that material) supplement the terms of this License with terms: + +- a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or +- b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or +- c) Prohibiting misrepresentation of the origin of that material, + or requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or +- d) Limiting the use for publicity purposes of names of licensors + or authors of the material; or +- e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or +- f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions + of it) with contractual assumptions of liability to the recipient, + for any liability that these contractual assumptions directly + impose on those licensors and authors. + +All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + +If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + +Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; the +above requirements apply either way. + +#### 8. Termination. + +You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + +However, if you cease all violation of this License, then your license +from a particular copyright holder is reinstated (a) provisionally, +unless and until the copyright holder explicitly and finally +terminates your license, and (b) permanently, if the copyright holder +fails to notify you of the violation by some reasonable means prior to +60 days after the cessation. + +Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + +Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + +#### 9. Acceptance Not Required for Having Copies. + +You are not required to accept this License in order to receive or run +a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + +#### 10. Automatic Licensing of Downstream Recipients. + +Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + +An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + +You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + +#### 11. Patents. + +A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + +A contributor's "essential patent claims" are all patent claims owned +or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + +Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + +In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + +If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + +If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + +A patent license is "discriminatory" if it does not include within the +scope of its coverage, prohibits the exercise of, or is conditioned on +the non-exercise of one or more of the rights that are specifically +granted under this License. You may not convey a covered work if you +are a party to an arrangement with a third party that is in the +business of distributing software, under which you make payment to the +third party based on the extent of your activity of conveying the +work, and under which the third party grants, to any of the parties +who would receive the covered work from you, a discriminatory patent +license (a) in connection with copies of the covered work conveyed by +you (or copies made from those copies), or (b) primarily for and in +connection with specific products or compilations that contain the +covered work, unless you entered into that arrangement, or that patent +license was granted, prior to 28 March 2007. + +Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + +#### 12. No Surrender of Others' Freedom. + +If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under +this License and any other pertinent obligations, then as a +consequence you may not convey it at all. For example, if you agree to +terms that obligate you to collect a royalty for further conveying +from those to whom you convey the Program, the only way you could +satisfy both those terms and this License would be to refrain entirely +from conveying the Program. + +#### 13. Remote Network Interaction; Use with the GNU General Public License. + +Notwithstanding any other provision of this License, if you modify the +Program, your modified version must prominently offer all users +interacting with it remotely through a computer network (if your +version supports such interaction) an opportunity to receive the +Corresponding Source of your version by providing access to the +Corresponding Source from a network server at no charge, through some +standard or customary means of facilitating copying of software. This +Corresponding Source shall include the Corresponding Source for any +work covered by version 3 of the GNU General Public License that is +incorporated pursuant to the following paragraph. + +Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the work with which it is combined will remain governed by version +3 of the GNU General Public License. + +#### 14. Revised Versions of this License. + +The Free Software Foundation may publish revised and/or new versions +of the GNU Affero General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies that a certain numbered version of the GNU Affero General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU Affero General Public License, you may choose any version ever +published by the Free Software Foundation. + +If the Program specifies that a proxy can decide which future versions +of the GNU Affero General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + +Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + +#### 15. Disclaimer of Warranty. + +THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT +WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND +PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE +DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR +CORRECTION. + +#### 16. Limitation of Liability. + +IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR +CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES +ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT +NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR +LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM +TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER +PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +#### 17. Interpretation of Sections 15 and 16. + +If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. diff --git a/frappe/core/doctype/package/licenses/GNU General Public License.md b/frappe/core/doctype/package/licenses/GNU General Public License.md new file mode 100644 index 0000000000..c4580f2eb6 --- /dev/null +++ b/frappe/core/doctype/package/licenses/GNU General Public License.md @@ -0,0 +1,617 @@ +### GNU GENERAL PUBLIC LICENSE + +Version 3, 29 June 2007 + +Copyright (C) 2007 Free Software Foundation, Inc. + + +Everyone is permitted to copy and distribute verbatim copies of this +license document, but changing it is not allowed. + +### Preamble + +The GNU General Public License is a free, copyleft license for +software and other kinds of works. + +The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom +to share and change all versions of a program--to make sure it remains +free software for all its users. We, the Free Software Foundation, use +the GNU General Public License for most of our software; it applies +also to any other work released this way by its authors. You can apply +it to your programs, too. + +When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + +To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you +have certain responsibilities if you distribute copies of the +software, or if you modify it: responsibilities to respect the freedom +of others. + +For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + +Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + +For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + +Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the +manufacturer can do so. This is fundamentally incompatible with the +aim of protecting users' freedom to change the software. The +systematic pattern of such abuse occurs in the area of products for +individuals to use, which is precisely where it is most unacceptable. +Therefore, we have designed this version of the GPL to prohibit the +practice for those products. If such problems arise substantially in +other domains, we stand ready to extend this provision to those +domains in future versions of the GPL, as needed to protect the +freedom of users. + +Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish +to avoid the special danger that patents applied to a free program +could make it effectively proprietary. To prevent this, the GPL +assures that patents cannot be used to render the program non-free. + +The precise terms and conditions for copying, distribution and +modification follow. + +### TERMS AND CONDITIONS + +#### 0. Definitions. + +"This License" refers to version 3 of the GNU General Public License. + +"Copyright" also means copyright-like laws that apply to other kinds +of works, such as semiconductor masks. + +"The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + +To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of +an exact copy. The resulting work is called a "modified version" of +the earlier work or a work "based on" the earlier work. + +A "covered work" means either the unmodified Program or a work based +on the Program. + +To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + +To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user +through a computer network, with no transfer of a copy, is not +conveying. + +An interactive user interface displays "Appropriate Legal Notices" to +the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + +#### 1. Source Code. + +The "source code" for a work means the preferred form of the work for +making modifications to it. "Object code" means any non-source form of +a work. + +A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + +The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + +The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + +The Corresponding Source need not include anything that users can +regenerate automatically from other parts of the Corresponding Source. + +The Corresponding Source for a work in source code form is that same +work. + +#### 2. Basic Permissions. + +All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + +You may make, run and propagate covered works that you do not convey, +without conditions so long as your license otherwise remains in force. +You may convey covered works to others for the sole purpose of having +them make modifications exclusively for you, or provide you with +facilities for running those works, provided that you comply with the +terms of this License in conveying all material for which you do not +control copyright. Those thus making or running the covered works for +you must do so exclusively on your behalf, under your direction and +control, on terms that prohibit them from making any copies of your +copyrighted material outside their relationship with you. + +Conveying under any other circumstances is permitted solely under the +conditions stated below. Sublicensing is not allowed; section 10 makes +it unnecessary. + +#### 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + +No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + +When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such +circumvention is effected by exercising rights under this License with +respect to the covered work, and you disclaim any intention to limit +operation or modification of the work as a means of enforcing, against +the work's users, your or third parties' legal rights to forbid +circumvention of technological measures. + +#### 4. Conveying Verbatim Copies. + +You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + +You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + +#### 5. Conveying Modified Source Versions. + +You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these +conditions: + +- a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. +- b) The work must carry prominent notices stating that it is + released under this License and any conditions added under + section 7. This requirement modifies the requirement in section 4 + to "keep intact all notices". +- c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. +- d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + +A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + +#### 6. Conveying Non-Source Forms. + +You may convey a covered work in object code form under the terms of +sections 4 and 5, provided that you also convey the machine-readable +Corresponding Source under the terms of this License, in one of these +ways: + +- a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. +- b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the Corresponding + Source from a network server at no charge. +- c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. +- d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. +- e) Convey the object code using peer-to-peer transmission, + provided you inform other peers where the object code and + Corresponding Source of the work are being offered to the general + public at no charge under subsection 6d. + +A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + +A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, +family, or household purposes, or (2) anything designed or sold for +incorporation into a dwelling. In determining whether a product is a +consumer product, doubtful cases shall be resolved in favor of +coverage. For a particular product received by a particular user, +"normally used" refers to a typical or common use of that class of +product, regardless of the status of the particular user or of the way +in which the particular user actually uses, or expects or is expected +to use, the product. A product is a consumer product regardless of +whether the product has substantial commercial, industrial or +non-consumer uses, unless such uses represent the only significant +mode of use of the product. + +"Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to +install and execute modified versions of a covered work in that User +Product from a modified version of its Corresponding Source. The +information must suffice to ensure that the continued functioning of +the modified object code is in no case prevented or interfered with +solely because modification has been made. + +If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + +The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or +updates for a work that has been modified or installed by the +recipient, or for the User Product in which it has been modified or +installed. Access to a network may be denied when the modification +itself materially and adversely affects the operation of the network +or violates the rules and protocols for communication across the +network. + +Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + +#### 7. Additional Terms. + +"Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + +When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + +Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders +of that material) supplement the terms of this License with terms: + +- a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or +- b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or +- c) Prohibiting misrepresentation of the origin of that material, + or requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or +- d) Limiting the use for publicity purposes of names of licensors + or authors of the material; or +- e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or +- f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions + of it) with contractual assumptions of liability to the recipient, + for any liability that these contractual assumptions directly + impose on those licensors and authors. + +All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + +If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + +Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; the +above requirements apply either way. + +#### 8. Termination. + +You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + +However, if you cease all violation of this License, then your license +from a particular copyright holder is reinstated (a) provisionally, +unless and until the copyright holder explicitly and finally +terminates your license, and (b) permanently, if the copyright holder +fails to notify you of the violation by some reasonable means prior to +60 days after the cessation. + +Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + +Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + +#### 9. Acceptance Not Required for Having Copies. + +You are not required to accept this License in order to receive or run +a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + +#### 10. Automatic Licensing of Downstream Recipients. + +Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + +An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + +You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + +#### 11. Patents. + +A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + +A contributor's "essential patent claims" are all patent claims owned +or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + +Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + +In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + +If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + +If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + +A patent license is "discriminatory" if it does not include within the +scope of its coverage, prohibits the exercise of, or is conditioned on +the non-exercise of one or more of the rights that are specifically +granted under this License. You may not convey a covered work if you +are a party to an arrangement with a third party that is in the +business of distributing software, under which you make payment to the +third party based on the extent of your activity of conveying the +work, and under which the third party grants, to any of the parties +who would receive the covered work from you, a discriminatory patent +license (a) in connection with copies of the covered work conveyed by +you (or copies made from those copies), or (b) primarily for and in +connection with specific products or compilations that contain the +covered work, unless you entered into that arrangement, or that patent +license was granted, prior to 28 March 2007. + +Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + +#### 12. No Surrender of Others' Freedom. + +If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under +this License and any other pertinent obligations, then as a +consequence you may not convey it at all. For example, if you agree to +terms that obligate you to collect a royalty for further conveying +from those to whom you convey the Program, the only way you could +satisfy both those terms and this License would be to refrain entirely +from conveying the Program. + +#### 13. Use with the GNU Affero General Public License. + +Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + +#### 14. Revised Versions of this License. + +The Free Software Foundation may publish revised and/or new versions +of the GNU General Public License from time to time. Such new versions +will be similar in spirit to the present version, but may differ in +detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies that a certain numbered version of the GNU General Public +License "or any later version" applies to it, you have the option of +following the terms and conditions either of that numbered version or +of any later version published by the Free Software Foundation. If the +Program does not specify a version number of the GNU General Public +License, you may choose any version ever published by the Free +Software Foundation. + +If the Program specifies that a proxy can decide which future versions +of the GNU General Public License can be used, that proxy's public +statement of acceptance of a version permanently authorizes you to +choose that version for the Program. + +Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + +#### 15. Disclaimer of Warranty. + +THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT +WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND +PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE +DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR +CORRECTION. + +#### 16. Limitation of Liability. + +IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR +CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES +ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT +NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR +LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM +TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER +PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +#### 17. Interpretation of Sections 15 and 16. + +If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. diff --git a/frappe/core/doctype/package/licenses/MIT License.md b/frappe/core/doctype/package/licenses/MIT License.md new file mode 100644 index 0000000000..c038ee76ae --- /dev/null +++ b/frappe/core/doctype/package/licenses/MIT License.md @@ -0,0 +1,17 @@ +### MIT License + +Permission is hereby granted, free of charge, to any person obtaining a copy of this +software and associated documentation files (the "Software"), to deal in the Software +without restriction, including without limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies +or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/frappe/core/doctype/package/package.js b/frappe/core/doctype/package/package.js new file mode 100644 index 0000000000..90e2eed1e3 --- /dev/null +++ b/frappe/core/doctype/package/package.js @@ -0,0 +1,17 @@ +// Copyright (c) 2021, Frappe Technologies and contributors +// For license information, please see license.txt + +frappe.ui.form.on('Package', { + validate: function(frm) { + if (!frm.doc.package_name) { + frm.set_value('package_name', frm.doc.name.toLowerCase().replace(' ', '-')); + } + }, + + license_type: function(frm) { + frappe.call('frappe.core.doctype.package.package.get_license_text', + {'license_type': frm.doc.license_type}).then(r => { + frm.set_value('license', r.message); + }); + } +}); diff --git a/frappe/core/doctype/package/package.json b/frappe/core/doctype/package/package.json new file mode 100644 index 0000000000..285e17a5bb --- /dev/null +++ b/frappe/core/doctype/package/package.json @@ -0,0 +1,76 @@ +{ + "actions": [], + "allow_rename": 1, + "autoname": "Prompt", + "creation": "2021-09-04 11:54:35.155687", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "package_name", + "readme", + "license_type", + "license" + ], + "fields": [ + { + "fieldname": "readme", + "fieldtype": "Markdown Editor", + "label": "Readme" + }, + { + "fieldname": "package_name", + "fieldtype": "Data", + "in_list_view": 1, + "label": "Package Name", + "reqd": 1 + }, + { + "fieldname": "license_type", + "fieldtype": "Select", + "label": "License Type", + "options": "\nMIT License\nGNU General Public License\nGNU Affero General Public License" + }, + { + "fieldname": "license", + "fieldtype": "Markdown Editor", + "label": "License" + } + ], + "index_web_pages_for_search": 1, + "links": [ + { + "group": "Modules", + "link_doctype": "Module Def", + "link_fieldname": "package" + }, + { + "group": "Release", + "link_doctype": "Package Release", + "link_fieldname": "package" + } + ], + "modified": "2021-09-05 13:15:01.130982", + "modified_by": "Administrator", + "module": "Core", + "name": "Package", + "naming_rule": "Set by user", + "owner": "Administrator", + "permissions": [ + { + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "System Manager", + "share": 1, + "write": 1 + } + ], + "sort_field": "modified", + "sort_order": "DESC", + "track_changes": 1 +} \ No newline at end of file diff --git a/frappe/core/doctype/package/package.py b/frappe/core/doctype/package/package.py new file mode 100644 index 0000000000..aa9735c061 --- /dev/null +++ b/frappe/core/doctype/package/package.py @@ -0,0 +1,18 @@ +# Copyright (c) 2021, Frappe Technologies and contributors +# For license information, please see license.txt + +import frappe +import os +from frappe.model.document import Document + +class Package(Document): + def validate(self): + if not self.package_name: + self.package_name = self.name.lower().replace(' ', '-') + +@frappe.whitelist() +def get_license_text(license_type): + with open(os.path.join(os.path.dirname(__file__), 'licenses', + license_type + '.md'), 'r') as textfile: + return textfile.read() + diff --git a/frappe/core/doctype/package/test_package.py b/frappe/core/doctype/package/test_package.py new file mode 100644 index 0000000000..3fb8d48274 --- /dev/null +++ b/frappe/core/doctype/package/test_package.py @@ -0,0 +1,89 @@ +# Copyright (c) 2021, Frappe Technologies and Contributors +# See license.txt + +import frappe +import os +import json +import unittest + +class TestPackage(unittest.TestCase): + def test_package_release(self): + make_test_package() + make_test_module() + make_test_doctype() + make_test_server_script() + make_test_web_page() + + # make release + frappe.get_doc(dict( + doctype = 'Package Release', + package = 'Test Package', + publish = 1 + )).insert() + + self.assertTrue(os.path.exists(frappe.get_site_path('packages', 'test-package'))) + self.assertTrue(os.path.exists(frappe.get_site_path('packages', 'test-package', 'test_module_for_package'))) + self.assertTrue(os.path.exists(frappe.get_site_path('packages', 'test-package', 'test_module_for_package', 'doctype', 'test_doctype_for_package'))) + with open(frappe.get_site_path('packages', 'test-package', 'test_module_for_package', + 'doctype', 'test_doctype_for_package', 'test_doctype_for_package.json')) as f: + doctype = json.loads(f.read()) + self.assertEqual(doctype['doctype'], 'DocType') + self.assertEqual(doctype['name'], 'Test DocType for Package') + self.assertEqual(doctype['fields'][0]['fieldname'], 'test_field') + + +def make_test_package(): + if not frappe.db.exists('Package', 'Test Package'): + frappe.get_doc(dict( + doctype = 'Package', + name = 'Test Package', + package_name = 'test-package', + readme = '# Test Package' + )).insert() + +def make_test_module(): + if not frappe.db.exists('Module Def', 'Test Module for Package'): + frappe.get_doc(dict( + doctype = 'Module Def', + module_name = 'Test Module for Package', + custom = 1, + app_name = 'frappe', + package = 'Test Package' + )).insert() + +def make_test_doctype(): + if not frappe.db.exists('DocType', 'Test DocType for Package'): + frappe.get_doc(dict( + doctype = 'DocType', + name = 'Test DocType for Package', + custom = 1, + module = 'Test Module for Package', + autoname = 'Prompt', + fields = [dict( + fieldname = 'test_field', + fieldtype = 'Data', + label = 'Test Field' + )] + )).insert() + +def make_test_server_script(): + if not frappe.db.exists('Server Script', 'Test Script for Package'): + frappe.get_doc(dict( + doctype = 'Server Script', + name = 'Test Script for Package', + module = 'Test Module for Package', + script_type = 'DocType Event', + reference_doctype = 'Test DocType for Package', + doctype_event = 'Before Save', + script = 'frappe.msgprint("Test")' + )).insert() + +def make_test_web_page(): + if not frappe.db.exists('Web Page', 'test-web-page-for-package'): + frappe.get_doc(dict( + doctype = "Web Page", + module = 'Test Module for Package', + main_section = "Some content", + published = 1, + title = "Test Web Page for Package" + )).insert() diff --git a/frappe/core/doctype/package_import/__init__.py b/frappe/core/doctype/package_import/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/frappe/core/doctype/package_import/package_import.js b/frappe/core/doctype/package_import/package_import.js new file mode 100644 index 0000000000..c01a6266cc --- /dev/null +++ b/frappe/core/doctype/package_import/package_import.js @@ -0,0 +1,8 @@ +// Copyright (c) 2021, Frappe Technologies and contributors +// For license information, please see license.txt + +frappe.ui.form.on('Package Import', { + // refresh: function(frm) { + + // } +}); diff --git a/frappe/core/doctype/package_import/package_import.json b/frappe/core/doctype/package_import/package_import.json new file mode 100644 index 0000000000..f3c6168f8d --- /dev/null +++ b/frappe/core/doctype/package_import/package_import.json @@ -0,0 +1,65 @@ +{ + "actions": [], + "allow_rename": 1, + "autoname": "format:Package Import at {creation}", + "creation": "2021-09-05 16:36:46.680094", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "attach_package", + "activate", + "force", + "log" + ], + "fields": [ + { + "fieldname": "attach_package", + "fieldtype": "Attach", + "label": "Attach Package" + }, + { + "default": "0", + "fieldname": "activate", + "fieldtype": "Check", + "label": "Activate" + }, + { + "fieldname": "log", + "fieldtype": "Code", + "label": "Log", + "read_only": 1 + }, + { + "default": "0", + "fieldname": "force", + "fieldtype": "Check", + "label": "Force" + } + ], + "index_web_pages_for_search": 1, + "links": [], + "modified": "2021-09-05 21:30:04.796090", + "modified_by": "Administrator", + "module": "Core", + "name": "Package Import", + "naming_rule": "Expression", + "owner": "Administrator", + "permissions": [ + { + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "System Manager", + "share": 1, + "write": 1 + } + ], + "sort_field": "modified", + "sort_order": "DESC", + "track_changes": 1 +} \ No newline at end of file diff --git a/frappe/core/doctype/package_import/package_import.py b/frappe/core/doctype/package_import/package_import.py new file mode 100644 index 0000000000..f4a2d666dd --- /dev/null +++ b/frappe/core/doctype/package_import/package_import.py @@ -0,0 +1,58 @@ +# Copyright (c) 2021, Frappe Technologies and contributors +# For license information, please see license.txt + +import frappe +import os +import json +import subprocess +from frappe.model.document import Document +from frappe.desk.form.load import get_attachments +from frappe.model.sync import get_doc_files +from frappe.modules.import_file import import_file_by_path, import_doc + +class PackageImport(Document): + def validate(self): + if self.activate: + self.import_package() + + def import_package(self): + attachment = get_attachments(self.doctype, self.name) + + if not attachment: + frappe.throw(frappe._('Please attach the package')) + + attachment = attachment[0] + + # get package_name from file (package_name-0.0.0.tar.gz) + package_name = attachment.file_name.split('.')[0].rsplit('-', 1)[0] + if not os.path.exists(frappe.get_site_path('packages')): + os.makedirs(frappe.get_site_path('packages')) + + # extract + subprocess.check_output(['tar', 'xzf', + frappe.get_site_path(attachment.file_url.strip('/')), '-C', + frappe.get_site_path('packages')]) + + package_path = frappe.get_site_path('packages', package_name) + + # import Package + with open(os.path.join(package_path, package_name + '.json'), 'r') as packagefile: + doc_dict = json.loads(packagefile.read()) + + frappe.flags.package = import_doc(doc_dict) + + # collect modules + files = [] + log = [] + for module in os.listdir(package_path): + module_path = os.path.join(package_path, module) + if os.path.isdir(module_path): + get_doc_files(files, module_path) + + # import files + for file in files: + import_file_by_path(file, force=self.force, ignore_version=True, + for_sync=True) + log.append('Imported {}'.format(file)) + + self.log = '\n'.join(log) diff --git a/frappe/core/doctype/package_import/test_package_import.py b/frappe/core/doctype/package_import/test_package_import.py new file mode 100644 index 0000000000..04628fed93 --- /dev/null +++ b/frappe/core/doctype/package_import/test_package_import.py @@ -0,0 +1,8 @@ +# Copyright (c) 2021, Frappe Technologies and Contributors +# See license.txt + +# import frappe +import unittest + +class TestPackageImport(unittest.TestCase): + pass diff --git a/frappe/core/doctype/package_release/__init__.py b/frappe/core/doctype/package_release/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/frappe/core/doctype/package_release/package_release.js b/frappe/core/doctype/package_release/package_release.js new file mode 100644 index 0000000000..9eabe36839 --- /dev/null +++ b/frappe/core/doctype/package_release/package_release.js @@ -0,0 +1,8 @@ +// Copyright (c) 2021, Frappe Technologies and contributors +// For license information, please see license.txt + +frappe.ui.form.on('Package Release', { + // refresh: function(frm) { + + // } +}); diff --git a/frappe/core/doctype/package_release/package_release.json b/frappe/core/doctype/package_release/package_release.json new file mode 100644 index 0000000000..b651d699c4 --- /dev/null +++ b/frappe/core/doctype/package_release/package_release.json @@ -0,0 +1,95 @@ +{ + "actions": [], + "allow_rename": 1, + "creation": "2021-09-05 12:59:01.932327", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "package", + "publish", + "path", + "column_break_3", + "major", + "minor", + "patch", + "section_break_7", + "release_notes" + ], + "fields": [ + { + "fieldname": "package", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Package", + "options": "Package", + "reqd": 1 + }, + { + "fieldname": "major", + "fieldtype": "Int", + "label": "Major" + }, + { + "fieldname": "minor", + "fieldtype": "Int", + "label": "Minor" + }, + { + "fieldname": "patch", + "fieldtype": "Int", + "label": "Patch", + "no_copy": 1 + }, + { + "fieldname": "path", + "fieldtype": "Small Text", + "label": "Path", + "read_only": 1 + }, + { + "fieldname": "column_break_3", + "fieldtype": "Column Break" + }, + { + "fieldname": "section_break_7", + "fieldtype": "Section Break" + }, + { + "fieldname": "release_notes", + "fieldtype": "Markdown Editor", + "label": "Release Notes" + }, + { + "default": "0", + "fieldname": "publish", + "fieldtype": "Check", + "label": "Publish" + } + ], + "index_web_pages_for_search": 1, + "links": [], + "modified": "2021-09-05 16:04:32.860988", + "modified_by": "Administrator", + "module": "Core", + "name": "Package Release", + "naming_rule": "By script", + "owner": "Administrator", + "permissions": [ + { + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "System Manager", + "share": 1, + "write": 1 + } + ], + "sort_field": "modified", + "sort_order": "DESC", + "track_changes": 1 +} \ No newline at end of file diff --git a/frappe/core/doctype/package_release/package_release.py b/frappe/core/doctype/package_release/package_release.py new file mode 100644 index 0000000000..1fb8796882 --- /dev/null +++ b/frappe/core/doctype/package_release/package_release.py @@ -0,0 +1,81 @@ +# Copyright (c) 2021, Frappe Technologies and contributors +# For license information, please see license.txt + +import frappe +from frappe.model.document import Document +from frappe.modules.export_file import export_doc +import os +import subprocess + +class PackageRelease(Document): + def set_version(self): + # set the next patch release by default + if not self.major: + self.major = frappe.db.max('Package Release', 'major', dict(package=self.package)) + if not self.minor: + self.minor = frappe.db.max('Package Release', 'minor', dict(package=self.package)) + if not self.patch: + self.patch = frappe.db.max('Package Release', 'patch', dict(package=self.package)) + 1 + + def autoname(self): + self.set_version() + self.name = '{}-{}.{}.{}'.format( + frappe.db.get_value('Package', self.package, 'package_name'), + self.major, self.minor, self.patch) + + def validate(self): + if self.publish: + self.export_files() + + def export_files(self): + '''Export all the documents in this package to site/packages folder''' + package = frappe.get_doc('Package', self.package) + + self.export_modules() + self.export_package_files(package) + self.make_tarfile(package) + + def export_modules(self): + for m in frappe.db.get_all('Module Def', dict(package=self.package)): + module = frappe.get_doc('Module Def', m.name) + for l in module.meta.links: + if l.link_doctype == 'Module Def': + continue + # all documents of the type in the module + for d in frappe.get_all(l.link_doctype, dict(module=m.name)): + export_doc(frappe.get_doc(l.link_doctype, d.name)) + + def export_package_files(self, package): + # write readme + with open(frappe.get_site_path('packages', package.package_name, 'README.md'), 'w') as readme: + readme.write(package.readme) + + # write license + if package.license: + with open(frappe.get_site_path('packages', package.package_name, 'LICENSE.md'), 'w') as license: + license.write(package.license) + + # write package.json as `frappe_package.json` + with open(frappe.get_site_path('packages', package.package_name, package.package_name + '.json'), 'w') as packagefile: + packagefile.write(frappe.as_json(package.as_dict(no_nulls=True))) + + def make_tarfile(self, package): + # make tarfile + filename = '{}.tar.gz'.format(self.name) + subprocess.check_output(['tar', 'czf', filename, package.package_name], + cwd=frappe.get_site_path('packages')) + + # move file + subprocess.check_output(['mv', frappe.get_site_path('packages', filename), + frappe.get_site_path('public', 'files')]) + + # make attachment + file = frappe.get_doc(dict( + doctype = 'File', + file_url = '/' + os.path.join('files', filename), + attached_to_doctype = self.doctype, + attached_to_name = self.name + )) + + file.flags.ignore_duplicate_entry_error = True + file.insert() diff --git a/frappe/core/doctype/package_release/test_package_release.py b/frappe/core/doctype/package_release/test_package_release.py new file mode 100644 index 0000000000..6a15e8625b --- /dev/null +++ b/frappe/core/doctype/package_release/test_package_release.py @@ -0,0 +1,8 @@ +# Copyright (c) 2021, Frappe Technologies and Contributors +# See license.txt + +# import frappe +import unittest + +class TestPackageRelease(unittest.TestCase): + pass diff --git a/frappe/core/doctype/page/__init__.py b/frappe/core/doctype/page/__init__.py index 0e57cb68c3..eb5ba62e5c 100644 --- a/frappe/core/doctype/page/__init__.py +++ b/frappe/core/doctype/page/__init__.py @@ -1,3 +1,3 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE diff --git a/frappe/core/doctype/page/page.py b/frappe/core/doctype/page/page.py index 5aa18cd9e3..894e180bb1 100644 --- a/frappe/core/doctype/page/page.py +++ b/frappe/core/doctype/page/page.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import frappe import os diff --git a/frappe/core/doctype/page/test_page.py b/frappe/core/doctype/page/test_page.py index 18b4aea2c8..7db32497a8 100644 --- a/frappe/core/doctype/page/test_page.py +++ b/frappe/core/doctype/page/test_page.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# See license.txt +# License: MIT. See LICENSE import frappe import unittest diff --git a/frappe/core/doctype/patch_log/__init__.py b/frappe/core/doctype/patch_log/__init__.py index 0e57cb68c3..eb5ba62e5c 100644 --- a/frappe/core/doctype/patch_log/__init__.py +++ b/frappe/core/doctype/patch_log/__init__.py @@ -1,3 +1,3 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE diff --git a/frappe/core/doctype/patch_log/patch_log.py b/frappe/core/doctype/patch_log/patch_log.py index cc66955eb8..9a5da24e37 100644 --- a/frappe/core/doctype/patch_log/patch_log.py +++ b/frappe/core/doctype/patch_log/patch_log.py @@ -1,7 +1,7 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe diff --git a/frappe/core/doctype/patch_log/test_patch_log.py b/frappe/core/doctype/patch_log/test_patch_log.py index d0690ecee0..df1ca16b22 100644 --- a/frappe/core/doctype/patch_log/test_patch_log.py +++ b/frappe/core/doctype/patch_log/test_patch_log.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# See license.txt +# License: MIT. See LICENSE import frappe import unittest diff --git a/frappe/core/doctype/payment_gateway/payment_gateway.py b/frappe/core/doctype/payment_gateway/payment_gateway.py index 1459635b01..d0fa550ea1 100644 --- a/frappe/core/doctype/payment_gateway/payment_gateway.py +++ b/frappe/core/doctype/payment_gateway/payment_gateway.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe from frappe.model.document import Document diff --git a/frappe/core/doctype/payment_gateway/test_payment_gateway.py b/frappe/core/doctype/payment_gateway/test_payment_gateway.py index 66f899bd27..e2ad081cfa 100644 --- a/frappe/core/doctype/payment_gateway/test_payment_gateway.py +++ b/frappe/core/doctype/payment_gateway/test_payment_gateway.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# See license.txt +# License: MIT. See LICENSE import frappe import unittest diff --git a/frappe/core/doctype/prepared_report/prepared_report.py b/frappe/core/doctype/prepared_report/prepared_report.py index c9b5fd9d2e..2d1b026572 100644 --- a/frappe/core/doctype/prepared_report/prepared_report.py +++ b/frappe/core/doctype/prepared_report/prepared_report.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2018, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import json diff --git a/frappe/core/doctype/prepared_report/test_prepared_report.py b/frappe/core/doctype/prepared_report/test_prepared_report.py index ef324dd01a..5b12990f64 100644 --- a/frappe/core/doctype/prepared_report/test_prepared_report.py +++ b/frappe/core/doctype/prepared_report/test_prepared_report.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2018, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE import frappe import unittest import json diff --git a/frappe/core/doctype/report/__init__.py b/frappe/core/doctype/report/__init__.py index 0e57cb68c3..eb5ba62e5c 100644 --- a/frappe/core/doctype/report/__init__.py +++ b/frappe/core/doctype/report/__init__.py @@ -1,3 +1,3 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE diff --git a/frappe/core/doctype/report/boilerplate/controller.py b/frappe/core/doctype/report/boilerplate/controller.py index b8e9cb7467..ccf732a405 100644 --- a/frappe/core/doctype/report/boilerplate/controller.py +++ b/frappe/core/doctype/report/boilerplate/controller.py @@ -1,5 +1,5 @@ # Copyright (c) 2013, {app_publisher} and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE # import frappe diff --git a/frappe/core/doctype/report/report.py b/frappe/core/doctype/report/report.py index a5c61fa436..6a54314667 100644 --- a/frappe/core/doctype/report/report.py +++ b/frappe/core/doctype/report/report.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import frappe import json, datetime from frappe import _, scrub diff --git a/frappe/core/doctype/report/test_report.py b/frappe/core/doctype/report/test_report.py index 9c953db1f0..36e3b09254 100644 --- a/frappe/core/doctype/report/test_report.py +++ b/frappe/core/doctype/report/test_report.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# See license.txt +# License: MIT. See LICENSE import frappe, json, os import unittest diff --git a/frappe/core/doctype/report_column/report_column.py b/frappe/core/doctype/report_column/report_column.py index f9078d820d..3b2c1e130b 100644 --- a/frappe/core/doctype/report_column/report_column.py +++ b/frappe/core/doctype/report_column/report_column.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE # import frappe from frappe.model.document import Document diff --git a/frappe/core/doctype/report_filter/report_filter.py b/frappe/core/doctype/report_filter/report_filter.py index ccdcc0eb6f..b325985308 100644 --- a/frappe/core/doctype/report_filter/report_filter.py +++ b/frappe/core/doctype/report_filter/report_filter.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE # import frappe from frappe.model.document import Document diff --git a/frappe/core/doctype/role/__init__.py b/frappe/core/doctype/role/__init__.py index 0e57cb68c3..eb5ba62e5c 100644 --- a/frappe/core/doctype/role/__init__.py +++ b/frappe/core/doctype/role/__init__.py @@ -1,3 +1,3 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE diff --git a/frappe/core/doctype/role/role.py b/frappe/core/doctype/role/role.py index 28b444e1e7..f4fa855ea1 100644 --- a/frappe/core/doctype/role/role.py +++ b/frappe/core/doctype/role/role.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import frappe diff --git a/frappe/core/doctype/role/test_role.py b/frappe/core/doctype/role/test_role.py index 471f6cac43..1671f9a9c8 100644 --- a/frappe/core/doctype/role/test_role.py +++ b/frappe/core/doctype/role/test_role.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import frappe import unittest diff --git a/frappe/core/doctype/role_permission_for_page_and_report/role_permission_for_page_and_report.py b/frappe/core/doctype/role_permission_for_page_and_report/role_permission_for_page_and_report.py index 59f34a1483..cd9a6dc0fa 100644 --- a/frappe/core/doctype/role_permission_for_page_and_report/role_permission_for_page_and_report.py +++ b/frappe/core/doctype/role_permission_for_page_and_report/role_permission_for_page_and_report.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe from frappe.core.doctype.report.report import is_prepared_report_disabled diff --git a/frappe/core/doctype/role_profile/role_profile.py b/frappe/core/doctype/role_profile/role_profile.py index 986cf834eb..cb0a43d68f 100644 --- a/frappe/core/doctype/role_profile/role_profile.py +++ b/frappe/core/doctype/role_profile/role_profile.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE from frappe.model.document import Document import frappe diff --git a/frappe/core/doctype/role_profile/test_role_profile.py b/frappe/core/doctype/role_profile/test_role_profile.py index 57b77d868b..b208a186de 100644 --- a/frappe/core/doctype/role_profile/test_role_profile.py +++ b/frappe/core/doctype/role_profile/test_role_profile.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE import frappe import unittest diff --git a/frappe/core/doctype/scheduled_job_log/scheduled_job_log.py b/frappe/core/doctype/scheduled_job_log/scheduled_job_log.py index 7f54a3b6ae..bd5c15bc31 100644 --- a/frappe/core/doctype/scheduled_job_log/scheduled_job_log.py +++ b/frappe/core/doctype/scheduled_job_log/scheduled_job_log.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE # import frappe from frappe.model.document import Document diff --git a/frappe/core/doctype/scheduled_job_log/test_scheduled_job_log.py b/frappe/core/doctype/scheduled_job_log/test_scheduled_job_log.py index 85471d0d71..9957f6c34c 100644 --- a/frappe/core/doctype/scheduled_job_log/test_scheduled_job_log.py +++ b/frappe/core/doctype/scheduled_job_log/test_scheduled_job_log.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE # import frappe import unittest diff --git a/frappe/core/doctype/scheduled_job_type/scheduled_job_type.py b/frappe/core/doctype/scheduled_job_type/scheduled_job_type.py index b6515b1e79..1a795bab82 100644 --- a/frappe/core/doctype/scheduled_job_type/scheduled_job_type.py +++ b/frappe/core/doctype/scheduled_job_type/scheduled_job_type.py @@ -1,5 +1,5 @@ # Copyright (c) 2021, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import json from datetime import datetime diff --git a/frappe/core/doctype/scheduled_job_type/test_scheduled_job_type.py b/frappe/core/doctype/scheduled_job_type/test_scheduled_job_type.py index a071cfe9a9..dc3353b176 100644 --- a/frappe/core/doctype/scheduled_job_type/test_scheduled_job_type.py +++ b/frappe/core/doctype/scheduled_job_type/test_scheduled_job_type.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE import frappe import unittest from frappe.utils import get_datetime diff --git a/frappe/core/doctype/server_script/server_script.json b/frappe/core/doctype/server_script/server_script.json index b7e49673f8..520c0008c5 100644 --- a/frappe/core/doctype/server_script/server_script.json +++ b/frappe/core/doctype/server_script/server_script.json @@ -13,6 +13,7 @@ "api_method", "allow_guest", "column_break_3", + "module", "disabled", "section_break_8", "script", @@ -93,6 +94,12 @@ "label": "Event Frequency", "mandatory_depends_on": "eval:doc.script_type == \"Scheduler Event\"", "options": "All\nHourly\nDaily\nWeekly\nMonthly\nYearly\nHourly Long\nDaily Long\nWeekly Long\nMonthly Long" + }, + { + "fieldname": "module", + "fieldtype": "Link", + "label": "Module (for export)", + "options": "Module Def" } ], "index_web_pages_for_search": 1, @@ -102,7 +109,7 @@ "link_fieldname": "server_script" } ], - "modified": "2021-02-18 12:36:19.803425", + "modified": "2021-09-04 12:02:43.671240", "modified_by": "Administrator", "module": "Core", "name": "Server Script", diff --git a/frappe/core/doctype/server_script/server_script.py b/frappe/core/doctype/server_script/server_script.py index ebd581ce87..79fe7a9140 100644 --- a/frappe/core/doctype/server_script/server_script.py +++ b/frappe/core/doctype/server_script/server_script.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import ast from types import FunctionType, MethodType, ModuleType @@ -27,6 +27,11 @@ class ServerScript(Document): for job in self.scheduled_jobs: frappe.delete_doc("Scheduled Job Type", job.name) + def get_code_fields(self): + return { + 'script': 'py' + } + @property def scheduled_jobs(self) -> List[Dict[str, str]]: return frappe.get_all( diff --git a/frappe/core/doctype/server_script/test_server_script.py b/frappe/core/doctype/server_script/test_server_script.py index ed6b5539c5..6c028ff136 100644 --- a/frappe/core/doctype/server_script/test_server_script.py +++ b/frappe/core/doctype/server_script/test_server_script.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE import frappe import unittest import requests diff --git a/frappe/core/doctype/session_default/session_default.py b/frappe/core/doctype/session_default/session_default.py index 70ff103111..9470a1bb38 100644 --- a/frappe/core/doctype/session_default/session_default.py +++ b/frappe/core/doctype/session_default/session_default.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE # import frappe from frappe.model.document import Document diff --git a/frappe/core/doctype/session_default_settings/session_default_settings.py b/frappe/core/doctype/session_default_settings/session_default_settings.py index 25f7522c86..52c917223e 100644 --- a/frappe/core/doctype/session_default_settings/session_default_settings.py +++ b/frappe/core/doctype/session_default_settings/session_default_settings.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe from frappe import _ diff --git a/frappe/core/doctype/session_default_settings/test_session_default_settings.py b/frappe/core/doctype/session_default_settings/test_session_default_settings.py index 7d20015b66..7a7e971aed 100644 --- a/frappe/core/doctype/session_default_settings/test_session_default_settings.py +++ b/frappe/core/doctype/session_default_settings/test_session_default_settings.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE import frappe import unittest from frappe.core.doctype.session_default_settings.session_default_settings import set_session_default_values, clear_session_defaults diff --git a/frappe/core/doctype/sms_parameter/sms_parameter.py b/frappe/core/doctype/sms_parameter/sms_parameter.py index d1fb1c53db..fb8466eac6 100644 --- a/frappe/core/doctype/sms_parameter/sms_parameter.py +++ b/frappe/core/doctype/sms_parameter/sms_parameter.py @@ -1,5 +1,5 @@ -# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt +# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors +# License: MIT. See LICENSE import frappe diff --git a/frappe/core/doctype/sms_settings/sms_settings.json b/frappe/core/doctype/sms_settings/sms_settings.json index 073fb88bc7..d29949af45 100755 --- a/frappe/core/doctype/sms_settings/sms_settings.json +++ b/frappe/core/doctype/sms_settings/sms_settings.json @@ -1,238 +1,80 @@ { - "allow_copy": 1, - "allow_guest_to_view": 0, - "allow_import": 0, - "allow_rename": 0, - "beta": 0, - "creation": "2013-01-10 16:34:24", - "custom": 0, - "docstatus": 0, - "doctype": "DocType", - "editable_grid": 0, + "actions": [], + "allow_copy": 1, + "creation": "2013-01-10 16:34:24", + "doctype": "DocType", + "engine": "InnoDB", + "field_order": [ + "sms_gateway_url", + "message_parameter", + "receiver_parameter", + "static_parameters_section", + "parameters", + "use_post" + ], "fields": [ { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "description": "Eg. smsgateway.com/api/send_sms.cgi", - "fieldname": "sms_gateway_url", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "SMS Gateway URL", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, + "description": "Eg. smsgateway.com/api/send_sms.cgi", + "fieldname": "sms_gateway_url", + "fieldtype": "Small Text", + "in_list_view": 1, + "label": "SMS Gateway URL", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "description": "Enter url parameter for message", - "fieldname": "message_parameter", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Message Parameter", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, + "description": "Enter url parameter for message", + "fieldname": "message_parameter", + "fieldtype": "Data", + "in_list_view": 1, + "label": "Message Parameter", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "description": "Enter url parameter for receiver nos", - "fieldname": "receiver_parameter", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Receiver Parameter", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, + "description": "Enter url parameter for receiver nos", + "fieldname": "receiver_parameter", + "fieldtype": "Data", + "in_list_view": 1, + "label": "Receiver Parameter", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "static_parameters_section", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0, + "fieldname": "static_parameters_section", + "fieldtype": "Column Break", "width": "50%" - }, + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "description": "Enter static url parameters here (Eg. sender=ERPNext, username=ERPNext, password=1234 etc.)", - "fieldname": "parameters", - "fieldtype": "Table", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Static Parameters", - "length": 0, - "no_copy": 0, - "options": "SMS Parameter", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, + "description": "Enter static url parameters here (Eg. sender=ERPNext, username=ERPNext, password=1234 etc.)", + "fieldname": "parameters", + "fieldtype": "Table", + "label": "Static Parameters", + "options": "SMS Parameter" + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "use_post", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Use POST", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 + "default": "0", + "fieldname": "use_post", + "fieldtype": "Check", + "label": "Use POST" } - ], - "has_web_view": 0, - "hide_heading": 0, - "hide_toolbar": 0, - "icon": "fa fa-cog", - "idx": 1, - "image_view": 0, - "in_create": 0, - "is_submittable": 0, - "issingle": 1, - "istable": 0, - "max_attachments": 0, - "modified": "2021-03-02 18:06:00.868688", - "modified_by": "Administrator", - "module": "Core", - "name": "SMS Settings", - "owner": "Administrator", + ], + "icon": "fa fa-cog", + "idx": 1, + "issingle": 1, + "links": [], + "modified": "2021-09-21 19:45:26.809793", + "modified_by": "Administrator", + "module": "Core", + "name": "SMS Settings", + "owner": "Administrator", "permissions": [ { - "amend": 0, - "apply_user_permissions": 0, - "cancel": 0, - "create": 1, - "delete": 0, - "email": 0, - "export": 0, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 0, - "read": 1, - "report": 0, - "role": "System Manager", - "set_user_permissions": 0, - "share": 1, - "submit": 0, + "create": 1, + "read": 1, + "role": "System Manager", + "share": 1, "write": 1 } - ], - "quick_entry": 0, - "read_only": 0, - "read_only_onload": 0, - "show_name_in_global_search": 0, - "track_changes": 1, - "track_seen": 0 -} + ], + "sort_field": "modified", + "sort_order": "DESC", + "track_changes": 1 +} \ No newline at end of file diff --git a/frappe/core/doctype/sms_settings/sms_settings.py b/frappe/core/doctype/sms_settings/sms_settings.py index 58a0ff08f6..f15ba7e4f6 100644 --- a/frappe/core/doctype/sms_settings/sms_settings.py +++ b/frappe/core/doctype/sms_settings/sms_settings.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt +# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors +# License: MIT. See LICENSE import frappe diff --git a/frappe/core/doctype/sms_settings/test_sms_settings.py b/frappe/core/doctype/sms_settings/test_sms_settings.py index 862f5e3965..b3be912f9e 100644 --- a/frappe/core/doctype/sms_settings/test_sms_settings.py +++ b/frappe/core/doctype/sms_settings/test_sms_settings.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE import frappe import unittest diff --git a/frappe/core/doctype/success_action/success_action.py b/frappe/core/doctype/success_action/success_action.py index 4ebd3d250b..afb3a87485 100644 --- a/frappe/core/doctype/success_action/success_action.py +++ b/frappe/core/doctype/success_action/success_action.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2018, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE from frappe.model.document import Document diff --git a/frappe/core/doctype/system_settings/system_settings.py b/frappe/core/doctype/system_settings/system_settings.py index 466914569f..1ae8e9e79e 100644 --- a/frappe/core/doctype/system_settings/system_settings.py +++ b/frappe/core/doctype/system_settings/system_settings.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe from frappe import _ diff --git a/frappe/core/doctype/system_settings/test_system_settings.py b/frappe/core/doctype/system_settings/test_system_settings.py index a65c602abe..f95e26b793 100644 --- a/frappe/core/doctype/system_settings/test_system_settings.py +++ b/frappe/core/doctype/system_settings/test_system_settings.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE import frappe import unittest diff --git a/frappe/core/doctype/test/test.py b/frappe/core/doctype/test/test.py index 98e36e6a30..4cb088c117 100644 --- a/frappe/core/doctype/test/test.py +++ b/frappe/core/doctype/test/test.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2021, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE # import frappe from frappe.model.document import Document diff --git a/frappe/core/doctype/test/test_test.py b/frappe/core/doctype/test/test_test.py index d8ca975d63..d8508b8651 100644 --- a/frappe/core/doctype/test/test_test.py +++ b/frappe/core/doctype/test/test_test.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2021, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE # import frappe import unittest diff --git a/frappe/core/doctype/transaction_log/test_transaction_log.py b/frappe/core/doctype/transaction_log/test_transaction_log.py index 0d9b9353d0..c332a82f65 100644 --- a/frappe/core/doctype/transaction_log/test_transaction_log.py +++ b/frappe/core/doctype/transaction_log/test_transaction_log.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2018, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE import frappe import unittest import hashlib diff --git a/frappe/core/doctype/transaction_log/transaction_log.py b/frappe/core/doctype/transaction_log/transaction_log.py index 58d0b3d176..bb94642f48 100644 --- a/frappe/core/doctype/transaction_log/transaction_log.py +++ b/frappe/core/doctype/transaction_log/transaction_log.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2018, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe from frappe import _ diff --git a/frappe/core/doctype/translation/test_translation.py b/frappe/core/doctype/translation/test_translation.py index e5b5d2d393..982d9bf976 100644 --- a/frappe/core/doctype/translation/test_translation.py +++ b/frappe/core/doctype/translation/test_translation.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE import frappe import unittest diff --git a/frappe/core/doctype/translation/translation.py b/frappe/core/doctype/translation/translation.py index b1f4642791..a01552903c 100644 --- a/frappe/core/doctype/translation/translation.py +++ b/frappe/core/doctype/translation/translation.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe from frappe.model.document import Document diff --git a/frappe/core/doctype/user/test_user.py b/frappe/core/doctype/user/test_user.py index eb8ad9cdbd..e47846958a 100644 --- a/frappe/core/doctype/user/test_user.py +++ b/frappe/core/doctype/user/test_user.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import json import unittest from unittest.mock import patch diff --git a/frappe/core/doctype/user/user.py b/frappe/core/doctype/user/user.py index 1336f6eab7..e4b94cdbb6 100644 --- a/frappe/core/doctype/user/user.py +++ b/frappe/core/doctype/user/user.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE from bs4 import BeautifulSoup import frappe import frappe.share @@ -788,7 +788,7 @@ def sign_up(email, full_name, redirect_to): return 2, _("Please ask your administrator to verify your sign-up") @frappe.whitelist(allow_guest=True) -@rate_limit(key='user', limit=get_password_reset_limit, seconds = 24*60*60, methods=['POST']) +@rate_limit(limit=get_password_reset_limit, seconds = 24*60*60, methods=['POST']) def reset_password(user): if user=="Administrator": return 'not allowed' diff --git a/frappe/core/doctype/user_document_type/user_document_type.py b/frappe/core/doctype/user_document_type/user_document_type.py index 48dbf87b3d..a14d735e6a 100644 --- a/frappe/core/doctype/user_document_type/user_document_type.py +++ b/frappe/core/doctype/user_document_type/user_document_type.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2021, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE # import frappe from frappe.model.document import Document diff --git a/frappe/core/doctype/user_email/user_email.py b/frappe/core/doctype/user_email/user_email.py index 729aa03444..daad083577 100644 --- a/frappe/core/doctype/user_email/user_email.py +++ b/frappe/core/doctype/user_email/user_email.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe from frappe.model.document import Document diff --git a/frappe/core/doctype/user_group/test_user_group.py b/frappe/core/doctype/user_group/test_user_group.py index 2f89d032e1..b5d642ae9c 100644 --- a/frappe/core/doctype/user_group/test_user_group.py +++ b/frappe/core/doctype/user_group/test_user_group.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2021, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE # import frappe import unittest diff --git a/frappe/core/doctype/user_group/user_group.py b/frappe/core/doctype/user_group/user_group.py index 178775d407..05ff71e353 100644 --- a/frappe/core/doctype/user_group/user_group.py +++ b/frappe/core/doctype/user_group/user_group.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2021, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE # import frappe from frappe.model.document import Document diff --git a/frappe/core/doctype/user_group_member/test_user_group_member.py b/frappe/core/doctype/user_group_member/test_user_group_member.py index 8dbaed9e65..6d4650a3d0 100644 --- a/frappe/core/doctype/user_group_member/test_user_group_member.py +++ b/frappe/core/doctype/user_group_member/test_user_group_member.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2021, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE # import frappe import unittest diff --git a/frappe/core/doctype/user_group_member/user_group_member.py b/frappe/core/doctype/user_group_member/user_group_member.py index f85ddc3209..69718d8d91 100644 --- a/frappe/core/doctype/user_group_member/user_group_member.py +++ b/frappe/core/doctype/user_group_member/user_group_member.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2021, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE # import frappe from frappe.model.document import Document diff --git a/frappe/core/doctype/user_permission/user_permission.py b/frappe/core/doctype/user_permission/user_permission.py index 5201ffef8d..66ffd48822 100644 --- a/frappe/core/doctype/user_permission/user_permission.py +++ b/frappe/core/doctype/user_permission/user_permission.py @@ -1,5 +1,5 @@ # Copyright (c) 2021, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe, json from frappe.model.document import Document diff --git a/frappe/core/doctype/user_select_document_type/user_select_document_type.py b/frappe/core/doctype/user_select_document_type/user_select_document_type.py index 13e3f0d351..18a21931e5 100644 --- a/frappe/core/doctype/user_select_document_type/user_select_document_type.py +++ b/frappe/core/doctype/user_select_document_type/user_select_document_type.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2021, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE # import frappe from frappe.model.document import Document diff --git a/frappe/core/doctype/user_social_login/user_social_login.py b/frappe/core/doctype/user_social_login/user_social_login.py index 4a34006d2b..80c0c89383 100644 --- a/frappe/core/doctype/user_social_login/user_social_login.py +++ b/frappe/core/doctype/user_social_login/user_social_login.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE from frappe.model.document import Document diff --git a/frappe/core/doctype/user_type/test_user_type.py b/frappe/core/doctype/user_type/test_user_type.py index 1c47f02bbb..7080e1830b 100644 --- a/frappe/core/doctype/user_type/test_user_type.py +++ b/frappe/core/doctype/user_type/test_user_type.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2021, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE # import frappe import unittest diff --git a/frappe/core/doctype/user_type/user_type.py b/frappe/core/doctype/user_type/user_type.py index 82ffb090f1..79a90933e7 100644 --- a/frappe/core/doctype/user_type/user_type.py +++ b/frappe/core/doctype/user_type/user_type.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2021, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe from frappe import _ @@ -36,8 +36,11 @@ class UserType(Document): if not self.user_doctypes: return - modules = frappe.get_all('DocType', fields=['distinct module as module'], - filters={'name': ('in', [d.document_type for d in self.user_doctypes])}) + modules = frappe.get_all("DocType", + fields=["module"], + filters={"name": ("in", [d.document_type for d in self.user_doctypes])}, + distinct=True, + ) self.set('user_type_modules', []) for row in modules: diff --git a/frappe/core/doctype/user_type_module/user_type_module.py b/frappe/core/doctype/user_type_module/user_type_module.py index 9afbcd294d..d25479f869 100644 --- a/frappe/core/doctype/user_type_module/user_type_module.py +++ b/frappe/core/doctype/user_type_module/user_type_module.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2021, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE # import frappe from frappe.model.document import Document diff --git a/frappe/core/doctype/version/test_version.py b/frappe/core/doctype/version/test_version.py index f6c099c4ea..608dc9f0ab 100644 --- a/frappe/core/doctype/version/test_version.py +++ b/frappe/core/doctype/version/test_version.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# See license.txt +# License: MIT. See LICENSE import frappe import unittest, copy from frappe.test_runner import make_test_objects diff --git a/frappe/core/doctype/version/version.css b/frappe/core/doctype/version/version.css deleted file mode 100644 index 769b352585..0000000000 --- a/frappe/core/doctype/version/version.css +++ /dev/null @@ -1,21 +0,0 @@ -.version-info { - overflow: auto; -} - -.version-info pre { - border: 0px; - margin: 0px; - background-color: inherit; -} - -.version-info .table { - background-color: inherit; -} - -.version-info .success { - background-color: #dff0d8 !important; -} - -.version-info .danger { - background-color: #f2dede !important; -} diff --git a/frappe/core/doctype/version/version.py b/frappe/core/doctype/version/version.py index a1bd851346..fcb558650a 100644 --- a/frappe/core/doctype/version/version.py +++ b/frappe/core/doctype/version/version.py @@ -1,7 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt - -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe, json diff --git a/frappe/core/doctype/view_log/test_view_log.py b/frappe/core/doctype/view_log/test_view_log.py index 025f3d8ad9..efa9538fbf 100644 --- a/frappe/core/doctype/view_log/test_view_log.py +++ b/frappe/core/doctype/view_log/test_view_log.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2018, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE import frappe import unittest diff --git a/frappe/core/doctype/view_log/view_log.py b/frappe/core/doctype/view_log/view_log.py index 242250be8b..fbbd6e1154 100644 --- a/frappe/core/doctype/view_log/view_log.py +++ b/frappe/core/doctype/view_log/view_log.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2018, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe from frappe.model.document import Document diff --git a/frappe/core/notifications.py b/frappe/core/notifications.py index 707de43f28..b43d424df5 100644 --- a/frappe/core/notifications.py +++ b/frappe/core/notifications.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import frappe diff --git a/frappe/core/page/__init__.py b/frappe/core/page/__init__.py index 0e57cb68c3..eb5ba62e5c 100644 --- a/frappe/core/page/__init__.py +++ b/frappe/core/page/__init__.py @@ -1,3 +1,3 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE diff --git a/frappe/core/page/background_jobs/background_jobs.py b/frappe/core/page/background_jobs/background_jobs.py index 1f3555e351..5d9bb815da 100644 --- a/frappe/core/page/background_jobs/background_jobs.py +++ b/frappe/core/page/background_jobs/background_jobs.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import json from typing import TYPE_CHECKING, Dict, List diff --git a/frappe/core/page/permission_manager/__init__.py b/frappe/core/page/permission_manager/__init__.py index 0e57cb68c3..eb5ba62e5c 100644 --- a/frappe/core/page/permission_manager/__init__.py +++ b/frappe/core/page/permission_manager/__init__.py @@ -1,3 +1,3 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE diff --git a/frappe/core/page/permission_manager/permission_manager.py b/frappe/core/page/permission_manager/permission_manager.py index 2a99283dda..08642c599e 100644 --- a/frappe/core/page/permission_manager/permission_manager.py +++ b/frappe/core/page/permission_manager/permission_manager.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import frappe from frappe import _ diff --git a/frappe/core/report/__init__.py b/frappe/core/report/__init__.py index 0e57cb68c3..eb5ba62e5c 100644 --- a/frappe/core/report/__init__.py +++ b/frappe/core/report/__init__.py @@ -1,3 +1,3 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE diff --git a/frappe/core/report/permitted_documents_for_user/permitted_documents_for_user.py b/frappe/core/report/permitted_documents_for_user/permitted_documents_for_user.py index 13602ca777..535d354250 100644 --- a/frappe/core/report/permitted_documents_for_user/permitted_documents_for_user.py +++ b/frappe/core/report/permitted_documents_for_user/permitted_documents_for_user.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import frappe from frappe import _, throw diff --git a/frappe/core/report/transaction_log_report/transaction_log_report.py b/frappe/core/report/transaction_log_report/transaction_log_report.py index ff8d8345d6..0a74ece322 100644 --- a/frappe/core/report/transaction_log_report/transaction_log_report.py +++ b/frappe/core/report/transaction_log_report/transaction_log_report.py @@ -1,5 +1,5 @@ # Copyright (c) 2019, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe import hashlib diff --git a/frappe/core/utils.py b/frappe/core/utils.py index 9b8ee3a326..d4690cae89 100644 --- a/frappe/core/utils.py +++ b/frappe/core/utils.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import frappe diff --git a/frappe/core/workspace/build/build.json b/frappe/core/workspace/build/build.json index 464052ba39..8536c807d2 100644 --- a/frappe/core/workspace/build/build.json +++ b/frappe/core/workspace/build/build.json @@ -2,7 +2,7 @@ "cards_label": "Elements", "category": "", "charts": [], - "content": "[{\"type\": \"header\", \"data\": {\"text\": \"Your Shortcuts\", \"level\": 4, \"col\": 12}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"DocType\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Workspace\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Report\", \"col\": 4}}, {\"type\": \"spacer\", \"data\": {\"col\": 12}}, {\"type\": \"header\", \"data\": {\"text\": \"Elements\", \"level\": 4, \"col\": 12}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Modules\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Models\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Views\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Scripting\", \"col\": 4}}]", + "content": "[{\"type\":\"header\",\"data\":{\"text\":\"Your Shortcuts\",\"level\":4,\"col\":12}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"DocType\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Workspace\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Report\",\"col\":4}},{\"type\":\"spacer\",\"data\":{\"col\":12}},{\"type\":\"header\",\"data\":{\"text\":\"Elements\",\"level\":4,\"col\":12}},{\"type\":\"card\",\"data\":{\"card_name\":\"Modules\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Models\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Views\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Scripting\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Packages\",\"col\":4}}]", "creation": "2021-01-02 10:51:16.579957", "developer_mode_only": 0, "disable_user_customization": 0, @@ -200,9 +200,37 @@ "onboard": 0, "only_for": "", "type": "Link" + }, + { + "hidden": 0, + "is_query_report": 0, + "label": "Packages", + "link_count": 2, + "onboard": 0, + "type": "Card Break" + }, + { + "hidden": 0, + "is_query_report": 0, + "label": "Package", + "link_count": 0, + "link_to": "Package", + "link_type": "DocType", + "onboard": 0, + "type": "Link" + }, + { + "hidden": 0, + "is_query_report": 0, + "label": "Package Import", + "link_count": 0, + "link_to": "Package Import", + "link_type": "DocType", + "onboard": 0, + "type": "Link" } ], - "modified": "2021-08-05 12:15:55.793022", + "modified": "2021-09-05 21:14:52.384815", "modified_by": "Administrator", "module": "Core", "name": "Build", diff --git a/frappe/custom/doctype/client_script/__init__.py b/frappe/custom/doctype/client_script/__init__.py index 0e57cb68c3..eb5ba62e5c 100644 --- a/frappe/custom/doctype/client_script/__init__.py +++ b/frappe/custom/doctype/client_script/__init__.py @@ -1,3 +1,3 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE diff --git a/frappe/custom/doctype/client_script/client_script.json b/frappe/custom/doctype/client_script/client_script.json index db02d8d4bc..50f6bf3cc4 100644 --- a/frappe/custom/doctype/client_script/client_script.json +++ b/frappe/custom/doctype/client_script/client_script.json @@ -9,7 +9,10 @@ "field_order": [ "dt", "view", + "column_break_3", + "module", "enabled", + "section_break_6", "script", "sample" ], @@ -53,13 +56,27 @@ "label": "Apply To", "options": "List\nForm", "set_only_once": 1 + }, + { + "fieldname": "column_break_3", + "fieldtype": "Column Break" + }, + { + "fieldname": "module", + "fieldtype": "Link", + "label": "Module (for export)", + "options": "Module Def" + }, + { + "fieldname": "section_break_6", + "fieldtype": "Section Break" } ], "icon": "fa fa-glass", "idx": 1, "index_web_pages_for_search": 1, "links": [], - "modified": "2021-03-16 20:33:51.400191", + "modified": "2021-09-04 12:03:27.029815", "modified_by": "Administrator", "module": "Custom", "name": "Client Script", diff --git a/frappe/custom/doctype/client_script/client_script.py b/frappe/custom/doctype/client_script/client_script.py index 9c098fe8c9..fd6bc9accd 100644 --- a/frappe/custom/doctype/client_script/client_script.py +++ b/frappe/custom/doctype/client_script/client_script.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import frappe from frappe import _ diff --git a/frappe/custom/doctype/client_script/test_client_script.py b/frappe/custom/doctype/client_script/test_client_script.py index b8358468b9..4887956001 100644 --- a/frappe/custom/doctype/client_script/test_client_script.py +++ b/frappe/custom/doctype/client_script/test_client_script.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# See license.txt +# License: MIT. See LICENSE import frappe import unittest diff --git a/frappe/custom/doctype/custom_field/__init__.py b/frappe/custom/doctype/custom_field/__init__.py index 0e57cb68c3..eb5ba62e5c 100644 --- a/frappe/custom/doctype/custom_field/__init__.py +++ b/frappe/custom/doctype/custom_field/__init__.py @@ -1,3 +1,3 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE diff --git a/frappe/custom/doctype/custom_field/custom_field.json b/frappe/custom/doctype/custom_field/custom_field.json index 55a7ec5963..235f11aad8 100644 --- a/frappe/custom/doctype/custom_field/custom_field.json +++ b/frappe/custom/doctype/custom_field/custom_field.json @@ -1,453 +1,458 @@ { - "actions": [], - "allow_import": 1, - "creation": "2013-01-10 16:34:01", - "description": "Adds a custom field to a DocType", - "doctype": "DocType", - "document_type": "Setup", - "engine": "InnoDB", - "field_order": [ - "dt", - "label", - "label_help", - "fieldname", - "insert_after", - "length", - "column_break_6", - "fieldtype", - "precision", - "hide_seconds", - "hide_days", - "options", - "fetch_from", - "fetch_if_empty", - "options_help", - "section_break_11", - "collapsible", - "collapsible_depends_on", - "default", - "depends_on", - "mandatory_depends_on", - "read_only_depends_on", - "properties", - "non_negative", - "reqd", - "unique", - "read_only", - "ignore_user_permissions", - "hidden", - "print_hide", - "print_hide_if_no_value", - "print_width", - "no_copy", - "allow_on_submit", - "in_list_view", - "in_standard_filter", - "in_global_search", - "in_preview", - "bold", - "report_hide", - "search_index", - "allow_in_quick_entry", - "ignore_xss_filter", - "translatable", - "hide_border", - "description", - "permlevel", - "width", - "columns" - ], - "fields": [ - { - "bold": 1, - "fieldname": "dt", - "fieldtype": "Link", - "in_filter": 1, - "in_list_view": 1, - "label": "Document", - "oldfieldname": "dt", - "oldfieldtype": "Link", - "options": "DocType", - "reqd": 1, - "search_index": 1 - }, - { - "bold": 1, - "fieldname": "label", - "fieldtype": "Data", - "in_filter": 1, - "label": "Label", - "no_copy": 1, - "oldfieldname": "label", - "oldfieldtype": "Data" - }, - { - "fieldname": "label_help", - "fieldtype": "HTML", - "label": "Label Help", - "oldfieldtype": "HTML" - }, - { - "fieldname": "fieldname", - "fieldtype": "Data", - "in_list_view": 1, - "label": "Fieldname", - "no_copy": 1, - "oldfieldname": "fieldname", - "oldfieldtype": "Data", - "read_only": 1 - }, - { - "description": "Select the label after which you want to insert new field.", - "fieldname": "insert_after", - "fieldtype": "Select", - "label": "Insert After", - "no_copy": 1, - "oldfieldname": "insert_after", - "oldfieldtype": "Select" - }, - { - "fieldname": "column_break_6", - "fieldtype": "Column Break" - }, - { - "bold": 1, - "default": "Data", - "fieldname": "fieldtype", - "fieldtype": "Select", - "in_filter": 1, - "in_list_view": 1, - "label": "Field Type", - "oldfieldname": "fieldtype", - "oldfieldtype": "Select", - "options": "Attach\nAttach Image\nBarcode\nButton\nCheck\nCode\nColor\nColumn Break\nCurrency\nData\nDate\nDatetime\nDuration\nDynamic Link\nFloat\nFold\nGeolocation\nHeading\nHTML\nHTML Editor\nIcon\nImage\nInt\nLink\nLong Text\nMarkdown Editor\nPassword\nPercent\nRead Only\nRating\nSection Break\nSelect\nSmall Text\nTable\nTable MultiSelect\nText\nText Editor\nTime\nSignature", - "reqd": 1 - }, - { - "depends_on": "eval:in_list([\"Float\", \"Currency\", \"Percent\"], doc.fieldtype)", - "description": "Set non-standard precision for a Float or Currency field", - "fieldname": "precision", - "fieldtype": "Select", - "label": "Precision", - "options": "\n0\n1\n2\n3\n4\n5\n6\n7\n8\n9" - }, - { - "fieldname": "options", - "fieldtype": "Small Text", - "in_list_view": 1, - "label": "Options", - "oldfieldname": "options", - "oldfieldtype": "Text" - }, - { - "fieldname": "fetch_from", - "fieldtype": "Small Text", - "label": "Fetch From" - }, - { - "default": "0", - "description": "If checked, this field will be not overwritten based on Fetch From if a value already exists.", - "fieldname": "fetch_if_empty", - "fieldtype": "Check", - "label": "Fetch If Empty" - }, - { - "fieldname": "options_help", - "fieldtype": "HTML", - "label": "Options Help", - "oldfieldtype": "HTML" - }, - { - "fieldname": "section_break_11", - "fieldtype": "Section Break" - }, - { - "default": "0", - "depends_on": "eval:doc.fieldtype==\"Section Break\"", - "fieldname": "collapsible", - "fieldtype": "Check", - "label": "Collapsible" - }, - { - "depends_on": "eval:doc.fieldtype==\"Section Break\"", - "fieldname": "collapsible_depends_on", - "fieldtype": "Code", - "label": "Collapsible Depends On" - }, - { - "fieldname": "default", - "fieldtype": "Text", - "label": "Default Value", - "oldfieldname": "default", - "oldfieldtype": "Text" - }, - { - "fieldname": "depends_on", - "fieldtype": "Code", - "label": "Depends On", - "length": 255 - }, - { - "fieldname": "description", - "fieldtype": "Text", - "label": "Field Description", - "oldfieldname": "description", - "oldfieldtype": "Text", - "print_width": "300px", - "width": "300px" - }, - { - "default": "0", - "fieldname": "permlevel", - "fieldtype": "Int", - "label": "Permission Level", - "oldfieldname": "permlevel", - "oldfieldtype": "Int" - }, - { - "fieldname": "width", - "fieldtype": "Data", - "label": "Width", - "oldfieldname": "width", - "oldfieldtype": "Data" - }, - { - "description": "Number of columns for a field in a List View or a Grid (Total Columns should be less than 11)", - "fieldname": "columns", - "fieldtype": "Int", - "label": "Columns" - }, - { - "fieldname": "properties", - "fieldtype": "Column Break", - "oldfieldtype": "Column Break", - "print_width": "50%", - "width": "50%" - }, - { - "default": "0", - "fieldname": "reqd", - "fieldtype": "Check", - "in_list_view": 1, - "label": "Is Mandatory Field", - "oldfieldname": "reqd", - "oldfieldtype": "Check" - }, - { - "default": "0", - "fieldname": "unique", - "fieldtype": "Check", - "label": "Unique" - }, - { - "default": "0", - "fieldname": "read_only", - "fieldtype": "Check", - "label": "Read Only" - }, - { - "default": "0", - "depends_on": "eval:doc.fieldtype===\"Link\"", - "fieldname": "ignore_user_permissions", - "fieldtype": "Check", - "label": "Ignore User Permissions" - }, - { - "default": "0", - "fieldname": "hidden", - "fieldtype": "Check", - "label": "Hidden" - }, - { - "default": "0", - "fieldname": "print_hide", - "fieldtype": "Check", - "label": "Print Hide", - "oldfieldname": "print_hide", - "oldfieldtype": "Check" - }, - { - "default": "0", - "depends_on": "eval:[\"Int\", \"Float\", \"Currency\", \"Percent\"].indexOf(doc.fieldtype)!==-1", - "fieldname": "print_hide_if_no_value", - "fieldtype": "Check", - "label": "Print Hide If No Value" - }, - { - "fieldname": "print_width", - "fieldtype": "Data", - "hidden": 1, - "label": "Print Width", - "no_copy": 1, - "print_hide": 1 - }, - { - "default": "0", - "fieldname": "no_copy", - "fieldtype": "Check", - "label": "No Copy", - "oldfieldname": "no_copy", - "oldfieldtype": "Check" - }, - { - "default": "0", - "fieldname": "allow_on_submit", - "fieldtype": "Check", - "label": "Allow on Submit", - "oldfieldname": "allow_on_submit", - "oldfieldtype": "Check" - }, - { - "default": "0", - "fieldname": "in_list_view", - "fieldtype": "Check", - "label": "In List View" - }, - { - "default": "0", - "fieldname": "in_standard_filter", - "fieldtype": "Check", - "label": "In Standard Filter" - }, - { - "default": "0", - "depends_on": "eval:([\"Data\", \"Select\", \"Table\", \"Text\", \"Text Editor\", \"Link\", \"Small Text\", \"Long Text\", \"Read Only\", \"Heading\", \"Dynamic Link\"].indexOf(doc.fieldtype) !== -1)", - "fieldname": "in_global_search", - "fieldtype": "Check", - "label": "In Global Search" - }, - { - "default": "0", - "fieldname": "bold", - "fieldtype": "Check", - "label": "Bold" - }, - { - "default": "0", - "fieldname": "report_hide", - "fieldtype": "Check", - "label": "Report Hide", - "oldfieldname": "report_hide", - "oldfieldtype": "Check" - }, - { - "default": "0", - "fieldname": "search_index", - "fieldtype": "Check", - "hidden": 1, - "label": "Index", - "no_copy": 1, - "print_hide": 1 - }, - { - "default": "0", - "description": "Don't HTML Encode HTML tags like <script> or just characters like < or >, as they could be intentionally used in this field", - "fieldname": "ignore_xss_filter", - "fieldtype": "Check", - "label": "Ignore XSS Filter" - }, - { - "default": "1", - "depends_on": "eval:['Data', 'Select', 'Text', 'Small Text', 'Text Editor'].includes(doc.fieldtype)", - "fieldname": "translatable", - "fieldtype": "Check", - "label": "Translatable" - }, - { - "depends_on": "eval:in_list(['Data', 'Link', 'Dynamic Link', 'Password', 'Select', 'Read Only', 'Attach', 'Attach Image', 'Int'], doc.fieldtype)", - "fieldname": "length", - "fieldtype": "Int", - "label": "Length" - }, - { - "fieldname": "mandatory_depends_on", - "fieldtype": "Code", - "label": "Mandatory Depends On", - "length": 255 - }, - { - "fieldname": "read_only_depends_on", - "fieldtype": "Code", - "label": "Read Only Depends On", - "length": 255 - }, - { - "default": "0", - "fieldname": "allow_in_quick_entry", - "fieldtype": "Check", - "label": "Allow in Quick Entry" - }, - { - "default": "0", - "depends_on": "eval:!in_list(['Table', 'Table MultiSelect'], doc.fieldtype);", - "fieldname": "in_preview", - "fieldtype": "Check", - "label": "In Preview" - }, - { - "default": "0", - "depends_on": "eval:doc.fieldtype=='Duration'", - "fieldname": "hide_seconds", - "fieldtype": "Check", - "label": "Hide Seconds" - }, - { - "default": "0", - "depends_on": "eval:doc.fieldtype=='Duration'", - "fieldname": "hide_days", - "fieldtype": "Check", - "label": "Hide Days" - }, - { - "default": "0", - "depends_on": "eval:doc.fieldtype=='Section Break'", - "fieldname": "hide_border", - "fieldtype": "Check", - "label": "Hide Border" - }, - { - "default": "0", - "depends_on": "eval:in_list([\"Int\", \"Float\", \"Currency\"], doc.fieldtype)", - "fieldname": "non_negative", - "fieldtype": "Check", - "label": "Non Negative" - } - ], - "icon": "fa fa-glass", - "idx": 1, - "index_web_pages_for_search": 1, - "links": [], - "modified": "2021-07-12 05:54:13.042319", - "modified_by": "Administrator", - "module": "Custom", - "name": "Custom Field", - "owner": "Administrator", - "permissions": [ - { - "create": 1, - "delete": 1, - "email": 1, - "print": 1, - "read": 1, - "report": 1, - "role": "Administrator", - "share": 1, - "write": 1 - }, - { - "create": 1, - "delete": 1, - "email": 1, - "print": 1, - "read": 1, - "report": 1, - "role": "System Manager", - "share": 1, - "write": 1 - } - ], - "search_fields": "dt,label,fieldtype,options", - "sort_field": "modified", - "sort_order": "ASC", - "track_changes": 1 + "actions": [], + "allow_import": 1, + "creation": "2013-01-10 16:34:01", + "description": "Adds a custom field to a DocType", + "doctype": "DocType", + "document_type": "Setup", + "engine": "InnoDB", + "field_order": [ + "dt", + "module", + "label", + "label_help", + "fieldname", + "insert_after", + "length", + "column_break_6", + "fieldtype", + "precision", + "hide_seconds", + "hide_days", + "options", + "fetch_from", + "fetch_if_empty", + "options_help", + "section_break_11", + "collapsible", + "collapsible_depends_on", + "default", + "depends_on", + "mandatory_depends_on", + "read_only_depends_on", + "properties", + "non_negative", + "reqd", + "unique", + "read_only", + "ignore_user_permissions", + "hidden", + "print_hide", + "print_hide_if_no_value", + "print_width", + "no_copy", + "allow_on_submit", + "in_list_view", + "in_standard_filter", + "in_global_search", + "in_preview", + "bold", + "report_hide", + "search_index", + "allow_in_quick_entry", + "ignore_xss_filter", + "translatable", + "hide_border", + "description", + "permlevel", + "width", + "columns" + ], + "fields": [{ + "bold": 1, + "fieldname": "dt", + "fieldtype": "Link", + "in_filter": 1, + "in_list_view": 1, + "label": "Document", + "oldfieldname": "dt", + "oldfieldtype": "Link", + "options": "DocType", + "reqd": 1, + "search_index": 1 + }, + { + "bold": 1, + "fieldname": "label", + "fieldtype": "Data", + "in_filter": 1, + "label": "Label", + "no_copy": 1, + "oldfieldname": "label", + "oldfieldtype": "Data" + }, + { + "fieldname": "label_help", + "fieldtype": "HTML", + "label": "Label Help", + "oldfieldtype": "HTML" + }, + { + "fieldname": "fieldname", + "fieldtype": "Data", + "in_list_view": 1, + "label": "Fieldname", + "no_copy": 1, + "oldfieldname": "fieldname", + "oldfieldtype": "Data", + "read_only": 1 + }, + { + "description": "Select the label after which you want to insert new field.", + "fieldname": "insert_after", + "fieldtype": "Select", + "label": "Insert After", + "no_copy": 1, + "oldfieldname": "insert_after", + "oldfieldtype": "Select" + }, + { + "fieldname": "column_break_6", + "fieldtype": "Column Break" + }, + { + "bold": 1, + "default": "Data", + "fieldname": "fieldtype", + "fieldtype": "Select", + "in_filter": 1, + "in_list_view": 1, + "label": "Field Type", + "oldfieldname": "fieldtype", + "oldfieldtype": "Select", + "options": "Attach\nAttach Image\nBarcode\nButton\nCheck\nCode\nColor\nColumn Break\nCurrency\nData\nDate\nDatetime\nDuration\nDynamic Link\nFloat\nFold\nGeolocation\nHeading\nHTML\nHTML Editor\nIcon\nImage\nInt\nLink\nLong Text\nMarkdown Editor\nPassword\nPercent\nRead Only\nRating\nSection Break\nSelect\nSmall Text\nTable\nTable MultiSelect\nText\nText Editor\nTime\nSignature\nTab Break", + "reqd": 1 + }, + { + "depends_on": "eval:in_list([\"Float\", \"Currency\", \"Percent\"], doc.fieldtype)", + "description": "Set non-standard precision for a Float or Currency field", + "fieldname": "precision", + "fieldtype": "Select", + "label": "Precision", + "options": "\n0\n1\n2\n3\n4\n5\n6\n7\n8\n9" + }, + { + "fieldname": "options", + "fieldtype": "Small Text", + "in_list_view": 1, + "label": "Options", + "oldfieldname": "options", + "oldfieldtype": "Text" + }, + { + "fieldname": "fetch_from", + "fieldtype": "Small Text", + "label": "Fetch From" + }, + { + "default": "0", + "description": "If checked, this field will be not overwritten based on Fetch From if a value already exists.", + "fieldname": "fetch_if_empty", + "fieldtype": "Check", + "label": "Fetch If Empty" + }, + { + "fieldname": "options_help", + "fieldtype": "HTML", + "label": "Options Help", + "oldfieldtype": "HTML" + }, + { + "fieldname": "section_break_11", + "fieldtype": "Section Break" + }, + { + "default": "0", + "depends_on": "eval:doc.fieldtype==\"Section Break\"", + "fieldname": "collapsible", + "fieldtype": "Check", + "label": "Collapsible" + }, + { + "depends_on": "eval:doc.fieldtype==\"Section Break\"", + "fieldname": "collapsible_depends_on", + "fieldtype": "Code", + "label": "Collapsible Depends On" + }, + { + "fieldname": "default", + "fieldtype": "Text", + "label": "Default Value", + "oldfieldname": "default", + "oldfieldtype": "Text" + }, + { + "fieldname": "depends_on", + "fieldtype": "Code", + "label": "Depends On", + "length": 255 + }, + { + "fieldname": "description", + "fieldtype": "Text", + "label": "Field Description", + "oldfieldname": "description", + "oldfieldtype": "Text", + "print_width": "300px", + "width": "300px" + }, + { + "default": "0", + "fieldname": "permlevel", + "fieldtype": "Int", + "label": "Permission Level", + "oldfieldname": "permlevel", + "oldfieldtype": "Int" + }, + { + "fieldname": "width", + "fieldtype": "Data", + "label": "Width", + "oldfieldname": "width", + "oldfieldtype": "Data" + }, + { + "description": "Number of columns for a field in a List View or a Grid (Total Columns should be less than 11)", + "fieldname": "columns", + "fieldtype": "Int", + "label": "Columns" + }, + { + "fieldname": "properties", + "fieldtype": "Column Break", + "oldfieldtype": "Column Break", + "print_width": "50%", + "width": "50%" + }, + { + "default": "0", + "fieldname": "reqd", + "fieldtype": "Check", + "in_list_view": 1, + "label": "Is Mandatory Field", + "oldfieldname": "reqd", + "oldfieldtype": "Check" + }, + { + "default": "0", + "fieldname": "unique", + "fieldtype": "Check", + "label": "Unique" + }, + { + "default": "0", + "fieldname": "read_only", + "fieldtype": "Check", + "label": "Read Only" + }, + { + "default": "0", + "depends_on": "eval:doc.fieldtype===\"Link\"", + "fieldname": "ignore_user_permissions", + "fieldtype": "Check", + "label": "Ignore User Permissions" + }, + { + "default": "0", + "fieldname": "hidden", + "fieldtype": "Check", + "label": "Hidden" + }, + { + "default": "0", + "fieldname": "print_hide", + "fieldtype": "Check", + "label": "Print Hide", + "oldfieldname": "print_hide", + "oldfieldtype": "Check" + }, + { + "default": "0", + "depends_on": "eval:[\"Int\", \"Float\", \"Currency\", \"Percent\"].indexOf(doc.fieldtype)!==-1", + "fieldname": "print_hide_if_no_value", + "fieldtype": "Check", + "label": "Print Hide If No Value" + }, + { + "fieldname": "print_width", + "fieldtype": "Data", + "hidden": 1, + "label": "Print Width", + "no_copy": 1, + "print_hide": 1 + }, + { + "default": "0", + "fieldname": "no_copy", + "fieldtype": "Check", + "label": "No Copy", + "oldfieldname": "no_copy", + "oldfieldtype": "Check" + }, + { + "default": "0", + "fieldname": "allow_on_submit", + "fieldtype": "Check", + "label": "Allow on Submit", + "oldfieldname": "allow_on_submit", + "oldfieldtype": "Check" + }, + { + "default": "0", + "fieldname": "in_list_view", + "fieldtype": "Check", + "label": "In List View" + }, + { + "default": "0", + "fieldname": "in_standard_filter", + "fieldtype": "Check", + "label": "In Standard Filter" + }, + { + "default": "0", + "depends_on": "eval:([\"Data\", \"Select\", \"Table\", \"Text\", \"Text Editor\", \"Link\", \"Small Text\", \"Long Text\", \"Read Only\", \"Heading\", \"Dynamic Link\"].indexOf(doc.fieldtype) !== -1)", + "fieldname": "in_global_search", + "fieldtype": "Check", + "label": "In Global Search" + }, + { + "default": "0", + "fieldname": "bold", + "fieldtype": "Check", + "label": "Bold" + }, + { + "default": "0", + "fieldname": "report_hide", + "fieldtype": "Check", + "label": "Report Hide", + "oldfieldname": "report_hide", + "oldfieldtype": "Check" + }, + { + "default": "0", + "fieldname": "search_index", + "fieldtype": "Check", + "hidden": 1, + "label": "Index", + "no_copy": 1, + "print_hide": 1 + }, + { + "default": "0", + "description": "Don't HTML Encode HTML tags like <script> or just characters like < or >, as they could be intentionally used in this field", + "fieldname": "ignore_xss_filter", + "fieldtype": "Check", + "label": "Ignore XSS Filter" + }, + { + "default": "1", + "depends_on": "eval:['Data', 'Select', 'Text', 'Small Text', 'Text Editor'].includes(doc.fieldtype)", + "fieldname": "translatable", + "fieldtype": "Check", + "label": "Translatable" + }, + { + "depends_on": "eval:in_list(['Data', 'Link', 'Dynamic Link', 'Password', 'Select', 'Read Only', 'Attach', 'Attach Image', 'Int'], doc.fieldtype)", + "fieldname": "length", + "fieldtype": "Int", + "label": "Length" + }, + { + "fieldname": "mandatory_depends_on", + "fieldtype": "Code", + "label": "Mandatory Depends On", + "length": 255 + }, + { + "fieldname": "read_only_depends_on", + "fieldtype": "Code", + "label": "Read Only Depends On", + "length": 255 + }, + { + "default": "0", + "fieldname": "allow_in_quick_entry", + "fieldtype": "Check", + "label": "Allow in Quick Entry" + }, + { + "default": "0", + "depends_on": "eval:!in_list(['Table', 'Table MultiSelect'], doc.fieldtype);", + "fieldname": "in_preview", + "fieldtype": "Check", + "label": "In Preview" + }, + { + "default": "0", + "depends_on": "eval:doc.fieldtype=='Duration'", + "fieldname": "hide_seconds", + "fieldtype": "Check", + "label": "Hide Seconds" + }, + { + "default": "0", + "depends_on": "eval:doc.fieldtype=='Duration'", + "fieldname": "hide_days", + "fieldtype": "Check", + "label": "Hide Days" + }, + { + "default": "0", + "depends_on": "eval:doc.fieldtype=='Section Break'", + "fieldname": "hide_border", + "fieldtype": "Check", + "label": "Hide Border" + }, + { + "default": "0", + "depends_on": "eval:in_list([\"Int\", \"Float\", \"Currency\"], doc.fieldtype)", + "fieldname": "non_negative", + "fieldtype": "Check", + "label": "Non Negative" + }, + { + "fieldname": "module", + "fieldtype": "Link", + "label": "Module (for export)", + "options": "Module Def" + } + ], + "icon": "fa fa-glass", + "idx": 1, + "index_web_pages_for_search": 1, + "links": [], + "modified": "2021-09-04 12:45:23.810120", + "modified_by": "Administrator", + "module": "Custom", + "name": "Custom Field", + "owner": "Administrator", + "permissions": [{ + "create": 1, + "delete": 1, + "email": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "Administrator", + "share": 1, + "write": 1 + }, + { + "create": 1, + "delete": 1, + "email": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "System Manager", + "share": 1, + "write": 1 + } + ], + "search_fields": "dt,label,fieldtype,options", + "sort_field": "modified", + "sort_order": "ASC", + "track_changes": 1 } \ No newline at end of file diff --git a/frappe/custom/doctype/custom_field/custom_field.py b/frappe/custom/doctype/custom_field/custom_field.py index e266455f7a..bf606701da 100644 --- a/frappe/custom/doctype/custom_field/custom_field.py +++ b/frappe/custom/doctype/custom_field/custom_field.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import frappe import json @@ -18,7 +18,7 @@ class CustomField(Document): if not self.fieldname: label = self.label if not label: - if self.fieldtype in ["Section Break", "Column Break"]: + if self.fieldtype in ["Section Break", "Column Break", "Tab Break"]: label = self.fieldtype + "_" + str(self.idx) else: frappe.throw(_("Label is mandatory")) diff --git a/frappe/custom/doctype/custom_field/test_custom_field.py b/frappe/custom/doctype/custom_field/test_custom_field.py index 3196b66ee8..9633f0eb8a 100644 --- a/frappe/custom/doctype/custom_field/test_custom_field.py +++ b/frappe/custom/doctype/custom_field/test_custom_field.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# See license.txt +# License: MIT. See LICENSE import frappe import unittest diff --git a/frappe/custom/doctype/customize_form/__init__.py b/frappe/custom/doctype/customize_form/__init__.py index 0e57cb68c3..eb5ba62e5c 100644 --- a/frappe/custom/doctype/customize_form/__init__.py +++ b/frappe/custom/doctype/customize_form/__init__.py @@ -1,3 +1,3 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE diff --git a/frappe/custom/doctype/customize_form/test_customize_form.py b/frappe/custom/doctype/customize_form/test_customize_form.py index 266ece8a1e..8a287b17e8 100644 --- a/frappe/custom/doctype/customize_form/test_customize_form.py +++ b/frappe/custom/doctype/customize_form/test_customize_form.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import frappe, unittest, json from frappe.test_runner import make_test_records_for_doctype diff --git a/frappe/custom/doctype/customize_form_field/__init__.py b/frappe/custom/doctype/customize_form_field/__init__.py index 0e57cb68c3..eb5ba62e5c 100644 --- a/frappe/custom/doctype/customize_form_field/__init__.py +++ b/frappe/custom/doctype/customize_form_field/__init__.py @@ -1,3 +1,3 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE diff --git a/frappe/custom/doctype/customize_form_field/customize_form_field.json b/frappe/custom/doctype/customize_form_field/customize_form_field.json index 0a456b1026..986b99a7af 100644 --- a/frappe/custom/doctype/customize_form_field/customize_form_field.json +++ b/frappe/custom/doctype/customize_form_field/customize_form_field.json @@ -82,7 +82,7 @@ "label": "Type", "oldfieldname": "fieldtype", "oldfieldtype": "Select", - "options": "Attach\nAttach Image\nBarcode\nButton\nCheck\nCode\nColor\nColumn Break\nCurrency\nData\nDate\nDatetime\nDuration\nDynamic Link\nFloat\nFold\nGeolocation\nHeading\nHTML\nHTML Editor\nIcon\nImage\nInt\nLink\nLong Text\nMarkdown Editor\nPassword\nPercent\nRating\nRead Only\nSection Break\nSelect\nSignature\nSmall Text\nTable\nTable MultiSelect\nText\nText Editor\nTime", + "options": "Attach\nAttach Image\nBarcode\nButton\nCheck\nCode\nColor\nColumn Break\nCurrency\nData\nDate\nDatetime\nDuration\nDynamic Link\nFloat\nFold\nGeolocation\nHeading\nHTML\nHTML Editor\nIcon\nImage\nInt\nLink\nLong Text\nMarkdown Editor\nPassword\nPercent\nRating\nRead Only\nSection Break\nSelect\nSignature\nSmall Text\nTable\nTable MultiSelect\nText\nText Editor\nTime\nTab Break", "reqd": 1, "search_index": 1 }, @@ -428,7 +428,7 @@ "index_web_pages_for_search": 1, "istable": 1, "links": [], - "modified": "2021-07-10 21:57:24.479749", + "modified": "2021-07-11 21:57:24.479749", "modified_by": "Administrator", "module": "Custom", "name": "Customize Form Field", diff --git a/frappe/custom/doctype/customize_form_field/customize_form_field.py b/frappe/custom/doctype/customize_form_field/customize_form_field.py index f288e70754..67563cf048 100644 --- a/frappe/custom/doctype/customize_form_field/customize_form_field.py +++ b/frappe/custom/doctype/customize_form_field/customize_form_field.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import frappe diff --git a/frappe/custom/doctype/doctype_layout/doctype_layout.py b/frappe/custom/doctype/doctype_layout/doctype_layout.py index 0dc320353d..fa285ddb62 100644 --- a/frappe/custom/doctype/doctype_layout/doctype_layout.py +++ b/frappe/custom/doctype/doctype_layout/doctype_layout.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE from frappe.model.document import Document diff --git a/frappe/custom/doctype/doctype_layout/test_doctype_layout.py b/frappe/custom/doctype/doctype_layout/test_doctype_layout.py index dcde3c00a4..a63dd7ee16 100644 --- a/frappe/custom/doctype/doctype_layout/test_doctype_layout.py +++ b/frappe/custom/doctype/doctype_layout/test_doctype_layout.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE # import frappe import unittest diff --git a/frappe/custom/doctype/doctype_layout_field/doctype_layout_field.py b/frappe/custom/doctype/doctype_layout_field/doctype_layout_field.py index c1e963602f..3f8487b659 100644 --- a/frappe/custom/doctype/doctype_layout_field/doctype_layout_field.py +++ b/frappe/custom/doctype/doctype_layout_field/doctype_layout_field.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE # import frappe from frappe.model.document import Document diff --git a/frappe/custom/doctype/property_setter/__init__.py b/frappe/custom/doctype/property_setter/__init__.py index 0e57cb68c3..eb5ba62e5c 100644 --- a/frappe/custom/doctype/property_setter/__init__.py +++ b/frappe/custom/doctype/property_setter/__init__.py @@ -1,3 +1,3 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE diff --git a/frappe/custom/doctype/property_setter/property_setter.json b/frappe/custom/doctype/property_setter/property_setter.json index b318d92c5a..fcb36637fe 100644 --- a/frappe/custom/doctype/property_setter/property_setter.json +++ b/frappe/custom/doctype/property_setter/property_setter.json @@ -13,6 +13,8 @@ "field_name", "row_name", "column_break0", + "module", + "section_break_9", "property", "property_type", "value", @@ -91,13 +93,23 @@ "fieldname": "row_name", "fieldtype": "Data", "label": "Row Name" + }, + { + "fieldname": "module", + "fieldtype": "Link", + "label": "Module (for export)", + "options": "Module Def" + }, + { + "fieldname": "section_break_9", + "fieldtype": "Section Break" } ], "icon": "fa fa-glass", "idx": 1, "index_web_pages_for_search": 1, "links": [], - "modified": "2020-09-24 14:42:38.599684", + "modified": "2021-09-04 12:46:17.860769", "modified_by": "Administrator", "module": "Custom", "name": "Property Setter", diff --git a/frappe/custom/doctype/property_setter/property_setter.py b/frappe/custom/doctype/property_setter/property_setter.py index 2a6c06b70a..d71b7b0021 100644 --- a/frappe/custom/doctype/property_setter/property_setter.py +++ b/frappe/custom/doctype/property_setter/property_setter.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import frappe from frappe import _ @@ -34,7 +34,7 @@ class PropertySetter(Document): fields=['fieldname', 'label', 'fieldtype'], filters={ 'parent': dt, - 'fieldtype': ['not in', ('Section Break', 'Column Break', 'HTML', 'Read Only', 'Fold') + frappe.model.table_fields], + 'fieldtype': ['not in', ('Section Break', 'Column Break', 'Tab Break', 'HTML', 'Read Only', 'Fold') + frappe.model.table_fields], 'fieldname': ['!=', ''] }, order_by='label asc', diff --git a/frappe/custom/doctype/property_setter/test_property_setter.py b/frappe/custom/doctype/property_setter/test_property_setter.py index 4d4de66d51..1bbbe59a0f 100644 --- a/frappe/custom/doctype/property_setter/test_property_setter.py +++ b/frappe/custom/doctype/property_setter/test_property_setter.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# See license.txt +# License: MIT. See LICENSE import frappe import unittest diff --git a/frappe/custom/doctype/test_rename_new/test_rename_new.py b/frappe/custom/doctype/test_rename_new/test_rename_new.py index 32d2396b2b..fc4ab97cfe 100644 --- a/frappe/custom/doctype/test_rename_new/test_rename_new.py +++ b/frappe/custom/doctype/test_rename_new/test_rename_new.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2021, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE # import frappe from frappe.model.document import Document diff --git a/frappe/custom/doctype/test_rename_new/test_test_rename_new.py b/frappe/custom/doctype/test_rename_new/test_test_rename_new.py index b3ea4818de..03202669ed 100644 --- a/frappe/custom/doctype/test_rename_new/test_test_rename_new.py +++ b/frappe/custom/doctype/test_rename_new/test_test_rename_new.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2021, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE # import frappe import unittest diff --git a/frappe/data/sample_site_config.json b/frappe/data/sample_site_config.json deleted file mode 100644 index 715cd7b9fa..0000000000 --- a/frappe/data/sample_site_config.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "db_name": "testdb", - "db_password": "password", - "mute_emails": true, - - "limits": { - "emails": 1500, - "space": 0.157, - "expiry": "2016-07-25", - "users": 1 - }, - - "developer_mode": 1, - "auto_cache_clear": true, - "disable_website_cache": true, - "max_file_size": 1000000, - - "mail_server": "localhost", - "mail_login": null, - "mail_password": null, - "mail_port": 25, - "use_ssl": 0, - "auto_email_id": "hello@example.com", - - "google_analytics_id": "google_analytics_id", - "google_analytics_anonymize_ip": 1, - - "google_login": { - "client_id": "google_client_id", - "client_secret": "google_client_secret" - }, - "github_login": { - "client_id": "github_client_id", - "client_secret": "github_client_secret" - }, - "facebook_login": { - "client_id": "facebook_client_id", - "client_secret": "facebook_client_secret" - }, - - "celery_broker": "redis://localhost", - "celery_result_backend": null, - "scheduler_interval": 300, - "celery_queue_per_site": true -} diff --git a/frappe/data_migration/doctype/data_migration_connector/data_migration_connector.py b/frappe/data_migration/doctype/data_migration_connector/data_migration_connector.py index d1137f2e67..2e4e4d45b3 100644 --- a/frappe/data_migration/doctype/data_migration_connector/data_migration_connector.py +++ b/frappe/data_migration/doctype/data_migration_connector/data_migration_connector.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe, os from frappe.model.document import Document diff --git a/frappe/data_migration/doctype/data_migration_connector/test_data_migration_connector.py b/frappe/data_migration/doctype/data_migration_connector/test_data_migration_connector.py index fd45f86ec1..ffc96c8266 100644 --- a/frappe/data_migration/doctype/data_migration_connector/test_data_migration_connector.py +++ b/frappe/data_migration/doctype/data_migration_connector/test_data_migration_connector.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE import unittest class TestDataMigrationConnector(unittest.TestCase): diff --git a/frappe/data_migration/doctype/data_migration_mapping/data_migration_mapping.py b/frappe/data_migration/doctype/data_migration_mapping/data_migration_mapping.py index 5cb20ba56c..46d33eaca9 100644 --- a/frappe/data_migration/doctype/data_migration_mapping/data_migration_mapping.py +++ b/frappe/data_migration/doctype/data_migration_mapping/data_migration_mapping.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe from frappe.model.document import Document diff --git a/frappe/data_migration/doctype/data_migration_mapping/test_data_migration_mapping.py b/frappe/data_migration/doctype/data_migration_mapping/test_data_migration_mapping.py index df11fc0522..b1040aaa58 100644 --- a/frappe/data_migration/doctype/data_migration_mapping/test_data_migration_mapping.py +++ b/frappe/data_migration/doctype/data_migration_mapping/test_data_migration_mapping.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE import unittest class TestDataMigrationMapping(unittest.TestCase): diff --git a/frappe/data_migration/doctype/data_migration_mapping_detail/data_migration_mapping_detail.py b/frappe/data_migration/doctype/data_migration_mapping_detail/data_migration_mapping_detail.py index 6d3ef50937..ce46f60f67 100644 --- a/frappe/data_migration/doctype/data_migration_mapping_detail/data_migration_mapping_detail.py +++ b/frappe/data_migration/doctype/data_migration_mapping_detail/data_migration_mapping_detail.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE from frappe.model.document import Document diff --git a/frappe/data_migration/doctype/data_migration_plan/data_migration_plan.py b/frappe/data_migration/doctype/data_migration_plan/data_migration_plan.py index a8d0e40a4c..94ed77e2ec 100644 --- a/frappe/data_migration/doctype/data_migration_plan/data_migration_plan.py +++ b/frappe/data_migration/doctype/data_migration_plan/data_migration_plan.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe from frappe.modules import get_module_path, scrub_dt_dn diff --git a/frappe/data_migration/doctype/data_migration_plan/test_data_migration_plan.py b/frappe/data_migration/doctype/data_migration_plan/test_data_migration_plan.py index 14c585a82d..649f7db903 100644 --- a/frappe/data_migration/doctype/data_migration_plan/test_data_migration_plan.py +++ b/frappe/data_migration/doctype/data_migration_plan/test_data_migration_plan.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE import unittest class TestDataMigrationPlan(unittest.TestCase): diff --git a/frappe/data_migration/doctype/data_migration_plan_mapping/data_migration_plan_mapping.py b/frappe/data_migration/doctype/data_migration_plan_mapping/data_migration_plan_mapping.py index ba4cf28eb8..7939a68d97 100644 --- a/frappe/data_migration/doctype/data_migration_plan_mapping/data_migration_plan_mapping.py +++ b/frappe/data_migration/doctype/data_migration_plan_mapping/data_migration_plan_mapping.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE from frappe.model.document import Document diff --git a/frappe/data_migration/doctype/data_migration_run/data_migration_run.py b/frappe/data_migration/doctype/data_migration_run/data_migration_run.py index c35af5827b..deb14baf27 100644 --- a/frappe/data_migration/doctype/data_migration_run/data_migration_run.py +++ b/frappe/data_migration/doctype/data_migration_run/data_migration_run.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe, json, math from frappe.model.document import Document diff --git a/frappe/data_migration/doctype/data_migration_run/test_data_migration_run.py b/frappe/data_migration/doctype/data_migration_run/test_data_migration_run.py index ef7b70dca2..485f86a7f9 100644 --- a/frappe/data_migration/doctype/data_migration_run/test_data_migration_run.py +++ b/frappe/data_migration/doctype/data_migration_run/test_data_migration_run.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE import frappe, unittest class TestDataMigrationRun(unittest.TestCase): diff --git a/frappe/database/__init__.py b/frappe/database/__init__.py index a899bec3d1..b0e3183d4f 100644 --- a/frappe/database/__init__.py +++ b/frappe/database/__init__.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE # Database Module # -------------------- diff --git a/frappe/database/database.py b/frappe/database/database.py index 9fab8e116f..0ee11ea075 100644 --- a/frappe/database/database.py +++ b/frappe/database/database.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE # Database Module # -------------------- @@ -332,7 +332,7 @@ class Database(object): values[key] = value if isinstance(value, (list, tuple)): # value is a tuple like ("!=", 0) - _operator = value[0] + _operator = value[0].lower() values[key] = value[1] if isinstance(value[1], (tuple, list)): # value is a list in tuple ("in", ("A", "B")) @@ -839,6 +839,30 @@ class Database(object): return count + def sum(self, dt, fieldname, filters=None): + return self._get_aggregation('SUM', dt, fieldname, filters) + + def avg(self, dt, fieldname, filters=None): + return self._get_aggregation('AVG', dt, fieldname, filters) + + def min(self, dt, fieldname, filters=None): + return self._get_aggregation('MIN', dt, fieldname, filters) + + def max(self, dt, fieldname, filters=None): + return self._get_aggregation('MAX', dt, fieldname, filters) + + def _get_aggregation(self, function, dt, fieldname, filters=None): + if not self.has_column(dt, fieldname): + frappe.throw(frappe._('Invalid column'), self.InvalidColumnName) + + query = f'SELECT {function}({fieldname}) AS value FROM `tab{dt}`' + values = () + if filters: + conditions, values = self.build_conditions(filters) + query = f"{query} WHERE {conditions}" + + return self.sql(query, values)[0][0] or 0 + @staticmethod def format_date(date): return getdate(date).strftime("%Y-%m-%d") @@ -895,13 +919,13 @@ class Database(object): WHERE table_name = 'tab{0}' AND column_name = '{1}' '''.format(doctype, column))[0][0] def has_index(self, table_name, index_name): - pass + raise NotImplementedError def add_index(self, doctype, fields, index_name=None): - pass + raise NotImplementedError def add_unique(self, doctype, fields, constraint_name=None): - pass + raise NotImplementedError @staticmethod def get_index_name(fields): @@ -927,7 +951,7 @@ class Database(object): def escape(s, percent=True): """Excape quotes and percent in given string.""" # implemented in specific class - pass + raise NotImplementedError @staticmethod def is_column_missing(e): diff --git a/frappe/database/mariadb/database.py b/frappe/database/mariadb/database.py index d4a119804b..2f6d640743 100644 --- a/frappe/database/mariadb/database.py +++ b/frappe/database/mariadb/database.py @@ -22,11 +22,11 @@ class MariaDBDatabase(Database): def setup_type_map(self): self.db_type = 'mariadb' self.type_map = { - 'Currency': ('decimal', '18,6'), + 'Currency': ('decimal', '21,9'), 'Int': ('int', '11'), 'Long Int': ('bigint', '20'), - 'Float': ('decimal', '18,6'), - 'Percent': ('decimal', '18,6'), + 'Float': ('decimal', '21,9'), + 'Percent': ('decimal', '21,9'), 'Check': ('int', '1'), 'Small Text': ('text', ''), 'Long Text': ('longtext', ''), @@ -51,7 +51,7 @@ class MariaDBDatabase(Database): 'Color': ('varchar', self.VARCHAR_LEN), 'Barcode': ('longtext', ''), 'Geolocation': ('longtext', ''), - 'Duration': ('decimal', '18,6'), + 'Duration': ('decimal', '21,9'), 'Icon': ('varchar', self.VARCHAR_LEN) } @@ -135,8 +135,8 @@ class MariaDBDatabase(Database): table_name = get_table_name(doctype) return self.sql(f"DESC `{table_name}`") - def change_column_type(self, table: str, column: str, type: str) -> Union[List, Tuple]: - table_name = get_table_name(table) + def change_column_type(self, doctype: str, column: str, type: str) -> Union[List, Tuple]: + table_name = get_table_name(doctype) return self.sql(f"ALTER TABLE `{table_name}` MODIFY `{column}` {type} NOT NULL") # exception types @@ -195,7 +195,7 @@ class MariaDBDatabase(Database): `password` TEXT NOT NULL, `encrypted` INT(1) NOT NULL DEFAULT 0, PRIMARY KEY (`doctype`, `name`, `fieldname`) - ) ENGINE=InnoDB ROW_FORMAT=COMPRESSED CHARACTER SET=utf8mb4 COLLATE=utf8mb4_unicode_ci""") + ) ENGINE=InnoDB ROW_FORMAT=DYNAMIC CHARACTER SET=utf8mb4 COLLATE=utf8mb4_unicode_ci""") def create_global_search_table(self): if not '__global_search' in self.get_tables(): @@ -256,11 +256,11 @@ class MariaDBDatabase(Database): index_name=index_name )) - def add_index(self, doctype, fields, index_name=None): + def add_index(self, doctype: str, fields: List, index_name: str = None): """Creates an index with given fields if not already created. Index name will be `fieldname1_fieldname2_index`""" index_name = index_name or self.get_index_name(fields) - table_name = 'tab' + doctype + table_name = get_table_name(doctype) if not self.has_index(table_name, index_name): self.commit() self.sql("""ALTER TABLE `%s` diff --git a/frappe/database/mariadb/framework_mariadb.sql b/frappe/database/mariadb/framework_mariadb.sql index f8841e9417..670fb71aa2 100644 --- a/frappe/database/mariadb/framework_mariadb.sql +++ b/frappe/database/mariadb/framework_mariadb.sql @@ -61,6 +61,7 @@ CREATE TABLE `tabDocField` ( `in_preview` int(1) NOT NULL DEFAULT 0, `read_only` int(1) NOT NULL DEFAULT 0, `precision` varchar(255) DEFAULT NULL, + `max_height` varchar(10) DEFAULT NULL, `length` int(11) NOT NULL DEFAULT 0, `translatable` int(1) NOT NULL DEFAULT 0, `hide_border` int(1) NOT NULL DEFAULT 0, @@ -71,7 +72,7 @@ CREATE TABLE `tabDocField` ( KEY `label` (`label`), KEY `fieldtype` (`fieldtype`), KEY `fieldname` (`fieldname`) -) ENGINE=InnoDB ROW_FORMAT=COMPRESSED CHARACTER SET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +) ENGINE=InnoDB ROW_FORMAT=DYNAMIC CHARACTER SET=utf8mb4 COLLATE=utf8mb4_unicode_ci; -- @@ -108,7 +109,7 @@ CREATE TABLE `tabDocPerm` ( `email` int(1) NOT NULL DEFAULT 1, PRIMARY KEY (`name`), KEY `parent` (`parent`) -) ENGINE=InnoDB ROW_FORMAT=COMPRESSED CHARACTER SET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +) ENGINE=InnoDB ROW_FORMAT=DYNAMIC CHARACTER SET=utf8mb4 COLLATE=utf8mb4_unicode_ci; -- -- Table structure for table `tabDocType Action` @@ -132,7 +133,7 @@ CREATE TABLE `tabDocType Action` ( PRIMARY KEY (`name`), KEY `parent` (`parent`), KEY `modified` (`modified`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=COMPRESSED; +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=DYNAMIC; -- -- Table structure for table `tabDocType Action` @@ -155,7 +156,7 @@ CREATE TABLE `tabDocType Link` ( PRIMARY KEY (`name`), KEY `parent` (`parent`), KEY `modified` (`modified`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=COMPRESSED; +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=DYNAMIC; -- -- Table structure for table `tabDocType` @@ -183,6 +184,7 @@ CREATE TABLE `tabDocType` ( `restrict_to_domain` varchar(255) DEFAULT NULL, `app` varchar(255) DEFAULT NULL, `autoname` varchar(255) DEFAULT NULL, + `naming_rule` varchar(40) DEFAULT NULL, `name_case` varchar(255) DEFAULT NULL, `title_field` varchar(255) DEFAULT NULL, `image_field` varchar(255) DEFAULT NULL, @@ -226,7 +228,7 @@ CREATE TABLE `tabDocType` ( `sender_field` varchar(255) DEFAULT NULL, PRIMARY KEY (`name`), KEY `parent` (`parent`) -) ENGINE=InnoDB ROW_FORMAT=COMPRESSED CHARACTER SET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +) ENGINE=InnoDB ROW_FORMAT=DYNAMIC CHARACTER SET=utf8mb4 COLLATE=utf8mb4_unicode_ci; -- -- Table structure for table `tabSeries` @@ -237,7 +239,7 @@ CREATE TABLE `tabSeries` ( `name` varchar(100), `current` int(10) NOT NULL DEFAULT 0, PRIMARY KEY(`name`) -) ENGINE=InnoDB ROW_FORMAT=COMPRESSED CHARACTER SET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +) ENGINE=InnoDB ROW_FORMAT=DYNAMIC CHARACTER SET=utf8mb4 COLLATE=utf8mb4_unicode_ci; -- @@ -254,7 +256,7 @@ CREATE TABLE `tabSessions` ( `device` varchar(255) DEFAULT 'desktop', `status` varchar(20) DEFAULT NULL, KEY `sid` (`sid`) -) ENGINE=InnoDB ROW_FORMAT=COMPRESSED CHARACTER SET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +) ENGINE=InnoDB ROW_FORMAT=DYNAMIC CHARACTER SET=utf8mb4 COLLATE=utf8mb4_unicode_ci; -- @@ -267,7 +269,7 @@ CREATE TABLE `tabSingles` ( `field` varchar(255) DEFAULT NULL, `value` text, KEY `singles_doctype_field_index` (`doctype`, `field`) -) ENGINE=InnoDB ROW_FORMAT=COMPRESSED CHARACTER SET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +) ENGINE=InnoDB ROW_FORMAT=DYNAMIC CHARACTER SET=utf8mb4 COLLATE=utf8mb4_unicode_ci; -- -- Table structure for table `__Auth` @@ -281,7 +283,7 @@ CREATE TABLE `__Auth` ( `password` TEXT NOT NULL, `encrypted` INT(1) NOT NULL DEFAULT 0, PRIMARY KEY (`doctype`, `name`, `fieldname`) -) ENGINE=InnoDB ROW_FORMAT=COMPRESSED CHARACTER SET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +) ENGINE=InnoDB ROW_FORMAT=DYNAMIC CHARACTER SET=utf8mb4 COLLATE=utf8mb4_unicode_ci; -- -- Table structure for table `tabFile` @@ -309,7 +311,7 @@ CREATE TABLE `tabFile` ( KEY `parent` (`parent`), KEY `attached_to_name` (`attached_to_name`), KEY `attached_to_doctype` (`attached_to_doctype`) -) ENGINE=InnoDB ROW_FORMAT=COMPRESSED CHARACTER SET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +) ENGINE=InnoDB ROW_FORMAT=DYNAMIC CHARACTER SET=utf8mb4 COLLATE=utf8mb4_unicode_ci; -- -- Table structure for table `tabDefaultValue` @@ -332,4 +334,4 @@ CREATE TABLE `tabDefaultValue` ( PRIMARY KEY (`name`), KEY `parent` (`parent`), KEY `defaultvalue_parent_defkey_index` (`parent`,`defkey`) -) ENGINE=InnoDB ROW_FORMAT=COMPRESSED CHARACTER SET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +) ENGINE=InnoDB ROW_FORMAT=DYNAMIC CHARACTER SET=utf8mb4 COLLATE=utf8mb4_unicode_ci; diff --git a/frappe/database/mariadb/schema.py b/frappe/database/mariadb/schema.py index b40af59286..5768a2f23d 100644 --- a/frappe/database/mariadb/schema.py +++ b/frappe/database/mariadb/schema.py @@ -4,18 +4,22 @@ from frappe.database.schema import DBTable class MariaDBTable(DBTable): def create(self): - add_text = '' + additional_definitions = "" + engine = self.meta.get("engine") or "InnoDB" + varchar_len = frappe.db.VARCHAR_LEN # columns column_defs = self.get_column_definitions() - if column_defs: add_text += ',\n'.join(column_defs) + ',\n' + if column_defs: + additional_definitions += ',\n'.join(column_defs) + ',\n' # index index_defs = self.get_index_definitions() - if index_defs: add_text += ',\n'.join(index_defs) + ',\n' + if index_defs: + additional_definitions += ',\n'.join(index_defs) + ',\n' # create table - frappe.db.sql("""create table `%s` ( + query = f"""create table `{self.table_name}` ( name varchar({varchar_len}) not null primary key, creation datetime(6), modified datetime(6), @@ -26,13 +30,15 @@ class MariaDBTable(DBTable): parentfield varchar({varchar_len}), parenttype varchar({varchar_len}), idx int(8) not null default '0', - %sindex parent(parent), + {additional_definitions} + index parent(parent), index modified(modified)) ENGINE={engine} - ROW_FORMAT=COMPRESSED + ROW_FORMAT=DYNAMIC CHARACTER SET=utf8mb4 - COLLATE=utf8mb4_unicode_ci""".format(varchar_len=frappe.db.VARCHAR_LEN, - engine=self.meta.get("engine") or 'InnoDB') % (self.table_name, add_text)) + COLLATE=utf8mb4_unicode_ci""" + + frappe.db.sql(query) def alter(self): for col in self.columns.values(): diff --git a/frappe/database/postgres/database.py b/frappe/database/postgres/database.py index 00e60fb8d2..bfa5515111 100644 --- a/frappe/database/postgres/database.py +++ b/frappe/database/postgres/database.py @@ -4,6 +4,7 @@ from typing import List, Tuple, Union import psycopg2 import psycopg2.extensions from psycopg2.extensions import ISOLATION_LEVEL_AUTOCOMMIT +from psycopg2.errorcodes import STRING_DATA_RIGHT_TRUNCATION import frappe from frappe.database.database import Database @@ -31,11 +32,11 @@ class PostgresDatabase(Database): def setup_type_map(self): self.db_type = 'postgres' self.type_map = { - 'Currency': ('decimal', '18,6'), + 'Currency': ('decimal', '21,9'), 'Int': ('bigint', None), 'Long Int': ('bigint', None), - 'Float': ('decimal', '18,6'), - 'Percent': ('decimal', '18,6'), + 'Float': ('decimal', '21,9'), + 'Percent': ('decimal', '21,9'), 'Check': ('smallint', None), 'Small Text': ('text', ''), 'Long Text': ('text', ''), @@ -60,7 +61,7 @@ class PostgresDatabase(Database): 'Color': ('varchar', self.VARCHAR_LEN), 'Barcode': ('text', ''), 'Geolocation': ('text', ''), - 'Duration': ('decimal', '18,6'), + 'Duration': ('decimal', '21,9'), 'Icon': ('varchar', self.VARCHAR_LEN) } @@ -171,7 +172,7 @@ class PostgresDatabase(Database): @staticmethod def is_data_too_long(e): - return e.pgcode == '22001' + return e.pgcode == STRING_DATA_RIGHT_TRUNCATION def rename_table(self, old_name: str, new_name: str) -> Union[List, Tuple]: old_name = get_table_name(old_name) @@ -182,8 +183,8 @@ class PostgresDatabase(Database): table_name = get_table_name(doctype) return self.sql(f"SELECT COLUMN_NAME FROM information_schema.COLUMNS WHERE TABLE_NAME = '{table_name}'") - def change_column_type(self, table: str, column: str, type: str) -> Union[List, Tuple]: - table_name = get_table_name(table) + def change_column_type(self, doctype: str, column: str, type: str) -> Union[List, Tuple]: + table_name = get_table_name(doctype) return self.sql(f'ALTER TABLE "{table_name}" ALTER COLUMN "{column}" TYPE {type}') def create_auth_table(self): @@ -258,14 +259,14 @@ class PostgresDatabase(Database): return self.sql("""SELECT 1 FROM pg_indexes WHERE tablename='{table_name}' and indexname='{index_name}' limit 1""".format(table_name=table_name, index_name=index_name)) - def add_index(self, doctype, fields, index_name=None): + def add_index(self, doctype: str, fields: List, index_name: str = None): """Creates an index with given fields if not already created. Index name will be `fieldname1_fieldname2_index`""" + table_name = get_table_name(doctype) index_name = index_name or self.get_index_name(fields) - table_name = 'tab' + doctype + fields_str = '", "'.join(re.sub(r"\(.*\)", "", field) for field in fields) - self.commit() - self.sql("""CREATE INDEX IF NOT EXISTS "{}" ON `{}`("{}")""".format(index_name, table_name, '", "'.join(fields))) + self.sql_ddl(f'CREATE INDEX IF NOT EXISTS "{index_name}" ON `{table_name}` ("{fields_str}")') def add_unique(self, doctype, fields, constraint_name=None): if isinstance(fields, str): diff --git a/frappe/database/postgres/framework_postgres.sql b/frappe/database/postgres/framework_postgres.sql index a4e94aa326..868f98fc98 100644 --- a/frappe/database/postgres/framework_postgres.sql +++ b/frappe/database/postgres/framework_postgres.sql @@ -61,6 +61,7 @@ CREATE TABLE "tabDocField" ( "in_preview" smallint NOT NULL DEFAULT 0, "read_only" smallint NOT NULL DEFAULT 0, "precision" varchar(255) DEFAULT NULL, + "max_height" varchar(10) DEFAULT NULL, "length" bigint NOT NULL DEFAULT 0, "translatable" smallint NOT NULL DEFAULT 0, "hide_border" smallint NOT NULL DEFAULT 0, @@ -188,6 +189,7 @@ CREATE TABLE "tabDocType" ( "restrict_to_domain" varchar(255) DEFAULT NULL, "app" varchar(255) DEFAULT NULL, "autoname" varchar(255) DEFAULT NULL, + "naming_rule" varchar(40) DEFAULT NULL, "name_case" varchar(255) DEFAULT NULL, "title_field" varchar(255) DEFAULT NULL, "image_field" varchar(255) DEFAULT NULL, diff --git a/frappe/database/schema.py b/frappe/database/schema.py index 31f11dbd5e..ce9fcb4147 100644 --- a/frappe/database/schema.py +++ b/frappe/database/schema.py @@ -303,6 +303,8 @@ def get_definition(fieldtype, precision=None, length=None): size = d[1] if d[1] else None if size: + # This check needs to exist for backward compatibility. + # Till V13, default size used for float, currency and percent are (18, 6). if fieldtype in ["Float", "Currency", "Percent"] and cint(precision) > 6: size = '21,9' diff --git a/frappe/defaults.py b/frappe/defaults.py index d4c338388d..75feabc332 100644 --- a/frappe/defaults.py +++ b/frappe/defaults.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import frappe from frappe.desk.notifications import clear_notifications diff --git a/frappe/desk/__init__.py b/frappe/desk/__init__.py index 0e57cb68c3..eb5ba62e5c 100644 --- a/frappe/desk/__init__.py +++ b/frappe/desk/__init__.py @@ -1,3 +1,3 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE diff --git a/frappe/desk/calendar.py b/frappe/desk/calendar.py index 273b2654bf..66e6dd8434 100644 --- a/frappe/desk/calendar.py +++ b/frappe/desk/calendar.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import frappe from frappe import _ diff --git a/frappe/desk/desk_page.py b/frappe/desk/desk_page.py index d373dbda0e..a01008280c 100644 --- a/frappe/desk/desk_page.py +++ b/frappe/desk/desk_page.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import frappe from frappe.translate import send_translations diff --git a/frappe/desk/desktop.py b/frappe/desk/desktop.py index e9036b98b0..b9b01d0a74 100644 --- a/frappe/desk/desktop.py +++ b/frappe/desk/desktop.py @@ -1,5 +1,5 @@ # Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE # Author - Shivam Mishra import frappe @@ -573,7 +573,7 @@ def save_new_widget(doc, page, blocks, new_widgets): doc.build_links_table_from_card(widgets.card) # remove duplicate and unwanted widgets - if widgets: + if widgets: clean_up(doc, blocks) try: @@ -597,7 +597,7 @@ def clean_up(original_page, blocks): page_widgets = {} for wid in ['shortcut', 'card', 'chart']: - # get list of widget's name from blocks + # get list of widget's name from blocks page_widgets[wid] = [x['data'][wid + '_name'] for x in loads(blocks) if x['type'] == wid] # shortcut & chart cleanup diff --git a/frappe/desk/doctype/bulk_update/bulk_update.py b/frappe/desk/doctype/bulk_update/bulk_update.py index 469ee839f1..b512ca175c 100644 --- a/frappe/desk/doctype/bulk_update/bulk_update.py +++ b/frappe/desk/doctype/bulk_update/bulk_update.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe from frappe.model.document import Document diff --git a/frappe/desk/doctype/calendar_view/calendar_view.py b/frappe/desk/doctype/calendar_view/calendar_view.py index 3a986f3273..11612f5587 100644 --- a/frappe/desk/doctype/calendar_view/calendar_view.py +++ b/frappe/desk/doctype/calendar_view/calendar_view.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE from frappe.model.document import Document diff --git a/frappe/desk/doctype/console_log/console_log.py b/frappe/desk/doctype/console_log/console_log.py index 5d0f1cfa93..e0b552ebfd 100644 --- a/frappe/desk/doctype/console_log/console_log.py +++ b/frappe/desk/doctype/console_log/console_log.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE # import frappe from frappe.model.document import Document diff --git a/frappe/desk/doctype/console_log/test_console_log.py b/frappe/desk/doctype/console_log/test_console_log.py index 3bb1605204..c41b9d68c8 100644 --- a/frappe/desk/doctype/console_log/test_console_log.py +++ b/frappe/desk/doctype/console_log/test_console_log.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE # import frappe import unittest diff --git a/frappe/desk/doctype/dashboard/dashboard.py b/frappe/desk/doctype/dashboard/dashboard.py index 1d333609db..0dfd458a37 100644 --- a/frappe/desk/doctype/dashboard/dashboard.py +++ b/frappe/desk/doctype/dashboard/dashboard.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE from frappe.model.document import Document from frappe.modules.export_file import export_to_files diff --git a/frappe/desk/doctype/dashboard/test_dashboard.py b/frappe/desk/doctype/dashboard/test_dashboard.py index dd1bc31d86..15c132c027 100644 --- a/frappe/desk/doctype/dashboard/test_dashboard.py +++ b/frappe/desk/doctype/dashboard/test_dashboard.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE import unittest class TestDashboard(unittest.TestCase): diff --git a/frappe/desk/doctype/dashboard_chart/dashboard_chart.py b/frappe/desk/doctype/dashboard_chart/dashboard_chart.py index db5964e7b2..598b5e0b2b 100644 --- a/frappe/desk/doctype/dashboard_chart/dashboard_chart.py +++ b/frappe/desk/doctype/dashboard_chart/dashboard_chart.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe from frappe import _ diff --git a/frappe/desk/doctype/dashboard_chart/test_dashboard_chart.py b/frappe/desk/doctype/dashboard_chart/test_dashboard_chart.py index 9f10522b12..5562f2fc92 100644 --- a/frappe/desk/doctype/dashboard_chart/test_dashboard_chart.py +++ b/frappe/desk/doctype/dashboard_chart/test_dashboard_chart.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE import unittest, frappe from frappe.utils import getdate, formatdate, get_last_day from frappe.utils.dateutils import get_period_ending, get_period diff --git a/frappe/desk/doctype/dashboard_chart_field/dashboard_chart_field.py b/frappe/desk/doctype/dashboard_chart_field/dashboard_chart_field.py index 7d6f66daa2..8b2fba2e58 100644 --- a/frappe/desk/doctype/dashboard_chart_field/dashboard_chart_field.py +++ b/frappe/desk/doctype/dashboard_chart_field/dashboard_chart_field.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE # import frappe from frappe.model.document import Document diff --git a/frappe/desk/doctype/dashboard_chart_link/dashboard_chart_link.py b/frappe/desk/doctype/dashboard_chart_link/dashboard_chart_link.py index 359801a303..87d095d5d1 100644 --- a/frappe/desk/doctype/dashboard_chart_link/dashboard_chart_link.py +++ b/frappe/desk/doctype/dashboard_chart_link/dashboard_chart_link.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE # import frappe from frappe.model.document import Document diff --git a/frappe/desk/doctype/dashboard_chart_source/dashboard_chart_source.py b/frappe/desk/doctype/dashboard_chart_source/dashboard_chart_source.py index 791dbc563b..71ded32837 100644 --- a/frappe/desk/doctype/dashboard_chart_source/dashboard_chart_source.py +++ b/frappe/desk/doctype/dashboard_chart_source/dashboard_chart_source.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe, os from frappe import _ diff --git a/frappe/desk/doctype/dashboard_chart_source/test_dashboard_chart_source.py b/frappe/desk/doctype/dashboard_chart_source/test_dashboard_chart_source.py index 53fe127dfb..6d6773d52e 100644 --- a/frappe/desk/doctype/dashboard_chart_source/test_dashboard_chart_source.py +++ b/frappe/desk/doctype/dashboard_chart_source/test_dashboard_chart_source.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE import unittest class TestDashboardChartSource(unittest.TestCase): diff --git a/frappe/desk/doctype/dashboard_settings/dashboard_settings.py b/frappe/desk/doctype/dashboard_settings/dashboard_settings.py index df61c52114..2f29b3e989 100644 --- a/frappe/desk/doctype/dashboard_settings/dashboard_settings.py +++ b/frappe/desk/doctype/dashboard_settings/dashboard_settings.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE # import frappe from frappe.model.document import Document diff --git a/frappe/desk/doctype/desktop_icon/desktop_icon.py b/frappe/desk/doctype/desktop_icon/desktop_icon.py index 28c5a670cb..194b0d0ca4 100644 --- a/frappe/desk/doctype/desktop_icon/desktop_icon.py +++ b/frappe/desk/doctype/desktop_icon/desktop_icon.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe from frappe import _ diff --git a/frappe/desk/doctype/event/__init__.py b/frappe/desk/doctype/event/__init__.py index 0e57cb68c3..eb5ba62e5c 100644 --- a/frappe/desk/doctype/event/__init__.py +++ b/frappe/desk/doctype/event/__init__.py @@ -1,3 +1,3 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE diff --git a/frappe/desk/doctype/event/event.py b/frappe/desk/doctype/event/event.py index e7e7be530b..d4c185e56f 100644 --- a/frappe/desk/doctype/event/event.py +++ b/frappe/desk/doctype/event/event.py @@ -1,5 +1,5 @@ # Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import frappe diff --git a/frappe/desk/doctype/event/test_event.py b/frappe/desk/doctype/event/test_event.py index 8f56d11da3..6b7f6ee471 100644 --- a/frappe/desk/doctype/event/test_event.py +++ b/frappe/desk/doctype/event/test_event.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE """Use blog post test to test user permissions logic""" import frappe diff --git a/frappe/desk/doctype/event_participants/event_participants.py b/frappe/desk/doctype/event_participants/event_participants.py index ca4fae9930..b834ba3a82 100644 --- a/frappe/desk/doctype/event_participants/event_participants.py +++ b/frappe/desk/doctype/event_participants/event_participants.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2018, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE from frappe.model.document import Document class EventParticipants(Document): diff --git a/frappe/desk/doctype/form_tour/form_tour.py b/frappe/desk/doctype/form_tour/form_tour.py index dbc667ce28..82d47224dd 100644 --- a/frappe/desk/doctype/form_tour/form_tour.py +++ b/frappe/desk/doctype/form_tour/form_tour.py @@ -1,5 +1,5 @@ # Copyright (c) 2021, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe from frappe.model.document import Document @@ -25,7 +25,7 @@ class FormTour(Document): def on_update(self): if frappe.conf.developer_mode and self.is_standard: export_to_files([['Form Tour', self.name]], self.module) - + def before_export(self, doc): for d in doc.steps: d.field = "" diff --git a/frappe/desk/doctype/form_tour/test_form_tour.py b/frappe/desk/doctype/form_tour/test_form_tour.py index a4a796ce41..3670cbc218 100644 --- a/frappe/desk/doctype/form_tour/test_form_tour.py +++ b/frappe/desk/doctype/form_tour/test_form_tour.py @@ -1,5 +1,5 @@ # Copyright (c) 2021, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE # import frappe import unittest diff --git a/frappe/desk/doctype/form_tour_step/form_tour_step.py b/frappe/desk/doctype/form_tour_step/form_tour_step.py index 0df5665c63..bbc8edea08 100644 --- a/frappe/desk/doctype/form_tour_step/form_tour_step.py +++ b/frappe/desk/doctype/form_tour_step/form_tour_step.py @@ -1,5 +1,5 @@ # Copyright (c) 2021, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE # import frappe from frappe.model.document import Document diff --git a/frappe/desk/doctype/global_search_doctype/global_search_doctype.py b/frappe/desk/doctype/global_search_doctype/global_search_doctype.py index de8a48af01..30a31f959f 100644 --- a/frappe/desk/doctype/global_search_doctype/global_search_doctype.py +++ b/frappe/desk/doctype/global_search_doctype/global_search_doctype.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE # import frappe from frappe.model.document import Document diff --git a/frappe/desk/doctype/global_search_settings/global_search_settings.py b/frappe/desk/doctype/global_search_settings/global_search_settings.py index 9112349c1b..9ffe9aaf06 100644 --- a/frappe/desk/doctype/global_search_settings/global_search_settings.py +++ b/frappe/desk/doctype/global_search_settings/global_search_settings.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe from frappe.model.document import Document diff --git a/frappe/desk/doctype/kanban_board/kanban_board.py b/frappe/desk/doctype/kanban_board/kanban_board.py index 5100727f43..155a925fcf 100644 --- a/frappe/desk/doctype/kanban_board/kanban_board.py +++ b/frappe/desk/doctype/kanban_board/kanban_board.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe import json diff --git a/frappe/desk/doctype/kanban_board/test_kanban_board.py b/frappe/desk/doctype/kanban_board/test_kanban_board.py index f9503d736a..f00446141a 100644 --- a/frappe/desk/doctype/kanban_board/test_kanban_board.py +++ b/frappe/desk/doctype/kanban_board/test_kanban_board.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE import frappe import unittest diff --git a/frappe/desk/doctype/kanban_board_column/kanban_board_column.py b/frappe/desk/doctype/kanban_board_column/kanban_board_column.py index aebba3351c..d919fd6aed 100644 --- a/frappe/desk/doctype/kanban_board_column/kanban_board_column.py +++ b/frappe/desk/doctype/kanban_board_column/kanban_board_column.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe from frappe.model.document import Document diff --git a/frappe/desk/doctype/list_filter/list_filter.py b/frappe/desk/doctype/list_filter/list_filter.py index 2467ae40a4..d2b01d301e 100644 --- a/frappe/desk/doctype/list_filter/list_filter.py +++ b/frappe/desk/doctype/list_filter/list_filter.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2018, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe, json from frappe.model.document import Document diff --git a/frappe/desk/doctype/list_view_settings/list_view_settings.py b/frappe/desk/doctype/list_view_settings/list_view_settings.py index f4a288b7ba..78b56fe7d5 100644 --- a/frappe/desk/doctype/list_view_settings/list_view_settings.py +++ b/frappe/desk/doctype/list_view_settings/list_view_settings.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe from frappe.model.document import Document diff --git a/frappe/desk/doctype/list_view_settings/test_list_view_settings.py b/frappe/desk/doctype/list_view_settings/test_list_view_settings.py index 00010d7604..85872dd36e 100644 --- a/frappe/desk/doctype/list_view_settings/test_list_view_settings.py +++ b/frappe/desk/doctype/list_view_settings/test_list_view_settings.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE # import frappe import unittest diff --git a/frappe/desk/doctype/module_onboarding/module_onboarding.py b/frappe/desk/doctype/module_onboarding/module_onboarding.py index 6f01e0fd8d..aa268c792c 100644 --- a/frappe/desk/doctype/module_onboarding/module_onboarding.py +++ b/frappe/desk/doctype/module_onboarding/module_onboarding.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe from frappe.model.document import Document diff --git a/frappe/desk/doctype/module_onboarding/test_module_onboarding.py b/frappe/desk/doctype/module_onboarding/test_module_onboarding.py index 39184401a1..42f472abc1 100644 --- a/frappe/desk/doctype/module_onboarding/test_module_onboarding.py +++ b/frappe/desk/doctype/module_onboarding/test_module_onboarding.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE # import frappe import unittest diff --git a/frappe/desk/doctype/note/note.json b/frappe/desk/doctype/note/note.json index 8d476e83fe..69a9518ac4 100644 --- a/frappe/desk/doctype/note/note.json +++ b/frappe/desk/doctype/note/note.json @@ -1,322 +1,106 @@ { - "allow_copy": 0, - "allow_guest_to_view": 0, - "allow_import": 0, - "allow_rename": 1, - "beta": 0, - "creation": "2013-05-24 13:41:00", - "custom": 0, - "description": "", - "docstatus": 0, - "doctype": "DocType", - "document_type": "Document", - "editable_grid": 0, - "fields": [ - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "title", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 1, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Title", - "length": 0, - "no_copy": 1, - "permlevel": 0, - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 1, - "collapsible": 0, - "columns": 0, - "description": "", - "fieldname": "public", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Public", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 1, - "collapsible": 0, - "columns": 0, - "depends_on": "public", - "fieldname": "notify_on_login", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Notify users with a popup when they log in", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 1, - "collapsible": 0, - "columns": 0, - "default": "0", - "depends_on": "notify_on_login", - "description": "If enabled, users will be notified every time they login. If not enabled, users will only be notified once.", - "fieldname": "notify_on_every_login", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Notify Users On Every Login", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "eval:doc.notify_on_login && doc.public", - "fieldname": "expire_notification_on", - "fieldtype": "Date", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Expire Notification On", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 1, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 1, - "collapsible": 0, - "columns": 0, - "description": "Help: To link to another record in the system, use \"#Form/Note/[Note Name]\" as the Link URL. (don't use \"http://\")", - "fieldname": "content", - "fieldtype": "Text Editor", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 1, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Content", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 1, - "columns": 0, - "fieldname": "seen_by_section", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Seen By", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "seen_by", - "fieldtype": "Table", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Seen By Table", - "length": 0, - "no_copy": 0, - "options": "Note Seen By", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - } - ], - "has_web_view": 0, - "hide_heading": 0, - "hide_toolbar": 0, - "icon": "fa fa-file-text", - "idx": 1, - "image_view": 0, - "in_create": 0, - "is_submittable": 0, - "issingle": 0, - "istable": 0, - "max_attachments": 0, - "modified": "2018-09-21 15:15:44.909636", - "modified_by": "Administrator", - "module": "Desk", - "name": "Note", - "owner": "Administrator", - "permissions": [ - { - "amend": 0, - "cancel": 0, - "create": 1, - "delete": 1, - "email": 1, - "export": 0, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 0, - "role": "All", - "set_user_permissions": 0, - "share": 1, - "submit": 0, - "write": 1 - } - ], - "quick_entry": 1, - "read_only": 0, - "read_only_onload": 1, - "show_name_in_global_search": 0, - "sort_order": "ASC", - "track_changes": 1, - "track_seen": 0, - "track_views": 0 - } \ No newline at end of file + "actions": [], + "allow_rename": 1, + "creation": "2013-05-24 13:41:00", + "doctype": "DocType", + "document_type": "Document", + "engine": "InnoDB", + "field_order": [ + "title", + "public", + "notify_on_login", + "notify_on_every_login", + "expire_notification_on", + "content", + "seen_by_section", + "seen_by" + ], + "fields": [ + { + "fieldname": "title", + "fieldtype": "Data", + "in_global_search": 1, + "in_list_view": 1, + "label": "Title", + "no_copy": 1, + "print_hide": 1, + "reqd": 1 + }, + { + "bold": 1, + "default": "0", + "fieldname": "public", + "fieldtype": "Check", + "label": "Public", + "print_hide": 1 + }, + { + "bold": 1, + "default": "0", + "depends_on": "public", + "fieldname": "notify_on_login", + "fieldtype": "Check", + "label": "Notify users with a popup when they log in" + }, + { + "bold": 1, + "default": "0", + "depends_on": "notify_on_login", + "description": "If enabled, users will be notified every time they login. If not enabled, users will only be notified once.", + "fieldname": "notify_on_every_login", + "fieldtype": "Check", + "label": "Notify Users On Every Login" + }, + { + "depends_on": "eval:doc.notify_on_login && doc.public", + "fieldname": "expire_notification_on", + "fieldtype": "Date", + "label": "Expire Notification On", + "search_index": 1 + }, + { + "bold": 1, + "description": "Help: To link to another record in the system, use \"/app/note/[Note Name]\" as the Link URL. (don't use \"http://\")", + "fieldname": "content", + "fieldtype": "Text Editor", + "in_global_search": 1, + "label": "Content" + }, + { + "collapsible": 1, + "fieldname": "seen_by_section", + "fieldtype": "Section Break", + "label": "Seen By" + }, + { + "fieldname": "seen_by", + "fieldtype": "Table", + "label": "Seen By Table", + "options": "Note Seen By" + } + ], + "icon": "fa fa-file-text", + "idx": 1, + "links": [], + "modified": "2021-09-18 10:57:51.352643", + "modified_by": "Administrator", + "module": "Desk", + "name": "Note", + "owner": "Administrator", + "permissions": [ + { + "create": 1, + "delete": 1, + "email": 1, + "print": 1, + "read": 1, + "role": "All", + "share": 1, + "write": 1 + } + ], + "quick_entry": 1, + "sort_field": "modified", + "sort_order": "ASC", + "track_changes": 1 +} \ No newline at end of file diff --git a/frappe/desk/doctype/note/note.py b/frappe/desk/doctype/note/note.py index 790f9a514c..ae7af07cd9 100644 --- a/frappe/desk/doctype/note/note.py +++ b/frappe/desk/doctype/note/note.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# License: See license.txt +# License: MIT. See LICENSE import frappe from frappe.model.document import Document diff --git a/frappe/desk/doctype/note/test_note.py b/frappe/desk/doctype/note/test_note.py index 3207fa9b8d..ac2116c38a 100644 --- a/frappe/desk/doctype/note/test_note.py +++ b/frappe/desk/doctype/note/test_note.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors and Contributors -# See license.txt +# License: MIT. See LICENSE import frappe import unittest diff --git a/frappe/desk/doctype/note_seen_by/note_seen_by.py b/frappe/desk/doctype/note_seen_by/note_seen_by.py index cec4628b20..01bee05a9f 100644 --- a/frappe/desk/doctype/note_seen_by/note_seen_by.py +++ b/frappe/desk/doctype/note_seen_by/note_seen_by.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe from frappe.model.document import Document diff --git a/frappe/desk/doctype/notification_log/notification_log.py b/frappe/desk/doctype/notification_log/notification_log.py index d7d7f68b74..12e628ada2 100644 --- a/frappe/desk/doctype/notification_log/notification_log.py +++ b/frappe/desk/doctype/notification_log/notification_log.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe from frappe import _ diff --git a/frappe/desk/doctype/notification_log/test_notification_log.py b/frappe/desk/doctype/notification_log/test_notification_log.py index bedb10b495..4c415a860c 100644 --- a/frappe/desk/doctype/notification_log/test_notification_log.py +++ b/frappe/desk/doctype/notification_log/test_notification_log.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE import frappe from frappe.core.doctype.user.user import get_system_users from frappe.desk.form.assign_to import add as assign_task diff --git a/frappe/desk/doctype/notification_settings/notification_settings.py b/frappe/desk/doctype/notification_settings/notification_settings.py index eb3a16435f..cf6bb2d78d 100644 --- a/frappe/desk/doctype/notification_settings/notification_settings.py +++ b/frappe/desk/doctype/notification_settings/notification_settings.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe from frappe.model.document import Document diff --git a/frappe/desk/doctype/notification_subscribed_document/notification_subscribed_document.py b/frappe/desk/doctype/notification_subscribed_document/notification_subscribed_document.py index 6931e77754..1fdba22779 100644 --- a/frappe/desk/doctype/notification_subscribed_document/notification_subscribed_document.py +++ b/frappe/desk/doctype/notification_subscribed_document/notification_subscribed_document.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE # import frappe from frappe.model.document import Document diff --git a/frappe/desk/doctype/number_card/number_card.py b/frappe/desk/doctype/number_card/number_card.py index d8d5fe0953..5662523a9d 100644 --- a/frappe/desk/doctype/number_card/number_card.py +++ b/frappe/desk/doctype/number_card/number_card.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe from frappe.model.document import Document diff --git a/frappe/desk/doctype/number_card/test_number_card.py b/frappe/desk/doctype/number_card/test_number_card.py index c395f5f915..cc92e63341 100644 --- a/frappe/desk/doctype/number_card/test_number_card.py +++ b/frappe/desk/doctype/number_card/test_number_card.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE # import frappe import unittest diff --git a/frappe/desk/doctype/number_card_link/number_card_link.py b/frappe/desk/doctype/number_card_link/number_card_link.py index 6c16f45f4b..0b55ae6dcd 100644 --- a/frappe/desk/doctype/number_card_link/number_card_link.py +++ b/frappe/desk/doctype/number_card_link/number_card_link.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE # import frappe from frappe.model.document import Document diff --git a/frappe/desk/doctype/onboarding_permission/onboarding_permission.py b/frappe/desk/doctype/onboarding_permission/onboarding_permission.py index 40d3dc33b1..a0e87c3067 100644 --- a/frappe/desk/doctype/onboarding_permission/onboarding_permission.py +++ b/frappe/desk/doctype/onboarding_permission/onboarding_permission.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE # import frappe from frappe.model.document import Document diff --git a/frappe/desk/doctype/onboarding_permission/test_onboarding_permission.py b/frappe/desk/doctype/onboarding_permission/test_onboarding_permission.py index 80b166de0a..c13fb29678 100644 --- a/frappe/desk/doctype/onboarding_permission/test_onboarding_permission.py +++ b/frappe/desk/doctype/onboarding_permission/test_onboarding_permission.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE # import frappe import unittest diff --git a/frappe/desk/doctype/onboarding_step/onboarding_step.py b/frappe/desk/doctype/onboarding_step/onboarding_step.py index 2336ff52f8..45e0ca34fd 100644 --- a/frappe/desk/doctype/onboarding_step/onboarding_step.py +++ b/frappe/desk/doctype/onboarding_step/onboarding_step.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe from frappe import _ diff --git a/frappe/desk/doctype/onboarding_step/test_onboarding_step.py b/frappe/desk/doctype/onboarding_step/test_onboarding_step.py index 2425577478..b0651da4da 100644 --- a/frappe/desk/doctype/onboarding_step/test_onboarding_step.py +++ b/frappe/desk/doctype/onboarding_step/test_onboarding_step.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE # import frappe import unittest diff --git a/frappe/desk/doctype/onboarding_step_map/onboarding_step_map.py b/frappe/desk/doctype/onboarding_step_map/onboarding_step_map.py index c79244c4ad..7c20e220db 100644 --- a/frappe/desk/doctype/onboarding_step_map/onboarding_step_map.py +++ b/frappe/desk/doctype/onboarding_step_map/onboarding_step_map.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE # import frappe from frappe.model.document import Document diff --git a/frappe/desk/doctype/route_history/route_history.py b/frappe/desk/doctype/route_history/route_history.py index 95872440c7..01184fcc3a 100644 --- a/frappe/desk/doctype/route_history/route_history.py +++ b/frappe/desk/doctype/route_history/route_history.py @@ -1,5 +1,5 @@ # Copyright (c) 2021, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe from frappe.model.document import Document diff --git a/frappe/desk/doctype/system_console/system_console.js b/frappe/desk/doctype/system_console/system_console.js index 48dd2ba108..0fe3932671 100644 --- a/frappe/desk/doctype/system_console/system_console.js +++ b/frappe/desk/doctype/system_console/system_console.js @@ -10,15 +10,95 @@ frappe.ui.form.on('System Console', { description: __('Execute Console script'), ignore_inputs: true, }); + frm.set_value("type", "Python"); }, refresh: function(frm) { frm.disable_save(); frm.page.set_primary_action(__("Execute"), $btn => { - $btn.text(__('Executing...')); - return frm.execute_action("Execute").then(() => { - $btn.text(__('Execute')); - }); + $btn.text(__("Executing...")); + return frm + .execute_action("Execute") + .then(() => frm.trigger("render_sql_output")) + .finally(() => $btn.text(__("Execute"))); + }); + }, + + type: function(frm) { + if (frm.doc.type == "Python") { + frm.set_value("output", ""); + if (frm.sql_output) { + frm.sql_output.destroy(); + frm.get_field("sql_output").html(""); + } + } + }, + + render_sql_output: function(frm) { + if (frm.doc.type !== "SQL") return; + if (frm.sql_output) { + frm.sql_output.destroy(); + frm.get_field("sql_output").html(""); + } + + if (frm.doc.output.startsWith("Traceback")) { + return; + } + + let result = JSON.parse(frm.doc.output); + frm.set_value("output", `${result.length} ${result.length == 1 ? 'row' : 'rows'}`); + + if (result.length) { + let columns = Object.keys(result[0]); + frm.sql_output = new DataTable( + frm.get_field("sql_output").$wrapper.get(0), + { + columns, + data: result + } + ); + } + }, + + show_processlist: function(frm) { + if (frm.doc.show_processlist) { + // keep refreshing every 5 seconds + frm.events.refresh_processlist(frm); + frm.processlist_interval = setInterval(() => frm.events.refresh_processlist(frm), 5000); + } else { + if (frm.processlist_interval) { + + // end it + clearInterval(frm.processlist_interval); + frm.get_field("processlist").html(''); + } + } + }, + + refresh_processlist: function(frm) { + let timestamp = new Date(); + frappe.call('frappe.desk.doctype.system_console.system_console.show_processlist').then(r => { + let rows = ''; + for (let row of r.message) { + rows += ` + ${row.Id} + ${row.Time} + ${row.State} + ${row.Info} + ${row.Progress} + ` + } + frm.get_field('processlist').html(` +

Requested on: ${timestamp}

+ + + + ${rows}`); }); } }); diff --git a/frappe/desk/doctype/system_console/system_console.json b/frappe/desk/doctype/system_console/system_console.json index 14e36e6fd3..657e9df89d 100644 --- a/frappe/desk/doctype/system_console/system_console.json +++ b/frappe/desk/doctype/system_console/system_console.json @@ -17,9 +17,15 @@ "editable_grid": 1, "engine": "InnoDB", "field_order": [ + "execute_section", + "type", "console", "commit", - "output" + "output", + "sql_output", + "database_processes_section", + "show_processlist", + "processlist" ], "fields": [ { @@ -40,13 +46,47 @@ "fieldname": "commit", "fieldtype": "Check", "label": "Commit" + }, + { + "fieldname": "execute_section", + "fieldtype": "Section Break", + "label": "Execute" + }, + { + "fieldname": "database_processes_section", + "fieldtype": "Section Break", + "label": "Database Processes" + }, + { + "default": "0", + "fieldname": "show_processlist", + "fieldtype": "Check", + "label": "Show Processlist" + }, + { + "fieldname": "processlist", + "fieldtype": "HTML", + "label": "processlist" + }, + { + "default": "Python", + "fieldname": "type", + "fieldtype": "Select", + "label": "Type", + "options": "Python\nSQL" + }, + { + "depends_on": "eval:doc.type == 'SQL'", + "fieldname": "sql_output", + "fieldtype": "HTML", + "label": "SQL Output" } ], "hide_toolbar": 1, "index_web_pages_for_search": 1, "issingle": 1, "links": [], - "modified": "2020-08-21 14:44:35.296877", + "modified": "2021-09-15 17:17:44.844767", "modified_by": "Administrator", "module": "Desk", "name": "System Console", @@ -65,4 +105,4 @@ "sort_field": "modified", "sort_order": "DESC", "track_changes": 1 -} +} \ No newline at end of file diff --git a/frappe/desk/doctype/system_console/system_console.py b/frappe/desk/doctype/system_console/system_console.py index e2b5656bc0..107ab2f932 100644 --- a/frappe/desk/doctype/system_console/system_console.py +++ b/frappe/desk/doctype/system_console/system_console.py @@ -1,11 +1,11 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import json import frappe -from frappe.utils.safe_exec import safe_exec +from frappe.utils.safe_exec import safe_exec, read_sql from frappe.model.document import Document class SystemConsole(Document): @@ -13,8 +13,11 @@ class SystemConsole(Document): frappe.only_for('System Manager') try: frappe.debug_log = [] - safe_exec(self.console) - self.output = '\n'.join(frappe.debug_log) + if self.type == 'Python': + safe_exec(self.console) + self.output = '\n'.join(frappe.debug_log) + elif self.type == 'SQL': + self.output = frappe.as_json(read_sql(self.console, as_dict=1)) except: # noqa: E722 self.output = frappe.get_traceback() @@ -33,4 +36,9 @@ class SystemConsole(Document): def execute_code(doc): console = frappe.get_doc(json.loads(doc)) console.run() - return console.as_dict() \ No newline at end of file + return console.as_dict() + +@frappe.whitelist() +def show_processlist(): + frappe.only_for('System Manager') + return frappe.db.sql('show full processlist', as_dict=1) diff --git a/frappe/desk/doctype/system_console/test_system_console.py b/frappe/desk/doctype/system_console/test_system_console.py index 743c2d6dde..fa7c577faa 100644 --- a/frappe/desk/doctype/system_console/test_system_console.py +++ b/frappe/desk/doctype/system_console/test_system_console.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE import frappe import unittest diff --git a/frappe/desk/doctype/tag/tag.py b/frappe/desk/doctype/tag/tag.py index 2341d721e2..aff1bd6973 100644 --- a/frappe/desk/doctype/tag/tag.py +++ b/frappe/desk/doctype/tag/tag.py @@ -1,5 +1,5 @@ # Copyright (c) 2019, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe from frappe.model.document import Document @@ -128,46 +128,35 @@ def delete_tags_for_document(doc): }) def update_tags(doc, tags): - """ - Adds tags for documents - :param doc: Document to be added to global tags - """ + """Adds tags for documents + :param doc: Document to be added to global tags + """ new_tags = {tag.strip() for tag in tags.split(",") if tag} - - for tag in new_tags: - if not frappe.db.exists("Tag Link", {"parenttype": doc.doctype, "parent": doc.name, "tag": tag}): - frappe.get_doc({ - "doctype": "Tag Link", - "document_type": doc.doctype, - "document_name": doc.name, - "parenttype": doc.doctype, - "parent": doc.name, - "title": doc.get_title() or '', - "tag": tag - }).insert(ignore_permissions=True) - existing_tags = [tag.tag for tag in frappe.get_list("Tag Link", filters={ "document_type": doc.doctype, "document_name": doc.name }, fields=["tag"])] - deleted_tags = get_deleted_tags(new_tags, existing_tags) - - if deleted_tags: - for tag in deleted_tags: - delete_tag_for_document(doc.doctype, doc.name, tag) - -def get_deleted_tags(new_tags, existing_tags): - - return list(set(existing_tags) - set(new_tags)) - -def delete_tag_for_document(dt, dn, tag): - frappe.db.delete("Tag Link", { - "document_type": dt, - "document_name": dn, - "tag": tag - }) + added_tags = set(new_tags) - set(existing_tags) + for tag in added_tags: + frappe.get_doc({ + "doctype": "Tag Link", + "document_type": doc.doctype, + "document_name": doc.name, + "parenttype": doc.doctype, + "parent": doc.name, + "title": doc.get_title() or '', + "tag": tag + }).insert(ignore_permissions=True) + + deleted_tags = list(set(existing_tags) - set(new_tags)) + for tag in deleted_tags: + frappe.db.delete("Tag Link", { + "document_type": doc.doctype, + "document_name": doc.name, + "tag": tag + }) @frappe.whitelist() def get_documents_for_tag(tag): diff --git a/frappe/desk/doctype/tag_link/tag_link.json b/frappe/desk/doctype/tag_link/tag_link.json index 00a7349c5c..9142279fa3 100644 --- a/frappe/desk/doctype/tag_link/tag_link.json +++ b/frappe/desk/doctype/tag_link/tag_link.json @@ -1,4 +1,5 @@ { + "actions": [], "creation": "2019-09-24 13:25:36.435685", "doctype": "DocType", "editable_grid": 1, @@ -44,7 +45,8 @@ "read_only": 1 } ], - "modified": "2019-10-03 16:42:35.932409", + "links": [], + "modified": "2021-09-20 16:53:37.217998", "modified_by": "Administrator", "module": "Desk", "name": "Tag Link", @@ -61,6 +63,17 @@ "role": "System Manager", "share": 1, "write": 1 + }, + { + "create": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "All", + "share": 1, + "write": 1 } ], "read_only": 1, diff --git a/frappe/desk/doctype/tag_link/tag_link.py b/frappe/desk/doctype/tag_link/tag_link.py index 4c5149f42c..d07894989d 100644 --- a/frappe/desk/doctype/tag_link/tag_link.py +++ b/frappe/desk/doctype/tag_link/tag_link.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE # import frappe from frappe.model.document import Document diff --git a/frappe/desk/doctype/tag_link/test_tag_link.py b/frappe/desk/doctype/tag_link/test_tag_link.py index 297ee3cc96..fa6a22903f 100644 --- a/frappe/desk/doctype/tag_link/test_tag_link.py +++ b/frappe/desk/doctype/tag_link/test_tag_link.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE # import frappe import unittest diff --git a/frappe/desk/doctype/todo/__init__.py b/frappe/desk/doctype/todo/__init__.py index 0e57cb68c3..eb5ba62e5c 100644 --- a/frappe/desk/doctype/todo/__init__.py +++ b/frappe/desk/doctype/todo/__init__.py @@ -1,3 +1,3 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE diff --git a/frappe/desk/doctype/todo/test_todo.py b/frappe/desk/doctype/todo/test_todo.py index f6371c5921..34d3cee191 100644 --- a/frappe/desk/doctype/todo/test_todo.py +++ b/frappe/desk/doctype/todo/test_todo.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# See license.txt +# License: MIT. See LICENSE import frappe import unittest from frappe.model.db_query import DatabaseQuery diff --git a/frappe/desk/doctype/todo/todo.py b/frappe/desk/doctype/todo/todo.py index 754b94cdcb..6f3f4160e6 100644 --- a/frappe/desk/doctype/todo/todo.py +++ b/frappe/desk/doctype/todo/todo.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import frappe import json diff --git a/frappe/desk/doctype/workspace/test_workspace.py b/frappe/desk/doctype/workspace/test_workspace.py index f13a136c20..6c16e69afe 100644 --- a/frappe/desk/doctype/workspace/test_workspace.py +++ b/frappe/desk/doctype/workspace/test_workspace.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE import frappe import unittest class TestWorkspace(unittest.TestCase): diff --git a/frappe/desk/doctype/workspace/workspace.json b/frappe/desk/doctype/workspace/workspace.json index 1e111b8d12..756a40da4b 100644 --- a/frappe/desk/doctype/workspace/workspace.json +++ b/frappe/desk/doctype/workspace/workspace.json @@ -165,8 +165,6 @@ "default": "0", "fieldname": "is_standard", "fieldtype": "Check", - "in_list_view": 1, - "in_standard_filter": 1, "label": "Is Standard", "search_index": 1 }, @@ -181,7 +179,6 @@ "depends_on": "eval:doc.extends_another_page == 1 || doc.for_user", "fieldname": "extends", "fieldtype": "Link", - "in_standard_filter": 1, "label": "Extends", "options": "Workspace", "search_index": 1 @@ -228,6 +225,8 @@ "default": "0", "fieldname": "public", "fieldtype": "Check", + "in_list_view": 1, + "in_standard_filter": 1, "label": "Public" }, { @@ -265,11 +264,13 @@ "label": "Roles" } ], + "in_create": 1, "links": [], - "modified": "2021-08-30 18:47:18.227154", + "modified": "2021-09-16 12:01:06.450621", "modified_by": "Administrator", "module": "Desk", "name": "Workspace", + "naming_rule": "By fieldname", "owner": "Administrator", "permissions": [ { diff --git a/frappe/desk/doctype/workspace/workspace.py b/frappe/desk/doctype/workspace/workspace.py index 33c6adbd2f..a0a22a43fc 100644 --- a/frappe/desk/doctype/workspace/workspace.py +++ b/frappe/desk/doctype/workspace/workspace.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe from frappe import _ @@ -62,7 +62,7 @@ class Workspace(Document): for link in self.links: link = link.as_dict() if link.type == "Card Break": - if card_links and (not current_card.get('only_for') or current_card.get('only_for') == frappe.get_system_settings('country')): + if card_links and (not current_card.get('only_for') or current_card.get('only_for') == frappe.get_system_settings('country')): current_card['links'] = card_links cards.append(current_card) @@ -167,7 +167,7 @@ def get_report_type(report): def save_page(title, icon, parent, public, sb_public_items, sb_private_items, deleted_pages, new_widgets, blocks, save): save = frappe.parse_json(save) public = frappe.parse_json(public) - if save: + if save: doc = frappe.new_doc('Workspace') doc.title = title doc.icon = icon @@ -208,17 +208,17 @@ def save_page(title, icon, parent, public, sb_public_items, sb_private_items, de if loads(deleted_pages): return delete_pages(loads(deleted_pages)) - return {"name": title, "public": public} + return {"name": title, "public": public, "label": doc.label} def delete_pages(deleted_pages): for page in deleted_pages: if page.get("public") and "Workspace Manager" not in frappe.get_roles(): - return {"name": page.get("title"), "public": 1} + return {"name": page.get("title"), "public": 1, "label": page.get("label")} if frappe.db.exists("Workspace", page.get("name")): frappe.get_doc("Workspace", page.get("name")).delete(ignore_permissions=True) - return {"name": "Home", "public": 1} + return {"name": "Home", "public": 1, "label": "Home"} def sort_pages(sb_public_items, sb_private_items): wspace_public_pages = get_page_list(['name', 'title'], {'public': 1}) diff --git a/frappe/desk/doctype/workspace_chart/workspace_chart.py b/frappe/desk/doctype/workspace_chart/workspace_chart.py index 6ec7abfd3c..a3b66d99ab 100644 --- a/frappe/desk/doctype/workspace_chart/workspace_chart.py +++ b/frappe/desk/doctype/workspace_chart/workspace_chart.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2021, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE # import frappe from frappe.model.document import Document diff --git a/frappe/desk/doctype/workspace_link/workspace_link.py b/frappe/desk/doctype/workspace_link/workspace_link.py index d6ccc5306a..72256ba490 100644 --- a/frappe/desk/doctype/workspace_link/workspace_link.py +++ b/frappe/desk/doctype/workspace_link/workspace_link.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2021, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE # import frappe from frappe.model.document import Document diff --git a/frappe/desk/doctype/workspace_shortcut/workspace_shortcut.py b/frappe/desk/doctype/workspace_shortcut/workspace_shortcut.py index 83b446e454..1dad4cca05 100644 --- a/frappe/desk/doctype/workspace_shortcut/workspace_shortcut.py +++ b/frappe/desk/doctype/workspace_shortcut/workspace_shortcut.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2021, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE # import frappe from frappe.model.document import Document diff --git a/frappe/desk/form/__init__.py b/frappe/desk/form/__init__.py index 0e57cb68c3..eb5ba62e5c 100644 --- a/frappe/desk/form/__init__.py +++ b/frappe/desk/form/__init__.py @@ -1,3 +1,3 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE diff --git a/frappe/desk/form/assign_to.py b/frappe/desk/form/assign_to.py index 3eda291d1e..bf77170eeb 100644 --- a/frappe/desk/form/assign_to.py +++ b/frappe/desk/form/assign_to.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE """assign/unassign to ToDo""" diff --git a/frappe/desk/form/document_follow.py b/frappe/desk/form/document_follow.py index 7f65f76a58..14970092d0 100644 --- a/frappe/desk/form/document_follow.py +++ b/frappe/desk/form/document_follow.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import frappe import frappe.utils diff --git a/frappe/desk/form/linked_with.py b/frappe/desk/form/linked_with.py index ae48b7fc6b..3aff3877d6 100644 --- a/frappe/desk/form/linked_with.py +++ b/frappe/desk/form/linked_with.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import json from collections import defaultdict diff --git a/frappe/desk/form/load.py b/frappe/desk/form/load.py index a62bfd01d0..d276a9707f 100644 --- a/frappe/desk/form/load.py +++ b/frappe/desk/form/load.py @@ -1,6 +1,7 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE +from typing import Dict, List, Union import frappe, json import frappe.utils import frappe.share @@ -105,9 +106,10 @@ def get_docinfo(doc=None, doctype=None, name=None): "assignment_logs": get_comments(doc.doctype, doc.name, 'assignment'), "permissions": get_doc_permissions(doc), "shared": frappe.share.get_users(doc.doctype, doc.name), - "info_logs": get_comments(doc.doctype, doc.name, 'Info'), + "info_logs": get_comments(doc.doctype, doc.name, comment_type=['Info', 'Edit', 'Label']), "share_logs": get_comments(doc.doctype, doc.name, 'share'), "like_logs": get_comments(doc.doctype, doc.name, 'Like'), + "workflow_logs": get_comments(doc.doctype, doc.name, comment_type="Workflow"), "views": get_view_logs(doc.doctype, doc.name), "energy_point_logs": get_point_logs(doc.doctype, doc.name), "additional_timeline_content": get_additional_timeline_content(doc.doctype, doc.name), @@ -138,10 +140,11 @@ def get_communications(doctype, name, start=0, limit=20): return _get_communications(doctype, name, start, limit) -def get_comments(doctype, name, comment_type='Comment'): - comment_types = [comment_type] +def get_comments(doctype: str, name: str, comment_type : Union[str, List[str]] = "Comment") -> List[frappe._dict]: + if isinstance(comment_type, list): + comment_types = comment_type - if comment_type == 'share': + elif comment_type == 'share': comment_types = ['Shared', 'Unshared'] elif comment_type == 'assignment': @@ -150,15 +153,21 @@ def get_comments(doctype, name, comment_type='Comment'): elif comment_type == 'attachment': comment_types = ['Attachment', 'Attachment Removed'] - comments = frappe.get_all('Comment', fields = ['name', 'creation', 'content', 'owner', 'comment_type'], filters=dict( - reference_doctype = doctype, - reference_name = name, - comment_type = ['in', comment_types] - )) + else: + comment_types = [comment_type] + + comments = frappe.get_all("Comment", + fields=["name", "creation", "content", "owner", "comment_type"], + filters={ + "reference_doctype": doctype, + "reference_name": name, + "comment_type": ['in', comment_types], + } + ) # convert to markdown (legacy ?) - if comment_type == 'Comment': - for c in comments: + for c in comments: + if c.comment_type == "Comment": c.content = frappe.utils.markdown(c.content) return comments diff --git a/frappe/desk/form/meta.py b/frappe/desk/form/meta.py index cf3606e785..b91dd3d481 100644 --- a/frappe/desk/form/meta.py +++ b/frappe/desk/form/meta.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import io import os diff --git a/frappe/desk/form/save.py b/frappe/desk/form/save.py index a7a4b829d8..b580e2c769 100644 --- a/frappe/desk/form/save.py +++ b/frappe/desk/form/save.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import frappe, json from frappe.desk.form.load import run_onload diff --git a/frappe/desk/form/test_form.py b/frappe/desk/form/test_form.py index f3c4132777..86c3aba29a 100644 --- a/frappe/desk/form/test_form.py +++ b/frappe/desk/form/test_form.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import frappe, unittest diff --git a/frappe/desk/form/utils.py b/frappe/desk/form/utils.py index d7ac940d21..a4dcee4ab3 100644 --- a/frappe/desk/form/utils.py +++ b/frappe/desk/form/utils.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import frappe, json import frappe.desk.form.meta diff --git a/frappe/desk/gantt.py b/frappe/desk/gantt.py index 7f0889c751..58ef3b836e 100644 --- a/frappe/desk/gantt.py +++ b/frappe/desk/gantt.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import frappe, json diff --git a/frappe/desk/like.py b/frappe/desk/like.py index d44d58a761..4480ed8a1e 100644 --- a/frappe/desk/like.py +++ b/frappe/desk/like.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE """Allow adding of likes to documents""" diff --git a/frappe/desk/listview.py b/frappe/desk/listview.py index d2c84d36bf..f079205cb0 100644 --- a/frappe/desk/listview.py +++ b/frappe/desk/listview.py @@ -1,5 +1,5 @@ # Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import frappe @frappe.whitelist(allow_guest=True) diff --git a/frappe/desk/moduleview.py b/frappe/desk/moduleview.py index 021698ac92..e2e2c4c155 100644 --- a/frappe/desk/moduleview.py +++ b/frappe/desk/moduleview.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import frappe import json diff --git a/frappe/desk/notifications.py b/frappe/desk/notifications.py index c84027928e..2a4567ab4f 100644 --- a/frappe/desk/notifications.py +++ b/frappe/desk/notifications.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import frappe from frappe.desk.doctype.notification_settings.notification_settings import get_subscribed_documents diff --git a/frappe/desk/page/activity/activity.py b/frappe/desk/page/activity/activity.py index 3abc8e0ea5..71130f2304 100644 --- a/frappe/desk/page/activity/activity.py +++ b/frappe/desk/page/activity/activity.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# License: See license.txt +# License: MIT. See LICENSE import frappe from frappe.utils import cint diff --git a/frappe/desk/page/leaderboard/leaderboard.py b/frappe/desk/page/leaderboard/leaderboard.py index 9469096f50..ad22eb9199 100644 --- a/frappe/desk/page/leaderboard/leaderboard.py +++ b/frappe/desk/page/leaderboard/leaderboard.py @@ -1,5 +1,5 @@ # Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import frappe @frappe.whitelist() diff --git a/frappe/desk/page/setup_wizard/install_fixtures.py b/frappe/desk/page/setup_wizard/install_fixtures.py index 06301cdeaf..1ef83f7ba0 100644 --- a/frappe/desk/page/setup_wizard/install_fixtures.py +++ b/frappe/desk/page/setup_wizard/install_fixtures.py @@ -1,5 +1,5 @@ -# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt +# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors +# License: MIT. See LICENSE import frappe from frappe import _ diff --git a/frappe/desk/page/setup_wizard/setup_wizard.py b/frappe/desk/page/setup_wizard/setup_wizard.py index 5edb44e182..c729c1d78b 100755 --- a/frappe/desk/page/setup_wizard/setup_wizard.py +++ b/frappe/desk/page/setup_wizard/setup_wizard.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# License: See license.txt +# License: MIT. See LICENSE import frappe, json, os from frappe.utils import strip, cint diff --git a/frappe/desk/query_report.py b/frappe/desk/query_report.py index 610eaf466a..9a37d16d0a 100644 --- a/frappe/desk/query_report.py +++ b/frappe/desk/query_report.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import frappe import os diff --git a/frappe/desk/report/todo/todo.py b/frappe/desk/report/todo/todo.py index 6bd22b843e..b1e49bc95d 100644 --- a/frappe/desk/report/todo/todo.py +++ b/frappe/desk/report/todo/todo.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import frappe from frappe import _ diff --git a/frappe/desk/report_dump.py b/frappe/desk/report_dump.py index b2d3ca3443..f57ed97fa5 100644 --- a/frappe/desk/report_dump.py +++ b/frappe/desk/report_dump.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import frappe diff --git a/frappe/desk/reportview.py b/frappe/desk/reportview.py index 1dbc52eb5b..d758ebb590 100644 --- a/frappe/desk/reportview.py +++ b/frappe/desk/reportview.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE """build query for doclistview and return results""" diff --git a/frappe/desk/search.py b/frappe/desk/search.py index 9a5e7533d1..db88e6ec52 100644 --- a/frappe/desk/search.py +++ b/frappe/desk/search.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE # Search import frappe, json diff --git a/frappe/desk/treeview.py b/frappe/desk/treeview.py index 66acde4cb2..f40c135653 100644 --- a/frappe/desk/treeview.py +++ b/frappe/desk/treeview.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import frappe from frappe import _ @@ -69,13 +69,11 @@ def make_tree_args(**kwarg): doctype = kwarg['doctype'] parent_field = 'parent_' + doctype.lower().replace(' ', '_') - name_field = kwarg.get('name_field', doctype.lower().replace(' ', '_') + '_name') if kwarg['is_root'] == 'false': kwarg['is_root'] = False if kwarg['is_root'] == 'true': kwarg['is_root'] = True kwarg.update({ - name_field: kwarg[name_field], parent_field: kwarg.get("parent") or kwarg.get(parent_field) }) diff --git a/frappe/desk/utils.py b/frappe/desk/utils.py index 01b47ac106..5908277386 100644 --- a/frappe/desk/utils.py +++ b/frappe/desk/utils.py @@ -1,5 +1,5 @@ # Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import frappe diff --git a/frappe/email/__init__.py b/frappe/email/__init__.py index 3fb539398a..79dec977b7 100644 --- a/frappe/email/__init__.py +++ b/frappe/email/__init__.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import frappe from frappe.desk.reportview import build_match_conditions diff --git a/frappe/email/doctype/auto_email_report/auto_email_report.py b/frappe/email/doctype/auto_email_report/auto_email_report.py index ccfff594b7..37089d58df 100644 --- a/frappe/email/doctype/auto_email_report/auto_email_report.py +++ b/frappe/email/doctype/auto_email_report/auto_email_report.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import calendar from datetime import timedelta diff --git a/frappe/email/doctype/auto_email_report/test_auto_email_report.py b/frappe/email/doctype/auto_email_report/test_auto_email_report.py index 211a141ec0..559adfbe1a 100644 --- a/frappe/email/doctype/auto_email_report/test_auto_email_report.py +++ b/frappe/email/doctype/auto_email_report/test_auto_email_report.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE import json import unittest diff --git a/frappe/email/doctype/document_follow/document_follow.py b/frappe/email/doctype/document_follow/document_follow.py index a04f8ef4c2..97f8237736 100644 --- a/frappe/email/doctype/document_follow/document_follow.py +++ b/frappe/email/doctype/document_follow/document_follow.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE from frappe.model.document import Document diff --git a/frappe/email/doctype/document_follow/test_document_follow.py b/frappe/email/doctype/document_follow/test_document_follow.py index 456c0931f8..050add65e9 100644 --- a/frappe/email/doctype/document_follow/test_document_follow.py +++ b/frappe/email/doctype/document_follow/test_document_follow.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE import frappe import unittest import frappe.desk.form.document_follow as document_follow diff --git a/frappe/email/doctype/email_account/email_account.json b/frappe/email/doctype/email_account/email_account.json index 8cfd75d839..e20f38c74a 100644 --- a/frappe/email/doctype/email_account/email_account.json +++ b/frappe/email/doctype/email_account/email_account.json @@ -226,7 +226,7 @@ }, { "default": "UNSEEN", - "depends_on": "eval: doc.enable_incoming", + "depends_on": "eval: doc.enable_incoming && doc.use_imap", "fieldname": "email_sync_option", "fieldtype": "Select", "hide_days": 1, @@ -236,7 +236,7 @@ }, { "default": "250", - "depends_on": "eval: doc.enable_incoming", + "depends_on": "eval: doc.enable_incoming && doc.use_imap", "description": "Total number of emails to sync in initial sync process ", "fieldname": "initial_sync_count", "fieldtype": "Select", @@ -567,7 +567,7 @@ "icon": "fa fa-inbox", "index_web_pages_for_search": 1, "links": [], - "modified": "2021-08-31 15:23:25.714366", + "modified": "2021-09-21 16:44:25.728637", "modified_by": "Administrator", "module": "Email", "name": "Email Account", @@ -589,4 +589,4 @@ "sort_field": "modified", "sort_order": "DESC", "track_changes": 1 -} \ No newline at end of file +} diff --git a/frappe/email/doctype/email_account/email_account.py b/frappe/email/doctype/email_account/email_account.py index fb7349adba..d90c56d90d 100755 --- a/frappe/email/doctype/email_account/email_account.py +++ b/frappe/email/doctype/email_account/email_account.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import email.utils import functools import imaplib diff --git a/frappe/email/doctype/email_account/test_email_account.py b/frappe/email/doctype/email_account/test_email_account.py index da03a5959e..21dc4b84c4 100644 --- a/frappe/email/doctype/email_account/test_email_account.py +++ b/frappe/email/doctype/email_account/test_email_account.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# See license.txt +# License: MIT. See LICENSE import os import email diff --git a/frappe/email/doctype/email_domain/email_domain.py b/frappe/email/doctype/email_domain/email_domain.py index 0856549eb7..1611d32351 100644 --- a/frappe/email/doctype/email_domain/email_domain.py +++ b/frappe/email/doctype/email_domain/email_domain.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe from frappe import _ diff --git a/frappe/email/doctype/email_domain/test_email_domain.py b/frappe/email/doctype/email_domain/test_email_domain.py index 8607151ca8..1064c7684a 100644 --- a/frappe/email/doctype/email_domain/test_email_domain.py +++ b/frappe/email/doctype/email_domain/test_email_domain.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# See license.txt +# License: MIT. See LICENSE import frappe import unittest from frappe.test_runner import make_test_objects diff --git a/frappe/email/doctype/email_flag_queue/email_flag_queue.py b/frappe/email/doctype/email_flag_queue/email_flag_queue.py index 9bb30f08b2..886cf3c24b 100644 --- a/frappe/email/doctype/email_flag_queue/email_flag_queue.py +++ b/frappe/email/doctype/email_flag_queue/email_flag_queue.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe from frappe.model.document import Document diff --git a/frappe/email/doctype/email_flag_queue/test_email_flag_queue.py b/frappe/email/doctype/email_flag_queue/test_email_flag_queue.py index d09b823ce6..b0e17b3b85 100644 --- a/frappe/email/doctype/email_flag_queue/test_email_flag_queue.py +++ b/frappe/email/doctype/email_flag_queue/test_email_flag_queue.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE import frappe import unittest diff --git a/frappe/email/doctype/email_group/email_group.py b/frappe/email/doctype/email_group/email_group.py index 2679353edf..ad52d9a9ec 100755 --- a/frappe/email/doctype/email_group/email_group.py +++ b/frappe/email/doctype/email_group/email_group.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe from frappe import _ diff --git a/frappe/email/doctype/email_group/test_email_group.py b/frappe/email/doctype/email_group/test_email_group.py index 3e894118df..06341c128e 100644 --- a/frappe/email/doctype/email_group/test_email_group.py +++ b/frappe/email/doctype/email_group/test_email_group.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE import frappe import unittest diff --git a/frappe/email/doctype/email_group_member/email_group_member.py b/frappe/email/doctype/email_group_member/email_group_member.py index 1f9303b83e..a9fd26f710 100644 --- a/frappe/email/doctype/email_group_member/email_group_member.py +++ b/frappe/email/doctype/email_group_member/email_group_member.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe from frappe.model.document import Document diff --git a/frappe/email/doctype/email_group_member/test_email_group_member.py b/frappe/email/doctype/email_group_member/test_email_group_member.py index 829d686400..de006dccb9 100644 --- a/frappe/email/doctype/email_group_member/test_email_group_member.py +++ b/frappe/email/doctype/email_group_member/test_email_group_member.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE import frappe import unittest diff --git a/frappe/email/doctype/email_queue/email_queue.py b/frappe/email/doctype/email_queue/email_queue.py index e1e332f978..4489a68cac 100644 --- a/frappe/email/doctype/email_queue/email_queue.py +++ b/frappe/email/doctype/email_queue/email_queue.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import traceback import json diff --git a/frappe/email/doctype/email_queue/test_email_queue.py b/frappe/email/doctype/email_queue/test_email_queue.py index b76d6347b9..8ebcb68a38 100644 --- a/frappe/email/doctype/email_queue/test_email_queue.py +++ b/frappe/email/doctype/email_queue/test_email_queue.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE import frappe import unittest diff --git a/frappe/email/doctype/email_queue_recipient/email_queue_recipient.py b/frappe/email/doctype/email_queue_recipient/email_queue_recipient.py index 055bdb3fc1..95b8593c4c 100644 --- a/frappe/email/doctype/email_queue_recipient/email_queue_recipient.py +++ b/frappe/email/doctype/email_queue_recipient/email_queue_recipient.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe from frappe.model.document import Document diff --git a/frappe/email/doctype/email_rule/email_rule.py b/frappe/email/doctype/email_rule/email_rule.py index 9807724ef1..b2a4be5421 100644 --- a/frappe/email/doctype/email_rule/email_rule.py +++ b/frappe/email/doctype/email_rule/email_rule.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe from frappe.model.document import Document diff --git a/frappe/email/doctype/email_rule/test_email_rule.py b/frappe/email/doctype/email_rule/test_email_rule.py index b2213f7405..eef5448e57 100644 --- a/frappe/email/doctype/email_rule/test_email_rule.py +++ b/frappe/email/doctype/email_rule/test_email_rule.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE import frappe import unittest diff --git a/frappe/email/doctype/email_template/email_template.py b/frappe/email/doctype/email_template/email_template.py index 4711451fd2..c51c46d72d 100644 --- a/frappe/email/doctype/email_template/email_template.py +++ b/frappe/email/doctype/email_template/email_template.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe, json from frappe.model.document import Document diff --git a/frappe/email/doctype/email_template/test_email_template.py b/frappe/email/doctype/email_template/test_email_template.py index 5a9ee969c6..a92ee9f9c3 100644 --- a/frappe/email/doctype/email_template/test_email_template.py +++ b/frappe/email/doctype/email_template/test_email_template.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2018, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE import unittest class TestEmailTemplate(unittest.TestCase): diff --git a/frappe/email/doctype/email_unsubscribe/email_unsubscribe.py b/frappe/email/doctype/email_unsubscribe/email_unsubscribe.py index 6c47d8c538..d2ee828a55 100644 --- a/frappe/email/doctype/email_unsubscribe/email_unsubscribe.py +++ b/frappe/email/doctype/email_unsubscribe/email_unsubscribe.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe from frappe.model.document import Document diff --git a/frappe/email/doctype/email_unsubscribe/test_email_unsubscribe.py b/frappe/email/doctype/email_unsubscribe/test_email_unsubscribe.py index 602840fe3b..fdea802fdf 100644 --- a/frappe/email/doctype/email_unsubscribe/test_email_unsubscribe.py +++ b/frappe/email/doctype/email_unsubscribe/test_email_unsubscribe.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# See license.txt +# License: MIT. See LICENSE import frappe import unittest diff --git a/frappe/email/doctype/newsletter_email_group/newsletter_email_group.py b/frappe/email/doctype/newsletter_email_group/newsletter_email_group.py index a453dda9e4..89476c4d53 100644 --- a/frappe/email/doctype/newsletter_email_group/newsletter_email_group.py +++ b/frappe/email/doctype/newsletter_email_group/newsletter_email_group.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe from frappe.model.document import Document diff --git a/frappe/email/doctype/notification/notification.py b/frappe/email/doctype/notification/notification.py index b93cdc16fc..6b4ee92043 100644 --- a/frappe/email/doctype/notification/notification.py +++ b/frappe/email/doctype/notification/notification.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2018, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe import json, os diff --git a/frappe/email/doctype/notification/test_notification.py b/frappe/email/doctype/notification/test_notification.py index 803113e8ea..a086ded3fb 100644 --- a/frappe/email/doctype/notification/test_notification.py +++ b/frappe/email/doctype/notification/test_notification.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2018, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE import frappe, frappe.utils, frappe.utils.scheduler from frappe.desk.form import assign_to import unittest diff --git a/frappe/email/doctype/notification_recipient/notification_recipient.py b/frappe/email/doctype/notification_recipient/notification_recipient.py index d8480c5455..68871e5047 100644 --- a/frappe/email/doctype/notification_recipient/notification_recipient.py +++ b/frappe/email/doctype/notification_recipient/notification_recipient.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2018, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe from frappe.model.document import Document diff --git a/frappe/email/doctype/unhandled_email/test_unhandled_email.py b/frappe/email/doctype/unhandled_email/test_unhandled_email.py index 5606b8ff30..37c65584e0 100644 --- a/frappe/email/doctype/unhandled_email/test_unhandled_email.py +++ b/frappe/email/doctype/unhandled_email/test_unhandled_email.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# See license.txt +# License: MIT. See LICENSE import frappe import unittest diff --git a/frappe/email/doctype/unhandled_email/unhandled_email.py b/frappe/email/doctype/unhandled_email/unhandled_email.py index b445c98aa6..db14a50d09 100644 --- a/frappe/email/doctype/unhandled_email/unhandled_email.py +++ b/frappe/email/doctype/unhandled_email/unhandled_email.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe from frappe.model.document import Document diff --git a/frappe/email/email_body.py b/frappe/email/email_body.py index ffb44d3412..6a32ae6fd9 100755 --- a/frappe/email/email_body.py +++ b/frappe/email/email_body.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import frappe, re, os from frappe.utils.pdf import get_pdf diff --git a/frappe/email/queue.py b/frappe/email/queue.py index ef59302bab..16e3fecf48 100755 --- a/frappe/email/queue.py +++ b/frappe/email/queue.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import frappe from frappe import msgprint, _ diff --git a/frappe/email/receive.py b/frappe/email/receive.py index 2e42008951..a755ec5e74 100644 --- a/frappe/email/receive.py +++ b/frappe/email/receive.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import datetime import email diff --git a/frappe/email/smtp.py b/frappe/email/smtp.py index 74492c09c3..6f73a73f11 100644 --- a/frappe/email/smtp.py +++ b/frappe/email/smtp.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import frappe import smtplib diff --git a/frappe/email/test_email_body.py b/frappe/email/test_email_body.py index 2c7d119fce..c542bc2578 100644 --- a/frappe/email/test_email_body.py +++ b/frappe/email/test_email_body.py @@ -1,5 +1,6 @@ -# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt +# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors +# License: MIT. See LICENSE + import unittest, os, base64 from frappe import safe_decode from frappe.email.receive import Email diff --git a/frappe/email/utils.py b/frappe/email/utils.py index 24ce77b922..1138698491 100644 --- a/frappe/email/utils.py +++ b/frappe/email/utils.py @@ -1,5 +1,5 @@ # Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import imaplib, poplib from frappe.utils import cint diff --git a/frappe/event_streaming/doctype/document_type_field_mapping/document_type_field_mapping.py b/frappe/event_streaming/doctype/document_type_field_mapping/document_type_field_mapping.py index fc8164d8a4..3019d70035 100644 --- a/frappe/event_streaming/doctype/document_type_field_mapping/document_type_field_mapping.py +++ b/frappe/event_streaming/doctype/document_type_field_mapping/document_type_field_mapping.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE # import frappe from frappe.model.document import Document diff --git a/frappe/event_streaming/doctype/document_type_mapping/document_type_mapping.py b/frappe/event_streaming/doctype/document_type_mapping/document_type_mapping.py index 2cf7282a5a..8f1e5504da 100644 --- a/frappe/event_streaming/doctype/document_type_mapping/document_type_mapping.py +++ b/frappe/event_streaming/doctype/document_type_mapping/document_type_mapping.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe import json from frappe import _ diff --git a/frappe/event_streaming/doctype/document_type_mapping/test_document_type_mapping.py b/frappe/event_streaming/doctype/document_type_mapping/test_document_type_mapping.py index b1bb322855..a277139985 100644 --- a/frappe/event_streaming/doctype/document_type_mapping/test_document_type_mapping.py +++ b/frappe/event_streaming/doctype/document_type_mapping/test_document_type_mapping.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE # import frappe import unittest diff --git a/frappe/event_streaming/doctype/event_consumer/event_consumer.py b/frappe/event_streaming/doctype/event_consumer/event_consumer.py index 00d304f7f4..e8b84d1345 100644 --- a/frappe/event_streaming/doctype/event_consumer/event_consumer.py +++ b/frappe/event_streaming/doctype/event_consumer/event_consumer.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe import json diff --git a/frappe/event_streaming/doctype/event_consumer/test_event_consumer.py b/frappe/event_streaming/doctype/event_consumer/test_event_consumer.py index b8072ecabd..11c69e7ba3 100644 --- a/frappe/event_streaming/doctype/event_consumer/test_event_consumer.py +++ b/frappe/event_streaming/doctype/event_consumer/test_event_consumer.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE # import frappe import unittest diff --git a/frappe/event_streaming/doctype/event_consumer_document_type/event_consumer_document_type.py b/frappe/event_streaming/doctype/event_consumer_document_type/event_consumer_document_type.py index cf5d18edfd..b33313087f 100644 --- a/frappe/event_streaming/doctype/event_consumer_document_type/event_consumer_document_type.py +++ b/frappe/event_streaming/doctype/event_consumer_document_type/event_consumer_document_type.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE # import frappe from frappe.model.document import Document diff --git a/frappe/event_streaming/doctype/event_producer/event_producer.py b/frappe/event_streaming/doctype/event_producer/event_producer.py index 4836276734..0be15e461b 100644 --- a/frappe/event_streaming/doctype/event_producer/event_producer.py +++ b/frappe/event_streaming/doctype/event_producer/event_producer.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import json import time diff --git a/frappe/event_streaming/doctype/event_producer/test_event_producer.py b/frappe/event_streaming/doctype/event_producer/test_event_producer.py index 883f4f2df2..3d697ceb3a 100644 --- a/frappe/event_streaming/doctype/event_producer/test_event_producer.py +++ b/frappe/event_streaming/doctype/event_producer/test_event_producer.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE import frappe import unittest import json diff --git a/frappe/event_streaming/doctype/event_producer_document_type/event_producer_document_type.py b/frappe/event_streaming/doctype/event_producer_document_type/event_producer_document_type.py index 9ae70e0f97..3e9623f56f 100644 --- a/frappe/event_streaming/doctype/event_producer_document_type/event_producer_document_type.py +++ b/frappe/event_streaming/doctype/event_producer_document_type/event_producer_document_type.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE # import frappe from frappe.model.document import Document diff --git a/frappe/event_streaming/doctype/event_producer_last_update/event_producer_last_update.py b/frappe/event_streaming/doctype/event_producer_last_update/event_producer_last_update.py index 391cf79c27..0868e86253 100644 --- a/frappe/event_streaming/doctype/event_producer_last_update/event_producer_last_update.py +++ b/frappe/event_streaming/doctype/event_producer_last_update/event_producer_last_update.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE # import frappe from frappe.model.document import Document diff --git a/frappe/event_streaming/doctype/event_producer_last_update/test_event_producer_last_update.py b/frappe/event_streaming/doctype/event_producer_last_update/test_event_producer_last_update.py index 62ea71edab..c2d943a463 100644 --- a/frappe/event_streaming/doctype/event_producer_last_update/test_event_producer_last_update.py +++ b/frappe/event_streaming/doctype/event_producer_last_update/test_event_producer_last_update.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE # import frappe import unittest diff --git a/frappe/event_streaming/doctype/event_sync_log/event_sync_log.py b/frappe/event_streaming/doctype/event_sync_log/event_sync_log.py index 1d255a5c30..c26ca46e05 100644 --- a/frappe/event_streaming/doctype/event_sync_log/event_sync_log.py +++ b/frappe/event_streaming/doctype/event_sync_log/event_sync_log.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE # import frappe from frappe.model.document import Document diff --git a/frappe/event_streaming/doctype/event_sync_log/test_event_sync_log.py b/frappe/event_streaming/doctype/event_sync_log/test_event_sync_log.py index ef55dc0f16..b901f92ef8 100644 --- a/frappe/event_streaming/doctype/event_sync_log/test_event_sync_log.py +++ b/frappe/event_streaming/doctype/event_sync_log/test_event_sync_log.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE # import frappe import unittest diff --git a/frappe/event_streaming/doctype/event_update_log/event_update_log.py b/frappe/event_streaming/doctype/event_update_log/event_update_log.py index ae851c70d1..f4871be312 100644 --- a/frappe/event_streaming/doctype/event_update_log/event_update_log.py +++ b/frappe/event_streaming/doctype/event_update_log/event_update_log.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe from frappe.model.document import Document diff --git a/frappe/event_streaming/doctype/event_update_log/test_event_update_log.py b/frappe/event_streaming/doctype/event_update_log/test_event_update_log.py index 99ced3c209..752f4bbb44 100644 --- a/frappe/event_streaming/doctype/event_update_log/test_event_update_log.py +++ b/frappe/event_streaming/doctype/event_update_log/test_event_update_log.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and Contributors -# See license.txt +# License: MIT. See LICENSE # import frappe import unittest diff --git a/frappe/event_streaming/doctype/event_update_log_consumer/event_update_log_consumer.py b/frappe/event_streaming/doctype/event_update_log_consumer/event_update_log_consumer.py index 80a59e4c31..47180db74e 100644 --- a/frappe/event_streaming/doctype/event_update_log_consumer/event_update_log_consumer.py +++ b/frappe/event_streaming/doctype/event_update_log_consumer/event_update_log_consumer.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE # import frappe from frappe.model.document import Document diff --git a/frappe/exceptions.py b/frappe/exceptions.py index 13abd8f4f8..31a94ac883 100644 --- a/frappe/exceptions.py +++ b/frappe/exceptions.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE # BEWARE don't put anything in this file except exceptions from werkzeug.exceptions import NotFound diff --git a/frappe/geo/country_info.py b/frappe/geo/country_info.py index ddebd1fb0e..86f1d9bc2f 100644 --- a/frappe/geo/country_info.py +++ b/frappe/geo/country_info.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE # all country info import os, json, frappe diff --git a/frappe/geo/doctype/country/country.py b/frappe/geo/doctype/country/country.py index 54935e6eaf..a648744058 100644 --- a/frappe/geo/doctype/country/country.py +++ b/frappe/geo/doctype/country/country.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# License: See license.txt +# License: MIT. See LICENSE import frappe diff --git a/frappe/geo/doctype/country/test_country.py b/frappe/geo/doctype/country/test_country.py index e00d6ecf37..b4d15f81b3 100644 --- a/frappe/geo/doctype/country/test_country.py +++ b/frappe/geo/doctype/country/test_country.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# License: See license.txt +# License: MIT. See LICENSE import frappe test_records = frappe.get_test_records('Country') \ No newline at end of file diff --git a/frappe/geo/doctype/currency/currency.py b/frappe/geo/doctype/currency/currency.py index b3ce67cc67..fbe37e73bd 100644 --- a/frappe/geo/doctype/currency/currency.py +++ b/frappe/geo/doctype/currency/currency.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# License: See license.txt +# License: MIT. See LICENSE import frappe from frappe import throw, _ diff --git a/frappe/geo/doctype/currency/test_currency.py b/frappe/geo/doctype/currency/test_currency.py index 5552e675ec..71b963cc86 100644 --- a/frappe/geo/doctype/currency/test_currency.py +++ b/frappe/geo/doctype/currency/test_currency.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# License: See license.txt +# License: MIT. See LICENSE # pre loaded diff --git a/frappe/geo/utils.py b/frappe/geo/utils.py index 89de176f0b..9b44a2f3d8 100644 --- a/frappe/geo/utils.py +++ b/frappe/geo/utils.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe diff --git a/frappe/handler.py b/frappe/handler.py index 2e9fb7b454..352a9672bf 100755 --- a/frappe/handler.py +++ b/frappe/handler.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE from werkzeug.wrappers import Response diff --git a/frappe/hooks.py b/frappe/hooks.py index f3d25d6bf4..2ae5a59066 100644 --- a/frappe/hooks.py +++ b/frappe/hooks.py @@ -12,11 +12,11 @@ source_link = "https://github.com/frappe/frappe" app_license = "MIT" app_logo_url = '/assets/frappe/images/frappe-framework-logo.svg' -develop_version = '13.x.x-develop' +develop_version = '14.x.x-develop' -app_email = "info@frappe.io" +app_email = "developers@frappe.io" -docs_app = "frappe_io" +docs_app = "frappe_docs" translator_url = "https://translate.erpnext.com" @@ -164,7 +164,8 @@ doc_events = { "after_rename": "frappe.desk.notifications.clear_doctype_notifications", "on_cancel": [ "frappe.desk.notifications.clear_doctype_notifications", - "frappe.workflow.doctype.workflow_action.workflow_action.process_workflow_actions" + "frappe.workflow.doctype.workflow_action.workflow_action.process_workflow_actions", + "frappe.event_streaming.doctype.event_update_log.event_update_log.notify_consumers" ], "on_trash": [ "frappe.desk.notifications.clear_doctype_notifications", diff --git a/frappe/installer.py b/frappe/installer.py index d4d8117fcb..f0bf0cb51c 100755 --- a/frappe/installer.py +++ b/frappe/installer.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import json import os @@ -445,9 +445,21 @@ def extract_sql_from_archive(sql_file_path): else: decompressed_file_name = sql_file_path + # convert archive sql to latest compatible + convert_archive_content(decompressed_file_name) + return decompressed_file_name +def convert_archive_content(sql_file_path): + if frappe.conf.db_type == "mariadb": + # ever since mariaDB 10.6, row_format COMPRESSED has been deprecated and removed + # this step is added to ease restoring sites depending on older mariaDB servers + contents = open(sql_file_path).read() + with open(sql_file_path, "w") as f: + f.write(contents.replace("ROW_FORMAT=COMPRESSED", "ROW_FORMAT=DYNAMIC")) + + def extract_sql_gzip(sql_gz_path): import subprocess @@ -457,7 +469,7 @@ def extract_sql_gzip(sql_gz_path): decompressed_file = original_file.rstrip(".gz") cmd = 'gzip -dvf < {0} > {1}'.format(original_file, decompressed_file) subprocess.check_call(cmd, shell=True) - except: + except Exception: raise return decompressed_file diff --git a/frappe/integrations/doctype/braintree_settings/braintree_settings.py b/frappe/integrations/doctype/braintree_settings/braintree_settings.py index 9dc9778bee..59751185b9 100644 --- a/frappe/integrations/doctype/braintree_settings/braintree_settings.py +++ b/frappe/integrations/doctype/braintree_settings/braintree_settings.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2018, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe from frappe.model.document import Document diff --git a/frappe/integrations/doctype/braintree_settings/test_braintree_settings.py b/frappe/integrations/doctype/braintree_settings/test_braintree_settings.py index 72a678a92c..721158fb4a 100644 --- a/frappe/integrations/doctype/braintree_settings/test_braintree_settings.py +++ b/frappe/integrations/doctype/braintree_settings/test_braintree_settings.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2018, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE import unittest class TestBraintreeSettings(unittest.TestCase): diff --git a/frappe/integrations/doctype/connected_app/connected_app.py b/frappe/integrations/doctype/connected_app/connected_app.py index 449e30f6d0..fcb5fe7ee9 100644 --- a/frappe/integrations/doctype/connected_app/connected_app.py +++ b/frappe/integrations/doctype/connected_app/connected_app.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import os from urllib.parse import urljoin diff --git a/frappe/integrations/doctype/connected_app/test_connected_app.py b/frappe/integrations/doctype/connected_app/test_connected_app.py index d1ff19ecb2..eff7104ce0 100644 --- a/frappe/integrations/doctype/connected_app/test_connected_app.py +++ b/frappe/integrations/doctype/connected_app/test_connected_app.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors -# See license.txt +# License: MIT. See LICENSE import unittest import requests from urllib.parse import urljoin diff --git a/frappe/integrations/doctype/dropbox_settings/dropbox_settings.py b/frappe/integrations/doctype/dropbox_settings/dropbox_settings.py index 53f0935c80..90927e13f8 100644 --- a/frappe/integrations/doctype/dropbox_settings/dropbox_settings.py +++ b/frappe/integrations/doctype/dropbox_settings/dropbox_settings.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import json import os diff --git a/frappe/integrations/doctype/dropbox_settings/test_dropbox_settings.py b/frappe/integrations/doctype/dropbox_settings/test_dropbox_settings.py index d34e65de50..458f876444 100644 --- a/frappe/integrations/doctype/dropbox_settings/test_dropbox_settings.py +++ b/frappe/integrations/doctype/dropbox_settings/test_dropbox_settings.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE # import frappe import unittest diff --git a/frappe/integrations/doctype/google_calendar/google_calendar.py b/frappe/integrations/doctype/google_calendar/google_calendar.py index f93be35aa7..0d4c5bbe5c 100644 --- a/frappe/integrations/doctype/google_calendar/google_calendar.py +++ b/frappe/integrations/doctype/google_calendar/google_calendar.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE from datetime import datetime, timedelta diff --git a/frappe/integrations/doctype/google_contacts/google_contacts.py b/frappe/integrations/doctype/google_contacts/google_contacts.py index 1705f98e91..a63b0b6d80 100644 --- a/frappe/integrations/doctype/google_contacts/google_contacts.py +++ b/frappe/integrations/doctype/google_contacts/google_contacts.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import google.oauth2.credentials diff --git a/frappe/integrations/doctype/google_drive/google_drive.py b/frappe/integrations/doctype/google_drive/google_drive.py index 93b6fa3f8d..beac7898a9 100644 --- a/frappe/integrations/doctype/google_drive/google_drive.py +++ b/frappe/integrations/doctype/google_drive/google_drive.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import os from urllib.parse import quote diff --git a/frappe/integrations/doctype/google_drive/test_google_drive.py b/frappe/integrations/doctype/google_drive/test_google_drive.py index 96e8577c7c..fbd9dce7f4 100644 --- a/frappe/integrations/doctype/google_drive/test_google_drive.py +++ b/frappe/integrations/doctype/google_drive/test_google_drive.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE # import frappe import unittest diff --git a/frappe/integrations/doctype/google_settings/google_settings.py b/frappe/integrations/doctype/google_settings/google_settings.py index db65abdb65..94df43e69c 100644 --- a/frappe/integrations/doctype/google_settings/google_settings.py +++ b/frappe/integrations/doctype/google_settings/google_settings.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe from frappe.model.document import Document diff --git a/frappe/integrations/doctype/google_settings/test_google_settings.py b/frappe/integrations/doctype/google_settings/test_google_settings.py index 32d43a323b..cddf9f3697 100644 --- a/frappe/integrations/doctype/google_settings/test_google_settings.py +++ b/frappe/integrations/doctype/google_settings/test_google_settings.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2021, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE from __future__ import unicode_literals import frappe diff --git a/frappe/integrations/doctype/integration_request/integration_request.py b/frappe/integrations/doctype/integration_request/integration_request.py index 4c4961d96d..ae0e024f58 100644 --- a/frappe/integrations/doctype/integration_request/integration_request.py +++ b/frappe/integrations/doctype/integration_request/integration_request.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe from frappe.model.document import Document diff --git a/frappe/integrations/doctype/integration_request/test_integration_request.py b/frappe/integrations/doctype/integration_request/test_integration_request.py index a26eb4ba93..e26ccabc96 100644 --- a/frappe/integrations/doctype/integration_request/test_integration_request.py +++ b/frappe/integrations/doctype/integration_request/test_integration_request.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE import frappe import unittest diff --git a/frappe/integrations/doctype/ldap_group_mapping/ldap_group_mapping.py b/frappe/integrations/doctype/ldap_group_mapping/ldap_group_mapping.py index b6bb77d964..b9838b996f 100644 --- a/frappe/integrations/doctype/ldap_group_mapping/ldap_group_mapping.py +++ b/frappe/integrations/doctype/ldap_group_mapping/ldap_group_mapping.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE # import frappe from frappe.model.document import Document diff --git a/frappe/integrations/doctype/ldap_settings/ldap_settings.py b/frappe/integrations/doctype/ldap_settings/ldap_settings.py index 7c89c31844..1c5abb454c 100644 --- a/frappe/integrations/doctype/ldap_settings/ldap_settings.py +++ b/frappe/integrations/doctype/ldap_settings/ldap_settings.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe from frappe import _, safe_encode diff --git a/frappe/integrations/doctype/ldap_settings/test_ldap_settings.py b/frappe/integrations/doctype/ldap_settings/test_ldap_settings.py index 1b2a9b155f..7b0638876b 100644 --- a/frappe/integrations/doctype/ldap_settings/test_ldap_settings.py +++ b/frappe/integrations/doctype/ldap_settings/test_ldap_settings.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE import frappe import unittest import functools @@ -172,7 +172,7 @@ class LDAP_TestCase(): # Clear OpenLDAP connection self.connection = None - + @mock_ldap_connection def test_mandatory_fields(self): @@ -218,7 +218,7 @@ class LDAP_TestCase(): localdoc = self.doc.copy() localdoc[non_mandatory_field] = '' - + try: frappe.get_doc(localdoc).save() @@ -324,7 +324,7 @@ class LDAP_TestCase(): self.assertTrue(kwargs['user'] == self.base_dn, 'ldap3.Connection user does not match provided user') - ldap3_connection_method.assert_called_with(server=ldap3_server_method.return_value, + ldap3_connection_method.assert_called_with(server=ldap3_server_method.return_value, auto_bind=True, password=self.base_password, raise_exceptions=True, @@ -467,7 +467,7 @@ class LDAP_TestCase(): self.test_class.create_or_update_user(self.user1doc, test_user_data[test_user]) self.assertTrue(sync_roles_method.called, 'User roles need to be updated for a new user') - self.assertFalse(update_user_fields_method.called, + self.assertFalse(update_user_fields_method.called, 'User roles are not required to be updated for a new user, this will occur during logon') @@ -489,7 +489,7 @@ class LDAP_TestCase(): @mock_ldap_connection def test_fetch_ldap_groups(self): - + if self.TEST_LDAP_SERVER.lower() == 'openldap': test_users = { 'posix.user': ['Users', 'Administrators'], @@ -523,7 +523,7 @@ class LDAP_TestCase(): @mock_ldap_connection def test_authenticate(self): - + with mock.patch('frappe.integrations.doctype.ldap_settings.ldap_settings.LDAPSettings.fetch_ldap_groups') as \ fetch_ldap_groups_function: @@ -543,7 +543,7 @@ class LDAP_TestCase(): {'': 'posix_user_password'}, {'': ''} ] # All invalid users should return 'invalid username or password' - + for username, password in enumerate(invalid_users): with self.assertRaises(frappe.exceptions.ValidationError) as display_massage: diff --git a/frappe/integrations/doctype/oauth_authorization_code/oauth_authorization_code.py b/frappe/integrations/doctype/oauth_authorization_code/oauth_authorization_code.py index 0c7f02844c..5a3f380e84 100644 --- a/frappe/integrations/doctype/oauth_authorization_code/oauth_authorization_code.py +++ b/frappe/integrations/doctype/oauth_authorization_code/oauth_authorization_code.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe from frappe.model.document import Document diff --git a/frappe/integrations/doctype/oauth_authorization_code/test_oauth_authorization_code.py b/frappe/integrations/doctype/oauth_authorization_code/test_oauth_authorization_code.py index 6084dd64b4..bc6d29cbdb 100644 --- a/frappe/integrations/doctype/oauth_authorization_code/test_oauth_authorization_code.py +++ b/frappe/integrations/doctype/oauth_authorization_code/test_oauth_authorization_code.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE import frappe import unittest diff --git a/frappe/integrations/doctype/oauth_bearer_token/oauth_bearer_token.py b/frappe/integrations/doctype/oauth_bearer_token/oauth_bearer_token.py index 916d0205d2..ff6f96cc4d 100644 --- a/frappe/integrations/doctype/oauth_bearer_token/oauth_bearer_token.py +++ b/frappe/integrations/doctype/oauth_bearer_token/oauth_bearer_token.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe from frappe.model.document import Document diff --git a/frappe/integrations/doctype/oauth_bearer_token/test_oauth_bearer_token.py b/frappe/integrations/doctype/oauth_bearer_token/test_oauth_bearer_token.py index 6028cebcf9..965feb4f78 100644 --- a/frappe/integrations/doctype/oauth_bearer_token/test_oauth_bearer_token.py +++ b/frappe/integrations/doctype/oauth_bearer_token/test_oauth_bearer_token.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE import frappe import unittest diff --git a/frappe/integrations/doctype/oauth_client/oauth_client.py b/frappe/integrations/doctype/oauth_client/oauth_client.py index 0b449ff968..42fba07ecb 100644 --- a/frappe/integrations/doctype/oauth_client/oauth_client.py +++ b/frappe/integrations/doctype/oauth_client/oauth_client.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe from frappe import _ diff --git a/frappe/integrations/doctype/oauth_client/test_oauth_client.py b/frappe/integrations/doctype/oauth_client/test_oauth_client.py index a4e50e15d8..fa03fa06e7 100644 --- a/frappe/integrations/doctype/oauth_client/test_oauth_client.py +++ b/frappe/integrations/doctype/oauth_client/test_oauth_client.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE import frappe import unittest diff --git a/frappe/integrations/doctype/oauth_provider_settings/oauth_provider_settings.py b/frappe/integrations/doctype/oauth_provider_settings/oauth_provider_settings.py index 3ab5df92ac..ec1636659f 100644 --- a/frappe/integrations/doctype/oauth_provider_settings/oauth_provider_settings.py +++ b/frappe/integrations/doctype/oauth_provider_settings/oauth_provider_settings.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe from frappe.model.document import Document diff --git a/frappe/integrations/doctype/oauth_scope/oauth_scope.py b/frappe/integrations/doctype/oauth_scope/oauth_scope.py index ae579e6b51..cf5fa1f341 100644 --- a/frappe/integrations/doctype/oauth_scope/oauth_scope.py +++ b/frappe/integrations/doctype/oauth_scope/oauth_scope.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE # import frappe from frappe.model.document import Document diff --git a/frappe/integrations/doctype/paypal_settings/paypal_settings.py b/frappe/integrations/doctype/paypal_settings/paypal_settings.py index da045d2c6a..30ac905792 100644 --- a/frappe/integrations/doctype/paypal_settings/paypal_settings.py +++ b/frappe/integrations/doctype/paypal_settings/paypal_settings.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE """ # Integrating PayPal diff --git a/frappe/integrations/doctype/paytm_settings/paytm_settings.py b/frappe/integrations/doctype/paytm_settings/paytm_settings.py index 9f15d73f09..5255360242 100644 --- a/frappe/integrations/doctype/paytm_settings/paytm_settings.py +++ b/frappe/integrations/doctype/paytm_settings/paytm_settings.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import json import requests diff --git a/frappe/integrations/doctype/paytm_settings/test_paytm_settings.py b/frappe/integrations/doctype/paytm_settings/test_paytm_settings.py index a00ce86327..425fc87a3f 100644 --- a/frappe/integrations/doctype/paytm_settings/test_paytm_settings.py +++ b/frappe/integrations/doctype/paytm_settings/test_paytm_settings.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE # import frappe import unittest diff --git a/frappe/integrations/doctype/query_parameters/query_parameters.py b/frappe/integrations/doctype/query_parameters/query_parameters.py index 13fb94dbe3..68e97e9071 100644 --- a/frappe/integrations/doctype/query_parameters/query_parameters.py +++ b/frappe/integrations/doctype/query_parameters/query_parameters.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE # import frappe from frappe.model.document import Document diff --git a/frappe/integrations/doctype/razorpay_settings/razorpay_settings.py b/frappe/integrations/doctype/razorpay_settings/razorpay_settings.py index d24e15f480..9ae16a31f8 100644 --- a/frappe/integrations/doctype/razorpay_settings/razorpay_settings.py +++ b/frappe/integrations/doctype/razorpay_settings/razorpay_settings.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE """ # Integrating RazorPay diff --git a/frappe/integrations/doctype/s3_backup_settings/s3_backup_settings.py b/frappe/integrations/doctype/s3_backup_settings/s3_backup_settings.py index 1346811652..dc824e18b9 100755 --- a/frappe/integrations/doctype/s3_backup_settings/s3_backup_settings.py +++ b/frappe/integrations/doctype/s3_backup_settings/s3_backup_settings.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import os import os.path import frappe diff --git a/frappe/integrations/doctype/s3_backup_settings/test_s3_backup_settings.py b/frappe/integrations/doctype/s3_backup_settings/test_s3_backup_settings.py index 3aecdf3489..2a586c30d4 100755 --- a/frappe/integrations/doctype/s3_backup_settings/test_s3_backup_settings.py +++ b/frappe/integrations/doctype/s3_backup_settings/test_s3_backup_settings.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE import unittest class TestS3BackupSettings(unittest.TestCase): diff --git a/frappe/integrations/doctype/slack_webhook_url/slack_webhook_url.py b/frappe/integrations/doctype/slack_webhook_url/slack_webhook_url.py index a970fc1f11..a74c0a36ca 100644 --- a/frappe/integrations/doctype/slack_webhook_url/slack_webhook_url.py +++ b/frappe/integrations/doctype/slack_webhook_url/slack_webhook_url.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2018, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe from frappe.model.document import Document diff --git a/frappe/integrations/doctype/slack_webhook_url/test_slack_webhook_url.py b/frappe/integrations/doctype/slack_webhook_url/test_slack_webhook_url.py index 4285c2c4bc..a256735f81 100644 --- a/frappe/integrations/doctype/slack_webhook_url/test_slack_webhook_url.py +++ b/frappe/integrations/doctype/slack_webhook_url/test_slack_webhook_url.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2018, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE import unittest class TestSlackWebhookURL(unittest.TestCase): diff --git a/frappe/integrations/doctype/social_login_key/social_login_key.py b/frappe/integrations/doctype/social_login_key/social_login_key.py index 4a4fcd44f4..d6f55e5758 100644 --- a/frappe/integrations/doctype/social_login_key/social_login_key.py +++ b/frappe/integrations/doctype/social_login_key/social_login_key.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe, json from frappe import _ diff --git a/frappe/integrations/doctype/social_login_key/test_social_login_key.py b/frappe/integrations/doctype/social_login_key/test_social_login_key.py index 23effd6a44..880f1ee99c 100644 --- a/frappe/integrations/doctype/social_login_key/test_social_login_key.py +++ b/frappe/integrations/doctype/social_login_key/test_social_login_key.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE import frappe from frappe.integrations.doctype.social_login_key.social_login_key import BaseUrlNotSetError import unittest diff --git a/frappe/integrations/doctype/stripe_settings/stripe_settings.py b/frappe/integrations/doctype/stripe_settings/stripe_settings.py index 9bb9c60775..81e40fa72f 100644 --- a/frappe/integrations/doctype/stripe_settings/stripe_settings.py +++ b/frappe/integrations/doctype/stripe_settings/stripe_settings.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe from frappe.model.document import Document diff --git a/frappe/integrations/doctype/stripe_settings/test_stripe_settings.py b/frappe/integrations/doctype/stripe_settings/test_stripe_settings.py index ba11c3c38b..e7113d3bd9 100644 --- a/frappe/integrations/doctype/stripe_settings/test_stripe_settings.py +++ b/frappe/integrations/doctype/stripe_settings/test_stripe_settings.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2018, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE import unittest class TestStripeSettings(unittest.TestCase): diff --git a/frappe/integrations/doctype/token_cache/test_token_cache.py b/frappe/integrations/doctype/token_cache/test_token_cache.py index 2ffd57403b..5fe648d225 100644 --- a/frappe/integrations/doctype/token_cache/test_token_cache.py +++ b/frappe/integrations/doctype/token_cache/test_token_cache.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors -# See license.txt +# License: MIT. See LICENSE import unittest import frappe diff --git a/frappe/integrations/doctype/token_cache/token_cache.py b/frappe/integrations/doctype/token_cache/token_cache.py index 3001d12b2b..ea86100cc2 100644 --- a/frappe/integrations/doctype/token_cache/token_cache.py +++ b/frappe/integrations/doctype/token_cache/token_cache.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE from datetime import datetime, timedelta diff --git a/frappe/integrations/doctype/webhook/__init__.py b/frappe/integrations/doctype/webhook/__init__.py index b92497f16c..6dcc0218a3 100644 --- a/frappe/integrations/doctype/webhook/__init__.py +++ b/frappe/integrations/doctype/webhook/__init__.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe diff --git a/frappe/integrations/doctype/webhook/test_webhook.py b/frappe/integrations/doctype/webhook/test_webhook.py index 1470f666a1..a1176aa38b 100644 --- a/frappe/integrations/doctype/webhook/test_webhook.py +++ b/frappe/integrations/doctype/webhook/test_webhook.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE import unittest import frappe diff --git a/frappe/integrations/doctype/webhook/webhook.py b/frappe/integrations/doctype/webhook/webhook.py index e3a8bda2aa..8546a9d2f8 100644 --- a/frappe/integrations/doctype/webhook/webhook.py +++ b/frappe/integrations/doctype/webhook/webhook.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import base64 import datetime diff --git a/frappe/integrations/doctype/webhook_data/webhook_data.py b/frappe/integrations/doctype/webhook_data/webhook_data.py index dbd9328482..6037ed5390 100644 --- a/frappe/integrations/doctype/webhook_data/webhook_data.py +++ b/frappe/integrations/doctype/webhook_data/webhook_data.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE # import frappe from frappe.model.document import Document diff --git a/frappe/integrations/doctype/webhook_header/webhook_header.py b/frappe/integrations/doctype/webhook_header/webhook_header.py index 428b287db2..e1944c84bc 100644 --- a/frappe/integrations/doctype/webhook_header/webhook_header.py +++ b/frappe/integrations/doctype/webhook_header/webhook_header.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE # import frappe from frappe.model.document import Document diff --git a/frappe/integrations/doctype/webhook_request_log/test_webhook_request_log.py b/frappe/integrations/doctype/webhook_request_log/test_webhook_request_log.py index dd11bf8a01..5de26a35ed 100644 --- a/frappe/integrations/doctype/webhook_request_log/test_webhook_request_log.py +++ b/frappe/integrations/doctype/webhook_request_log/test_webhook_request_log.py @@ -1,5 +1,5 @@ # Copyright (c) 2021, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE # import frappe import unittest diff --git a/frappe/integrations/doctype/webhook_request_log/webhook_request_log.py b/frappe/integrations/doctype/webhook_request_log/webhook_request_log.py index 493ebfd8f7..3f0558ce80 100644 --- a/frappe/integrations/doctype/webhook_request_log/webhook_request_log.py +++ b/frappe/integrations/doctype/webhook_request_log/webhook_request_log.py @@ -1,5 +1,5 @@ # Copyright (c) 2021, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE # import frappe from frappe.model.document import Document diff --git a/frappe/integrations/oauth2_logins.py b/frappe/integrations/oauth2_logins.py index c38b43beb7..b187d29b34 100644 --- a/frappe/integrations/oauth2_logins.py +++ b/frappe/integrations/oauth2_logins.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import frappe import frappe.utils diff --git a/frappe/integrations/offsite_backup_utils.py b/frappe/integrations/offsite_backup_utils.py index 7a263e9d04..416d656d90 100644 --- a/frappe/integrations/offsite_backup_utils.py +++ b/frappe/integrations/offsite_backup_utils.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe import glob diff --git a/frappe/integrations/utils.py b/frappe/integrations/utils.py index b897a35062..bda45a765d 100644 --- a/frappe/integrations/utils.py +++ b/frappe/integrations/utils.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe import json,datetime diff --git a/frappe/middlewares.py b/frappe/middlewares.py index 05944ec37a..38cb4cea21 100644 --- a/frappe/middlewares.py +++ b/frappe/middlewares.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import frappe import os diff --git a/frappe/migrate.py b/frappe/migrate.py index 061e4c98d7..92258502e4 100644 --- a/frappe/migrate.py +++ b/frappe/migrate.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import json import os diff --git a/frappe/model/__init__.py b/frappe/model/__init__.py index 1acd7ee670..b460db29a7 100644 --- a/frappe/model/__init__.py +++ b/frappe/model/__init__.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE # model __init__.py import frappe @@ -41,6 +41,7 @@ data_fieldtypes = ( no_value_fields = ( 'Section Break', 'Column Break', + 'Tab Break', 'HTML', 'Table', 'Table MultiSelect', @@ -53,6 +54,7 @@ no_value_fields = ( display_fieldtypes = ( 'Section Break', 'Column Break', + 'Tab Break', 'HTML', 'Button', 'Image', diff --git a/frappe/model/base_document.py b/frappe/model/base_document.py index 5a204caf70..5605ac61ed 100644 --- a/frappe/model/base_document.py +++ b/frappe/model/base_document.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import frappe import datetime from frappe import _ @@ -307,7 +307,7 @@ class BaseDocument(object): doc["doctype"] = self.doctype for df in self.meta.get_table_fields(): children = self.get(df.fieldname) or [] - doc[df.fieldname] = [d.as_dict(convert_dates_to_str=convert_dates_to_str, no_nulls=no_nulls) for d in children] + doc[df.fieldname] = [d.as_dict(convert_dates_to_str=convert_dates_to_str, no_nulls=no_nulls, no_default_fields=no_default_fields) for d in children] if no_nulls: for k in list(doc): diff --git a/frappe/model/create_new.py b/frappe/model/create_new.py index fba6765479..fff2156a10 100644 --- a/frappe/model/create_new.py +++ b/frappe/model/create_new.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE """ Create a new document with defaults set diff --git a/frappe/model/db_query.py b/frappe/model/db_query.py index 7ed681644f..978f3062c5 100644 --- a/frappe/model/db_query.py +++ b/frappe/model/db_query.py @@ -1,8 +1,10 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE """build query for doclistview and return results""" +from typing import List import frappe.defaults +from frappe.query_builder.utils import Column import frappe.share from frappe import _ import frappe.permissions @@ -33,7 +35,7 @@ class DatabaseQuery(object): join='left join', distinct=False, start=None, page_length=None, limit=None, ignore_ifnull=False, save_user_settings=False, save_user_settings_fields=False, update=None, add_total_row=None, user_settings=None, reference_doctype=None, - return_query=False, strict=True, pluck=None, ignore_ddl=False): + return_query=False, strict=True, pluck=None, ignore_ddl=False) -> List: if not ignore_permissions and \ not frappe.has_permission(self.doctype, "select", user=user) and \ not frappe.has_permission(self.doctype, "read", user=user): @@ -490,7 +492,7 @@ class DatabaseQuery(object): f.value = date_range fallback = "'0001-01-01 00:00:00'" - if f.operator in ('>', '<') and (f.fieldname in ('creation', 'modified')): + if (f.fieldname in ('creation', 'modified')): value = cstr(f.value) fallback = "NULL" @@ -546,8 +548,12 @@ class DatabaseQuery(object): value = flt(f.value) fallback = 0 + if isinstance(f.value, Column): + quote = '"' if frappe.conf.db_type == 'postgres' else "`" + value = f"{tname}.{quote}{f.value.name}{quote}" + # escape value - if isinstance(value, str) and not f.operator.lower() == 'between': + elif isinstance(value, str) and not f.operator.lower() == 'between': value = f"{frappe.db.escape(value, percent=False)}" if ( diff --git a/frappe/model/delete_doc.py b/frappe/model/delete_doc.py index 9ce74054e7..ac976e976c 100644 --- a/frappe/model/delete_doc.py +++ b/frappe/model/delete_doc.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import os import shutil diff --git a/frappe/model/docfield.py b/frappe/model/docfield.py index 6360c3866d..c173561b1e 100644 --- a/frappe/model/docfield.py +++ b/frappe/model/docfield.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE """docfield utililtes""" diff --git a/frappe/model/document.py b/frappe/model/document.py index 37549e2001..411d447d0f 100644 --- a/frappe/model/document.py +++ b/frappe/model/document.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import frappe import time from frappe import _, msgprint, is_whitelisted diff --git a/frappe/model/dynamic_links.py b/frappe/model/dynamic_links.py index 676c86d7da..7311b39b30 100644 --- a/frappe/model/dynamic_links.py +++ b/frappe/model/dynamic_links.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import frappe diff --git a/frappe/model/mapper.py b/frappe/model/mapper.py index fa8858d950..bde4fb6d73 100644 --- a/frappe/model/mapper.py +++ b/frappe/model/mapper.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import json import frappe diff --git a/frappe/model/meta.py b/frappe/model/meta.py index f89163e092..cd0d8e0f3a 100644 --- a/frappe/model/meta.py +++ b/frappe/model/meta.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE # metadata @@ -15,6 +15,7 @@ Example: ''' from datetime import datetime +import click import frappe, json, os from frappe.utils import cstr, cint, cast from frappe.model import default_fields, no_value_fields, optional_fields, data_fieldtypes, table_fields @@ -658,27 +659,48 @@ def get_default_df(fieldname): fieldtype = "Data" ) -def trim_tables(doctype=None): +def trim_tables(doctype=None, dry_run=False, quiet=False): """ Removes database fields that don't exist in the doctype (json or custom field). This may be needed as maintenance since removing a field in a DocType doesn't automatically delete the db field. """ - ignore_fields = default_fields + optional_fields - - filters={ "issingle": 0 } + UPDATED_TABLES = {} + filters = {"issingle": 0} if doctype: filters["name"] = doctype - for doctype in frappe.db.get_all("DocType", filters=filters): - doctype = doctype.name - columns = frappe.db.get_table_columns(doctype) - fields = frappe.get_meta(doctype).get_fieldnames_with_value() - columns_to_remove = [f for f in list(set(columns) - set(fields)) if f not in ignore_fields - and not f.startswith("_")] - if columns_to_remove: - print(doctype, "columns removed:", columns_to_remove) - columns_to_remove = ", ".join("drop `{0}`".format(c) for c in columns_to_remove) - query = """alter table `tab{doctype}` {columns}""".format( - doctype=doctype, columns=columns_to_remove) - frappe.db.sql_ddl(query) + for doctype in frappe.db.get_all("DocType", filters=filters, pluck="name"): + try: + dropped_columns = trim_table(doctype, dry_run=dry_run) + if dropped_columns: + UPDATED_TABLES[doctype] = dropped_columns + except frappe.db.TableMissingError: + if quiet: + continue + click.secho(f"Ignoring missing table for DocType: {doctype}", fg="yellow", err=True) + click.secho(f"Consider removing record in the DocType table for {doctype}", fg="yellow", err=True) + except Exception as e: + if quiet: + continue + click.echo(e, err=True) + + return UPDATED_TABLES + + +def trim_table(doctype, dry_run=True): + frappe.cache().hdel('table_columns', f"tab{doctype}") + ignore_fields = default_fields + optional_fields + columns = frappe.db.get_table_columns(doctype) + fields = frappe.get_meta(doctype, cached=False).get_fieldnames_with_value() + is_internal = lambda f: f not in ignore_fields and not f.startswith("_") + columns_to_remove = [ + f for f in list(set(columns) - set(fields)) if is_internal(f) + ] + DROPPED_COLUMNS = columns_to_remove[:] + + if columns_to_remove and not dry_run: + columns_to_remove = ", ".join(f"DROP `{c}`" for c in columns_to_remove) + frappe.db.sql_ddl(f"ALTER TABLE `tab{doctype}` {columns_to_remove}") + + return DROPPED_COLUMNS diff --git a/frappe/model/naming.py b/frappe/model/naming.py index 7705002706..71ff281642 100644 --- a/frappe/model/naming.py +++ b/frappe/model/naming.py @@ -10,7 +10,7 @@ the cancelled document naming pattern is changed to 'orig_name-CANC-X'. """ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import frappe from frappe import _ @@ -346,7 +346,7 @@ def _prompt_autoname(autoname, doc): """ # set from __newname in save.py if not doc.name: - frappe.throw(_("Name not set via prompt")) + frappe.throw(_("Please set the document name")) def _format_autoname(autoname, doc): """ diff --git a/frappe/model/rename_doc.py b/frappe/model/rename_doc.py index 9b8ac2574d..14f1dbf2b0 100644 --- a/frappe/model/rename_doc.py +++ b/frappe/model/rename_doc.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import frappe from frappe import _, bold from frappe.model.dynamic_links import get_dynamic_link_map diff --git a/frappe/model/sync.py b/frappe/model/sync.py index 836f70dd55..138f9eaad4 100644 --- a/frappe/model/sync.py +++ b/frappe/model/sync.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE """ Sync's doctype and docfields from txt files to database perms will get synced only if none exist @@ -80,9 +80,11 @@ def get_doc_files(files, start_path): # load in sequence - warning for devs document_types = ['doctype', 'page', 'report', 'dashboard_chart_source', 'print_format', - 'website_theme', 'web_form', 'web_template', 'notification', 'print_style', - 'data_migration_mapping', 'data_migration_plan', 'workspace', - 'onboarding_step', 'module_onboarding', 'form_tour'] + 'web_page', 'website_theme', 'web_form', 'web_template', + 'notification', 'print_style', + 'data_migration_mapping', 'data_migration_plan', + 'workspace', 'onboarding_step', 'module_onboarding', 'form_tour', + 'client_script', 'server_script', 'custom_field', 'property_setter'] for doctype in document_types: doctype_path = os.path.join(start_path, doctype) diff --git a/frappe/model/utils/__init__.py b/frappe/model/utils/__init__.py index 47615182e4..4cdca5e394 100644 --- a/frappe/model/utils/__init__.py +++ b/frappe/model/utils/__init__.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import frappe from frappe import _ from frappe.utils import cstr diff --git a/frappe/model/utils/link_count.py b/frappe/model/utils/link_count.py index 7562aaae45..404b6ec855 100644 --- a/frappe/model/utils/link_count.py +++ b/frappe/model/utils/link_count.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import frappe diff --git a/frappe/model/utils/rename_field.py b/frappe/model/utils/rename_field.py index 9fe9d64041..c9c454b7e8 100644 --- a/frappe/model/utils/rename_field.py +++ b/frappe/model/utils/rename_field.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import frappe import json from frappe.model import no_value_fields, table_fields diff --git a/frappe/model/workflow.py b/frappe/model/workflow.py index fa2f557370..e74d88c0f2 100644 --- a/frappe/model/workflow.py +++ b/frappe/model/workflow.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import frappe from frappe.utils import cint diff --git a/frappe/modules.txt b/frappe/modules.txt index ae10c3ad55..1229116a2e 100644 --- a/frappe/modules.txt +++ b/frappe/modules.txt @@ -12,4 +12,4 @@ Data Migration Chat Social Automation -Event Streaming \ No newline at end of file +Event Streaming diff --git a/frappe/modules/export_file.py b/frappe/modules/export_file.py index ae9f11d53b..17e84ee488 100644 --- a/frappe/modules/export_file.py +++ b/frappe/modules/export_file.py @@ -1,12 +1,12 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import frappe, os import frappe.model from frappe.modules import scrub, get_module_path, scrub_dt_dn def export_doc(doc): - export_to_files([[doc.doctype, doc.name]]) + write_document_file(doc) def export_to_files(record_list=None, record_module=None, verbose=0, create_init=None): """ @@ -21,16 +21,10 @@ def export_to_files(record_list=None, record_module=None, verbose=0, create_init write_document_file(frappe.get_doc(record[0], record[1]), record_module, create_init=create_init, folder_name=folder_name) def write_document_file(doc, record_module=None, create_init=True, folder_name=None): - newdoc = doc.as_dict(no_nulls=True) - doc.run_method("before_export", newdoc) - - # strip out default fields from children - for df in doc.meta.get_table_fields(): - for d in newdoc.get(df.fieldname): - for fieldname in frappe.model.default_fields: - if fieldname in d: - del d[fieldname] + doc_export = doc.as_dict(no_nulls=True) + doc.run_method("before_export", doc_export) + strip_default_fields(doc, doc_export) module = record_module or get_module_name(doc) # create folder @@ -39,10 +33,33 @@ def write_document_file(doc, record_module=None, create_init=True, folder_name=N else: folder = create_folder(module, doc.doctype, doc.name, create_init) - # write the data file fname = scrub(doc.name) + write_code_files(folder, fname, doc, doc_export) + + # write the data file with open(os.path.join(folder, fname + ".json"), 'w+') as txtfile: - txtfile.write(frappe.as_json(newdoc)) + txtfile.write(frappe.as_json(doc_export)) + +def strip_default_fields(doc, doc_export): + # strip out default fields from children + for df in doc.meta.get_table_fields(): + for d in doc_export.get(df.fieldname): + for fieldname in frappe.model.default_fields: + if fieldname in d: + del d[fieldname] + +def write_code_files(folder, fname, doc, doc_export): + '''Export code files and strip from values''' + if hasattr(doc, 'get_code_fields'): + for key, extn in doc.get_code_fields().items(): + if doc.get(key): + with open(os.path.join(folder, fname + "." + extn), 'w+') as txtfile: + txtfile.write(doc.get(key)) + + # remove from exporting + del doc_export[key] + + def get_module_name(doc): if doc.doctype == 'Module Def': @@ -57,7 +74,10 @@ def get_module_name(doc): return module def create_folder(module, dt, dn, create_init): - module_path = get_module_path(module) + if frappe.db.get_value('Module Def', module, 'custom'): + module_path = get_custom_module_path(module) + else: + module_path = get_module_path(module) dt, dn = scrub_dt_dn(dt, dn) @@ -72,6 +92,23 @@ def create_folder(module, dt, dn, create_init): return folder +def get_custom_module_path(module): + package = frappe.db.get_value('Module Def', module, 'package') + if not package: + frappe.throw('Package must be set for custom Module {module}'.format(module=module)) + + path = os.path.join(get_package_path(package), scrub(module)) + if not os.path.exists(path): + os.makedirs(path) + + return path + +def get_package_path(package): + path = os.path.join(frappe.get_site_path('packages'), frappe.db.get_value('Package', package, 'package_name')) + if not os.path.exists(path): + os.makedirs(path) + return path + def create_init_py(module_path, dt, dn): def create_if_not_exists(path): initpy = os.path.join(path, '__init__.py') diff --git a/frappe/modules/import_file.py b/frappe/modules/import_file.py index e743f0c3da..e7a1f5f97c 100644 --- a/frappe/modules/import_file.py +++ b/frappe/modules/import_file.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import frappe, os, json from frappe.modules import get_module_path, scrub_dt_dn from frappe.utils import get_datetime_str @@ -54,31 +54,26 @@ def import_file_by_path(path, force=False, data_import=False, pre_process=None, docs = [docs] for doc in docs: - if not force: - # check if timestamps match - db_modified = frappe.db.get_value(doc['doctype'], doc['name'], 'modified') - if db_modified and doc.get('modified')==get_datetime_str(db_modified): - return False + if not force and not is_changed(doc): + return False original_modified = doc.get("modified") - frappe.flags.in_import = True import_doc(doc, force=force, data_import=data_import, pre_process=pre_process, - ignore_version=ignore_version, reset_permissions=reset_permissions) - frappe.flags.in_import = False + ignore_version=ignore_version, reset_permissions=reset_permissions, path=path) if original_modified: - # since there is a new timestamp on the file, update timestamp in - if doc["doctype"] == doc["name"] and doc["name"]!="DocType": - frappe.db.sql("""update tabSingles set value=%s where field="modified" and doctype=%s""", - (original_modified, doc["name"])) - else: - frappe.db.sql("update `tab%s` set modified=%s where name=%s" % \ - (doc['doctype'], '%s', '%s'), - (original_modified, doc['name'])) + update_modified(original_modified, doc) return True +def is_changed(doc): + # check if timestamps match + db_modified = frappe.db.get_value(doc['doctype'], doc['name'], 'modified') + if db_modified and doc.get('modified')==get_datetime_str(db_modified): + return False + return True + def read_doc_from_file(path): doc = None if os.path.exists(path): @@ -93,8 +88,17 @@ def read_doc_from_file(path): return doc +def update_modified(original_modified, doc): + # since there is a new timestamp on the file, update timestamp in + if doc["doctype"] == doc["name"] and doc["name"]!="DocType": + frappe.db.sql("""update tabSingles set value=%s where field="modified" and doctype=%s""", + (original_modified, doc["name"])) + else: + frappe.db.sql("update `tab%s` set modified=%s where name=%s" % (doc['doctype'], + '%s', '%s'), (original_modified, doc['name'])) + def import_doc(docdict, force=False, data_import=False, pre_process=None, - ignore_version=None, reset_permissions=False): + ignore_version=None, reset_permissions=False, path=None): frappe.flags.in_import = True docdict["__islocal"] = 1 @@ -104,14 +108,8 @@ def import_doc(docdict, force=False, data_import=False, pre_process=None, doc = frappe.get_doc(docdict) - # Note on Tree DocTypes: - # The tree structure is maintained in the database via the fields "lft" and - # "rgt". They are automatically set and kept up-to-date. Importing them - # would destroy any existing tree structure. - if getattr(doc.meta, 'is_tree', None) and any([doc.lft, doc.rgt]): - print('Ignoring values of `lft` and `rgt` for {} "{}"'.format(doc.doctype, doc.name)) - doc.lft = None - doc.rgt = None + reset_tree_properties(doc) + load_code_properties(doc, path) doc.run_method("before_import") @@ -119,27 +117,9 @@ def import_doc(docdict, force=False, data_import=False, pre_process=None, if pre_process: pre_process(doc) - ignore = [] - if frappe.db.exists(doc.doctype, doc.name): + delete_old_doc(doc, reset_permissions) - old_doc = frappe.get_doc(doc.doctype, doc.name) - - if doc.doctype in ignore_values: - # update ignore values - for key in ignore_values.get(doc.doctype) or []: - doc.set(key, old_doc.get(key)) - - # update ignored docs into new doc - for df in doc.meta.get_table_fields(): - if df.options in ignore_doctypes and not reset_permissions: - doc.set(df.fieldname, []) - ignore.append(df.options) - - # delete old - frappe.delete_doc(doc.doctype, doc.name, force=1, ignore_doctypes=ignore, for_reload=True) - - doc.flags.ignore_children_type = ignore doc.flags.ignore_links = True if not data_import: doc.flags.ignore_validate = True @@ -149,3 +129,47 @@ def import_doc(docdict, force=False, data_import=False, pre_process=None, doc.insert() frappe.flags.in_import = False + + return doc + +def load_code_properties(doc, path): + '''Load code files stored in separate files with extensions''' + if path: + if hasattr(doc, 'get_code_fields'): + dirname, filename = os.path.split(path) + for key, extn in doc.get_code_fields().items(): + codefile = os.path.join(dirname, filename.split('.')[0]+'.'+extn) + if os.path.exists(codefile): + with open(codefile,'r') as txtfile: + doc.set(key, txtfile.read()) + + +def delete_old_doc(doc, reset_permissions): + ignore = [] + old_doc = frappe.get_doc(doc.doctype, doc.name) + + if doc.doctype in ignore_values: + # update ignore values + for key in ignore_values.get(doc.doctype) or []: + doc.set(key, old_doc.get(key)) + + # update ignored docs into new doc + for df in doc.meta.get_table_fields(): + if df.options in ignore_doctypes and not reset_permissions: + doc.set(df.fieldname, []) + ignore.append(df.options) + + # delete old + frappe.delete_doc(doc.doctype, doc.name, force=1, ignore_doctypes=ignore, for_reload=True) + + doc.flags.ignore_children_type = ignore + +def reset_tree_properties(doc): + # Note on Tree DocTypes: + # The tree structure is maintained in the database via the fields "lft" and + # "rgt". They are automatically set and kept up-to-date. Importing them + # would destroy any existing tree structure. + if getattr(doc.meta, 'is_tree', None) and any([doc.lft, doc.rgt]): + print('Ignoring values of `lft` and `rgt` for {} "{}"'.format(doc.doctype, doc.name)) + doc.lft = None + doc.rgt = None diff --git a/frappe/modules/patch_handler.py b/frappe/modules/patch_handler.py index 029234d5d9..8dfb27c0b8 100644 --- a/frappe/modules/patch_handler.py +++ b/frappe/modules/patch_handler.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE """ Execute Patch Files diff --git a/frappe/modules/utils.py b/frappe/modules/utils.py index ed2a839dc1..bbfd63a277 100644 --- a/frappe/modules/utils.py +++ b/frappe/modules/utils.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE """ Utilities for using modules """ diff --git a/frappe/monitor.py b/frappe/monitor.py index 34ca7d67f7..6bad03dfe9 100644 --- a/frappe/monitor.py +++ b/frappe/monitor.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE from datetime import datetime import json diff --git a/frappe/patches/v10_0/modify_smallest_currency_fraction.py b/frappe/patches/v10_0/modify_smallest_currency_fraction.py index c9ae477359..9469d546ce 100644 --- a/frappe/patches/v10_0/modify_smallest_currency_fraction.py +++ b/frappe/patches/v10_0/modify_smallest_currency_fraction.py @@ -1,5 +1,5 @@ # Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import frappe diff --git a/frappe/patches/v10_0/set_default_locking_time.py b/frappe/patches/v10_0/set_default_locking_time.py index 045fa0e3fa..11993e1163 100644 --- a/frappe/patches/v10_0/set_default_locking_time.py +++ b/frappe/patches/v10_0/set_default_locking_time.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import frappe diff --git a/frappe/patches/v11_0/change_email_signature_fieldtype.py b/frappe/patches/v11_0/change_email_signature_fieldtype.py index ccfa8541c3..7c57aa044e 100644 --- a/frappe/patches/v11_0/change_email_signature_fieldtype.py +++ b/frappe/patches/v11_0/change_email_signature_fieldtype.py @@ -1,5 +1,5 @@ # Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import frappe diff --git a/frappe/patches/v11_0/remove_doctype_user_permissions_for_page_and_report.py b/frappe/patches/v11_0/remove_doctype_user_permissions_for_page_and_report.py index 5c54b1e5c1..ff5cf3fc5e 100644 --- a/frappe/patches/v11_0/remove_doctype_user_permissions_for_page_and_report.py +++ b/frappe/patches/v11_0/remove_doctype_user_permissions_for_page_and_report.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import frappe diff --git a/frappe/patches/v12_0/set_default_password_reset_limit.py b/frappe/patches/v12_0/set_default_password_reset_limit.py index 188f2383e7..e403b5251e 100644 --- a/frappe/patches/v12_0/set_default_password_reset_limit.py +++ b/frappe/patches/v12_0/set_default_password_reset_limit.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import frappe diff --git a/frappe/patches/v13_0/delete_event_producer_and_consumer_keys.py b/frappe/patches/v13_0/delete_event_producer_and_consumer_keys.py index 776e9c796e..2d9e232da5 100644 --- a/frappe/patches/v13_0/delete_event_producer_and_consumer_keys.py +++ b/frappe/patches/v13_0/delete_event_producer_and_consumer_keys.py @@ -1,5 +1,5 @@ # Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import frappe diff --git a/frappe/patches/v13_0/delete_package_publish_tool.py b/frappe/patches/v13_0/delete_package_publish_tool.py index bf9aaf5a76..5c1678bdbe 100644 --- a/frappe/patches/v13_0/delete_package_publish_tool.py +++ b/frappe/patches/v13_0/delete_package_publish_tool.py @@ -1,5 +1,5 @@ # Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import frappe diff --git a/frappe/patches/v13_0/enable_custom_script.py b/frappe/patches/v13_0/enable_custom_script.py index 0684074fe7..de027ab97a 100644 --- a/frappe/patches/v13_0/enable_custom_script.py +++ b/frappe/patches/v13_0/enable_custom_script.py @@ -1,5 +1,5 @@ # Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import frappe diff --git a/frappe/patches/v13_0/generate_theme_files_in_public_folder.py b/frappe/patches/v13_0/generate_theme_files_in_public_folder.py index dd9fb1961a..6e8e0d7fc5 100644 --- a/frappe/patches/v13_0/generate_theme_files_in_public_folder.py +++ b/frappe/patches/v13_0/generate_theme_files_in_public_folder.py @@ -1,5 +1,5 @@ # Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import frappe diff --git a/frappe/patches/v13_0/increase_password_length.py b/frappe/patches/v13_0/increase_password_length.py index 62ca2ed779..deb7d7e98a 100644 --- a/frappe/patches/v13_0/increase_password_length.py +++ b/frappe/patches/v13_0/increase_password_length.py @@ -1,4 +1,4 @@ import frappe def execute(): - frappe.db.change_column_type(table="__Auth", column="password", type="TEXT") + frappe.db.change_column_type("__Auth", column="password", type="TEXT") diff --git a/frappe/patches/v13_0/jinja_hook.py b/frappe/patches/v13_0/jinja_hook.py index 990ae50f35..e1c9175576 100644 --- a/frappe/patches/v13_0/jinja_hook.py +++ b/frappe/patches/v13_0/jinja_hook.py @@ -1,5 +1,5 @@ # Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import frappe from click import secho diff --git a/frappe/patches/v13_0/queryreport_columns.py b/frappe/patches/v13_0/queryreport_columns.py index 5c381f4f3e..ed22ce4441 100644 --- a/frappe/patches/v13_0/queryreport_columns.py +++ b/frappe/patches/v13_0/queryreport_columns.py @@ -1,5 +1,5 @@ # Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import frappe import json diff --git a/frappe/patches/v13_0/remove_tailwind_from_page_builder.py b/frappe/patches/v13_0/remove_tailwind_from_page_builder.py index 2bf2c7bf87..b26d2bef4a 100644 --- a/frappe/patches/v13_0/remove_tailwind_from_page_builder.py +++ b/frappe/patches/v13_0/remove_tailwind_from_page_builder.py @@ -1,5 +1,5 @@ # Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import frappe diff --git a/frappe/patches/v13_0/remove_twilio_settings.py b/frappe/patches/v13_0/remove_twilio_settings.py index 7efaf876e2..826edfb951 100644 --- a/frappe/patches/v13_0/remove_twilio_settings.py +++ b/frappe/patches/v13_0/remove_twilio_settings.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import frappe diff --git a/frappe/patches/v13_0/rename_list_view_setting_to_list_view_settings.py b/frappe/patches/v13_0/rename_list_view_setting_to_list_view_settings.py index 3122de8bea..db3ab1b32a 100644 --- a/frappe/patches/v13_0/rename_list_view_setting_to_list_view_settings.py +++ b/frappe/patches/v13_0/rename_list_view_setting_to_list_view_settings.py @@ -1,5 +1,5 @@ # Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import frappe diff --git a/frappe/patches/v13_0/rename_notification_fields.py b/frappe/patches/v13_0/rename_notification_fields.py index 1413d80358..2f314df9c1 100644 --- a/frappe/patches/v13_0/rename_notification_fields.py +++ b/frappe/patches/v13_0/rename_notification_fields.py @@ -1,5 +1,5 @@ # Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import frappe from frappe.model.utils.rename_field import rename_field diff --git a/frappe/patches/v13_0/rename_onboarding.py b/frappe/patches/v13_0/rename_onboarding.py index 852065dfd2..cd910195ad 100644 --- a/frappe/patches/v13_0/rename_onboarding.py +++ b/frappe/patches/v13_0/rename_onboarding.py @@ -1,5 +1,5 @@ # Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import frappe diff --git a/frappe/patches/v13_0/replace_old_data_import.py b/frappe/patches/v13_0/replace_old_data_import.py index 838881b48e..7d2692a433 100644 --- a/frappe/patches/v13_0/replace_old_data_import.py +++ b/frappe/patches/v13_0/replace_old_data_import.py @@ -1,5 +1,5 @@ # Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import frappe diff --git a/frappe/patches/v13_0/update_duration_options.py b/frappe/patches/v13_0/update_duration_options.py index e0d8dea4ea..48f0dc0969 100644 --- a/frappe/patches/v13_0/update_duration_options.py +++ b/frappe/patches/v13_0/update_duration_options.py @@ -1,5 +1,5 @@ # Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import frappe diff --git a/frappe/patches/v13_0/update_newsletter_content_type.py b/frappe/patches/v13_0/update_newsletter_content_type.py index 5f047680ee..39758c8257 100644 --- a/frappe/patches/v13_0/update_newsletter_content_type.py +++ b/frappe/patches/v13_0/update_newsletter_content_type.py @@ -1,5 +1,5 @@ # Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import frappe diff --git a/frappe/patches/v13_0/update_notification_channel_if_empty.py b/frappe/patches/v13_0/update_notification_channel_if_empty.py index bcf9a7b28c..43cf813c74 100644 --- a/frappe/patches/v13_0/update_notification_channel_if_empty.py +++ b/frappe/patches/v13_0/update_notification_channel_if_empty.py @@ -1,5 +1,5 @@ # Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import frappe diff --git a/frappe/patches/v13_0/web_template_set_module.py b/frappe/patches/v13_0/web_template_set_module.py index 2ee9e3ba2d..d200f4e0da 100644 --- a/frappe/patches/v13_0/web_template_set_module.py +++ b/frappe/patches/v13_0/web_template_set_module.py @@ -1,5 +1,5 @@ # Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import frappe diff --git a/frappe/permissions.py b/frappe/permissions.py index af7bc3b602..7ee1119ebb 100644 --- a/frappe/permissions.py +++ b/frappe/permissions.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import copy import frappe diff --git a/frappe/printing/doctype/letter_head/letter_head.py b/frappe/printing/doctype/letter_head/letter_head.py index 948be60b88..eeaef28393 100644 --- a/frappe/printing/doctype/letter_head/letter_head.py +++ b/frappe/printing/doctype/letter_head/letter_head.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# License: MIT. See LICENSE import frappe from frappe.utils import is_image diff --git a/frappe/printing/doctype/letter_head/test_letter_head.py b/frappe/printing/doctype/letter_head/test_letter_head.py index 96dfc68705..67d307ee8b 100644 --- a/frappe/printing/doctype/letter_head/test_letter_head.py +++ b/frappe/printing/doctype/letter_head/test_letter_head.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE import frappe import unittest diff --git a/frappe/printing/doctype/network_printer_settings/__init__.py b/frappe/printing/doctype/network_printer_settings/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/frappe/printing/doctype/network_printer_settings/network_printer_settings.js b/frappe/printing/doctype/network_printer_settings/network_printer_settings.js new file mode 100644 index 0000000000..043afd388f --- /dev/null +++ b/frappe/printing/doctype/network_printer_settings/network_printer_settings.js @@ -0,0 +1,29 @@ +// Copyright (c) 2021, Frappe Technologies and contributors +// For license information, please see license.txt + +frappe.ui.form.on('Network Printer Settings', { + onload (frm) { + frm.trigger("connect_print_server"); + }, + server_ip (frm) { + frm.trigger("connect_print_server"); + }, + port (frm) { + frm.trigger("connect_print_server"); + }, + connect_print_server (frm) { + if (frm.doc.server_ip && frm.doc.port) { + frappe.call({ + "doc": frm.doc, + "method": "get_printers_list", + "args": { + ip: frm.doc.server_ip, + port: frm.doc.port + }, + callback: function(data) { + frm.set_df_property('printer_name', 'options', [""].concat(data.message)); + } + }); + } + } +}); diff --git a/frappe/printing/doctype/network_printer_settings/network_printer_settings.json b/frappe/printing/doctype/network_printer_settings/network_printer_settings.json new file mode 100644 index 0000000000..cbef4b8ba4 --- /dev/null +++ b/frappe/printing/doctype/network_printer_settings/network_printer_settings.json @@ -0,0 +1,66 @@ +{ + "actions": [], + "autoname": "Prompt", + "creation": "2021-09-17 11:26:06.943999", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "server_ip", + "port", + "column_break_4", + "printer_name" + ], + "fields": [ + { + "default": "localhost", + "fieldname": "server_ip", + "fieldtype": "Data", + "in_list_view": 1, + "label": "Server IP", + "reqd": 1 + }, + { + "default": "631", + "fieldname": "port", + "fieldtype": "Int", + "in_list_view": 1, + "label": "Port", + "reqd": 1 + }, + { + "fieldname": "column_break_4", + "fieldtype": "Column Break" + }, + { + "fieldname": "printer_name", + "fieldtype": "Select", + "label": "Printer Name", + "reqd": 1 + } + ], + "index_web_pages_for_search": 1, + "links": [], + "modified": "2021-09-17 11:30:16.781655", + "modified_by": "Administrator", + "module": "Printing", + "name": "Network Printer Settings", + "owner": "Administrator", + "permissions": [ + { + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "System Manager", + "share": 1, + "write": 1 + } + ], + "sort_field": "modified", + "sort_order": "DESC", + "track_changes": 1 +} \ No newline at end of file diff --git a/frappe/printing/doctype/network_printer_settings/network_printer_settings.py b/frappe/printing/doctype/network_printer_settings/network_printer_settings.py new file mode 100644 index 0000000000..e42ed818c7 --- /dev/null +++ b/frappe/printing/doctype/network_printer_settings/network_printer_settings.py @@ -0,0 +1,37 @@ +# Copyright (c) 2021, Frappe Technologies and contributors +# For license information, please see license.txt + +import frappe +from frappe.model.document import Document +from frappe import _ + +class NetworkPrinterSettings(Document): + @frappe.whitelist() + def get_printers_list(self,ip="localhost",port=631): + printer_list = [] + try: + import cups + except ImportError: + frappe.throw(_('''This feature can not be used as dependencies are missing. + Please contact your system manager to enable this by installing pycups!''')) + return + try: + cups.setServer(self.server_ip) + cups.setPort(self.port) + conn = cups.Connection() + printers = conn.getPrinters() + for printer_id,printer in printers.items(): + printer_list.append({ + 'value': printer_id, + 'label': printer['printer-make-and-model'] + }) + + except RuntimeError: + frappe.throw(_("Failed to connect to server")) + except frappe.ValidationError: + frappe.throw(_("Failed to connect to server")) + return printer_list + +@frappe.whitelist() +def get_network_printer_settings(): + return frappe.db.get_list('Network Printer Settings', pluck='name') diff --git a/frappe/printing/doctype/network_printer_settings/test_network_printer_settings.py b/frappe/printing/doctype/network_printer_settings/test_network_printer_settings.py new file mode 100644 index 0000000000..86509b239f --- /dev/null +++ b/frappe/printing/doctype/network_printer_settings/test_network_printer_settings.py @@ -0,0 +1,8 @@ +# Copyright (c) 2021, Frappe Technologies and Contributors +# See license.txt + +# import frappe +import unittest + +class TestNetworkPrinterSettings(unittest.TestCase): + pass diff --git a/frappe/printing/doctype/print_format/print_format.js b/frappe/printing/doctype/print_format/print_format.js index 786f8f97ab..adc5e2363c 100644 --- a/frappe/printing/doctype/print_format/print_format.js +++ b/frappe/printing/doctype/print_format/print_format.js @@ -36,21 +36,23 @@ frappe.ui.form.on("Print Format", { else if (frm.doc.custom_format && !frm.doc.raw_printing) { frm.set_df_property("html", "reqd", 1); } - frappe.db.get_value('DocType', frm.doc.doc_type, 'default_print_format', (r) => { - if (r.default_print_format != frm.doc.name) { - frm.add_custom_button(__("Set as Default"), function () { - frappe.call({ - method: "frappe.printing.doctype.print_format.print_format.make_default", - args: { - name: frm.doc.name - }, - callback: function() { - frm.refresh(); - } + if (frappe.perm.has_perm('DocType', 0, 'read', frm.doc.doc_type)) { + frappe.db.get_value('DocType', frm.doc.doc_type, 'default_print_format', (r) => { + if (r.default_print_format != frm.doc.name) { + frm.add_custom_button(__("Set as Default"), function () { + frappe.call({ + method: "frappe.printing.doctype.print_format.print_format.make_default", + args: { + name: frm.doc.name + }, + callback: function() { + frm.refresh(); + } + }); }); - }); - } - }); + } + }); + } } }, custom_format: function (frm) { diff --git a/frappe/printing/doctype/print_format/print_format.py b/frappe/printing/doctype/print_format/print_format.py index 5d4ff92fe2..878a864b38 100644 --- a/frappe/printing/doctype/print_format/print_format.py +++ b/frappe/printing/doctype/print_format/print_format.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe import frappe.utils diff --git a/frappe/printing/doctype/print_format/test_print_format.py b/frappe/printing/doctype/print_format/test_print_format.py index e65eb0183f..564a2c750c 100644 --- a/frappe/printing/doctype/print_format/test_print_format.py +++ b/frappe/printing/doctype/print_format/test_print_format.py @@ -1,5 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# See license.txt +# License: MIT. See LICENSE import frappe import unittest import re diff --git a/frappe/printing/doctype/print_heading/print_heading.py b/frappe/printing/doctype/print_heading/print_heading.py index f9955c019d..39c46ad152 100644 --- a/frappe/printing/doctype/print_heading/print_heading.py +++ b/frappe/printing/doctype/print_heading/print_heading.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe from frappe.model.document import Document diff --git a/frappe/printing/doctype/print_heading/test_print_heading.py b/frappe/printing/doctype/print_heading/test_print_heading.py index ce99cde607..7eaa1bc6ba 100644 --- a/frappe/printing/doctype/print_heading/test_print_heading.py +++ b/frappe/printing/doctype/print_heading/test_print_heading.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE import frappe import unittest diff --git a/frappe/printing/doctype/print_settings/print_settings.js b/frappe/printing/doctype/print_settings/print_settings.js index 9616892a31..b1311166ee 100644 --- a/frappe/printing/doctype/print_settings/print_settings.js +++ b/frappe/printing/doctype/print_settings/print_settings.js @@ -15,27 +15,5 @@ frappe.ui.form.on('Print Settings', { }, onload: function(frm) { frm.script_manager.trigger("print_style"); - }, - server_ip: function(frm) { - frm.trigger("connect_print_server"); - }, - port:function(frm) { - frm.trigger("connect_print_server"); - }, - connect_print_server:function(frm) { - if(frm.doc.server_ip && frm.doc.port){ - frappe.call({ - "doc": frm.doc, - "method": "get_printers", - "args": { - ip: frm.doc.server_ip, - port: frm.doc.port - }, - callback: function(data) { - frm.set_df_property('printer_name', 'options', [""].concat(data.message)); - }, - error: (data) => frm.set_value("enable_print_server", 0) - }); - } } }); diff --git a/frappe/printing/doctype/print_settings/print_settings.json b/frappe/printing/doctype/print_settings/print_settings.json index 31962be050..babbae248d 100644 --- a/frappe/printing/doctype/print_settings/print_settings.json +++ b/frappe/printing/doctype/print_settings/print_settings.json @@ -19,9 +19,6 @@ "allow_print_for_cancelled", "server_printer", "enable_print_server", - "server_ip", - "printer_name", - "port", "raw_printing_section", "enable_raw_printing", "print_style_section", @@ -107,29 +104,11 @@ }, { "default": "0", + "depends_on": "enable_print_server", "fieldname": "enable_print_server", "fieldtype": "Check", - "label": "Enable Print Server" - }, - { - "default": "localhost", - "depends_on": "enable_print_server", - "fieldname": "server_ip", - "fieldtype": "Data", - "label": "Server IP" - }, - { - "depends_on": "enable_print_server", - "fieldname": "printer_name", - "fieldtype": "Select", - "label": "Printer Name" - }, - { - "default": "631", - "depends_on": "enable_print_server", - "fieldname": "port", - "fieldtype": "Int", - "label": "Port" + "label": "Enable Print Server", + "mandatory_depends_on": "enable_print_server" }, { "fieldname": "raw_printing_section", @@ -183,7 +162,7 @@ "index_web_pages_for_search": 1, "issingle": 1, "links": [], - "modified": "2021-02-15 14:16:18.474254", + "modified": "2021-09-17 12:59:14.783694", "modified_by": "Administrator", "module": "Printing", "name": "Print Settings", diff --git a/frappe/printing/doctype/print_settings/print_settings.py b/frappe/printing/doctype/print_settings/print_settings.py index 610c083097..ff00317cf8 100644 --- a/frappe/printing/doctype/print_settings/print_settings.py +++ b/frappe/printing/doctype/print_settings/print_settings.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2018, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe from frappe import _ @@ -12,26 +12,6 @@ class PrintSettings(Document): def on_update(self): frappe.clear_cache() - @frappe.whitelist() - def get_printers(self,ip="localhost",port=631): - printer_list = [] - try: - import cups - except ImportError: - frappe.throw(_("You need to install pycups to use this feature!")) - return - try: - cups.setServer(self.server_ip) - cups.setPort(self.port) - conn = cups.Connection() - printers = conn.getPrinters() - printer_list = printers.keys() - except RuntimeError: - frappe.throw(_("Failed to connect to server")) - except frappe.ValidationError: - frappe.throw(_("Failed to connect to server")) - return printer_list - @frappe.whitelist() def is_print_server_enabled(): if not hasattr(frappe.local, 'enable_print_server'): diff --git a/frappe/printing/doctype/print_settings/test_print_settings.py b/frappe/printing/doctype/print_settings/test_print_settings.py index d1dec861b2..82883eaee5 100644 --- a/frappe/printing/doctype/print_settings/test_print_settings.py +++ b/frappe/printing/doctype/print_settings/test_print_settings.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2018, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE import unittest class TestPrintSettings(unittest.TestCase): diff --git a/frappe/printing/doctype/print_style/print_style.py b/frappe/printing/doctype/print_style/print_style.py index a91786795c..7985c006f4 100644 --- a/frappe/printing/doctype/print_style/print_style.py +++ b/frappe/printing/doctype/print_style/print_style.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and contributors -# For license information, please see license.txt +# License: MIT. See LICENSE import frappe from frappe.model.document import Document diff --git a/frappe/printing/doctype/print_style/test_print_style.py b/frappe/printing/doctype/print_style/test_print_style.py index b717b23df8..cbf5c465d1 100644 --- a/frappe/printing/doctype/print_style/test_print_style.py +++ b/frappe/printing/doctype/print_style/test_print_style.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and Contributors -# See license.txt +# License: MIT. See LICENSE import frappe import unittest diff --git a/frappe/printing/page/print/print.js b/frappe/printing/page/print/print.js index ca2a340661..d3b1c69815 100644 --- a/frappe/printing/page/print/print.js +++ b/frappe/printing/page/print/print.js @@ -165,20 +165,23 @@ frappe.ui.form.PrintView = class { frappe.set_route('Form', 'Print Settings'); }); - if ( - frappe.model.get_doc(':Print Settings', 'Print Settings') - .enable_raw_printing == '1' - ) { + if (this.print_settings.enable_raw_printing == '1') { this.page.add_menu_item(__('Raw Printing Setting'), () => { this.printer_setting_dialog(); }); } - if (frappe.user.has_role('System Manager')) { + if (frappe.perm.has_perm('Print Format', 0, 'create')) { this.page.add_menu_item(__('Customize'), () => this.edit_print_format() ); } + + if (this.print_settings.enable_print_server) { + this.page.add_menu_item(__('Select Network Printer'), () => + this.network_printer_setting_dialog() + ); + } } show(frm) { @@ -460,72 +463,108 @@ frappe.ui.form.PrintView = class { printit() { let me = this; - frappe.call({ - method: - 'frappe.printing.doctype.print_settings.print_settings.is_print_server_enabled', - callback: function(data) { - if (data.message) { - frappe.call({ - method: 'frappe.utils.print_format.print_by_server', - args: { - doctype: me.frm.doc.doctype, - name: me.frm.doc.name, - print_format: me.selected_format(), - no_letterhead: me.with_letterhead(), - letterhead: this.get_letterhead(), - }, - callback: function() {}, - }); - } else if (me.get_mapped_printer().length === 1) { - // printer is already mapped in localstorage (applies for both raw and pdf ) - if (me.is_raw_printing()) { - me.get_raw_commands(function(out) { - frappe.ui.form - .qz_connect() - .then(function() { - let printer_map = me.get_mapped_printer()[0]; - let data = [out.raw_commands]; - let config = qz.configs.create(printer_map.printer); - return qz.print(config, data); - }) - .then(frappe.ui.form.qz_success) - .catch((err) => { - frappe.ui.form.qz_fail(err); - }); + + if (me.print_settings.enable_print_server) { + if (localStorage.getItem('network_printer')) { + me.print_by_server(); + } else { + me.network_printer_setting_dialog(() => me.print_by_server()); + } + } else if (me.get_mapped_printer().length === 1) { + // printer is already mapped in localstorage (applies for both raw and pdf ) + if (me.is_raw_printing()) { + me.get_raw_commands(function(out) { + frappe.ui.form + .qz_connect() + .then(function() { + let printer_map = me.get_mapped_printer()[0]; + let data = [out.raw_commands]; + let config = qz.configs.create(printer_map.printer); + return qz.print(config, data); + }) + .then(frappe.ui.form.qz_success) + .catch((err) => { + frappe.ui.form.qz_fail(err); }); - } else { - frappe.show_alert( + }); + } else { + frappe.show_alert( + { + message: __('PDF printing via "Raw Print" is not supported.'), + subtitle: __( + 'Please remove the printer mapping in Printer Settings and try again.' + ), + indicator: 'info', + }, + 14 + ); + //Note: need to solve "Error: Cannot parse (FILE) as a PDF file" to enable qz pdf printing. + } + } else if (me.is_raw_printing()) { + // printer not mapped in localstorage and the current print format is raw printing + frappe.show_alert( + { + message: __('Printer mapping not set.'), + subtitle: __( + 'Please set a printer mapping for this print format in the Printer Settings' + ), + indicator: 'warning', + }, + 14 + ); + me.printer_setting_dialog(); + } else { + me.render_page('/printview?', true); + } + } + + print_by_server() { + let me = this; + if (localStorage.getItem('network_printer')) { + frappe.call({ + method: 'frappe.utils.print_format.print_by_server', + args: { + doctype: me.frm.doc.doctype, + name: me.frm.doc.name, + printer_setting: localStorage.getItem('network_printer'), + print_format: me.selected_format(), + no_letterhead: me.with_letterhead(), + letterhead: me.get_letterhead(), + }, + callback: function() {}, + }); + } + } + network_printer_setting_dialog(callback) { + frappe.call({ + method: 'frappe.printing.doctype.network_printer_settings.network_printer_settings.get_network_printer_settings', + callback: function(r) { + if (r.message) { + let d = new frappe.ui.Dialog({ + title: __('Select Network Printer'), + fields: [ { - message: __('PDF printing via "Raw Print" is not supported.'), - subtitle: __( - 'Please remove the printer mapping in Printer Settings and try again.' - ), - indicator: 'info', - }, - 14 - ); - //Note: need to solve "Error: Cannot parse (FILE) as a PDF file" to enable qz pdf printing. - } - } else if (me.is_raw_printing()) { - // printer not mapped in localstorage and the current print format is raw printing - frappe.show_alert( - { - message: __('Printer mapping not set.'), - subtitle: __( - 'Please set a printer mapping for this print format in the Printer Settings' - ), - indicator: 'warning', + "label": "Printer", + "fieldname": "printer", + "fieldtype": "Select", + "reqd": 1, + "options": r.message + } + ], + primary_action: function() { + localStorage.setItem('network_printer', d.get_values().printer); + if (typeof callback == "function") { + callback(); + } + d.hide(); }, - 14 - ); - me.printer_setting_dialog(); - } else { - me.render_page('/printview?', true); + primary_action_label: __('Select') + }); + d.show(); } }, }); } - render_page(method, printit = false) { let w = window.open( frappe.urllib.get_full_url( diff --git a/frappe/printing/page/print_format_builder/print_format_builder.js b/frappe/printing/page/print_format_builder/print_format_builder.js index ca2a8bc378..b73ff31d32 100644 --- a/frappe/printing/page/print_format_builder/print_format_builder.js +++ b/frappe/printing/page/print_format_builder/print_format_builder.js @@ -261,7 +261,7 @@ frappe.PrintFormatBuilder = class PrintFormatBuilder { } else if(f.fieldtype==="Column Break") { set_column(); - } else if(!in_list(["Section Break", "Column Break", "Fold"], f.fieldtype) + } else if (!in_list(["Section Break", "Column Break", "Tab Break", "Fold"], f.fieldtype) && f.label) { if(!column) set_column(); @@ -298,7 +298,7 @@ frappe.PrintFormatBuilder = class PrintFormatBuilder { init_visible_columns(f) { f.visible_columns = [] $.each(frappe.get_meta(f.options).fields, function(i, _f) { - if(!in_list(["Section Break", "Column Break"], _f.fieldtype) && + if (!in_list(["Section Break", "Column Break", "Tab Break"], _f.fieldtype) && !_f.print_hide && f.label) { // column names set as fieldname|width @@ -606,7 +606,7 @@ frappe.PrintFormatBuilder = class PrintFormatBuilder { // add remaining fields $.each(doc_fields, function(j, f) { if (f && !in_list(column_names, f.fieldname) - && !in_list(["Section Break", "Column Break"], f.fieldtype) && f.label) { + && !in_list(["Section Break", "Column Break", "Tab Break"], f.fieldtype) && f.label) { fields.push(f); } }) diff --git a/frappe/printing/page/print_format_builder/print_format_builder_sidebar.html b/frappe/printing/page/print_format_builder/print_format_builder_sidebar.html index 1ebb87ac31..c608eecbbd 100644 --- a/frappe/printing/page/print_format_builder/print_format_builder_sidebar.html +++ b/frappe/printing/page/print_format_builder/print_format_builder_sidebar.html @@ -4,7 +4,7 @@
Id + Time + State + Info + Progress +