From f7ee372c97ee4e3336b597492c8b0be24d1f40fe Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Thu, 21 Jul 2011 17:52:37 +0530 Subject: [PATCH] cleanup of modules --- cgi-bin/core/__init__.py | 53 ++++ cgi-bin/webnotes/model/code.py | 9 - cgi-bin/webnotes/model/doctype.py | 10 +- cgi-bin/webnotes/modules/__init__.py | 228 +++++++++++--- cgi-bin/webnotes/modules/compress.py | 343 --------------------- cgi-bin/webnotes/modules/export_module.py | 9 +- cgi-bin/webnotes/modules/import_module.py | 74 ----- cgi-bin/webnotes/modules/module_manager.py | 160 +--------- cgi-bin/webnotes/modules/utils.py | 37 +++ cgi-bin/webnotes/widgets/page.py | 68 ++-- 10 files changed, 342 insertions(+), 649 deletions(-) delete mode 100644 cgi-bin/webnotes/modules/compress.py delete mode 100644 cgi-bin/webnotes/modules/import_module.py create mode 100644 cgi-bin/webnotes/modules/utils.py diff --git a/cgi-bin/core/__init__.py b/cgi-bin/core/__init__.py index e69de29bb2..4517d253e2 100644 --- a/cgi-bin/core/__init__.py +++ b/cgi-bin/core/__init__.py @@ -0,0 +1,53 @@ +class BaseModel: + """ + New style models will be inherited from this base model class + This will contain methods for save update + + Standard attributes: + _type + _id + _created_by + _created_on + _modified_by + _modified_on + """ + def __init__(self, model_type = None, model_id = None, attributes = {}): + self._type = model_type + self._id = model_id + if attributes: + self.__dict__.update(attributes) + + def __getattr__(self, name): + """ + Getter is overridden so that it does not throw an exception + """ + if name in self.__dict__: + return self.__dict__[name] + else: + return None + + def _read(self): + """ + Read + """ + self.__dict__.update(webnotes.conn.sql(""" + select * from `%s` where _id=%s + """, (self._type, self._id), as_dict=1)[0]) + + def _create(self): + """ + Create + """ + pass + + def _update(self): + """ + Update + """ + pass + + def _delete(self): + """ + Delete + """ + pass \ No newline at end of file diff --git a/cgi-bin/webnotes/model/code.py b/cgi-bin/webnotes/model/code.py index 8886e4e57a..b312fe425d 100644 --- a/cgi-bin/webnotes/model/code.py +++ b/cgi-bin/webnotes/model/code.py @@ -54,25 +54,16 @@ def execute(code, doc=None, doclist=[]): import webnotes - set = webnotes.conn.set sql = webnotes.conn.sql get_value = webnotes.conn.get_value - in_transaction = webnotes.conn.in_transaction convert_to_lists = webnotes.conn.convert_to_lists if webnotes.user: get_roles = webnotes.user.get_roles locals().update({'get_obj':get_obj, 'get_server_obj':get_server_obj, 'run_server_obj':run_server_obj, 'updatedb':updatedb, 'check_syntax':check_syntax}) - version = 'v170' - NEWLINE = '\n' - BACKSLASH = '\\' - # execute it - # ----------------- exec code in locals() - # if doc - # ----------------- if doc: d = DocType(doc, doclist) return d diff --git a/cgi-bin/webnotes/model/doctype.py b/cgi-bin/webnotes/model/doctype.py index 599226972d..1090eddef8 100644 --- a/cgi-bin/webnotes/model/doctype.py +++ b/cgi-bin/webnotes/model/doctype.py @@ -240,9 +240,7 @@ class _DocType: * replaces `link:` in the `Select` fields * loads all related `Search Criteria` * updates the cache - """ - from webnotes.modules import compress - + """ tablefields = webnotes.model.meta.get_table_fields(self.name) if self.is_modified(): @@ -263,8 +261,10 @@ class _DocType: else: doclist = self._load_from_cache() - - doclist[0].fields['__client_script'] = compress.get_doctype_js(self.name) + + from webnotes.modules import Module + doc = doclist[0] + doc.fields['__client_script'] = Module(doc.module).get_doc_file('doctype', doc.name, '.js').read() self._load_select_options(doclist) self._clear_code(doclist) diff --git a/cgi-bin/webnotes/modules/__init__.py b/cgi-bin/webnotes/modules/__init__.py index bc38a2f96a..f061506ce3 100644 --- a/cgi-bin/webnotes/modules/__init__.py +++ b/cgi-bin/webnotes/modules/__init__.py @@ -7,7 +7,7 @@ transfer_types = ['Role', 'Print Format','DocType','Page','DocType Mapper','GL M def scrub(txt): return txt.replace(' ','_').replace('-', '_').replace('/', '_').lower() -def scrub_dt_and_dn(dt, dn): +def scrub_dt_dn(dt, dn): """ Returns in lowercase and code friendly names of doctype and name for certain types """ @@ -22,7 +22,7 @@ def get_item_file(module, dt, dn): Returns the path of the item file """ import os - ndt, ndn = scrub_dt_and_dn(dt, dn) + ndt, ndn = scrub_dt_dn(dt, dn) return os.path.join(get_module_path(module), ndt, ndn, ndn + '.txt') @@ -39,71 +39,128 @@ def get_module_path(module): Returns path of the given module (imports it and reads it from __file__) """ return Module(module).get_path() - -def switch_module(dt, dn, to, frm=None, export=None): + +def get_doc_path(dt, dn, module=None): """ - Change the module of the given doctype, if export is true, then also export txt and copy - code files from src + Return the path to a particular doc folder """ import os - webnotes.conn.sql("update `tab"+dt+"` set module=%s where name=%s", (to, dn)) + + if not module: + if dt=='Module Def': + module=dn + else: + module = webnotes.conn.get_value(dt, dn, 'module') - if export: - export_doc(dt, dn) + ndt, ndn = scrub_dt_dn(dt, dn) - # copy code files - if dt in ('DocType', 'Page', 'Search Criteria'): - from_path = os.path.join(get_module_path(frm), scrub(dt), scrub(dn), scrub(dn)) - to_path = os.path.join(get_module_path(to), scrub(dt), scrub(dn), scrub(dn)) + return os.path.join(get_module_path(module), ndt, ndn) - # make dire if exists - os.system('mkdir -p %s' % os.path.join(get_module_path(to), scrub(dt), scrub(dn))) - - for ext in ('py','js','html','css'): - os.system('cp %s %s') +def reload_doc(module, dt, dn): + """ + Sync a file from txt to module + Alias for:: + Module(module).reload(dt, dn) + """ + Module(module).reload(dt, dn) +class ModuleManager: + """ + Module manager class, used to run functions on all modules + """ + + def get_all_modules(self): + """ + Return list of all modules + """ + import webnotes.defs + from webnotes.modules.utils import listfolders + if hasattr(webnotes.defs, 'modules_path'): + return listfolders(webnotes.defs.modules_path, 1) class Module: """ - Represents a module in the framework + Represents a module in the framework, has classes for syncing files """ def __init__(self, name): self.name = name + self.path = None + self.sync_types = ['txt','sql'] + self.code_types = ['js','css','py','html','sql'] def get_path(self): """ Returns path of the module (imports it and reads it from __file__) """ - import webnotes.defs, os + if not self.path: - try: - exec ('import ' + scrub(self.name)) in locals() - modules_path = eval(scrub(self.name) + '.__file__') + import webnotes.defs, os - modules_path = os.path.sep.join(modules_path.split(os.path.sep)[:-1]) - except ImportError, e: - modules_path = os.path.join(webnotes.defs.modules_path, scrub(self.name)) - - return modules_path + try: + # by import + exec ('import ' + scrub(self.name)) in locals() + self.path = eval(scrub(self.name) + '.__file__') + self.path = os.path.sep.join(self.path.split(os.path.sep)[:-1]) + except ImportError, e: + # force + self.path = os.path.join(webnotes.defs.modules_path, scrub(self.name)) + return self.path + + def get_doc_file(self, dt, dn, extn='.txt'): + """ + Return file of a doc + """ + dt, dn = scrub_dt_dn(dt, dn) + return self.get_file(dt, dn, dn + extn) + def get_file(self, *path): """ Returns ModuleFile object, in path specifiy the package name and file name For example:: - Module('accounts').get_file('doctype','account.txt') + Module('accounts').get_file('doctype','account','account.txt') """ - return ModuleFile(self, os.path.join(self.get_path(), os.path.join(*path))) + import os + path = os.path.join(self.get_path(), os.path.join(*path)) + if path.endswith('.txt'): + return TxtModuleFile(path) + if path.endswith('.sql'): + return SqlModuleFile(path) + if path.endswith('.js'): + return JsModuleFile(path) + else: + return ModuleFile(path) + + def reload(self, dt, dn): + """ + Sync the file to the db + """ + dt, dn = scrub_dt_dn(dt, dn) + self.get_file(dt, dn, dn + '.txt').sync() + + def sync_all(self): + """ + Walk through all the files in the modules and sync all files + """ + import os + ret = [] + for walk_tuple in os.walk(self.get_path()): + for f in walk_tuple[2]: + if f.split('.')[-1] in self.sync_types: + self.get_file(os.path.join(walk_tuple[0], f)).sync() class ModuleFile: """ - Module file class + Module file class. + + Module files can be dynamically generated by specifying first line is "#!python" + the output """ - def __init__(self, path): - self.path = os.path.join(*path) + self.path = path def is_new(self): """ @@ -144,8 +201,109 @@ class ModuleFile: insert into __file_timestamp(file_name, tstamp) values (%s, %s) on duplicate key update""", (self.path, self.timestamp)) + def load_content(self): + """ + returns file contents + """ + try: + f = open(self.path,'r') + self.content = f.read() + f.close() + except IOError, e: + if e.args[0]==2: + self.content = '' + else: + raise e + + return self.content + + def read(self, do_execute = None): + """ + Return the file content, if dynamic, execute it + """ + self.load_content() + if do_execute and self.content.startswith('#!python'): + from webnotes.model.code import execute + self.content = execute(self.content) + + return self.content + + +class TxtModuleFile(ModuleFile): + """ + Class for .txt files, sync the doclist in the txt file into the database + """ + def __init__(self, path): + ModuleFile.__init__(self, path) + + def sync(self): + """ + import the doclist if new + """ + if self.is_new(): + + from webnotes.model.utils import peval_doclist + doclist = peval_doclist(self.read()) + + if doclist: + from webnotes.utils.transfer import set_doc + set_doc(doclist, 1, 1, 1) + + self.update() + +class SqlModuleFile(ModuleFile): + def __init__(self, path): + ModuleFile.__init__(self, path) + + def sync(self): + """ + execute the sql if new + """ + if self.is_new(): + content = mf.read() + + # execute everything but selects + if content.strip().split()[0].lower()!='select': + webnotes.conn.sql(mf.read()) + + mf.update() + +class JsModuleFile(ModuleFile): + """ + JS File. read method will read file and replace all $import() with relevant code + Example:: + $import(accounts/common.js) + """ + def __init__(self, path): + ModuleFile.__init__(self, path) + + def get_js(self, match): + """ + New style will expect file path or doctype + + """ + name = match.group('name') + import webnotes.defs, os + + if '/' in name: + path = os.path.join(webnotes.defs.modules_path, name) + else: + # its a doctype + path = os.path.join(get_doc_path('DocType', name), name + '.js') + + return JSModuleFile(path).read() + def read(self): """ - Return the file content + return js content (replace $imports if needed) """ - return open(self.path,'r').read() \ No newline at end of file + self.load_content() + code = self.content + + if code and code.strip(): + import re + p = re.compile('\$import\( (?P [^)]*) \)', re.VERBOSE) + + code = p.sub(self.get_js, code) + + return code \ No newline at end of file diff --git a/cgi-bin/webnotes/modules/compress.py b/cgi-bin/webnotes/modules/compress.py deleted file mode 100644 index da2b8bba71..0000000000 --- a/cgi-bin/webnotes/modules/compress.py +++ /dev/null @@ -1,343 +0,0 @@ -""" -Load compressed .js page scripts - -Will also replace $import(page) or $import(module.page) with the relevant js files -""" - - -# load "compressed" js code from modules -#============================================================================== - -def get_js_code(fn, extn='js'): - """ - Get js code from a file (uncompressed) - """ - import webnotes - from webnotes.modules import scrub - from webnotes.utils import get_file_timestamp - - src_file_name = fn + '.' + extn - - # src_timestamp = get_file_timestamp(src_file_name) - - # if no source, return - #if not src_timestamp: - # return '' - - # if timestamps are not same, compress - #if src_timestamp != get_file_timestamp(comp_file_name): - # compress(src_file_name, comp_file_name) - - # get the code - try: - file = open(src_file_name, 'r') - except IOError, e: - return '' - - code = file.read() - file.close() - - # return - return code - -# get doctype client -#============================================================================== - -def sub_get_doctype_js(match): - name = match.group('name') - return get_doctype_js(name) - -def get_doctype_js(dt): - """ - Returns the client-side (js) code of the DocType. - Adds custom script - and replaces $import(dt) with the code of that DocType - """ - import webnotes, os - from webnotes.modules import scrub, get_module_path - from webnotes.model.code import get_custom_script - - module = scrub(webnotes.conn.get_value('DocType',dt,'module')) - - code = get_js_code(os.path.join(get_module_path(scrub(module)), 'doctype', scrub(dt), scrub(dt))) \ - + '\n' + (get_custom_script(dt, 'Client') or '') - - # compile for import - if code.strip(): - import re - p = re.compile('\$import\( (?P [^)]*) \)', re.VERBOSE) - - code = p.sub(sub_get_doctype_js, code) - - return code - -# get page client -#============================================================================== - -def sub_get_page_js(match): - from webnotes.model.doc import Document - - name = match.group('name') - - if '.' in name: - name = name.split('.') - return get_page_js(name[1], name[0]) - - return get_page_js(Document('Page', name)) - -def get_page_js(page, module=None): - """ - Returns the js code of a page. Will replace $import (page) or $import(module.page) - with the code from the file - """ - import webnotes, os - from webnotes.modules import scrub, get_module_path - - if type(page)==str: - page_name = page - else: - page_name, module = page.name, page.module - - code = get_js_code(os.path.join(get_module_path(module), 'page', scrub(page_name), scrub(page_name))) - - if not code and type(page)!=str: - code = page.script - - # compile for import - if code and code.strip(): - import re - p = re.compile('\$import\( (?P [^)]*) \)', re.VERBOSE) - - code = p.sub(sub_get_page_js, code) - - return code - - -# compress -#============================================================================== - -def compress(src, comp): - out = open(comp, 'w') - - jsm = JavascriptMinify() - jsm.minify(open(src,'r'), out) - - out.close() - - - - -#============================================================================== -#============================================================================== -# -# This code is original from jsmin by Douglas Crockford, it was translated to -# Python by Baruch Even. The original code had the following copyright and -# license. -# -# /* jsmin.c -# 2007-05-22 -# -# Copyright (c) 2002 Douglas Crockford (www.crockford.com) -# -# 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 shall be used for Good, not Evil. -# -# 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. -# */ - -from StringIO import StringIO - -def jsmin(js): - ins = StringIO(js) - outs = StringIO() - JavascriptMinify().minify(ins, outs) - str = outs.getvalue() - if len(str) > 0 and str[0] == '\n': - str = str[1:] - return str - -def isAlphanum(c): - """return true if the character is a letter, digit, underscore, - dollar sign, or non-ASCII character. - """ - return ((c >= 'a' and c <= 'z') or (c >= '0' and c <= '9') or - (c >= 'A' and c <= 'Z') or c == '_' or c == '$' or c == '\\' or (c is not None and ord(c) > 126)); - -class UnterminatedComment(Exception): - pass - -class UnterminatedStringLiteral(Exception): - pass - -class UnterminatedRegularExpression(Exception): - pass - -class JavascriptMinify(object): - - def _outA(self): - self.outstream.write(self.theA) - def _outB(self): - self.outstream.write(self.theB) - - def _get(self): - """return the next character from stdin. Watch out for lookahead. If - the character is a control character, translate it to a space or - linefeed. - """ - c = self.theLookahead - self.theLookahead = None - if c == None: - c = self.instream.read(1) - if c >= ' ' or c == '\n': - return c - if c == '': # EOF - return '\000' - if c == '\r': - return '\n' - return ' ' - - def _peek(self): - self.theLookahead = self._get() - return self.theLookahead - - def _next(self): - """get the next character, excluding comments. peek() is used to see - if an unescaped '/' is followed by a '/' or '*'. - """ - c = self._get() - if c == '/' and self.theA != '\\': - p = self._peek() - if p == '/': - c = self._get() - while c > '\n': - c = self._get() - return c - if p == '*': - c = self._get() - while 1: - c = self._get() - if c == '*': - if self._peek() == '/': - self._get() - return ' ' - if c == '\000': - raise UnterminatedComment() - - return c - - def _action(self, action): - """do something! What you do is determined by the argument: - 1 Output A. Copy B to A. Get the next B. - 2 Copy B to A. Get the next B. (Delete A). - 3 Get the next B. (Delete B). - action treats a string as a single character. Wow! - action recognizes a regular expression if it is preceded by ( or , or =. - """ - if action <= 1: - self._outA() - - if action <= 2: - self.theA = self.theB - if self.theA == "'" or self.theA == '"': - while 1: - self._outA() - self.theA = self._get() - if self.theA == self.theB: - break - if self.theA <= '\n': - raise UnterminatedStringLiteral() - if self.theA == '\\': - self._outA() - self.theA = self._get() - - - if action <= 3: - self.theB = self._next() - if self.theB == '/' and (self.theA == '(' or self.theA == ',' or - self.theA == '=' or self.theA == ':' or - self.theA == '[' or self.theA == '?' or - self.theA == '!' or self.theA == '&' or - self.theA == '|' or self.theA == ';' or - self.theA == '{' or self.theA == '}' or - self.theA == '\n'): - self._outA() - self._outB() - while 1: - self.theA = self._get() - if self.theA == '/': - break - elif self.theA == '\\': - self._outA() - self.theA = self._get() - elif self.theA <= '\n': - raise UnterminatedRegularExpression() - self._outA() - self.theB = self._next() - - - def _jsmin(self): - """Copy the input to the output, deleting the characters which are - insignificant to JavaScript. Comments will be removed. Tabs will be - replaced with spaces. Carriage returns will be replaced with linefeeds. - Most spaces and linefeeds will be removed. - """ - self.theA = '\n' - self._action(3) - - while self.theA != '\000': - if self.theA == ' ': - if isAlphanum(self.theB): - self._action(1) - else: - self._action(2) - elif self.theA == '\n': - if self.theB in ['{', '[', '(', '+', '-']: - self._action(1) - elif self.theB == ' ': - self._action(3) - else: - if isAlphanum(self.theB): - self._action(1) - else: - self._action(2) - else: - if self.theB == ' ': - if isAlphanum(self.theA): - self._action(1) - else: - self._action(3) - elif self.theB == '\n': - if self.theA in ['}', ']', ')', '+', '-', '"', '\'']: - self._action(1) - else: - if isAlphanum(self.theA): - self._action(1) - else: - self._action(3) - else: - self._action(1) - - def minify(self, instream, outstream): - self.instream = instream - self.outstream = outstream - self.theA = '\n' - self.theB = None - self.theLookahead = None - - self._jsmin() - self.instream.close() diff --git a/cgi-bin/webnotes/modules/export_module.py b/cgi-bin/webnotes/modules/export_module.py index 3055fc5db9..32ad67e3f0 100644 --- a/cgi-bin/webnotes/modules/export_module.py +++ b/cgi-bin/webnotes/modules/export_module.py @@ -1,3 +1,7 @@ +""" + Export files to modules +""" + from webnotes.modules import scrub, get_module_path def export_to_files(record_list=[], record_module=None, verbose=0): @@ -106,8 +110,3 @@ def clear_code_fields(doclist, folder, code_type): doclist[0][code_field[0]] = None -def to_sandbox(record_list=[], record_module='Sandbox'): - """ - Export record_list to Sandbox. record_list is a list of lists ([doctype],[docname] ) , - """ - pass diff --git a/cgi-bin/webnotes/modules/import_module.py b/cgi-bin/webnotes/modules/import_module.py deleted file mode 100644 index 0708f95009..0000000000 --- a/cgi-bin/webnotes/modules/import_module.py +++ /dev/null @@ -1,74 +0,0 @@ -""" -Imports Documents from modules (.txt) files in the filesystem -""" - -import webnotes - -def import_module(module, verbose=0): - "imports the all the records and files from the given module" - from webnotes.modules import get_module_path - import os - - not_module = ('startup', 'files', 'patches') - if module in not_module: - if verbose: webnotes.msgprint('%s is not a module' % module) - return - - path = get_module_path(module) - - doctypes = listfolders(path, 1) - if 'doctype' in doctypes: - doctypes.remove('doctype') - doctypes = ['doctype'] + doctypes - - for doctype in doctypes: - for docname in listfolders(os.path.join(path, doctype), 1): - import_file(module, doctype, docname, path) - if verbose: webnotes.msgprint('Imported %s/%s/%s' % (module, doctype, docname)) - - import_attachments(module) - -def get_doclist(path, doctype, docname): - "returns a doclist (list of dictionaries) of multiple records for the given parameters" - import os - from webnotes.model.utils import peval_doclist - - do_not_import = ('control_panel') - - fname = os.path.join(path,doctype,docname,docname+'.txt') - if os.path.exists(fname) and (doctype not in do_not_import): - f = open(fname,'r') - dl = peval_doclist(f.read()) - f.close() - return dl - else: - return None - -def import_file(module, doctype, docname, path=None): - "imports a given file into the database" - - if not path: - from webnotes.modules import get_module_path - path = get_module_path(module) - - doclist = get_doclist(path, doctype, docname) - - if doclist: - from webnotes.utils.transfer import set_doc - set_doc(doclist, 1, 1, 1) - -def listfolders(path, only_name=0): - """returns the list of folders (with paths) in the given path, - if only_name is set, it returns only the folder names""" - - import os - out = [] - for each in os.listdir(path): - dirname = each.split(os.path.sep)[-1] - fullpath = os.path.join(path, dirname) - - if os.path.isdir(fullpath) and not dirname.startswith('.'): - out.append(only_name and dirname or fullname) - return out - - diff --git a/cgi-bin/webnotes/modules/module_manager.py b/cgi-bin/webnotes/modules/module_manager.py index c166646bff..55aa2d4a33 100644 --- a/cgi-bin/webnotes/modules/module_manager.py +++ b/cgi-bin/webnotes/modules/module_manager.py @@ -1,163 +1,13 @@ +""" + Deprecated: Will be deleted +""" - -#============================================================================== -# SYNC -#============================================================================== def reload_doc(module, dt, dn): "alias for webnotes.modules.import_module.import_file" - from webnotes.modules.import_module import import_file - - import_file(module, dt, dn) - -# -# get list of doctypes and their last update times -# -def get_doc_list(dt): - """ - returns the list of records and their last update times from the table - if the column _last_update does not exist, it will add it to the table - """ - - import webnotes - module = dt=='Module Def' and 'name' or 'module' - q = "select %s, name, _last_update from `tab%s`" % (module, dt) - try: - return webnotes.conn.sql(q) - except Exception, e: - if e.args[0]==1054: - webnotes.conn.commit() - webnotes.conn.sql("alter table `tab%s` add column _last_update varchar(32)" % dt) - webnotes.conn.begin() - return webnotes.conn.sql(q) - elif e.args[0]==1146: - return [] - else: - raise e - -# -# sync dt -# -def sync_one_doc(d, dt, ts): - import webnotes - from webnotes.model.db_schema import updatedb - reload_doc(d[0], dt, d[1]) - - # update schema(s) - if dt=='DocType': - updatedb(d[1]) - webnotes.conn.sql("update `tab%s` set _last_update=%s where name=%s" % (dt, '%s', '%s'), (ts, d[1])) - -# -# sync doctypes, mappers and -# -def sync_meta(): - import webnotes, os - from webnotes.modules import scrub, get_module_path - from webnotes.utils import cint - - tl = ['DocType', 'DocType Mapper', 'Module Def'] - - for dt in tl: - dtl = get_doc_list(dt) - - for d in filter(lambda x: x[0], dtl): - try: - ndt, ndn = dt, d[1] - if dt == 'DocType': - ndt, ndn = scrub(dt), scrub(d[1]) - - mp = get_module_path(scrub(d[0])) - ts = cint(os.stat(os.path.join(mp, ndt, ndn, ndn + '.txt')).st_mtime) - - if d[2] != str(ts): - sync_one_doc(d, dt, ts) - except OSError, e: - pass + from webnotes.modules import reload_doc + reload_doc(module, dt, dn) - -#============================================================================== - -def get_module_details(m): - from export_module import get_module_items - return {'in_files': get_module_items_from_files(m), \ - 'in_system':[[i[0], i[1], get_modified(i[0], i[1])] for i in get_module_items(m)]} - -#============================================================================== - -def get_modified(dt, dn): - import webnotes - try: - return str(webnotes.conn.sql("select modified from `tab%s` where replace(name,' ','_')=%s" % (dt,'%s'), dn)[0][0]) - except: - pass - -#============================================================================== - -def get_module_items_from_files(m): - import os, webnotes.defs - from import_module import listfolders - - items = [] - for item_type in listfolders(os.path.join(webnotes.defs.modules_path, m), 1): - for item_name in listfolders(os.path.join(webnotes.defs.modules_path, m, item_type), 1): - # read the file - file = open(os.path.join(webnotes.defs.modules_path, m, item_type, item_name, item_name)+'.txt','r') - doclist = eval(file.read()) - file.close() - - # append - items.append([item_type, item_name, doclist[0]['modified']]) - - return items - -#============================================================================== - -def get_last_update_for(mod): - import webnotes - try: - return webnotes.conn.sql("select last_updated_date from `tabModule Def` where name=%s", mod)[0][0] - except: - return '' - -#============================================================================== - -def init_db_login(ac_name, db_name): - import webnotes - import webnotes.db - import webnotes.profile - - if ac_name: - webnotes.conn = webnotes.db.Database(ac_name = ac_name) - webnotes.conn.use(webnotes.conn.user) - elif db_name: - webnotes.conn = webnotes.db.Database(user=db_name) - webnotes.conn.use(db_name) - else: - webnotes.conn = webnotes.db.Database(use_default=1) - - webnotes.session = {'user':'Administrator'} - webnotes.user = webnotes.profile.Profile() - -#============================================================================== -# Return module names present in File System -#============================================================================== -def get_modules_from_filesystem(): - import os, webnotes.defs - from import_module import listfolders - - modules = listfolders(webnotes.defs.modules_path, 1) - out = [] - modules.sort() - modules = filter(lambda x: x!='patches', modules) - - for m in modules: - file = open(os.path.join(webnotes.defs.modules_path, m, 'module.info'), 'r') - out.append([m, eval(file.read()), get_last_update_for(m), \ - webnotes.conn.exists('Module Def',m) and 'Installed' or 'Not Installed']) - file.close() - - return out \ No newline at end of file diff --git a/cgi-bin/webnotes/modules/utils.py b/cgi-bin/webnotes/modules/utils.py new file mode 100644 index 0000000000..2ac9c20050 --- /dev/null +++ b/cgi-bin/webnotes/modules/utils.py @@ -0,0 +1,37 @@ +def listfolders(path, only_name=0): + """ + Returns the list of folders (with paths) in the given path, + If only_name is set, it returns only the folder names + """ + + import os + out = [] + for each in os.listdir(path): + dirname = each.split(os.path.sep)[-1] + fullpath = os.path.join(path, dirname) + + if os.path.isdir(fullpath) and not dirname.startswith('.'): + out.append(only_name and dirname or fullname) + return out + +def switch_module(dt, dn, to, frm=None, export=None): + """ + Change the module of the given doctype, if export is true, then also export txt and copy + code files from src + """ + import os + webnotes.conn.sql("update `tab"+dt+"` set module=%s where name=%s", (to, dn)) + + if export: + export_doc(dt, dn) + + # copy code files + if dt in ('DocType', 'Page', 'Search Criteria'): + from_path = os.path.join(get_module_path(frm), scrub(dt), scrub(dn), scrub(dn)) + to_path = os.path.join(get_module_path(to), scrub(dt), scrub(dn), scrub(dn)) + + # make dire if exists + os.system('mkdir -p %s' % os.path.join(get_module_path(to), scrub(dt), scrub(dn))) + + for ext in ('py','js','html','css'): + os.system('cp %s %s') diff --git a/cgi-bin/webnotes/widgets/page.py b/cgi-bin/webnotes/widgets/page.py index 25e0387ac0..0cad0b72d6 100644 --- a/cgi-bin/webnotes/widgets/page.py +++ b/cgi-bin/webnotes/widgets/page.py @@ -14,45 +14,68 @@ class Page: def __init__(self, name): self.name = name - def get_from_files(self, doc): + def get_from_files(self, doc, module): """ Loads page info from files in module """ - from webnotes.modules import compress - from webnotes.model.code import get_code - # load js - doc.fields['__script'] = compress.get_page_js(doc) + doc.fields['__script'] = module.get_doc_file('page',doc.name,'.js').read() doc.script = None # load css - css = get_code(doc.module, 'page', doc.name, 'css') + css = module.get_doc_file('page',doc.name,'.css').read() if css: doc.style = css # html - doc.content = get_code(doc.module, 'page', doc.name, 'html') or doc.content + doc.content = module.get_doc_file('page',doc.name,'.html').read() or doc.content + + def get_template(self, template): + """ + Returns the page template content + """ + ret = '%(content)s' + # load code from template + if template: + from webnotes.modules import Module + ret = Module(webnotes.conn.get_value('Page Template', template, 'module'))\ + .get_doc_file('Page Template', template, '.html').read() + if not ret: + ret = webnotes.conn.get_value('Page Template', template, 'template') + return ret + + def process_content(self, doc): + """ + Put in template and generate dynamic if starts with #!python + """ + template = self.get_template(doc.template) + content = '' + + # eval content + if doc.content and doc.content.startswith('#!python'): + from webnotes.model.code import execute + content = template % {'content': execute(doc.content).get('content')} + else: + content = template % {'content': doc.content or ''} + + doc.__content = content + def load(self): """ Returns :term:`doclist` of the `Page` """ - from webnotes.model.code import get_code + from webnotes.modules import Module doclist = webnotes.model.doc.get('Page', self.name) doc = doclist[0] - if doc.module: self.get_from_files(doc) + # load from module + if doc.module: + module = Module(doc.module) + self.get_from_files(doc, module) - template = '%(content)s' - # load code from template - if doc.template: - template = get_code(webnotes.conn.get_value('Page Template', doc.template, 'module'), 'Page Template', doc.template, 'html', fieldname='template') - - # execute content - if doc.content and doc.content.startswith('#!python'): - doc.__content = template % {'content': webnotes.model.code.execute(doc.content).get('content')} - else: - doc.__content = template % {'content': doc.content or ''} + # process + self.process_content(doc) # add stylesheet if doc.stylesheet: @@ -66,16 +89,15 @@ class Page: loaded = eval(webnotes.form_dict.get('stylesheets') or '[]') if not stylesheet in loaded: import webnotes.model.doc - from webnotes.model.code import get_code + from webnotes.modules import Module # doclist sslist = webnotes.model.doc.get('Stylesheet', stylesheet) # stylesheet from file - css = get_code(sslist[0].module, 'Stylesheet', stylesheet, 'css') - - if css: sslist[0].stylesheet = css + css = Module(sslist[0].module).get_doc_file('Stylesheet', stylesheet, '.css').read() + if css: sslist[0].stylesheet = css return sslist else: return []