<commit_before># Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# MIT License. See license.txt

from __future__ import unicode_literals, print_function
"""
	Utilities for using modules
"""
import frappe, os, json
import frappe.utils
from frappe import _

def export_module_json(doc, is_standard, module):
	"""Make a folder for the given doc and add its json file (make it a standard
		object that will be synced)"""
	if (not frappe.flags.in_import and getattr(frappe.get_conf(),'developer_mode', 0)
		and is_standard):
		from frappe.modules.export_file import export_to_files

		# json
		export_to_files(record_list=[[doc.doctype, doc.name]], record_module=module,
			create_init=is_standard)

		path = os.path.join(frappe.get_module_path(module), scrub(doc.doctype),
			scrub(doc.name), scrub(doc.name))

		return path

def get_doc_module(module, doctype, name):
	"""Get custom module for given document"""
	module_name = "{app}.{module}.{doctype}.{name}.{name}".format(
			app = frappe.local.module_app[scrub(module)],
			doctype = scrub(doctype),
			module = scrub(module),
			name = scrub(name)
	)
	return frappe.get_module(module_name)

@frappe.whitelist()
def export_customizations(module, doctype, sync_on_migrate=0, with_permissions=0):
	"""Export Custom Field and Property Setter for the current document to the app folder.
		This will be synced with bench migrate"""
	if not frappe.get_conf().developer_mode:
		raise Exception('Not developer mode')

	custom = {'custom_fields': [], 'property_setters': [], 'custom_perms': [],
		'doctype': doctype, 'sync_on_migrate': 1}

	def add(_doctype):
		custom['custom_fields'] += frappe.get_all('Custom Field',
			fields='*', filters={'dt': _doctype})
		custom['property_setters'] += frappe.get_all('Property Setter',
			fields='*', filters={'doc_type': _doctype})

	add(doctype)

	if with_permissions:
		custom['custom_perms'] = frappe.get_all('Custom DocPerm',
			fields='*', filters={'parent': doctype})

	# add custom fields and property setters for all child tables
	for d in frappe.get_meta(doctype).get_table_fields():
		add(d.options)

	folder_path = os.path.join(get_module_path(module), 'custom')
	if not os.path.exists(folder_path):
		os.makedirs(folder_path)

	path = os.path.join(folder_path, scrub(doctype)+ '.json')
	with open(path, 'w') as f:
		f.write(frappe.as_json(custom))

	frappe.msgprint(_('Customizations exported to {0}').format(path))

def sync_customizations(app=None):
	'''Sync custom fields and property setters from custom folder in each app module'''

	if app:
		apps = [app]
	else:
		apps = frappe.get_installed_apps()

	for app_name in apps:
		for module_name in frappe.local.app_modules.get(app_name) or []:
			folder = frappe.get_app_path(app_name, module_name, 'custom')

			if os.path.exists(folder):
				for fname in os.listdir(folder):
					with open(os.path.join(folder, fname), 'r') as f:
						data = json.loads(f.read())

					if data.get('sync_on_migrate'):
						sync_customizations_for_doctype(data)


def sync_customizations_for_doctype(data):
	'''Sync doctype customzations for a particular data set'''
	from frappe.core.doctype.doctype.doctype import validate_fields_for_doctype

	doctype = data['doctype']
	update_schema = False

	def sync(key, custom_doctype, doctype_fieldname):
		frappe.db.sql('delete from `tab{0}` where `{1}`=%s'.format(custom_doctype, doctype_fieldname),
			doctype)

		for d in data[key]:
			d['doctype'] = custom_doctype
			doc = frappe.get_doc(d)
			doc.db_insert()

	if data['custom_fields']:
		sync('custom_fields', 'Custom Field', 'dt')
		update_schema = True

	if data['property_setters']:<commit_msg>[hotfix] delete and sync the child table customization (#4371)<commit_after># Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# MIT License. See license.txt

from __future__ import unicode_literals, print_function
"""
	Utilities for using modules
"""
import frappe, os, json
import frappe.utils
from frappe import _

def export_module_json(doc, is_standard, module):
	"""Make a folder for the given doc and add its json file (make it a standard
		object that will be synced)"""
	if (not frappe.flags.in_import and getattr(frappe.get_conf(),'developer_mode', 0)
		and is_standard):
		from frappe.modules.export_file import export_to_files

		# json
		export_to_files(record_list=[[doc.doctype, doc.name]], record_module=module,
			create_init=is_standard)

		path = os.path.join(frappe.get_module_path(module), scrub(doc.doctype),
			scrub(doc.name), scrub(doc.name))

		return path

def get_doc_module(module, doctype, name):
	"""Get custom module for given document"""
	module_name = "{app}.{module}.{doctype}.{name}.{name}".format(
			app = frappe.local.module_app[scrub(module)],
			doctype = scrub(doctype),
			module = scrub(module),
			name = scrub(name)
	)
	return frappe.get_module(module_name)

@frappe.whitelist()
def export_customizations(module, doctype, sync_on_migrate=0, with_permissions=0):
	"""Export Custom Field and Property Setter for the current document to the app folder.
		This will be synced with bench migrate"""
	if not frappe.get_conf().developer_mode:
		raise Exception('Not developer mode')

	custom = {'custom_fields': [], 'property_setters': [], 'custom_perms': [],
		'doctype': doctype, 'sync_on_migrate': 1}

	def add(_doctype):
		custom['custom_fields'] += frappe.get_all('Custom Field',
			fields='*', filters={'dt': _doctype})
		custom['property_setters'] += frappe.get_all('Property Setter',
			fields='*', filters={'doc_type': _doctype})

	add(doctype)

	if with_permissions:
		custom['custom_perms'] = frappe.get_all('Custom DocPerm',
			fields='*', filters={'parent': doctype})

	# add custom fields and property setters for all child tables
	for d in frappe.get_meta(doctype).get_table_fields():
		add(d.options)

	folder_path = os.path.join(get_module_path(module), 'custom')
	if not os.path.exists(folder_path):
		os.makedirs(folder_path)

	path = os.path.join(folder_path, scrub(doctype)+ '.json')
	with open(path, 'w') as f:
		f.write(frappe.as_json(custom))

	frappe.msgprint(_('Customizations exported to {0}').format(path))

def sync_customizations(app=None):
	'''Sync custom fields and property setters from custom folder in each app module'''

	if app:
		apps = [app]
	else:
		apps = frappe.get_installed_apps()

	for app_name in apps:
		for module_name in frappe.local.app_modules.get(app_name) or []:
			folder = frappe.get_app_path(app_name, module_name, 'custom')

			if os.path.exists(folder):
				for fname in os.listdir(folder):
					with open(os.path.join(folder, fname), 'r') as f:
						data = json.loads(f.read())

					if data.get('sync_on_migrate'):
						sync_customizations_for_doctype(data)


def sync_customizations_for_doctype(data):
	'''Sync doctype customzations for a particular data set'''
	from frappe.core.doctype.doctype.doctype import validate_fields_for_doctype

	doctype = data['doctype']
	update_schema = False

	def sync(key, custom_doctype, doctype_fieldname):
		doctypes = list(set(map(lambda row: row.get(doctype_fieldname), data[key])))
		frappe.db.sql('delete from `tab{0}` where `{1}` in ({2})'.format(
			custom_doctype, doctype_fieldname, ",".join(["'%s'" % dt for dt in doctypes])))

		for d in data[key]:
			d['doctype'] = custom_doctype
			doc = frappe.get_doc(d)
			doc.db_insert()

	if data['custom_fields']:
		sync('custom_fields', 'Custom Field', 'dt')
		update_schema = True

	if data['property_setters']:
{'fraction_non_alphanumeric': 0.1347698072805139, 'fraction_numerical': 0.003613490364025696, 'mean_word_length': 5.290404040404041, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2847237', 'n_tokens_mistral': 2808, 'n_tokens_neox': 2585, 'n_words': 628}