diff --git a/.gitmodules b/.gitmodules
deleted file mode 100644
index 5309500..0000000
--- a/.gitmodules
+++ /dev/null
@@ -1,3 +0,0 @@
-[submodule "paramecio/modules/admin/media/js/jsutils"]
- path = paramecio/modules/admin/media/js/jsutils
- url = git@git.cuchulu.com:paramecio/jsutils.git
diff --git a/LICENSE.txt b/LICENSE.txt
index be3f7b2..10926e8 100644
--- a/LICENSE.txt
+++ b/LICENSE.txt
@@ -1,21 +1,23 @@
- GNU AFFERO GENERAL PUBLIC LICENSE
- Version 3, 19 November 2007
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
- Copyright (C) 2007 Free Software Foundation, Inc.
+ 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 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,
-our General Public Licenses are intended to guarantee your freedom to
+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.
+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
@@ -24,34 +26,44 @@ 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.
+ 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.
- 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.
+ 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.
- 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.
+ 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.
- 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.
+ 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.
@@ -60,7 +72,7 @@ modification follow.
0. Definitions.
- "This License" refers to version 3 of the GNU Affero General Public License.
+ "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.
@@ -537,45 +549,35 @@ 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.
+ 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 General Public License into a single
+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 work with which it is combined will remain governed by version
-3 of the GNU General Public License.
+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 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
+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 Affero General
+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 Affero General Public License, you may choose any version ever published
+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 Affero General Public License can be used, that proxy's
+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.
@@ -633,29 +635,41 @@ the "copyright" line and a pointer to where the full notice is found.
Copyright (C)
This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published by
+ it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
+ GNU General Public License for more details.
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see .
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
Also add information on how to contact you by electronic and paper mail.
- If your software can interact with users remotely through a computer
-network, you should also make sure that it provides a way for users to
-get its source. For example, if your program is a web application, its
-interface could display a "Source" link that leads users to an archive
-of the code. There are many ways you could offer source, and different
-solutions will be better for different programs; see section 13 for the
-specific requirements.
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ Copyright (C)
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
-For more information on this, and how to apply and follow the GNU AGPL, see
-.
+For more information on this, and how to apply and follow the GNU GPL, see
+.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+.
+
diff --git a/MANIFEST.in b/MANIFEST.in
index 8497f71..22fb9d9 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -2,7 +2,8 @@ include paramecio/*.py
include README.md
include LICENSE
include REQUIREMENTS
-recursive-include paramecio/libraries *
+recursive-include paramecio/citoplasma *
recursive-include paramecio/frontend *
+recursive-include paramecio/cromosoma *
recursive-include paramecio/settings *
-recursive-include paramecio/modules *
+recursive-include paramecio/modules *
\ No newline at end of file
diff --git a/README.md b/README.md
index 7d67b25..3af5b9d 100644
--- a/README.md
+++ b/README.md
@@ -12,19 +12,22 @@ Also, you need the next software installed in your os:
### Python 3.4 or later.
-Paramecio should work fine since python 3.6 but is tested in 3.12 and 3.13 python 3 versions.
+Paramecio should work fine in 3.3 but is tested in 3.4 and 3.5 python 3 versions.
In Debian and Ubuntu you can install Python 3 using the next command: `apt-get install python3`.
-In Fedora and other Red Hat derived distros you can use `dnf install python3`.
+In Fedora and other Red Hat derived distros you can use `yum install python3`. In RedHat/Centos 6 or 7 you need install [Ius Repos](https://ius.io/GettingStarted/) for get sane versions of python3. In new Fedora versions you can use dnf, a drop-in replacement for yum: `dnf install python3`.
### MySQL or MariaDB database servers.
-MariaDB 10.6 and later are recommended.
+MariaDB 10.0 and later are recommended.
In Debian and Ubuntu you can install MariaDB using the next command: `apt-get install mariadb-server`.
-In Fedora and other Red Hat derived distros you can use `dnf install mariadb-server`.
+In Fedora and other Red Hat derived distros you can use `yum install mariadb-server`.
+In RedHat/Centos 6 probably you need install adittional repositories for get latest versions of mariadb, but with MySQL 5.5, Paramecio should work fine.
+
+When you will install the mysql server, you should create a new user and database for Paramecio.
### Pip
@@ -32,7 +35,7 @@ Pip is the package manager of python. You can use the package manager of your os
In Debian and Ubuntu you can install pip using the next command: `apt-get install python3-pip`.
-In Fedora and other Red Hat derived distros you can use `dnf install python3-pip`.
+In Fedora and other Red Hat derived distros you can use `yum install python3-pip`. Of course, the command can change if you use Centos 6/7 with **Ius repos**.
### Git
@@ -40,7 +43,7 @@ In Fedora and other Red Hat derived distros you can use `dnf install python3-pip
In Debian and Ubuntu you can install git using the next command: `apt-get install git`.
-In Fedora and other Red Hat derived distros you can use `dnf install git`.
+In Fedora and other Red Hat derived distros you can use `yum install git` or `dnf install git` in last fedora versions.
## Install Paramecio Framework
@@ -56,6 +59,8 @@ This command will install in your server paramecio framework with its dependenci
When Paramecio finish the installing, you can create your first paramecio site with `paramecio` command.
+> If you install passlib and bcrypt python modules, your paramecio install will use bcrypt algorithm for crypt system passwords. If not, default system implementation crypt algorithm (normally the more strong algorithm available in the system) will be used.
+
### Tipical errors
If you get an error in your installation of dependencies how MarkupSafe or SqlAlchemy, please install gcc or install manually mako and sqlalchemy with your system package manager. For example, for debian and ubuntu:
diff --git a/paramecio/libraries/__init__.py b/paramecio/citoplasma/__init__.py
similarity index 100%
rename from paramecio/libraries/__init__.py
rename to paramecio/citoplasma/__init__.py
diff --git a/paramecio/libraries/adminutils.py b/paramecio/citoplasma/adminutils.py
similarity index 89%
rename from paramecio/libraries/adminutils.py
rename to paramecio/citoplasma/adminutils.py
index 7698755..c890ab4 100644
--- a/paramecio/libraries/adminutils.py
+++ b/paramecio/citoplasma/adminutils.py
@@ -1,14 +1,14 @@
#!/usr/bin/env python3
from collections import OrderedDict
-from paramecio.libraries.sessions import get_session
-from paramecio.libraries.urls import make_url
-from paramecio.libraries.i18n import I18n
-from paramecio.libraries.httputils import GetPostFiles
-from paramecio.libraries.keyutils import create_key_encrypt, create_key_encrypt_256, create_key
-from paramecio.libraries.db.formsutils import generate_csrf
+from paramecio.citoplasma.sessions import get_session
+from paramecio.citoplasma.urls import make_url
+from paramecio.citoplasma.i18n import I18n
+from paramecio.citoplasma.httputils import GetPostFiles
+from paramecio.citoplasma.keyutils import create_key_encrypt, create_key_encrypt_256, create_key
+from paramecio.cromosoma.formsutils import generate_csrf
from bottle import response,request
-from paramecio.libraries.db.webmodel import WebModel
+from paramecio.cromosoma.webmodel import WebModel
from time import time
try:
@@ -98,8 +98,7 @@ def get_menu(modules_admin):
if len(menu[mod[2]])<4:
menu[mod[2]].append('')
- else:
- menu[mod[2]][3]=''.format(menu[mod[2]][3])
+
else:
menu[mod[2]]=mod[0]
@@ -115,8 +114,6 @@ def get_menu(modules_admin):
if len(menu[submod[2]])<4:
menu[submod[2]].append('')
- else:
- menu[submod[2]][3]=''.format(menu[submod[2]][3])
return menu
@@ -161,7 +158,7 @@ def login_model(ModelLogin, session='', enable_tries=False):
user_admin.conditions=['WHERE username=%s', [username]]
- arr_user=user_admin.select_a_row_where(['id', 'username', 'password', 'privileges', 'lang', 'num_tries', 'email', 'theme'])
+ arr_user=user_admin.select_a_row_where(['id', 'username', 'password', 'privileges', 'lang', 'num_tries', 'email'])
if arr_user==False:
@@ -183,7 +180,6 @@ def login_model(ModelLogin, session='', enable_tries=False):
s[session+'lang']=arr_user['lang']
s[session+'email']=arr_user['email']
s[session+'username']=arr_user['username']
- s[session+'theme']=str(arr_user['theme'])
if s['lang']=='':
s['lang']=I18n.default_lang
diff --git a/paramecio/libraries/base_admin.py b/paramecio/citoplasma/base_admin.py
similarity index 79%
rename from paramecio/libraries/base_admin.py
rename to paramecio/citoplasma/base_admin.py
index 4e40cfe..06e9673 100644
--- a/paramecio/libraries/base_admin.py
+++ b/paramecio/citoplasma/base_admin.py
@@ -1,10 +1,10 @@
#!/usr/bin/env python3
-from paramecio.libraries.mtemplates import PTemplate
-from paramecio.libraries.adminutils import check_login, get_language, get_menu
-from paramecio.libraries.db.webmodel import WebModel
-from paramecio.libraries.sessions import get_session
-from paramecio.libraries.i18n import I18n
+from paramecio.citoplasma.mtemplates import PTemplate
+from paramecio.citoplasma.adminutils import check_login, get_language, get_menu
+from paramecio.cromosoma.webmodel import WebModel
+from paramecio.citoplasma.sessions import get_session
+from paramecio.citoplasma.i18n import I18n
try:
diff --git a/paramecio/libraries/check_i18n.py b/paramecio/citoplasma/check_i18n.py
similarity index 97%
rename from paramecio/libraries/check_i18n.py
rename to paramecio/citoplasma/check_i18n.py
index 7d5832b..96ccba4 100644
--- a/paramecio/libraries/check_i18n.py
+++ b/paramecio/citoplasma/check_i18n.py
@@ -5,7 +5,7 @@ import os
import re
from pathlib import Path
from importlib import import_module
-from paramecio.libraries.i18n import I18n
+from paramecio.citoplasma.i18n import I18n
from settings import config
pattern=re.compile('^\w+\.(py|html|phtml|js)$')
@@ -48,8 +48,6 @@ def start():
#lang_t=re.compile("\${lang\('("+module_base+"?)',\s+'(.*?)',\s+'(.*?)'\)\}")
lang_t=re.compile("lang\('("+module_base+"?)',\s+'(.*?)',\s+'(.*?)'\)")
- lang_s=re.compile("slang\('(.*?)',\s+'(.*?)'\)"
-
if not os.path.isdir(path):
print("Error: directory to scan doesn't exists")
@@ -93,7 +91,7 @@ def start():
file_lang="#!/usr/bin/env python3\n\n"
- file_lang+="from paramecio.libraries.i18n import I18n\n\n"
+ file_lang+="from paramecio.citoplasma.i18n import I18n\n\n"
for lang in I18n.dict_i18n:
diff --git a/paramecio/libraries/datetime.py b/paramecio/citoplasma/datetime.py
similarity index 99%
rename from paramecio/libraries/datetime.py
rename to paramecio/citoplasma/datetime.py
index 4287712..9ad9703 100644
--- a/paramecio/libraries/datetime.py
+++ b/paramecio/citoplasma/datetime.py
@@ -6,7 +6,7 @@ try:
from settings import config
except:
config={}
-#from paramecio.libraries.sessions import get_session
+#from paramecio.citoplasma.sessions import get_session
from os import environ
"""Simple hook for timedate functions from Arrow datetime module. Maybe in the future use native python datetime functions or other libraries. Is simply an abstraction for not depend of particular library.
diff --git a/paramecio/libraries/error_reporting.py b/paramecio/citoplasma/error_reporting.py
similarity index 95%
rename from paramecio/libraries/error_reporting.py
rename to paramecio/citoplasma/error_reporting.py
index f6fc2ae..04b75de 100644
--- a/paramecio/libraries/error_reporting.py
+++ b/paramecio/citoplasma/error_reporting.py
@@ -3,7 +3,7 @@
# A bottle plugin for send emails if
from settings import config
-from paramecio.libraries.sendmail import SendMail
+from paramecio.citoplasma.sendmail import SendMail
import sys, traceback
email_failed=''
diff --git a/paramecio/libraries/filesize.py b/paramecio/citoplasma/filesize.py
similarity index 100%
rename from paramecio/libraries/filesize.py
rename to paramecio/citoplasma/filesize.py
diff --git a/paramecio/libraries/filterip.py b/paramecio/citoplasma/filterip.py
similarity index 100%
rename from paramecio/libraries/filterip.py
rename to paramecio/citoplasma/filterip.py
diff --git a/paramecio/libraries/generate_admin_class.py b/paramecio/citoplasma/generate_admin_class.py
similarity index 94%
rename from paramecio/libraries/generate_admin_class.py
rename to paramecio/citoplasma/generate_admin_class.py
index ec2e8da..f0a46dc 100644
--- a/paramecio/libraries/generate_admin_class.py
+++ b/paramecio/citoplasma/generate_admin_class.py
@@ -1,10 +1,10 @@
-from paramecio.libraries.lists import SimpleList
+from paramecio.citoplasma.lists import SimpleList
from bottle import request
-from paramecio.libraries.urls import add_get_parameters, redirect
-from paramecio.libraries.mtemplates import set_flash_message
-from paramecio.libraries.db.formsutils import show_form
-from paramecio.libraries.i18n import I18n
-from paramecio.libraries.httputils import GetPostFiles
+from paramecio.citoplasma.urls import add_get_parameters, redirect
+from paramecio.citoplasma.mtemplates import set_flash_message
+from paramecio.cromosoma.formsutils import show_form
+from paramecio.citoplasma.i18n import I18n
+from paramecio.citoplasma.httputils import GetPostFiles
from collections import OrderedDict
class GenerateAdminClass:
@@ -49,8 +49,6 @@ class GenerateAdminClass:
self.url_redirect=self.url
- self.pre_update=None
-
self.post_update=None
self.text_home=I18n.lang('common', 'home', 'Home')
@@ -128,9 +126,6 @@ class GenerateAdminClass:
title_edit=I18n.lang('common', 'edit_new_item', 'Edit item')
self.model.conditions=['WHERE `'+self.model.name+'`.`'+self.model.name_field_id+'`=%s', [getpostfiles.get['id']]]
- if self.pre_update:
- getpostfiles.post=self.pre_update(self, getpostfiles.post)
-
if insert_row(getpostfiles.post):
set_flash_message(I18n.lang('common', 'task_successful', 'Task successful'))
@@ -214,8 +209,6 @@ class GenerateConfigClass:
self.template_insert='utils/insertform.phtml'
- self.pre_update=None
-
self.post_update=None
self.text_home=I18n.lang('common', 'home', 'Home')
diff --git a/paramecio/libraries/gunicornssl.py b/paramecio/citoplasma/gunicornssl.py
similarity index 100%
rename from paramecio/libraries/gunicornssl.py
rename to paramecio/citoplasma/gunicornssl.py
diff --git a/paramecio/libraries/hierarchy_links.py b/paramecio/citoplasma/hierarchy_links.py
similarity index 98%
rename from paramecio/libraries/hierarchy_links.py
rename to paramecio/citoplasma/hierarchy_links.py
index f24f997..569b2bb 100644
--- a/paramecio/libraries/hierarchy_links.py
+++ b/paramecio/citoplasma/hierarchy_links.py
@@ -1,6 +1,6 @@
#/usr/bin/env python3
-from paramecio.libraries.urls import add_get_parameters
+from paramecio.citoplasma.urls import add_get_parameters
class HierarchyLinks:
diff --git a/paramecio/libraries/httputils.py b/paramecio/citoplasma/httputils.py
similarity index 83%
rename from paramecio/libraries/httputils.py
rename to paramecio/citoplasma/httputils.py
index 4a9769f..93ab337 100644
--- a/paramecio/libraries/httputils.py
+++ b/paramecio/citoplasma/httputils.py
@@ -2,12 +2,12 @@
import json, re
from bottle import request, response
-from paramecio.libraries.sessionplugin import get_session
-from paramecio.libraries.keyutils import create_key_encrypt
+from paramecio.citoplasma.sessions import get_session
+from paramecio.citoplasma.keyutils import create_key_encrypt
from bottle import HTTPResponse
no_csrf=False
-change_csrf=True
+change_csrf=False
try:
@@ -84,22 +84,15 @@ class GetPostFiles:
self.post={}
- if not request.json:
+ try:
- try:
+ self.post=request.forms.decode('utf-8')
- self.post=request.forms.decode('utf-8')
-
- except:
-
- request.forms.recode_unicode=False
- self.post=request.forms.decode('utf-8')
+ except:
+
+ request.forms.recode_unicode=False
+ self.post=request.forms.decode('utf-8')
-
- else:
- self.post=request.json
-
- #print(self.post.keys())
if len(required_post)==0:
required_post=self.post.keys()
@@ -107,20 +100,20 @@ class GetPostFiles:
self.post[post]=self.post.get(post, '')
s=get_session()
- #print('s', s)
+
if ignore_csrf_token==False and no_csrf==False:
if 'csrf_token' in s:
self.post['csrf_token']=self.post.get('csrf_token', '')
-
+
if self.post['csrf_token']!=s['csrf_token'] or self.post['csrf_token'].strip()=="":
# Clean csrf_token
- #del s['csrf_token']
+ del s['csrf_token']
- #s.save()
+ s.save()
#raise NameError('Error: you need a valid csrf_token')
raise HTTPResponse(body=json.dumps({'error_csrf': 1, 'error': 1, 'token_invalid': 1}), status=200, headers={'Content-type': 'application/json'})
@@ -131,7 +124,7 @@ class GetPostFiles:
del s['csrf_token']
- #s.save()
+ s.save()
else:
@@ -167,8 +160,8 @@ def check_csrf(post):
del s['csrf_token']
- #s.save()
+ s.save()
else:
#raise NameError('Error: you don\'t send any valid csrf_token')
- raise HTTPResponse(body=json.dumps({'error_csrf': 1, 'error': 1, 'message': 'Error: csrf token invalid', 'token_invalid': 0}), status=200, headers={'Content-type': 'application/json'})
+ raise HTTPResponse(body=json.dumps({'error_csrf': 1, 'error': 1, 'token_invalid': 0}), status=200, headers={'Content-type': 'application/json'})
diff --git a/paramecio/citoplasma/i18n.py b/paramecio/citoplasma/i18n.py
new file mode 100644
index 0000000..a205934
--- /dev/null
+++ b/paramecio/citoplasma/i18n.py
@@ -0,0 +1,95 @@
+#!/usr/bin/env python3
+
+from importlib import import_module
+from paramecio.citoplasma.sessions import get_session
+import json
+from bottle import request
+
+yes_session=False
+
+i18n_module={}
+
+def load_lang(*args):
+
+ for module in args:
+
+ lang_path=module[0]+'.i18n.'+module[1]
+
+ try:
+
+ i18n_module[lang_path]=import_module(lang_path)
+
+ pass
+
+ except:
+ pass
+
+ # here load the language
+
+
+class I18n:
+
+ default_lang='en-US'
+
+ dict_i18n=['en-US', 'es-ES']
+
+ l={}
+
+ #@staticmethod
+ #def set_lang(code_lang):
+ # if default_lang
+
+
+ @staticmethod
+ def get_default_lang():
+
+ lang=I18n.default_lang
+
+ s=get_session()
+
+ lang=s.get('lang', lang)
+
+ return lang
+
+ @staticmethod
+ def lang(module, symbol, text_default, lang=None):
+
+ if not lang:
+ lang=I18n.get_default_lang()
+
+ I18n.l[lang]=I18n.l.get(lang, {})
+
+ I18n.l[lang][module]=I18n.l[lang].get(module, {})
+
+ I18n.l[lang][module][symbol]=I18n.l[lang][module].get(symbol, text_default)
+
+ return I18n.l[lang][module][symbol]
+
+ @staticmethod
+ def extract_value(value):
+
+ value=json.loads(value)
+
+ lang=I18n.get_default_lang()
+
+ if value[lang]!='':
+
+ return value[lang]
+
+ return value[I18n.default_lang]
+
+ @staticmethod
+ def get_browser_lang():
+
+ return request.headers.get('Accept-Language', 'en-US')
+
+ @staticmethod
+ def lang_json(module, symbol, text_default):
+
+ arr_final={}
+
+ for l in I18n.dict_i18n:
+ arr_final[l]=I18n.lang(module, symbol, text_default, l)
+
+ return json.dumps(arr_final)
+
diff --git a/paramecio/libraries/js.py b/paramecio/citoplasma/js.py
similarity index 71%
rename from paramecio/libraries/js.py
rename to paramecio/citoplasma/js.py
index 230ef17..04b3ed7 100644
--- a/paramecio/libraries/js.py
+++ b/paramecio/citoplasma/js.py
@@ -1,5 +1,5 @@
-from paramecio.libraries.sessions import get_session
-from paramecio.libraries.i18n import I18n
+from paramecio.citoplasma.sessions import get_session
+from paramecio.citoplasma.i18n import I18n
from settings import config
def make_js_url(file_path, module):
diff --git a/paramecio/citoplasma/keyutils.py b/paramecio/citoplasma/keyutils.py
new file mode 100644
index 0000000..4cb4b8a
--- /dev/null
+++ b/paramecio/citoplasma/keyutils.py
@@ -0,0 +1,19 @@
+from hashlib import sha512, sha256
+from base64 import b64encode
+from os import urandom
+
+# Functions for create random strings usando urandom
+
+def create_key_encrypt(n=10):
+
+ return sha512(urandom(n)).hexdigest()
+
+def create_key_encrypt_256(n=10):
+
+ return sha256(urandom(n)).hexdigest()
+
+def create_key(n=10):
+
+ rand_bytes=urandom(n)
+
+ return b64encode(rand_bytes).decode('utf-8')[0:-2]
diff --git a/paramecio/libraries/lists.py b/paramecio/citoplasma/lists.py
similarity index 97%
rename from paramecio/libraries/lists.py
rename to paramecio/citoplasma/lists.py
index 93cf2aa..dc51a19 100644
--- a/paramecio/libraries/lists.py
+++ b/paramecio/citoplasma/lists.py
@@ -1,14 +1,14 @@
#By default id is not showed
-from paramecio.libraries.pages import Pages
-from paramecio.libraries.urls import add_get_parameters
-from paramecio.libraries.sessions import get_session
-from paramecio.libraries.i18n import I18n
-from paramecio.libraries.httputils import GetPostFiles
+from paramecio.citoplasma.pages import Pages
+from paramecio.citoplasma.urls import add_get_parameters
+from paramecio.citoplasma.sessions import get_session
+from paramecio.citoplasma.i18n import I18n
+from paramecio.citoplasma.httputils import GetPostFiles
from bottle import request
import sys
import re
-from paramecio.libraries.pages import Pages
+from paramecio.citoplasma.pages import Pages
class SimpleList:
diff --git a/paramecio/libraries/mtemplates.py b/paramecio/citoplasma/mtemplates.py
similarity index 66%
rename from paramecio/libraries/mtemplates.py
rename to paramecio/citoplasma/mtemplates.py
index fc054ae..8327d20 100644
--- a/paramecio/libraries/mtemplates.py
+++ b/paramecio/citoplasma/mtemplates.py
@@ -1,58 +1,22 @@
#!/usr/bin/python
-"""
-Parameciofm is a series of wrappers for Bottle.py, mako and others and construct a simple headless cms.
-
-Copyright (C) 2024 Antonio de la Rosa Caballero
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU Affero General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU Affero General Public License for more details.
-
-You should have received a copy of the GNU Affero General Public License
-along with this program. If not, see .
-"""
-
from bottle import hook
from mako.template import Template
from mako.lookup import TemplateLookup
-from paramecio.libraries.urls import make_url, make_url_domain, make_media_url, make_media_url_module, add_get_parameters
-from paramecio.libraries.i18n import I18n, PGetText
-from paramecio.libraries.sessionplugin import get_session
-from paramecio.libraries.adminutils import make_admin_url
-from paramecio.libraries.db.formsutils import csrf_token
-from paramecio.libraries.js import make_js_url
+from paramecio.citoplasma.urls import make_url, make_url_domain, make_media_url, make_media_url_module, add_get_parameters
+from paramecio.citoplasma.i18n import I18n
+from paramecio.citoplasma.sessions import get_session
+from paramecio.citoplasma.adminutils import make_admin_url
+from paramecio.cromosoma.formsutils import csrf_token
+from paramecio.citoplasma.js import make_js_url
from settings import config
from os import path
from collections import OrderedDict
-from paramecio.wsgiapp import app
# Preparing envs for views of modules, and views of
def env_theme(module, cache_enabled=True, cache_impl='', cache_args={}, module_directory="./tmp/modules"):
- """Function for create an environment for mako templates
-
- Function for create an environment for mako templates. Really is a shortcut for TemplateLookup mako function. You can define cache options and module_directory for templates compiled
-
- Args:
- module (str): The module where the templates can be founded
- cache_enabled (boolean): If True then mako template cache is enabled, is False, mako template cache is disabled.
- cache_args (dict): Cache Args dict parameter for TemplateLookup function from Mako templates. View Mako Templates documentation.
- module_directory (str): Module directory parameter for TemplateLookup function from Mako templates. View Mako Templates documentation.
-
- Returns:
-
- template (TemplateLookup): Return TemplateLookup object
-
- """
-
ext=module[len(module)-3:]
if ext=='.py':
@@ -86,33 +50,12 @@ def preload_templates(template_files, env):
return templates
-def url_for(name, **kwargs):
-
- return app.get_url(name, **kwargs)
-
class PTemplate:
- """A class used how shortcuts for Mako template functions.
- """
templates_loaded={}
def __init__(self, environment):
- """A class used how shortcuts for Mako template functions.
-
- This class is used to have a set of shortcuts and hooks to Mako templates functions and methods over a series of default options.
-
- Args:
- environment (TemplateLookup): A TemplateLookup object generated with env_theme function
-
- Attributes:
- autoescape_ext (set): A set of extensions file where automatic autoescape is used
- environment (TemplateLookup): A TemplateLookup object generated with env_theme function
- filters (list): A list of functions used for add filters to your templates.
- js (list): A list of javascript sources for generate js html load tags.
-
- """
-
# A simple method used in internal things of paramecio
self.show_basic_template=True
@@ -187,32 +130,6 @@ class PTemplate:
self.env=environment
- # Loading language domain for gettext in templates
-
- base_name=path.dirname(path.realpath(__file__))
-
- module_env=self.env.directories[1].replace('/templates', '')
-
- self.l=PGetText(module_env+'/app.py')
-
- self.add_filter(self._)
-
- self.i18n=I18n(base_name)
-
- self.add_filter(self.i18n.slang)
-
- self.add_filter(self.i18n.tlang)
-
- #self.url_for=lambda name: app.get_url(name)
- #x = lambda a : a + 10
- #print(self.url_for)
-
- self.add_filter(url_for)
-
- def _(self, text):
-
- return self.l.gettext(text)
-
#self.auto_reload=True
# Clean HeaderHTML
@@ -227,12 +144,6 @@ class PTemplate:
def guess_autoescape(self, template_name):
- """Simple helper method for get an extension from filename
-
- Args:
- template_name (str): The template name
- """
-
if template_name is None or '.' not in template_name:
return False
@@ -269,18 +180,6 @@ class PTemplate:
def load_template(self, template_file, **arguments):
- """Load a mako template and return the result
-
- Load a mako template and return the results with different arguments applied
-
- Args:
- template_file (str): The name of template file. The template is searched using configuration defined in self.env
- **arguments (mixed): Extra arguments with variables passed to template
-
- Returns:
- template (str): Return a template rendered using mako class from self.env
- """
-
template = self.env.get_template(template_file)
arguments.update(self.filters)
@@ -291,18 +190,6 @@ class PTemplate:
def render_template(self, template_file, **arguments):
- """Experimental method for parse a template
-
- Experimental method for parse a template, similar to load_template but try cache the template loaded
-
- Args:
- template_file (str): The name of template file. The template is searched using configuration defined in self.env
- **arguments (mixed): Extra arguments with variables passed to template
-
- Returns:
- dummy (str): Dummy return necessary because mako expect return something
- """
-
if not str(self.env.directories)+'/'+template_file in PTemplate.templates_loaded:
PTemplate.templates_loaded[str(self.env.directories)+'/'+template_file]=self.env.get_template(template_file)
@@ -448,7 +335,7 @@ class HeaderHTML:
s['flash']=''
- #s.save()
+ s.save()
return message
@@ -458,7 +345,7 @@ def set_flash_message(message):
s['flash']=message
- #s.save()
+ s.save()
def qf(text):
diff --git a/paramecio/libraries/pages.py b/paramecio/citoplasma/pages.py
similarity index 93%
rename from paramecio/libraries/pages.py
rename to paramecio/citoplasma/pages.py
index 33a68a6..d0f34d8 100644
--- a/paramecio/libraries/pages.py
+++ b/paramecio/citoplasma/pages.py
@@ -1,8 +1,8 @@
#!/usr/bin/env python3
from math import ceil, floor
-from paramecio.libraries.urls import add_get_parameters
-from paramecio.libraries.i18n import I18n
+from paramecio.citoplasma.urls import add_get_parameters
+from paramecio.citoplasma.i18n import I18n
class Pages:
diff --git a/paramecio/libraries/plugins.py b/paramecio/citoplasma/plugins.py
similarity index 95%
rename from paramecio/libraries/plugins.py
rename to paramecio/citoplasma/plugins.py
index c5c5756..8573ace 100644
--- a/paramecio/libraries/plugins.py
+++ b/paramecio/citoplasma/plugins.py
@@ -1,8 +1,8 @@
from paramecio.modules.admin.models.admin import UserAdmin
from bottle import request
-from paramecio.libraries.sessions import get_session
-from paramecio.libraries.urls import redirect, make_url
-from paramecio.libraries.db.webmodel import WebModel
+from paramecio.citoplasma.sessions import get_session
+from paramecio.citoplasma.urls import redirect, make_url
+from paramecio.cromosoma.webmodel import WebModel
import inspect
class LoginPlugin(object):
diff --git a/paramecio/libraries/sendmail.py b/paramecio/citoplasma/sendmail.py
similarity index 70%
rename from paramecio/libraries/sendmail.py
rename to paramecio/citoplasma/sendmail.py
index 588e7ae..84f7374 100644
--- a/paramecio/libraries/sendmail.py
+++ b/paramecio/citoplasma/sendmail.py
@@ -1,23 +1,4 @@
#!/usr/bin/env python3
-
-"""
-Parameciofm is a series of wrappers for bottle.py, mako and others and construct a simple headless cms.
-
-Copyright (C) 2024 Antonio de la Rosa Caballero
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU Affero General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU Affero General Public License for more details.
-
-You should have received a copy of the GNU Affero General Public License
-along with this program. If not, see .
-"""
import os
import smtplib
import mimetypes
@@ -32,8 +13,6 @@ import ssl as ssl_module
import sys
class SendMail:
- """Class for send email
- """
port=587
@@ -46,20 +25,6 @@ class SendMail:
#ssl=True
def __init__(self, ssl=True):
- """Class for send email
-
- Class for send email using standard python library
-
- Attributes:
- port (int): The port used for send email, by default 587
- host (str): The hostname of mail server used for send the email
- username (str): The username for login in mail server
- password (str): The password for login in mail server
- smtp (smtplib.SMTP): The python SMTP object used for send emails
- txt_error: (str): If error, is saved in this attribute
-
- """
-
self.smtp=None #smtplib.SMTP(host=self.host, port=self.port)
self.txt_error=''
@@ -114,9 +79,9 @@ class SendMail:
return False
- except smtplib.SMTPAuthenticationError as eauth:
+ except smtplib.SMTPAuthenticationError:
- self.txt_error='Error: cannot login. Wrong username or password '+eauth.__str__()
+ self.txt_error='Error: cannot login. Wrong username or password'
return False
@@ -129,18 +94,6 @@ class SendMail:
return True
def send(self, from_address, to_address: list, subject, message, content_type='plain', attachments=[]):
- """ Method that send email
-
- With this method you can send email to multiple address, html, and add attachments to email
-
- Args:
- from_address (str): The adress used for send the email
- to_address (list): A list of emails where the email will be sended.
- subject (str): The subject of the email
- message (str): The content of the message
- content_type (str): The type of mail content, can be plain or html.
- attachments (list): A list with a serie of file paths for attach to the email.
- """
if self.smtp==None:
if not self.connect():
@@ -221,14 +174,12 @@ class SendMail:
return True
def quit(self):
- """Function used when you need quit connection for any reason"""
if self.smtp!=None:
self.smtp.quit()
self.smtp=None
def __del__(self):
- """Method for clean the connection when the object is closed"""
if self.smtp!=None:
diff --git a/paramecio/libraries/sessions.py b/paramecio/citoplasma/sessions.py
similarity index 76%
rename from paramecio/libraries/sessions.py
rename to paramecio/citoplasma/sessions.py
index bf9938f..3d41064 100644
--- a/paramecio/libraries/sessions.py
+++ b/paramecio/citoplasma/sessions.py
@@ -1,7 +1,7 @@
#!/usr/bin/env python3
-from paramecio.libraries.keyutils import create_key_encrypt, create_key_encrypt_256, create_key
-#from oslo_concurrency import lockutils
+from paramecio.citoplasma.keyutils import create_key_encrypt, create_key_encrypt_256, create_key
+from oslo_concurrency import lockutils
try:
@@ -15,7 +15,7 @@ except:
key_encrypt=create_key_encrypt_256(30)
session_opts={'session.data_dir': 'sessions', 'session.type': 'file', 'session.path': 'paramecio'}
-#from itsdangerous import JSONWebSignatureSerializer
+from itsdangerous import JSONWebSignatureSerializer
from bottle import request, response
import os
try:
@@ -142,75 +142,40 @@ elif config.session_opts['session.type']=='redis':
import redis
- def generate_session(session={}, max_age=None):
-
- token=create_key(30).replace('/', '#')
-
- s={'token': token}
-
- # Bug in python 3.6, if you put max_age how None, is passed to header cookie.
-
- if not max_age:
- response.set_cookie(config.cookie_name, token, path=config.session_opts['session.path'], httponly=True)
- else:
- response.set_cookie(config.cookie_name, token, path=config.session_opts['session.path'], max_age=max_age, httponly=True)
-
- request.environ['session']=s
-
- save_session(token, s)
-
- request.environ['session']=s
-
- return s
-
- def regenerate_session():
-
- token=create_key(30).replace('/', '#')
-
- s={'token': token}
-
- response.set_cookie(config.cookie_name, token, path=config.session_opts['session.path'], httponly=True)
-
- save_session(token, s)
-
- request.environ['session']=s
-
- return ParamecioSession(s)
-
def load_session(token):
s={}
- r=redis.Redis(host=config.session_opts['session.host'], port=config.session_opts['session.port'], decode_responses=True)
+ r=redis.StrictRedis(host=config.session_opts['session.host'], port=config.session_opts['session.port'], db=config.session_opts['session.db'])
value=r.get(token)
- r.close()
-
if not value:
s={'token': token}
else:
try:
- s=json.loads(value)
+ s=json.loads(value.decode('utf-8'))
except:
s={'token': token}
return s
def save_session(token, session):
- r=redis.Redis(host=config.session_opts['session.host'], port=config.session_opts['session.port'])
+ r=redis.StrictRedis(host=config.session_opts['session.host'], port=config.session_opts['session.port'], db=config.session_opts['session.db'])
r.set(token, json.dumps(session))
- r.close()
-
def after_session():
pass
-
+
else:
def generate_session(session={}, max_age=None):
+ #secret=URLSafeSerializer(config.key_encrypt)
+
+ #session=secret.dumps(session)
+
token=create_key(30).replace('/', '#')
s={'token': token}
@@ -218,9 +183,9 @@ else:
# Bug in python 3.6, if you put max_age how None, is passed to header cookie.
if not max_age:
- response.set_cookie(config.cookie_name, token, path=config.session_opts['session.path'], httponly=True)
+ response.set_cookie(config.cookie_name, token, path=config.session_opts['session.path'])
else:
- response.set_cookie(config.cookie_name, token, path=config.session_opts['session.path'], max_age=max_age, httponly=True)
+ response.set_cookie(config.cookie_name, token, path=config.session_opts['session.path'], max_age=max_age)
#Set-Cookie: phango_session=n2ro4lghim75p8vjseb5v3lhap; path=/experiment2/
#response.set_header('Set-Cookie', '%s=%s; path=%s' % (config.cookie_name, token, config.session_opts['session.path']) )
@@ -240,7 +205,7 @@ else:
s={'token': token}
- response.set_cookie(config.cookie_name, token, path=config.session_opts['session.path'], httponly=True)
+ response.set_cookie(config.cookie_name, token, path=config.session_opts['session.path'])
file_session=config.session_opts['session.data_dir']+'/'+token+'_session'
@@ -272,7 +237,7 @@ else:
return s
- #@lockutils.synchronized('not_thread_safe')
+ @lockutils.synchronized('not_thread_safe')
def save_session(token, session, create_file=False):
file_session=config.session_opts['session.data_dir']+'/'+token+'_session'
diff --git a/paramecio/libraries/show_links.py b/paramecio/citoplasma/show_links.py
similarity index 100%
rename from paramecio/libraries/show_links.py
rename to paramecio/citoplasma/show_links.py
diff --git a/paramecio/libraries/slugify.py b/paramecio/citoplasma/slugify.py
similarity index 100%
rename from paramecio/libraries/slugify.py
rename to paramecio/citoplasma/slugify.py
diff --git a/paramecio/libraries/templates.py b/paramecio/citoplasma/templates.py
similarity index 95%
rename from paramecio/libraries/templates.py
rename to paramecio/citoplasma/templates.py
index 0056670..44138d4 100644
--- a/paramecio/libraries/templates.py
+++ b/paramecio/citoplasma/templates.py
@@ -1,9 +1,9 @@
#!/usr/bin/python
from jinja2 import Template, Environment, FileSystemLoader
-from paramecio.libraries.urls import make_url, make_media_url, make_media_url_module, add_get_parameters
-from paramecio.libraries.i18n import I18n
-from paramecio.libraries.sessions import get_session
+from paramecio.citoplasma.urls import make_url, make_media_url, make_media_url_module, add_get_parameters
+from paramecio.citoplasma.i18n import I18n
+from paramecio.citoplasma.sessions import get_session
from settings import config
# Preparing envs for views of modules, and views of
diff --git a/paramecio/libraries/templates/forms/colorform.phtml b/paramecio/citoplasma/templates/forms/colorform.phtml
similarity index 94%
rename from paramecio/libraries/templates/forms/colorform.phtml
rename to paramecio/citoplasma/templates/forms/colorform.phtml
index 9c2cbad..bb21e6d 100644
--- a/paramecio/libraries/templates/forms/colorform.phtml
+++ b/paramecio/citoplasma/templates/forms/colorform.phtml
@@ -1,3 +1,4 @@
+${add_js_home_local('jquery.min.js', 'admin')}
${add_js_home_local('spectrum.js', 'admin')}
${add_css_home_local('spectrum.css', 'admin')}
<%
diff --git a/paramecio/libraries/templates/forms/dateform.phtml b/paramecio/citoplasma/templates/forms/dateform.phtml
similarity index 100%
rename from paramecio/libraries/templates/forms/dateform.phtml
rename to paramecio/citoplasma/templates/forms/dateform.phtml
diff --git a/paramecio/libraries/templates/forms/fileform.phtml b/paramecio/citoplasma/templates/forms/fileform.phtml
similarity index 100%
rename from paramecio/libraries/templates/forms/fileform.phtml
rename to paramecio/citoplasma/templates/forms/fileform.phtml
diff --git a/paramecio/libraries/templates/forms/i18nform.phtml b/paramecio/citoplasma/templates/forms/i18nform.phtml
similarity index 100%
rename from paramecio/libraries/templates/forms/i18nform.phtml
rename to paramecio/citoplasma/templates/forms/i18nform.phtml
diff --git a/paramecio/libraries/templates/forms/modelform.html b/paramecio/citoplasma/templates/forms/modelform.html
similarity index 100%
rename from paramecio/libraries/templates/forms/modelform.html
rename to paramecio/citoplasma/templates/forms/modelform.html
diff --git a/paramecio/libraries/templates/forms/modelform.phtml b/paramecio/citoplasma/templates/forms/modelform.phtml
similarity index 100%
rename from paramecio/libraries/templates/forms/modelform.phtml
rename to paramecio/citoplasma/templates/forms/modelform.phtml
diff --git a/paramecio/libraries/templates/forms/texthtmlform.phtml b/paramecio/citoplasma/templates/forms/texthtmlform.phtml
similarity index 100%
rename from paramecio/libraries/templates/forms/texthtmlform.phtml
rename to paramecio/citoplasma/templates/forms/texthtmlform.phtml
diff --git a/paramecio/libraries/templates/utils/admin.phtml b/paramecio/citoplasma/templates/utils/admin.phtml
similarity index 100%
rename from paramecio/libraries/templates/utils/admin.phtml
rename to paramecio/citoplasma/templates/utils/admin.phtml
diff --git a/paramecio/libraries/templates/utils/insertform.phtml b/paramecio/citoplasma/templates/utils/insertform.phtml
similarity index 100%
rename from paramecio/libraries/templates/utils/insertform.phtml
rename to paramecio/citoplasma/templates/utils/insertform.phtml
diff --git a/paramecio/libraries/templates/utils/list.phtml b/paramecio/citoplasma/templates/utils/list.phtml
similarity index 100%
rename from paramecio/libraries/templates/utils/list.phtml
rename to paramecio/citoplasma/templates/utils/list.phtml
diff --git a/paramecio/libraries/templates/utils/translations.phtml b/paramecio/citoplasma/templates/utils/translations.phtml
similarity index 100%
rename from paramecio/libraries/templates/utils/translations.phtml
rename to paramecio/citoplasma/templates/utils/translations.phtml
diff --git a/paramecio/libraries/templates/utils/verify_delete.phtml b/paramecio/citoplasma/templates/utils/verify_delete.phtml
similarity index 100%
rename from paramecio/libraries/templates/utils/verify_delete.phtml
rename to paramecio/citoplasma/templates/utils/verify_delete.phtml
diff --git a/paramecio/libraries/urls.py b/paramecio/citoplasma/urls.py
similarity index 100%
rename from paramecio/libraries/urls.py
rename to paramecio/citoplasma/urls.py
diff --git a/paramecio/console.py b/paramecio/console.py
index 1f45d49..2e949a7 100644
--- a/paramecio/console.py
+++ b/paramecio/console.py
@@ -7,8 +7,8 @@ import getpass
import re
from pathlib import Path
from base64 import b64encode
-from paramecio.libraries.db.webmodel import WebModel
-from paramecio.modules.admin2.models.admin import UserAdmin2, LoginTries2
+from paramecio.cromosoma.webmodel import WebModel
+from paramecio.modules.admin.models.admin import UserAdmin
from subprocess import call
from urllib.parse import urlparse
@@ -52,7 +52,7 @@ def start():
print('Error: cannot create the directory. Check if exists and if you have permissions')
exit()
- # Create folder settings and copy app.py, admin.py
+ # Create folder settings and copy index.py, admin.py
path_settings=args.path+'/settings'
@@ -74,11 +74,11 @@ def start():
try:
- shutil.copy(workdir+'/frontend/app.py', args.path+'/app.py')
+ shutil.copy(workdir+'/frontend/index.py', args.path+'/index.py')
except:
- print('Error: cannot copy the file app.py. Check if exists and if you have permissions for this task')
+ print('Error: cannot copy the file index.py. Check if exists and if you have permissions for this task')
try:
@@ -112,7 +112,7 @@ def start():
print('Error: cannot copy the file create_module.py. Check if exists and if you have permissions for this task')
- """
+
try:
shutil.copy(workdir+'/settings/modules.py', path_settings+'/modules.py')
@@ -120,7 +120,6 @@ def start():
except:
print('Error: cannot copy the file modules.py. Check if exists and if you have permissions for this task')
- """
if args.symlink==True:
try:
@@ -222,9 +221,7 @@ def start():
conn=WebModel.connection()
- useradmin=UserAdmin2(conn)
-
- logintries=LoginTries2(conn)
+ useradmin=UserAdmin(conn)
# Check if db exists
@@ -251,15 +248,13 @@ def start():
try:
- #shutil.copy(workdir+'/settings/modules.py.admin', path_settings+'/modules.py')
+ shutil.copy(workdir+'/settings/modules.py.admin', path_settings+'/modules.py')
- #shutil.copy(workdir+'/settings/config_admin.py.sample', path_settings+'/config_admin.py')
+ shutil.copy(workdir+'/settings/config_admin.py.sample', path_settings+'/config_admin.py')
sql=useradmin.create_table()
- tries_sql=logintries.create_table()
-
- if not useradmin.query(sql) or not useradmin.query(tries_sql) :
+ if not useradmin.query(sql):
print('Error: cannot create table admin, you can create this table with padmin.py')
else:
@@ -270,8 +265,7 @@ def start():
f.close()
- #config_text=config_text.replace("modules=['paramecio.modules.welcome']", "modules=['paramecio.modules.welcome', 'paramecio.modules.lang']")
- config_text=config_text.replace("apps={'welcome': ['paramecio.modules.welcome', 'welcome_app', '/'], 'lang': ['paramecio.modules.lang', '', '']}", "apps={'welcome': ['paramecio.modules.welcome', 'welcome_app', '/'], 'lang': ['paramecio.modules.lang', '', ''], 'admin2': ['paramecio.modules.admin2', 'admin_app', '/admin/']}")
+ config_text=config_text.replace("modules=['paramecio.modules.welcome']", "modules=['paramecio.modules.welcome', 'paramecio.modules.admin', 'paramecio.modules.lang']")
with open(path_settings+'/config.py', 'w') as f:
@@ -366,7 +360,7 @@ def start():
os.chdir(args.path)
#Regenerating modules.py
- """
+
regenerate='regenerate.py'
os.chmod(regenerate, 0o755)
@@ -376,7 +370,7 @@ def start():
exit(1)
else:
print('Regeneration of modules.py finished')
- """
+
# Installing models
padmin='padmin.py'
@@ -391,7 +385,7 @@ def start():
models_files=os.listdir(models_path)
- m=re.compile(r".*\.py$")
+ m=re.compile(".*\.py$")
underscore=re.compile("^__.*")
diff --git a/paramecio/create_module.py b/paramecio/create_module.py
index 5f8e68f..96e7c87 100644
--- a/paramecio/create_module.py
+++ b/paramecio/create_module.py
@@ -8,11 +8,8 @@ import getpass
from pathlib import Path
from settings import config
from importlib import import_module
-import re
def start():
- """Module for create new modules for paramecio
- """
parser=argparse.ArgumentParser(description='A tool for create new modules for paramecio')
@@ -40,68 +37,17 @@ def start():
#f=open('modules/'+args.path+'/index.py', 'w')
- name_module=os.path.basename(args.path)
-
try:
- shutil.copy(workdir+'/examples/app.py', 'modules/'+args.path)
-
- with open('modules/'+args.path+'/app.py') as f:
-
- app_file=f.read()
-
- app_file=app_file.replace('/example', '/'+name_module)
-
- with open('modules/'+args.path+'/app.py', 'w') as f:
-
- f.write(app_file)
-
- pass
+ shutil.copy(workdir+'/examples/index.py', 'modules/'+args.path)
except:
print('Error: cannot copy controller example. Check if you have permissions')
exit(1)
- # Edit config.py
-
- #module_final='modules.'+name_module
- module_final=f"'{name_module}': ['modules.{name_module}', '', '']"
-
- try:
-
- with open('./settings/config.py') as f:
-
- #modules_final='\''+'\', \''.join(final_modules)+'\''
-
- p=re.compile(r"^apps=\{(.*)\}$")
-
- #config_file=p.sub(r"modules=[\1, "+modules_final+"]", "modules=['paramecio.modules.welcome', 'paramecio.modules.admin', 'paramecio.modules.lang', 'modules.pastafari', 'modules.monit', 'modules.example']")
-
- final_config=''
-
- for line in f:
- if p.match(line):
- line=p.sub(r"apps={\1, "+module_final+"}", line)
- final_config+=line
-
- with open('./settings/config.py', 'w') as f:
-
- f.write(final_config)
-
- print('Updated configuration for add new modules...')
-
-
- except:
-
- print('Cannot update configuration, you need add the new module by hand')
-
- # Reload config
-
- #config.modules.append(module_final)
-
# Regenerate modules
- #regenerate_modules_config()
+ regenerate_modules_config()
def regenerate_modules_config():
@@ -130,7 +76,7 @@ def regenerate_modules_config():
for controller in dir_controllers:
- if controller.find('.py')!=-1 and controller.find('_')==-1:
+ if controller.find('.py')!=-1 and controller.find('__init__')==-1:
controller_py=controller.replace('.py', '')
@@ -153,8 +99,11 @@ def regenerate_modules_config():
print("-"*60)
exit(1)
- with open('./settings/modules.py', 'w') as f:
- f.write("".join(modules))
+ f=open('./settings/modules.py', 'w')
+
+ f.write("".join(modules))
+
+ f.close()
if __name__=="__main__":
start()
diff --git a/paramecio/libraries/db/.gitignore b/paramecio/cromosoma/.gitignore
similarity index 100%
rename from paramecio/libraries/db/.gitignore
rename to paramecio/cromosoma/.gitignore
diff --git a/paramecio/libraries/db/LICENSE b/paramecio/cromosoma/LICENSE
similarity index 100%
rename from paramecio/libraries/db/LICENSE
rename to paramecio/cromosoma/LICENSE
diff --git a/paramecio/libraries/db/README.md b/paramecio/cromosoma/README.md
similarity index 100%
rename from paramecio/libraries/db/README.md
rename to paramecio/cromosoma/README.md
diff --git a/paramecio/libraries/db/__init__.py b/paramecio/cromosoma/__init__.py
similarity index 100%
rename from paramecio/libraries/db/__init__.py
rename to paramecio/cromosoma/__init__.py
diff --git a/paramecio/cromosoma/corefields.py b/paramecio/cromosoma/corefields.py
new file mode 100644
index 0000000..4c24ba3
--- /dev/null
+++ b/paramecio/cromosoma/corefields.py
@@ -0,0 +1,262 @@
+from paramecio.cromosoma.webmodel import PhangoField
+from paramecio.cromosoma import coreforms
+from paramecio.citoplasma.i18n import I18n
+
+class IntegerField(PhangoField):
+
+ """Class that figure an integer sql type field.
+
+ Args:
+ name (str): The name of new field
+ size (int): The size of the new field in database. By default 11.
+ required (bool): Boolean for define if
+
+ """
+
+ def __init__(self, name, size=11, required=False):
+ super(IntegerField, self).__init__(name, size, required)
+ self.default_value=0
+
+ def check(self, value):
+
+ """Method for check if value is integer
+
+ Args:
+ value (int): The value to check
+
+ """
+
+ self.error=False
+ self.txt_error=''
+
+ try:
+
+ value=str(int(value))
+
+ if value=="0" and self.required==True:
+ self.txt_error="The value is zero"
+ self.error=True
+ except:
+
+ value="0"
+ self.txt_error="The value is zero"
+ self.error=True
+
+ return value
+
+ def get_type_sql(self):
+
+ """Method for return the sql code for this type
+
+ """
+
+ return 'INT('+str(self.size)+') NOT NULL DEFAULT "0"'
+
+class BigIntegerField(IntegerField):
+
+ """Class that figure an big integer sql type field.
+
+ Only change the sql type with respect to IntegerField
+
+ """
+
+ def get_type_sql(self):
+
+ """Method for return the sql code for this type
+
+ """
+
+ return 'BIGINT('+str(self.size)+') NOT NULL DEFAULT "0"'
+
+
+class FloatField(PhangoField):
+
+ """Class that figure an float sql type field.
+
+ Args:
+ name (str): The name of new field
+ size (int): The size of the new field in database. By default 11.
+ required (bool): Boolean for define if
+
+ """
+
+ def __init__(self, name, size=11, required=False):
+ super(FloatField, self).__init__(name, size, required)
+
+ self.error_default="The value is zero"
+ self.default_value=0
+
+ def check(self, value):
+
+ """Method for check if value is integer
+
+ Args:
+ value (float): The value to check
+
+ """
+
+ self.error=False
+ self.txt_error=''
+
+ try:
+
+ value=str(value)
+
+ if value.find(',')!=-1:
+ value=value.replace(',', '.')
+
+ value=str(float(value))
+
+ if value==0 and self.required==True:
+ self.txt_error=self.error_default
+ self.error=True
+ except:
+
+ value="0"
+ self.txt_error=self.error_default
+ self.error=True
+
+ return value
+
+ def get_type_sql(self):
+
+ return 'FLOAT NOT NULL DEFAULT "0"'
+
+class DecimalField(FloatField):
+
+ def get_type_sql(self):
+
+ return 'DECIMAL(20, 2) NOT NULL DEFAULT "0"'
+
+class DoubleField(FloatField):
+
+ def get_type_sql(self):
+
+ return 'DOUBLE NOT NULL DEFAULT "0"'
+
+class CharField(PhangoField):
+
+ pass
+
+class TextField(PhangoField):
+
+ def __init__(self, name, required=False):
+ super().__init__(name, 11, required)
+
+ self.set_default='NOT NULL'
+
+ def get_type_sql(self):
+
+ """Method for return the sql code for this type
+
+ """
+
+ return 'TEXT '+self.set_default
+
+class HTMLField(TextField):
+
+ def __init__(self, name, required=False):
+ super().__init__(name, required)
+
+ def check(self, value):
+
+ return re.sub('<.*?script?>', '', value)
+
+
+class ForeignKeyField(IntegerField):
+
+ def __init__(self, name, related_table, size=11, required=False, identifier_field='id', named_field="id", select_fields=[]):
+
+ super(ForeignKeyField, self).__init__(name, size, required)
+
+ self.table_id=related_table.name_field_id
+
+ self.table_name=related_table.name
+
+ self.related_model=related_table
+
+ self.identifier_field=identifier_field
+
+ self.named_field=named_field
+
+ self.select_fields=select_fields
+
+ self.foreignkey=True
+
+ self.change_form(coreforms.SelectModelForm, [related_table, self.named_field, self.identifier_field])
+
+ self.default_value=None
+
+ def check(self, value):
+
+ value=super().check(value)
+
+ if value=='0' or value==0:
+ value='NULL'
+
+ return value
+
+ def get_type_sql(self):
+
+ """Method for return the sql code for this type
+
+ """
+
+ return 'INT NULL'
+
+
+class BooleanField(IntegerField):
+
+ def __init__(self, name, size=1):
+
+ required=False
+
+ self.yes_text=I18n.lang('common', 'yes', 'Yes')
+ self.no_text=I18n.lang('common', 'no', 'No')
+
+ super(IntegerField, self).__init__(name, size, required)
+
+ self.default_error="Need 0 or 1 value"
+ self.default_value=0
+
+ def check(self, value):
+
+ self.error=False
+ self.txt_error=''
+
+ try:
+
+ value=int(value)
+
+ if value<0 or value>1:
+ self.txt_error=self.default_error
+ self.error=True
+
+ except:
+
+ self.error=True
+ self.txt_error=self.default_error
+ value=0
+
+ value=str(value)
+
+ return value
+
+ def get_type_sql(self):
+
+ """Method for return the sql code for this type
+
+ """
+
+ return 'BOOLEAN NOT NULL DEFAULT "0"'
+
+ def show_formatted(self, value):
+
+ value=int(value)
+
+ if value==0:
+ value=self.no_text
+ else:
+ value=self.yes_text
+
+ return str(value)
diff --git a/paramecio/libraries/db/coreforms.py b/paramecio/cromosoma/coreforms.py
similarity index 52%
rename from paramecio/libraries/db/coreforms.py
rename to paramecio/cromosoma/coreforms.py
index 76d8a7a..3247ddc 100644
--- a/paramecio/libraries/db/coreforms.py
+++ b/paramecio/cromosoma/coreforms.py
@@ -1,55 +1,13 @@
#!/usr/bin/env python3
-"""
-Parameciofm is a series of wrappers for Bottle.py, mako and others and construct a simple headless cms.
-
-Copyright (C) 2024 Antonio de la Rosa Caballero
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU Affero General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU Affero General Public License for more details.
-
-You should have received a copy of the GNU Affero General Public License
-along with this program. If not, see .
-"""
-
-
from collections import OrderedDict
from html import escape
#Forms para python3
class BaseForm:
- """The class used by all forms classes
-
- BaseForm is the base class used for all form classes.
-
- A form class is used for generate simple html forms, how input type, text type, hidden type, etc. PhangoField classes use this forms for generate automatically forms using GenerateAdminClass and others.
- """
def __init__(self, name, value):
- """
- Args:
- name (str): The html name for this form
- value (str): The default value of this html form.
-
- Attributes:
- label (str): Label used in functions how show_form that generate a complete html form from a form class list
- name (str): Name of the html form.
- default_value (mixed): The default value of the form. Equal to value in typical html form.
- css (str): Used for add css classes to the html form
- type (str): Variable used for conventional html forms with html tag
- field (PhangoField): Field related with this form. Used in PhangoField.
- required (boolean): If form is required or not, used in functions that generate forms.
- name_field_id (str): The html id for the html form. Used for html things.
- help (str): A string with help text, used in functions that generate forms.
- """
self.label=name
self.name=name
@@ -59,45 +17,26 @@ class BaseForm:
self.field=None
self.required=False
self.txt_error=''
- self.error=False
self.name_field_id=self.name+'_form'
self.help=''
- self.placeholder=''
def form(self):
- """Method for returm the html code of the form
- """
- return ''
+ return ''
def show_formatted(self, value):
- """Method for show the value of form formatted
-
- Args:
- value (mixed): The value of field form
- """
return value
#Method for escape value for html input. DON'T CHANGE IF YOU DON'T KNOWN WHAT ARE YOU DOING
def setform(self, value):
- """A method for set the value in the form for escape and other things
-
- Args:
- value (mixed): The value of field form for set
- """
value=str(value)
return value.replace('"', '"').replace("'", ''')
def change_name(self, new_name):
- """A method for change the default form html name of the field form
-
- Args:
- new_name (str): The new name of the form. Always is finished with _form suffix
- """
self.name=new_name
@@ -106,8 +45,6 @@ class BaseForm:
return ""
class SimpleTextForm(BaseForm):
- """Form for simple text
- """
def __init__(self, name, value):
super().__init__(name, value)
@@ -119,8 +56,6 @@ class SimpleTextForm(BaseForm):
return super().form()+' '+self.after_text
class TextForm(BaseForm):
- """Form for simple text form
- """
def __init__(self, name, value):
super(TextForm, self).__init__(name, value)
@@ -130,8 +65,6 @@ class TextForm(BaseForm):
return ''
class PasswordForm(BaseForm):
- """Form for password forms
- """
def __init__(self, name, value, show_password=False):
super(PasswordForm, self).__init__(name, value)
@@ -146,8 +79,6 @@ class PasswordForm(BaseForm):
return value
class HiddenForm(BaseForm):
- """Form for hidden forms
- """
def __init__(self, name, value):
super(HiddenForm, self).__init__(name, value)
@@ -155,16 +86,8 @@ class HiddenForm(BaseForm):
class SelectForm(BaseForm):
- """Form for select html form
- """
def __init__(self, name, value, elements=OrderedDict()):
- """
- Args:
- name (str): The html name for this form
- value (str): The default value of this html form
- elements (OrderedDict): An ordered dict with the keys(the form value) and text label. Example, if you have a OrderedDict how {'0': 'Value selected'} in a html select form you have the next result: