@@ -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 |
@@ -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 | |||
@@ -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) | |||
@@ -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 export: | |||
export_doc(dt, dn) | |||
if not module: | |||
if dt=='Module Def': | |||
module=dn | |||
else: | |||
module = webnotes.conn.get_value(dt, dn, 'module') | |||
# 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)) | |||
ndt, ndn = scrub_dt_dn(dt, dn) | |||
# make dire if exists | |||
os.system('mkdir -p %s' % os.path.join(get_module_path(to), scrub(dt), scrub(dn))) | |||
return os.path.join(get_module_path(module), ndt, ndn) | |||
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 | |||
try: | |||
exec ('import ' + scrub(self.name)) in locals() | |||
modules_path = eval(scrub(self.name) + '.__file__') | |||
if not self.path: | |||
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)) | |||
import webnotes.defs, os | |||
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() | |||
self.load_content() | |||
code = self.content | |||
if code and code.strip(): | |||
import re | |||
p = re.compile('\$import\( (?P<name> [^)]*) \)', re.VERBOSE) | |||
code = p.sub(self.get_js, code) | |||
return code |
@@ -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<name> [^)]*) \)', 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<name> [^)]*) \)', 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() |
@@ -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 |
@@ -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 | |||
@@ -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 | |||
#============================================================================== | |||
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 | |||
from webnotes.modules import reload_doc | |||
reload_doc(module, dt, dn) | |||
#============================================================================== | |||
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 |
@@ -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') |
@@ -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 [] | |||