feat: PythonMapper done and documentated.

This commit is contained in:
KyMAN 2024-10-11 13:43:43 +02:00
parent 1b602ecb86
commit 87a11e5d1f
79 changed files with 2259 additions and 1 deletions

8
.gitignore vendored Normal file
View File

@ -0,0 +1,8 @@
/Data
/Public/data
*.[Ss]ecrets.*
*.[Ss]ecret.*
/Python/Abstracts/AnPMap.py
/Python/Abstracts/Applications.py
.sass-cache
__pycache__

View File

@ -0,0 +1,315 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="200mm"
height="200mm"
viewBox="0 0 200 200"
version="1.1"
id="svg5"
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
sodipodi:docname="PythonMapper.logo.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview7"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="mm"
showgrid="false"
inkscape:zoom="0.98164846"
inkscape:cx="322.41685"
inkscape:cy="363.67398"
inkscape:window-width="1920"
inkscape:window-height="1043"
inkscape:window-x="1920"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="layer2" />
<defs
id="defs2" />
<g
inkscape:label="Sheet"
inkscape:groupmode="layer"
id="layer1">
<path
id="rect111"
style="fill:#000000;stroke-width:0.270979"
d="M 44.999837 9.9999064 L 9.9999064 44.999837 L 9.9999064 189.99977 L 154.99984 189.99977 L 189.99977 154.99984 L 189.99977 9.9999064 L 44.999837 9.9999064 z M 51.111092 19.999813 L 179.99987 19.999813 L 179.99987 148.8891 L 148.8891 179.99987 L 19.999813 179.99987 L 19.999813 51.111092 L 51.111092 19.999813 z "
inkscape:label="Field" />
<path
id="rect360"
style="fill:#000000;stroke-width:0.252232"
d="M 50,30 30,50 h 20 z"
inkscape:label="Corner-Top-Left" />
<path
id="rect360-5"
style="fill:#000000;stroke-width:0.252232"
d="m 150,170 20,-20 h -20 z"
inkscape:label="Corner-Botom-Right" />
</g>
<g
inkscape:groupmode="layer"
id="layer2"
inkscape:label="Map">
<circle
style="fill:#000000;stroke-width:0.375816"
id="path751-3"
cx="45"
cy="60"
r="5" />
<circle
style="fill:#000000;stroke-width:0.375816"
id="path751-3-5-6"
cx="60"
cy="45"
r="5" />
<circle
style="fill:#000000;stroke-width:0.375816"
id="path751-3-5-6-2"
cx="60"
cy="60"
r="5" />
<circle
style="fill:#000000;stroke-width:0.375816"
id="path751-3-5-6-9"
cx="75"
cy="45"
r="5" />
<circle
style="fill:#000000;stroke-width:0.375816"
id="path751-3-5-6-0"
cx="90"
cy="45"
r="5" />
<circle
style="fill:#000000;stroke-width:0.375816"
id="path751-3-5-6-9-7"
cx="105"
cy="45"
r="5" />
<circle
style="fill:#000000;stroke-width:0.375816"
id="path751-3-5-6-92"
cx="120"
cy="45"
r="5" />
<circle
style="fill:#000000;stroke-width:0.375816"
id="path751-3-5-6-9-9"
cx="135"
cy="45"
r="5" />
<circle
style="fill:#000000;stroke-width:0.375816"
id="path751-3-5-6-2-2-7"
cx="135"
cy="60.000004"
r="5" />
<circle
style="fill:#000000;stroke-width:0.375816"
id="path751-3-5-6-2-23-6"
cx="150"
cy="59.999996"
r="5" />
<circle
style="fill:#000000;stroke-width:0.375816"
id="path751-3-5-6-9-93"
cx="75"
cy="90"
r="5" />
<circle
style="fill:#000000;stroke-width:0.375816"
id="path751-3-5-6-2-2-1"
cx="75"
cy="105"
r="5" />
<circle
style="fill:#000000;stroke-width:0.375816"
id="path751-3-5-6-0-9"
cx="90"
cy="90"
r="5" />
<circle
style="fill:#000000;stroke-width:0.375816"
id="path751-3-5-6-9-7-7"
cx="105.00001"
cy="90"
r="5" />
<circle
style="fill:#000000;stroke-width:0.375816"
id="path751-3-5-6-92-4"
cx="120.00001"
cy="90"
r="5" />
<circle
style="fill:#000000;stroke-width:0.375816"
id="path751-3-5-6-9-9-0"
cx="135"
cy="90"
r="5" />
<circle
style="fill:#000000;stroke-width:0.375816"
id="path751-3-5-6-0-9-7"
cx="90"
cy="165"
r="5" />
<circle
style="fill:#000000;stroke-width:0.375816"
id="path751-3-5-6-9-7-7-4"
cx="105.00001"
cy="165"
r="5" />
<circle
style="fill:#000000;stroke-width:0.375816"
id="path751-3-5-6-92-4-5"
cx="120.00001"
cy="165"
r="5" />
<circle
style="fill:#000000;stroke-width:0.375816"
id="path751-3-5-6-9-9-0-2"
cx="135"
cy="165"
r="5" />
<circle
style="fill:#000000;stroke-width:0.375816"
id="path751-3-9"
cx="45"
cy="75"
r="5" />
<circle
style="fill:#000000;stroke-width:0.375816"
id="path751-3-5-6-2-1"
cx="59.999996"
cy="75"
r="5" />
<circle
style="fill:#000000;stroke-width:0.375816"
id="path751-3-9-3"
cx="150"
cy="75"
r="5" />
<circle
style="fill:#000000;stroke-width:0.375816"
id="path751-3-2"
cx="45"
cy="90"
r="5" />
<circle
style="fill:#000000;stroke-width:0.375816"
id="path751-3-5-6-2-7"
cx="60.000004"
cy="90"
r="5" />
<circle
style="fill:#000000;stroke-width:0.375816"
id="path751-3-9-0"
cx="45"
cy="105.00001"
r="5" />
<circle
style="fill:#000000;stroke-width:0.375816"
id="path751-3-5-6-2-1-9"
cx="59.999996"
cy="105.00001"
r="5" />
<circle
style="fill:#000000;stroke-width:0.375816"
id="path751-3-3"
cx="45"
cy="120"
r="5" />
<circle
style="fill:#000000;stroke-width:0.375816"
id="path751-3-5-6-2-6"
cx="60"
cy="120"
r="5" />
<circle
style="fill:#000000;stroke-width:0.375816"
id="path751-3-9-06"
cx="45"
cy="135"
r="5" />
<circle
style="fill:#000000;stroke-width:0.375816"
id="path751-3-5-6-2-1-2"
cx="59.999996"
cy="135"
r="5" />
<circle
style="fill:#000000;stroke-width:0.375816"
id="path751-3-2-6"
cx="45"
cy="150"
r="5" />
<circle
style="fill:#000000;stroke-width:0.375816"
id="path751-3-5-6-2-7-1"
cx="60.000004"
cy="150"
r="5" />
<circle
style="fill:#000000;stroke-width:0.375816"
id="path751-3-3-1"
cx="105"
cy="120"
r="5" />
<circle
style="fill:#000000;stroke-width:0.375816"
id="path751-3-5-6-2-6-5"
cx="120"
cy="120"
r="5" />
<circle
style="fill:#000000;stroke-width:0.375816"
id="path751-3-5-6-2-1-2-4"
cx="120"
cy="135"
r="5" />
<circle
style="fill:#000000;stroke-width:0.375816"
id="path751-3-5-6-2-6-5-6"
cx="150"
cy="120"
r="5" />
<circle
style="fill:#000000;stroke-width:0.375816"
id="path751-3-5-6-2-1-2-4-5"
cx="150"
cy="135"
r="5" />
<circle
style="fill:#000000;stroke-width:0.375816"
id="path751-3-9-0-8"
cx="45"
cy="165"
r="5" />
<circle
style="fill:#000000;stroke-width:0.375816"
id="path751-3-5-6-2-1-9-7"
cx="59.999996"
cy="165"
r="5" />
<circle
style="fill:#000000;stroke-width:0.375816"
id="path751-3-5-6-9-9-0-6"
cx="135"
cy="75"
r="5" />
<circle
style="fill:#000000;stroke-width:0.375816"
id="path751-3-9-06-5-9"
cx="135"
cy="150"
r="5" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

View File

@ -0,0 +1,6 @@
{
"alarabiyah" : {
"python_mapper" : "PythonMapper"
}
}

View File

@ -0,0 +1,6 @@
{
"azerbaycanca" : {
"python_mapper" : "PythonMapper"
}
}

View File

@ -0,0 +1,6 @@
{
"blanga" : {
"python_mapper" : "MKVKNIFT"
}
}

View File

@ -0,0 +1,6 @@
{
"bokmal" : {
"python_mapper" : "PythonMapper"
}
}

View File

@ -0,0 +1,6 @@
{
"bulgarski" : {
"python_mapper" : "PythonMapper"
}
}

View File

@ -0,0 +1,6 @@
{
"catala" : {
"python_mapper" : "MKVBNSP"
}
}

View File

@ -0,0 +1,6 @@
{
"cestina" : {
"python_mapper" : "PythonMapper"
}
}

View File

@ -0,0 +1,6 @@
{
"dansk" : {
"python_mapper" : "I NÆRHEDEN AF PythonMapper"
}
}

View File

@ -0,0 +1,6 @@
{
"deutsch" : {
"python_mapper" : "PythonMapper"
}
}

View File

@ -0,0 +1,6 @@
{
"eesti" : {
"python_mapper" : "PythonMapper"
}
}

View File

@ -0,0 +1,6 @@
{
"ellinika" : {
"python_mapper" : "PythonMapper"
}
}

View File

@ -0,0 +1,6 @@
{
"english" : {
"python_mapper" : "PythonMapper"
}
}

View File

@ -0,0 +1,5 @@
{
"espanol" : {
"python_mapper" : "PythonMapper"
}
}

View File

@ -0,0 +1,6 @@
{
"esperanto" : {
"python_mapper" : "PythonMapper"
}
}

View File

@ -0,0 +1,6 @@
{
"farsi" : {
"python_mapper" : "PythonMapper"
}
}

View File

@ -0,0 +1,6 @@
{
"francais" : {
"python_mapper" : "PythonMapper"
}
}

View File

@ -0,0 +1,6 @@
{
"gaeilge" : {
"python_mapper" : "MKVBXTY"
}
}

View File

@ -0,0 +1,6 @@
{
"hangugeo" : {
"python_mapper" : "PythonMapper의 특징"
}
}

View File

@ -0,0 +1,6 @@
{
"hanyu" : {
"python_mapper" : "PythonMapper 相關相關相關相關相關相關相關相關相關相關相關相關相關相關相關相關相關相關相關相關相關相關相關相關相關相關相關相關相關相關相關相關相關相關相關相關相關相"
}
}

View File

@ -0,0 +1,6 @@
{
"hindi" : {
"python_mapper" : "PythonMapper"
}
}

View File

@ -0,0 +1,6 @@
{
"indonesia" : {
"python_mapper" : "LOGIN"
}
}

View File

@ -0,0 +1,6 @@
{
"italiano" : {
"python_mapper" : "PythonMapper"
}
}

View File

@ -0,0 +1,6 @@
{
"ivrit" : {
"python_mapper" : "PythonMapper"
}
}

View File

@ -0,0 +1,6 @@
{
"latviski" : {
"python_mapper" : "PythonMapper"
}
}

View File

@ -0,0 +1,6 @@
{
"lietuviskai" : {
"python_mapper" : "PythonMapperIS"
}
}

View File

@ -0,0 +1,6 @@
{
"magyar" : {
"python_mapper" : "PythonMapper"
}
}

View File

@ -0,0 +1,6 @@
{
"malayu" : {
"python_mapper" : "PythonMapper"
}
}

View File

@ -0,0 +1,6 @@
{
"nederlands" : {
"python_mapper" : "PythonMapper"
}
}

View File

@ -0,0 +1,6 @@
{
"nihongo" : {
"python_mapper" : "PythonMapperの"
}
}

View File

@ -0,0 +1,6 @@
{
"polski" : {
"python_mapper" : "PythonMapper"
}
}

View File

@ -0,0 +1,6 @@
{
"portugues" : {
"python_mapper" : "PythonMapper"
}
}

View File

@ -0,0 +1,6 @@
{
"romaneste" : {
"python_mapper" : "PythonMapper"
}
}

View File

@ -0,0 +1,6 @@
{
"russkiy" : {
"python_mapper" : "МКВБЖХГ"
}
}

View File

@ -0,0 +1,6 @@
{
"shqip" : {
"python_mapper" : "PythonMapper"
}
}

View File

@ -0,0 +1,6 @@
{
"slovencina" : {
"python_mapper" : "PythonMapper"
}
}

View File

@ -0,0 +1,6 @@
{
"slovenscina" : {
"python_mapper" : "PythonMapper"
}
}

View File

@ -0,0 +1,6 @@
{
"suomi" : {
"python_mapper" : "MKVBXH"
}
}

View File

@ -0,0 +1,6 @@
{
"svenska" : {
"python_mapper" : "PythonMapper"
}
}

View File

@ -0,0 +1,6 @@
{
"tagalog" : {
"python_mapper" : "MKBBFTQF"
}
}

View File

@ -0,0 +1,6 @@
{
"thai" : {
"python_mapper" : "ขนาด MKVBXLR"
}
}

View File

@ -0,0 +1,6 @@
{
"turkce" : {
"python_mapper" : "PythonMapper"
}
}

View File

@ -0,0 +1,6 @@
{
"ukrainska" : {
"python_mapper" : "МКВБКГСФ"
}
}

View File

@ -0,0 +1,6 @@
{
"urdu" : {
"python_mapper" : "میک‌بال‌زیم"
}
}

View File

@ -0,0 +1,6 @@
{
"zhongwen" : {
"python_mapper" : "PythonMapper 软件"
}
}

View File

@ -0,0 +1,3 @@
[
"get:/ /PythonMapper/Public"
]

View File

@ -0,0 +1,42 @@
{
"python_mapper_host_name" : "/^(https?\\:\\/{2})?pythonmapper\\.(k3y\\.pw|(anprm\\.)?local|anprm)/",
"python_mapper_default_settings_files" : [
"/JSON/PythonMapper.py.settings.json"
],
"python_mapper_default_secrets_files" : [
"/JSON/PythonMapper.py.settings.secrets.json"
],
"python_mapper_default_i18n_files" : [
"/JSON/I18N/PythonMapper.py.i18n.espanol.json"
],
"python_mapper_default_routes_files" : [
"/JSON/PythonMapper.py.routes.json",
"/JSON/PythonMapper.py.routes.secrets.json"
],
"python_mapper_default_views_files" : [],
"python_mapper_resources" : {
"charset" : "utf-8",
"logo" : "/images/PythonMapper.png",
"link" : "https://pythonmapper.k3y.pw/",
"git" : "https://git.k3y.pw/KyMAN/PythonMapper",
"project" : "PythonMapper",
"web" : "https://pythonmapper.k3y.pw",
"authors" : "KyMAN",
"class" : "python-mapper",
"snake" : "python_mapper",
"metas" : {},
"styles" : ["/scss/PythonMapper.scss"],
"menu" : [
["web", "_self", "/"],
["git", "_blank", "https://git.k3y.pw/KyMAN/PythonMapper"]
],
"licenses" : [
["copyright", null, null, {
"year" : "2024-2025",
"entity" : "KyMAN"
}],
["cc_by_nc_sa_4"]
],
"dictionary" : "https://wmarkdown.{domain}/json/WMarkDown.dict.es.kyman.json"
}
}

15
Public/doc/es/bugs.w.md Normal file
View File

@ -0,0 +1,15 @@
```wmd-options
language = es
title_i18n = python_mapper_title_bugs
title_text = Bugs y errors - PythonMapper
```
<!-- [[wmd]] -->
## Bugs y errors
Esta sección se dedicará a publicar todos los Bugs y errores reportados los cuales hallan sido catalogados por Srx00, con autoría de quien lo halla reportado, es decir, por falta de tiempo y recursos, posiblemente Srx00, autor de este proyecto no sea capaz de gestionar todas los reportes de Bugs y errores de dicho programa, aunque pondrá todo de su parte para dicho fin, y dichos reportes aparecerán con la autoría de quien lo halla descubierto para aplicar reconocimiento de dicha tarea.
También se podrá ver el estado del mismo, tanto por la descripción como por los estados de los Checkboxes que acompañen al Report.
<!-- [[wmd]] -->

View File

@ -0,0 +1,63 @@
Python, a la hora de trabajar con clases-objeto que se van generando en archivos que se van importando, estos archivos importados tienen un problema a la hora de asignar tipados de variables de elementos los cuales los importan, es decir: si tenemos una clase-objeto maestra donde el resto de clases-objeto de la estructura requieren de conocer al maestro, Python, sobre estructuras tipadas, ya sea por asignación voluntaria mediante "typing" como tipado forzoso como *py-py*, éste no puede ser asignado de esta forma por defecto.
> [!#] Un ejemplo de este caso sería el proyecto AnP, cuya filosofía exige un conocimiento de las clases-objetos pertenencientes a la clase-objeto AnP conozcan a dicho objeto que parte de éste último.
Con esta premisa, como se dijo antes, salvo usos específicos contra compiladores tipo *py-py* Python de por sí ignorará los tipados, por lo que si lo que se busca es tener un acceso al CodeDoc de código por parte del IDE a utilizar, se usará un archivo de elementos nulos y/o vacíos e inútiles que mapeen los elementos de dicha clase-objeto maestra, de esta forma no forzamos un tipado anidado por importación la cual es incompatible con Python. En cada librería que creemos implementamos los elementos a utilizar de dicha librería, simpre contando con que no se usen a modo de creación o ciertas características especiales, donde sí tendríamos que importar la librería original, como un modelo u objeto.
Explicando más claramente el problema, si nos basamos en la estructura base de AnP como ejemplo, lo que vemos es claramente que a la hora de importar la librería dependiente de AnP es que se forma un bucle infinito de cargas de dependencias, lo que determina en un error de dependencias en importación en Python.
```mermaid
flowchart LR
subgraph "Nivel 1"
A[AnP]
end
subgraph "Nivel 2"
P[Path]
S[Settings]
I[I18N]
end
A -->|tiene| P
A -->|tiene| S
A -->|tiene| I
P -->|depende de| A
S -->|depende de| A
I -->|depende de| A
S -->|depende de| P
I -->|depende de| P
```
> [!#] En un lenguaje como Java, PHP o Rust, este problema no existe pues una vez se cargan las librerías pertinentes, éstas quedan en ejecución al mismo nivel pero en el caso de Python es como que dichas librerías se ejecutan en un nivel independiente y por lo tanto, se crean niveles de dependencias entre ellos. A continuación se muestra otro gráfico de qué pasaría a la hora de hacer dicha dependencia dentro de AnP.
```mermaid
flowchart TD
A0["AnP original"]
P0["Path original"]
A1["AnP dependencia de nivel 1"]
P1["Path uso de nivel 1"]
A2["AnP dependencia de nivel 2"]
P2["Path uso de nivel 2"]
A3["AnP dependencia de nivel 3"]
P3["Path uso de nivel 3"]
AN(("AnP dependencia \nde nivel N (Infinito)"))
A0 -->|tiene| P0
P0 -->|"depende y carga"| A1
A1 -->|tiene| P1
P1 -->|"depende y carga"| A2
A2 -->|tiene| P2
P2 -->|"depende y carga"| A3
A3 -->|tiene| P3
P3 -->|"depende y carga"| AN
```
> [!! ¡IMPORTANTE!] Desde el equipo de desarrollo de este proyecto queremos matizar que esta filosofía de desarrollo no es eficiente, y no sería aconsejable su uso en proyectos cuya filosofía o motivo de existencia sea la eficiencia y el consumo reducido pues requeriríamos de compilaciones y ejecuciones más orientadas a *py-py*. Este proyecto sólo es viable para proyectos cuya filosofía sea más bien la facilidad cara el desarrollo de aplicaciones que no requieran de una eficiencia importante.
Para solucionar dicho problema y automatizar dicho proceso en dicha casuística, creamos la librería "mapper.py" en el lado del proyecto Python, una librería completamente independiente que nos permita hacer un mapeado automático de los ficheros que nosotros le asignemos.
> [!#] Ya existen librerías e importaciones Python que hace esta tarea pero tanto por aprender cómo sería por debajo uno de estos procesos, así como hacer un uso personalizado del mismo, se decidió crear la librería propia para dicho fin.

47
Public/doc/es/design.w.md Normal file
View File

@ -0,0 +1,47 @@
```wmd-options
language = es
title_i18n = python_mapper_title_design
title_text = Diseño - PythonMapper
```
<!-- [[wmd]] -->
## Diseño
El proyecto en cuestión no tendría un diseño específico si no fuese por el hecho de tener una documentación vinculada por el hecho de ser una simple librería para una función específica para tratar y procesar archivos Python para mapearlos y así ser vinculados sus elementos por tipado conocido, aunque éste sea falso, así como el logo del proyecto. El sistema de colores se basará en el WMarkDown, siguiendo con la siguiente tabla:
[|
|= Tipo | Hexadecimal | RGBA | Muestra
| Fondo | #EFEFEF | rgba\(239, 239, 239, 1) | [[#EFEFEF]]
| Frontal | #222 | rgba\(34, 34, 34, 1) | [[#222]]
| Primario | #459 | rgba\(64, 80, 144, 1) | [[#459]]
| Secundario | #BA5 | rgba\(176, 160, 80, 1) | [[#BA5]]
| Gris | #888 | rgba\(136, 136, 136, 1) | [[#888]]
| Tabla título | #19888888 | rgba\(136, 136, 136, 0.1) | [[color rgba(136, 136, 136, 0.1)]]
| Tabla Select | #19888888 | rgba\(136, 136, 136, 0.1) | [[color rgba(136, 136, 136, 0.1)]]
| Tabla impar | #38888888 | rgba\(136, 136, 136, 0.2) | [[color rgba(136, 136, 136, 0.2)]]
| Tabla par | #00FFFFFF | rgba\(255, 255, 255, 0) | [[color rgba(255, 255, 255, 0)]]
| Borde interno | #19888888 | rgba\(136, 136, 136, 0.5) | [[color rgba(136, 136, 136, 0.5)]]
| Diccionario | #333C5E | rgba\(51, 60, 94, 1) | [[#333C5E]]
| Diccionario en | #6F663C | rgba\(111, 102, 60, 1) | [[#6F663C]]
| Code impar | #38C8C8C8 | rgba\(200, 200, 200, 0.2) | [[color rgba(200, 200, 200, 0.2)]]
|]
> [!#] Los colores seleccionados van en referencia a los colores originales de Python puesto que es un proyecto dedicado única y exclusivamente a dicho entorno, pero no son los mismos, orientados a un diseño personalizado.
Con respecto a las fuentes, se dejan las que tiene por defecto WMarkDown, las cuales son:
* **Roboto**. Para el texto en general.
* https://fonts.google.com/specimen/Roboto?query=roboto
* **Roboto Mono**. Para los bloques de código.
* https://fonts.google.com/specimen/Roboto+Mono?query=roboto
* **Font Awesome**. Para la iconificación general de la Web.
* https://fontawesome.com/
Con respecto al logo, nos encontramos con un entorno cuadrado con dos esquinas dobladas simulando una hoja a modo de mapa, y dentro, mediante puntos, simulando un mapeado digital, las letras simplificadas de Python, las cuales son "Py". Dicho logo viene siendo el siguiente:
((!image /images/PythonMapper.png))
> [!@Srx00] Soy consciente de que los puntos que mapean las letras dentro del logo no están centradas, sin embargo, el objetivo era posicionar los puntos desde valores absolutos con separación y tamaño determinados, y por esto es el defecto que se ve, pero pareció bien la estética resultante y se determinó dejarlo así, además, de esta forma daba más aspecto de cubo por dicho desplazamiento, dando un segundo juego visual con sensación de volumen.
<!-- [[wmd]] -->

View File

@ -0,0 +1,55 @@
```wmd-options
language = es
title_i18n = python_mapper_title_donates
title_text = Donaciones - PythonMapper
```
<!-- [[wmd]] -->
## Donaciones
Este proyecto es plenamente gratuito pues es un proyecto orientado a complementar otros proyectos de los mismos desarrolladores. No tiene ningún plan de ingresos ni pasivos ni activos más allá de lo que se expone en este título. Si alguien quisiere colaborar en que este proyecto no sólo esté abierto por requisitos de los autores, sino también cara un mantenimiento hacia terceros, a continuación presentamos unas direcciones de Cryptoactivos donde se podrá donar sin ninguna cuantía mínima establecida.
- **Bitcoin** o *BTC*: [bitcoin:bc1qtar0zqxhss4n27cw8lsxpc5tnv6e9xwe0rkfs4?label=PythonMapperDonation bc1qtar0zqxhss4n27cw8lsxpc5tnv6e9xwe0rkfs4]
- **Litecoin** o *LTC*: [litecoin:ltc1q9ts8x70nse9jen6d6g2wuyehdl2wzclwycwv3m?label=PythonMapperDonation ltc1q9ts8x70nse9jen6d6g2wuyehdl2wzclwycwv3m]
- **Dogecoin** o *DOGE*: [dogecoin:DBYYDiKy3UoBn1LdWWHFpcUBseEgc5bGSi?label=PythonMapperDonation DBYYDiKy3UoBn1LdWWHFpcUBseEgc5bGSi]
- **Dash**: [dash:XsVkSBwZoH7R8QTAz82kiSe1jvQDv5WB93?label=PythonMapperDonation XsVkSBwZoH7R8QTAz82kiSe1jvQDv5WB93]
- **Faircoin** o *FAIR*: [faircoin:fFpdTtn5dqkuHy1oiaxhV72zx7Wd1VuTGk?label=PythonMapperDonation fFpdTtn5dqkuHy1oiaxhV72zx7Wd1VuTGk]
> [!!] Mientras no halla ninguna condición de recursos que impida el mantenimiento gratuito de este servicio, éste permanecerá mantenido y público independientemente de los ingresos obtenidos a partir de los donativos.
> [!#] Los usuarios que colaboren y quieran ser referenciados, éstos serán referenciados en este apartado mediante un Quote de comentario de usuario con el Nick y avatar correspondiente, pero sólo en caso de que ellos quieran aparecer aquí.
> [!#] Se mantendrá informados a los usuarios de todo aquel donativo dado y la cantidad económica adquirida, y será publicado su uso y tenencia para que halla constancia pública del uso que se le dé a dichos recursos.
> [!@Srx00] Quería agredecer de forma persona aquellas aportaciones que serán bien recibidas y valoradas para este proyecto, ya sea como valor simbólico como de mantenimiento. Así, que desde el desarrollo y como desarrollador de este proyecto, muchas gracias a todos aquellos que ponen su granito de arena para este proyecto y por lo tanto, en pro de todos. Muchas gracias, de verdad.
### Balance
A continuación se mostrará una tabla de balance con respecto a las cantidades y usos dados.
[|
|= Activo | Cantidad | Motivo | Usuario | Cantidad total actual
| **BTC** | 0 BTC | Inicio del contador de unidades de BTC. | | 0 BTC
| **LTC** | 0 LTC | Inicio del contador de unidades de LTC. | | 0 LTC
| **DOGE** | 0 DOGE | Inicio del contador de unidades de DOGE. | | 0 DOGE
| **DASH** | 0 DASH | Inicio del contador de unidades de DASH. | | 0 DASH
| **FAIR** | 0 FAIR | Inicio del contador de unidades de FAIR. | | 0 FAIR
|]
Cómputo total actual en tenencia.
[|
|= Activo | Cantidad | Número de Operaciones
| **BTC** | 0 BTC | 0
| **LTC** | 0 LTC | 0
| **DOGE** | 0 DOGE | 0
| **DASH** | 0 DASH | 0
| **FAIR** | 0 FAIR | 0
|]
### Donantes
A continuación, los comentarios de los donantes.
<!-- [[wmd]] -->

25
Public/doc/es/faq.w.md Normal file
View File

@ -0,0 +1,25 @@
```wmd-options
language = es
title_i18n = python_mapper_title_faq
title_text = F.A.Q. - PythonMapper
```
<!-- [[wmd]] -->
## F.A.Q.
En este apartado se responderán a las preguntas más frecuentes que se puedan realizar en el entorno cercano de este proyecto.
> [!?] **¿Por qué se crea este proyecto a pesar de que ya hay otros muchos que teóricamente hacen lo mismo ya implementados dentro de IDEs como Visual Studio Code, entre otros?** El problema es que aquí se trabaja una filosofía no nativa de Python, pero no implica incompatibilidad en su base, por lo que para poder trabajar literalmente dicho sistema se optó por desarrollar un sistema propio que mediante un proceso paralelo y automático a la par que se desarrolla un proyecto, éste pueda ir mapeando dicho proyecto para establecer las dependencias de tipado sobre los elementos que se van adjuntando, así queda plenamente separado del IDE y de cualquier otro recurso y sólo requeriría de ser ejecutado con el propio Python tras una configuración inicial del mismo.
> [!?] **¿Por qué este trabajo está público y gratuito?** Esta librería es una librería que sí o sí iba a desarrollar Srx00 para los fines de los distintos proyectos que desarrolla. Al no tener un modelo de negocio y no estar sujeto a clientes, éste quedará libre y gratuito, dentro de los términos y condiciones de la licencia Creative Commons BY-NC-SA 4.0. Ésto permite no sólo compartir con la comunidad, sino también currículum y una forma de extender el conocimiento de existencia de este tipo de proyectos de Srx00.
> [!?] **¿Por qué la licencia Creative Commons de Atribución, No Comercial y que se Permite Compartir, CC-BY-NC-SA 4.0?** Porque Srx00 quiere compartir con la comunidad este trabajo, sin embargo, una de las condiciones más importantes es reconocer la autoría original, lo que ofrece Currículum y conocimiento del trabajo del o los autores, además de no permitir la comercialización de dicho proyecto, lo que no impide que éste pueda estar en un proyecto comercial siempre que lo que se venda no sea este proyecto. Las licencias como MIT o GPL no cumplen con dichas espectativas y Srx00 tiene la filosofía de que todo trabajo ha de ser reconocido a su autor aunque éste no lo requiera o precise pues es su trabajo.
> [!?] **Al ser un proyecto CC-BY-NC-SA 4.0, el cual tiene como condición No Comercial. ¿Podría integrar este proyecto en un proyecto personal de caracter privado y comercial?** Sí, siempre que éste reconozca la autoría de este proyecto y que no sea éste la base de negocio económico de dicho proyecto, es decir, si se integra para gestionar los errores del proyecto o cualquier otra cosa que ayude o facilite el trabajo del mismo pero la base económica del proyecto sea otra cosa agena a eso se permite perfectamente el uso y manipulación del mismo.
> [!?] **Los métodos y funciones creados en el archivo del mapeado Python no retornan nada, simplemente se le asigna un cuerpo con la palabra clave *pass*. Una cosa similar pasa con las variables, que tienen como valor *None*. ¿Está correcto eso?** Pues sí, eso se hace con la finalidad de que el método o función exista pero no tenga repercusión a la hora de ser llamado pues cuando se llame desde un objeto, aunque el tipado referencie al mapeado, éste se ejecutará como nativamente es, ignorando el mapeado. Con respecto a las variables pasa exactamente lo mismo, sin embargo, sí hay una repercusión cara las variables estáticas o de clase las cuales salen de la propia definición de la clase. Para poder hacer uso del recurso estático original y no del mapeado ha de hacerse a partir del recurso relativo que estamos trabajando en ese momento.
> [!?] **Desde que hago uso del mapeado, cuando intento acceder a un recurso estático, éste sale con valores nulos o con métodos que no tienen ni retorno ni procesamiento. ¿Qué estoy haciendo mal?** Uno de los problemas que nos encontramos al hacer uso de los mapeados es que en el nivel de importación donde los usamos, éstos sobreescriben a las definiciones originales por lo que es de vital importancia que en caso de usar mapeados, los recursos estáticos sean accesibles desde los objetos de trabajo pues éstos siguen usando el mapeado original. Este es el motivo principal por el cual sólo ha de importarse las partes del mapeado que realmente se estén utilizando como tipados de referencia, pero nunca importar completamente éste pues nos dará este tipo de problemas inesperados.
<!-- [[wmd]] -->

27
Public/doc/es/index.w.md Normal file
View File

@ -0,0 +1,27 @@
```wmd-options
language = es
title_i18n = python_mapper_title_documentation
title_text = Documentación - PythonMapper
```
<!-- [[wmd]] -->
[[include description.md]]
[[include projects.w.md]]
[[include design.w.md]]
[[include manual/index.w.md]]
[[include faq.w.md]]
[[include bugs.w.md]]
[[include targets.w.md]]
[[include opinions.w.md]]
[[include donates.w.md]]
<!-- [[wmd]] -->

View File

@ -0,0 +1,17 @@
```wmd-options
language = es
title_i18n = python_mapper_title_manual
title_text = Manual - PythonMapper
```
<!-- [[wmd]] -->
## Manual
El manual de este proyecto se basa en dos partes bien diferenciadas: el manual de uso; y el manual del desarrollador para quienes quieran alterar dicho proyecto para fines específicos dentro de los términos de la licencia que lo sostenta.
[[include use.w.md]]
[[include technitian.w.md]]
<!-- [[wmd]] -->

View File

@ -0,0 +1,29 @@
```wmd-options
language = es
title_i18n = python_mapper_title_manual_technitian
title_text = Técnico - Manual - PythonMapper
```
<!-- [[wmd]] -->
### Manual tećnico
El sistema se basa únicamente en una librería Python la cual ha de ser ejecutada tras establecer la configuración del o los proyectos que queramos mapear. Una vez está ejecutado con dicha configuración, ésta creará un objeto **PythonMapper.Project** para gestionar los proyectos individualmente. El hilo de procesos que gestiona dicho proyecto es único y colgarán de éste un sistema de eventos similares a los Intervalos de JavaScript, el cual gestionará tiempos de espera, de carga y procesamiento en monohilo para evitar un consumo de recursos excesivo y permitir la convivencia de dicho proceso en entornos con más procesos dentro del ecosistema Software donde se aloje.
La configuración que se extrae para gestionar los valores de los objetos **PythonMapper.Project** serán sacados principalmente del diccionario dado para cada proyecto individualmente, y se complementará a partir de la clase estática **PythonMapper.Settings**, la cual contiene la configuración por defecto para todo el proyecto.
Por otro lado, tenemos un sistema de gestión de memoria anidada mediante la clase objeto **PythonMapper.SearchData**, contiene los datos necesarios para la gestión de cada una de las librerías del proyecto qeu se esté trabajando, ordenando sus recursos por niveles de dependencias y de contenidos.
Finalmente, el proyecto hace uso de la clase objeto **PythonMapper.ClassData** que contiene toda la información de cada uno de los niveles de clase de una librería, siendo el nivel 0 el Root de la propia librería y los siguientes niveles las clases, incluyendo las clases anidadas. También contiene los elementos estáticos, variables de objeto y métodos. Cada una de las clases anidadas estará compuesta por otro objeto **PythonMapper.ClassData** anidado sobre el anterior para establecer orden de dependencias.
Para poder gestionar de una forma óptima dicho contenido, todo se moverá sobre un objeto de la clase **PythonMapper**, el cual cargarálos proyectos y los asignará a objetos de tipo **PythonMapper.Project** gestionados a partir de un único hilo que funciona como un Intervalo JavaScript para gestionar los tiempos mediante simulaciones de Wait con tiempos no definidos para su trabajo tanto en la configuración como con la capacidad de poderse cerrar prácticamente instáneamente la aplicación, con una gestión de cola o de semáforo sobre un único hilo rápido.
Para hacer más efectivo el proceso, éste cacheará todos los archivos que ha de mapear, donde detectará si cada archivo fue alterado o no, donde si lo fue, éste se procesará y creará dará orden a actualizar el archivo de mapeado una vez termine de procesar todos los archivos.
El proceso de los archivos, para simplificar los patrones regulares y las estructuras de búsqueda, se formatearán mediante claves que identifican las anidaciones, mediante el método estático **PythonMapper.Project.unclean_data**. Tras dicho paso se Matchearán los patrones que identifican las clases, las variables tanto estáticas como de objeto, y los métodos, y se ignorarán los elementos privados y/o repetidos, quedándose sólo los elementos ocultos o públicos en su primera aparición. La gestión de los Matcheos se hace a partir de una estructura While True que gestiona el contenido hasta que éste sea finalizado.
Todos estos resultados se almacenan en la estructura anidada de tipo **PythonMapper.ClassData** para su posterior gestión. Cada vez que se detecta un fragmento a almacenar en dicha estructura, éste se le limpiará el formato mediante el método estático **PythonMapper.Project.clean_code**, y desprovisto de las tabulaciones iniciales para ser establecidas limpiamente después, listo para ser integrado dentro del archivo Mapper. Los niveles de anidamiento de la estructura de tipo **PythonMapper.ClassData** determinarán la tabulación.
El orden de los elementos dentro del archivo mapeado será el dado por los archivos, aunque habrá un orden establecido para los elementos integrados en una clase donde se establece la definición de nombre de clase, luego los elementos estáticos, luego el constructor con sus correspondientes variables objeto si éste los tuviese, y finalmente los métodos del mismo, incluyendo sus modificadores.
<!-- [[wmd]] -->

View File

@ -0,0 +1,256 @@
```wmd-options
language = es
title_i18n = python_mapper_title_manual_use
title_text = Usuario - Manual - PythonMapper
```
<!-- [[wmd]] -->
### Usuario
Para poder utilizar este proyecto simplemente hemos de desargar el archivo **[https://git.k3y.pw/KyMAN/PythonMapper/src/branch/main/Python/PythonMapper.py Python/PythonMapper.py]** del proyecto Git. Para evitar problemas con los Path relativos internos del proyecto se aconseja clonar el proyecto.
```sh
#!/bin/bash
git clone https://git.k3y.pw/KyMAN/PythonMapper
cd PythonMapper
```
Una vez clonado el proyecto, simplemente hemos de crear un archivo JSON dentro del directorio JSON de la raíz del proyecto llamado **PythonMapper.py.projects.secrets.json** donde instalaremos todos los proyectos con las librerías y propiedades que queramos automatizar a partir de la filosofía de trabajo de la librería *PythonMapper*. Este archivo JSON se compone de un diccionario donde se mete una clave para identificar cada uno de los proyectos, e internamente al valor de dicha clave, otro diccionario anidado con los siguientes atributos:
* **path** *\(Obligatorio)*: Path absoluto del que colgarán los archivos vinculados al proyecto.
* **files** *\(Obligatorio)*: Lista de los Path relativos al Path absoluto de los archivos Python que queramos mapear.
* **map** *\(Obligatorio)*: Path relativo al Path absoluto del archivo de mapeado resultante.
* **dependences** *\(Opcional)*: Lista de dependencias que queramos agregar a dicho fichero con respecto a los tipados tanto de extensión como de implementación de las clases, así como de los tipados usados por las variables, argumentos, parámetros y/o atributos.
* **definitions** *\(Opcional)*: Lista de variables predefinidas que queramos añadir a nuestro archivo de mapeado para su correcta interpretación. Éste viene siendo una lista sencilla de Strings donde dependiendo de qué se le establece, éste actuará de una forma distinta según ciertos criterios.
* **tabulation** *\(Optional)*: String que representaría los caracteres en blanco usados por tabulación. *Por defecto son 4 espacios, pero puede ser establecido 2 espacios en blanco, un caracter de tabulación, etc. A conveniencia del usuario desarrollador.*
* **timer** *\(Optional)*: Tiempo de espera para volver a analizar los ficheros para verificar cambios en éstos y reconstruir el archivo de mapeado en milisegundos. *Por defecto son 30000 milisegundos.*
* **rest** o **rest_timer** *\(Optional)*: Tiempo de espera para el procesamiento del siguiente fichero a la hora de analizar los ficheros de un proyecto. Este tiempo es bastante importante para evitar un trabajo excesivo sobre el procesador permitiendo un descanso en milisegundos entre el procesado de un archivo y otro. *Por defecto, el tiempo de espera es de 10 milisegundos.*
> [!!] Es importante destacar que los Paths que se usarán para la autogeneración del mepeado parten del **path** dado en la configuración concatenado mediante un Slash (**/**) al Path relativo que se esté trabajando, ya sea el del propio mapeado como el de cualquiera de los ficheros dados, por lo que es aconsejable no acabar con Slash el parámetro **path**; así como tampoco iniciar con dicho caracter ninguno de los ficheros definidos en **files** ni el Path relativo del mapeado establecido en **map**.
La ejecución de la librería **Python/PythonMapper.py** puede ser ejecutada desde un entorno Unix desde el fichero **Tools/run.sh** del proyecto en cuestiónk, aunque puede ser también ejecutado directamente desde Python. Dicho archivo Bash Shell está diseñado para simplificar y facilitar la ejecución del mismo.
#### Dependencias
La lista de dependencias no es más que una lista cuyos valores pueden depender acerca de la finalidad o el sistema de importar dicha dependencia. Dichos patrones serían los siguientes:
##### Dependencia directa
La dependencia directa no es más que un String el cual será interpretado como código Python de forma directa. Se distingue de la opción de establecer el nombre de la dependencia por la existencia de espacios en dicho String que complementa el Script Python.
```json
{
"AnP" : {
"dependences" : [
"from re import Pattern as REPattern"
]
}
}
```
```py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from re import Pattern as REPattern
```
##### Dependencia por nombre
La dependencia por nombre no es más que un String el cual contiene el nombre de la dependencia que queremos adjuntar. A diferencia de la dependencia directa, ésta no puede contener espacios y se espera el nombre o el Path Python de la dependencia separado por puntos, sin espacios y sin aliases.
```json
{
"AnP" : {
"dependences" : [
"datetime"
]
}
}
```
```py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import datetime
```
##### Dependencia parcial
La dependencia parcial consta de una lista de 2 elementos donde el primer elemento es un String que determina el Path Python del paquete de la dependencia; y el segundo elemento puede ser un String o una lista de Strings para determinar uno o más elementos a importar, específicamente de dicha librería, ahorrando una importación total, siendo ésta más definida y exclusiva al uso.
```json
{
"AnP" : {
"dependences" : [
["typing", ["Any", "Optional", "NewType"]],
["threading", "Thread"]
]
}
}
```
```py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from typing import Any, Optional, NewType
from threading import Thread
```
##### Importación con alias
La importación con alias se crea a partir de una lista de 3 elementos String los cuales son:
1. Path Python del paquete de la dependencia.
2. Elemento que queremos importar.
3. Alias que le queremos dar.
```json
{
"AnP" : {
"dependences" : [
["re", "Pattern", "REPattern"],
["re", "Match", "REMatch"]
]
}
}
```
```py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from re import Pattern as REPattern
from re import Match as REMatch
```
#### Definiciones
Las definiciones se usan para definir variables que ayuden a la interpretación correcta del mapeado si alguna dependencia no es aplicable desde un principio o en el conjunto del mapeado. La idea es crear temporal o permanentemente dentro del mapeado las variables de uso para tipados. Éstas pueden ser de las siguientes formas:
> [!!] Las definiciones no son variables con un tipado concreto, sino que es la definición de un tipado a usar dentro del mapeado.
> [!!] Si en el mapeado de Python no se integra la importación de **typing.NewType**, éste lo implementará automáticamente si hay alguna variable a crear.
##### Definición por nombre
Cuando se define una variable por nombre, ésta quedará con un tipado equivalente de *Any* mediante su nombre.
```json
{
"AnP" : {
"definitions" : [
"AnP"
]
}
}
```
```py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from typing import NewType
AnP = NewType("AnP", Any)
```
##### Definición cruda
La definición cruda viene siendo un String el cual genere la definición de por sí.
```json
{
"AnP" : {
"definitions" : [
"AnP = NewType(\"AnP\", Any)"
]
}
}
```
```py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
AnP = NewType("AnP", Any)
```
> [!! ¡IMPORTANTE!] Si se hace una definición cruda se entiende que toda dependencia que requiera está implementada en la sección de dependencias. si no es así, la librería de mapeado dará error.
> [!!] Este tipo de definiciones se aplican a tipados que requieren de especificar conceptos de tipado concretos.
#### Ejemplo
Un ejemplo de un proyecto a mapear sería el propio AnP, el cual, a fecha de la creación de dicha documentación sería de la siguiente forma:
```json
{
"anp" : {
"path" : "/media/kyman/SSD2TB/git/AnP/Python",
"files" : [
"Models/HTTP.py",
"Models/RoutesResponse.py",
"Abstracts/Applications.py",
"Models/Routes.py",
"Modules/ErrorsManager.py",
"Abstracts/Managers.py",
"Abstracts/OwnSettings.py",
"Abstracts/HTTP.py",
"Application/Events.py",
"Models/Threads.py",
"Models/Commands.py",
"Abstracts/Connections.py",
"Abstracts/Controllers.py",
"Managers/PrintTypes.py",
"Application/Path.py",
"Managers/Settings.py",
"Managers/I18N.py",
"Modules/WMarkDown.py",
"Models/Licenses.py",
"Managers/Licenses.py",
"Application/Threads.py",
"Application/Terminal.py",
"Managers/MimeExtensions.py",
"Managers/Connections.py",
"Managers/Views.py",
"Managers/Controllers.py",
"Managers/Routes.py",
"Managers/Servers.py",
"Managers/Applications.py",
"Models/Shell.py",
"Models/Proxy.py",
"Drivers/UnixDomainSocketWebServer.py",
"Drivers/Shell.py",
"Drivers/Curl.py",
"Drivers/CSV.py",
"Drivers/Selenium.py",
"Drivers/ProxiesList.py",
"Application/AnP.py"
],
"map" : "Abstracts/AnPMap.py",
"dependences" : [
["typing", ["Any", "Optional", "Callable"]],
["socket", "socket", "Socket"],
"datetime",
["re", "Pattern", "REPattern"],
["re", "Match", "REMatch"],
["threading", "Thread"]
],
"definitions" : [
"Self", "WebDriver", "WebElement", "AnP", "class ObjectSetter:pass"
]
}
}
```
<!-- [[wmd]] -->

View File

@ -0,0 +1,17 @@
```wmd-options
language = es
title_i18n = python_mapper_title_opinions
title_text = Opiniones y comentarios - PythonMapper
```
<!-- [[wmd]] -->
## Opiniones y comentarios
Esta sección va dedicada a publicar las opiniones y comentarios de usuarios cercanos a los desarrolladores del proyecto para que halla una visión externa a éste, aprobechando la confianza en éstos tanto para lo bueno como para lo malo.
> [!@Srx00] Quería agradecer personalmente a todos aquellos que me han dado una opinión y/o comentario acerca de este proyecto. Lo valoro mucho pues sea como crítica para aprender como apoyo a continuar con este tipo de trabajos, me son realmente importantes. ¡Muchas gracias!
> [!@Srx00] Como opinión personal, es un proyecto raro, que le da mayor complejidad a la aplicación que lo integre, sin embargo, da una faceta de ayuda paralelamente al IDE actualizando la dependencia que mapea los objetos de una forma más clásica tirando al sistema de Java o similares, un proyecto con dependencias anidadas Python.
<!-- [[wmd]] -->

View File

@ -0,0 +1,46 @@
```wmd-options
language = es
title_i18n = python_mapper_title_projects
title_text = Proyectos - PythonMapper
```
<!-- [[wmd]] -->
## Proyectos
Este proyecto es independiente a nivel de funcionamiento como librería, sin embargo, a nivel de página Web, éste hace uso de los siguientes proyectos.
[["""
WMarkDown
*https://wmarkdown.k3y.pw/images/WMarkDown.png
*https://wmarkdown.k3y.pw/favicon.ico
https://wmarkdown.k3y.pw/
https://git.k3y.pw/Whalers/WMarkDown
AnP
*https://anp.k3y.pw/images/AnP.png
*https://anp.k3y.pw/images/AnP-512.png
*https://anp.k3y.pw/favicon.ico
https://anp.k3y.pw/
https://git.k3y.pw/AnP/AnP
CDN de KyMAN
*https://cdn.k3y.pw/images/CDN.png
*https://cdn.k3y.pw/images/CDN-512.png
*https://cdn.k3y.pw/favicon.ico
https://cdn.k3y.pw/
https://git.k3y.pw/KyMAN/CDN
"""]]
> [!#] Dicho proyecto hereda de otros proyectos a partir de los aquí presentados, por ejemplo, a partir del WMarkDown hereda del MathJAX, highlight.js y MermaidJS de JavaScript, entre otros. Si vais al proyecto WMarkDown podréis ver más información acerca de dichas dependencias.
Por otro lado, este proyecto es usado en proyectos tales como los siguientes:
[["""
AnP
*https://anp.k3y.pw/images/AnP.png
*https://anp.k3y.pw/images/AnP-512.png
*https://anp.k3y.pw/favicon.ico
https://anp.k3y.pw/
https://git.k3y.pw/AnP/AnP
"""]]
<!-- [[wmd]] -->

View File

@ -0,0 +1,36 @@
```wmd-options
language = es
title_i18n = python_mapper_title_targets
title_text = Objetivos - PythonMapper
```
<!-- [[wmd]] -->
## Objetivos
A continuación se expondrán todos los objetivos que atañen a este proyecto.
+ [X] Crear proyecto Git.
+ [-] Construir base Web en AnP para gestión documental y estructuración del proyecto.
+ [X] Constructor del AnP Web contra WMarkDown.
+ [X] Documentar filosofía y motivos de existencia de este proyecto. *[[!description.w.md]].*
+ [X] Crear logo y diseño del proyecto.
+ [X] Crear las secciones pertinentes a la documentación del proyecto.
+ [ ] Adjuntar todos los términos de uso al diccionario del WMarkDown.
+ [X] Documentar funcionamiento.
+ [X] Crear librería de trabajo.
+ [X] Crear base para impresión de información sobre el terminal.
+ [X] Print.
+ [X] Validaciones.
+ [X] Excepciones.
+ [X] Establecer estructura de de proyecto JSON.
+ [X] Crear base de la clase del proyecto.
+ [X] Incluir gestor de proyectos.
+ [X] Generar cargador de ficheros y gestión de cambios por caché.
+ [X] Gestionador de bloques de anidación que afecten a los patrones regulares de identificación de elementos dentro de código.
+ [X] Generar identificador de estructuras a gestionar.
+ [X] Generar fichero de mapeado generado.
+ [-] Crear direcciones de donaciones.
+ [ ] Publicar.
<!-- [[wmd]] -->

BIN
Public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

11
Public/index.w.md Normal file
View File

@ -0,0 +1,11 @@
```wmd-options
language = es
title_i18n = python_mapper_title_documentation
title_text = Documentación - PythonMapper
```
<!-- [[wmd]] -->
[[include /doc/es/index.w.md]]
<!-- [[wmd]] -->

View File

@ -0,0 +1,154 @@
.python-mapper {
position: relative;
top: 0em;
left: 0em;
width: 100%;
height: 100%;
overflow: hidden;
background-color: #EFEFEF;
color: #222; }
.python-mapper, .python-mapper input, .python-mapper button, .python-mapper select {
font-family: "Roboto"; }
.python-mapper pre, .python-mapper textarea,
.python-mapper .wmd-code-block,
.python-mapper .wmd-code-block ol > li::marker,
.python-mapper .wmd-code-doc > .description {
font-family: "Roboto Mono"; }
.python-mapper [data-icon]::before {
font-family: "FA6FR"; }
.python-mapper input, .python-mapper button, .python-mapper select, .python-mapper textarea {
font-size: 1em; }
.python-mapper [data-visible=false], .python-mapper [data-hidden=true] {
display: none; }
.python-mapper a[href] {
text-decoration: none;
word-break: break-word; }
.python-mapper a[href], .python-mapper [onclick], .python-mapper [onmouseover], .python-mapper [onmousedown], .python-mapper button, .python-mapper [type=button], .python-mapper [type=reset], .python-mapper [type=submit] {
cursor: pointer;
transition-duration: 1s; }
.python-mapper a[href]:hover, .python-mapper [onclick]:hover, .python-mapper [onmouseover]:hover, .python-mapper [onmousedown]:hover, .python-mapper button:hover, .python-mapper [type=button]:hover, .python-mapper [type=reset]:hover, .python-mapper [type=submit]:hover {
transition-duration: 0.2s; }
.python-mapper a[href], .python-mapper [onclick], .python-mapper [onmouseover], .python-mapper [onmousedown], .python-mapper button, .python-mapper [type=button], .python-mapper [type=reset], .python-mapper [type=submit] {
color: #459;
transition-property: color; }
.python-mapper a[href]:hover, .python-mapper [onclick]:hover, .python-mapper [onmouseover]:hover, .python-mapper [onmousedown]:hover, .python-mapper button:hover, .python-mapper [type=button]:hover, .python-mapper [type=reset]:hover, .python-mapper [type=submit]:hover {
color: #BA5; }
.python-mapper [onmouseover], .python-mapper [onmousedown] {
color: #333c5e;
transition-property: color; }
.python-mapper [onmouseover]:hover, .python-mapper [onmousedown]:hover {
color: #6f663c; }
.python-mapper a[href], .python-mapper [onclick] {
transition-property: color; }
.python-mapper button, .python-mapper [type=button], .python-mapper [type=reset], .python-mapper [type=submit] {
border-color: 0.1em solid #459;
box-shadow: 0em 0em 0.4em #459;
transition-property: color,border-color,box-shadow; }
.python-mapper button:hover, .python-mapper [type=button]:hover, .python-mapper [type=reset]:hover, .python-mapper [type=submit]:hover {
border-color: 0.1em solid #BA5;
box-shadow: 0em 0em 0.4em #BA5; }
.python-mapper .wmd-dictionary-item {
color: #333c5e; }
.python-mapper .wmd-dictionary-item:hover {
color: #6f663c; }
.python-mapper h2 {
font-size: 2.6em; }
.python-mapper h3 {
font-size: 2.2em; }
.python-mapper h4 {
font-size: 1.8em; }
.python-mapper h5 {
font-size: 1.4em; }
.python-mapper h6 {
font-size: 1em; }
.python-mapper ul, .python-mapper ol {
padding: 0em 2em; }
.python-mapper header, .python-mapper main, .python-mapper footer {
position: absolute;
left: 0em;
width: 100%; }
.python-mapper header, .python-mapper footer {
overflow: hidden;
display: flex;
flex-direction: row;
box-shadow: 0em 0em 0.125em #EFEFEF, 0em 0em 0.25em #EFEFEF, 0em 0em 0.5em #EFEFEF, 0em 0em 1em #EFEFEF, 0em 0em 2em #EFEFEF; }
.python-mapper header > *, .python-mapper footer > * {
flex: auto;
align-self: center; }
.python-mapper header {
top: 0em;
height: 4em;
z-index: 20; }
.python-mapper header h1 {
margin: .2em 1em;
padding: 0em;
font-size: 1em;
text-wrap: nowrap; }
.python-mapper header h1 .image {
height: 3.6em; }
.python-mapper header h1 img {
width: auto;
height: 3.6em; }
.python-mapper header h1 img + span {
display: none; }
.python-mapper header h1 span + span {
font-size: 3.4em;
height: 0.9444444444em; }
.python-mapper header h1 a > span {
display: inline-block;
vertical-align: top; }
.python-mapper main {
top: 4em;
bottom: 2.5em;
padding: 1% 2%;
z-index: 10;
overflow: auto;
box-sizing: border-box; }
.python-mapper footer {
bottom: 0em;
height: 2.5em;
z-index: 30; }
.python-mapper .main-menu {
width: 25em;
text-align: center; }
.python-mapper .main-menu ul {
list-style-type: none;
margin: 0em;
padding: 0em; }
.python-mapper .main-menu li {
display: inline-block;
margin: 0em .6em; }
.python-mapper .licenses {
display: flex;
flex-direction: row;
justify-content: center;
position: absolute;
left: 0em;
bottom: 0em;
width: 100%;
text-align: center;
padding: .1em .2em;
font-weight: 900;
font-size: .85em;
box-sizing: border-box; }
.python-mapper .license {
display: flex;
flex-direction: row;
align-self: center;
margin: 0em .2em;
text-align: center;
box-sizing: border-box; }
.python-mapper .license span {
flex: auto;
align-self: center; }
.python-mapper .license > * {
vertical-align: middle; }
.python-mapper .license img {
width: auto;
height: 2.5em;
margin: .2em .2em; }
.python-mapper h1 .image + span {
font-size: 3.1em; }
/*# sourceMappingURL=PythonMapper.css.map */

View File

@ -0,0 +1,7 @@
{
"version": 3,
"mappings": "AAKA,cAAc;ECuBV,QAAQ,EAAG,QAAQ;EACnB,GAAG,EAAG,GAAG;EACT,IAAI,EAAG,GAAG;EACV,KAAK,EAAG,IAAI;EACZ,MAAM,EAAG,IAAI;EACb,QAAQ,EAAG,MAAM;EA4Hb,gBAAgB,ECzJV,OAAO;ED0Jb,KAAK,EC3JC,IAAI;EDgCd,kFAAqB;IAAC,WAAW,ECtBtB,QAAQ;EDuBnB;;;6CAG0B;IAAC,WAAW,ECxB7B,aAAa;EDyBtB,kCAAmB;IAAC,WAAW,ECvBtB,OAAO;EDwBhB,2FAA4B;IAAC,SAAS,EAAG,GAAG;EAE5C,sEAAuC;IAAC,OAAO,EAAG,IAAI;EAEtD,sBAAO;IACH,eAAe,EAAG,IAAI;IACtB,UAAU,EAAG,UAAU;EAE3B,4NAA6F;IACzF,MAAM,EAAG,OAAO;IAChB,mBAAmB,ECpBT,EAAE;IDqBZ,4QAAO;MAAC,mBAAmB,ECtBlB,IAAG;EDwBhB,4NAA6F;IACzF,KAAK,EDtDI,IAAI;ICuDb,mBAAmB,EAAG,KAAK;IAC3B,4QAAO;MAAC,KAAK,EDvDF,IAAI;ECyDnB,0DAA2B;IACvB,KAAK,EAAG,OAAqC;IAC7C,mBAAmB,EAAG,KAAK;IAC3B,sEAAO;MAAC,KAAK,EAAG,OAAuC;EAO3D,gDAAiB;IAAC,mBAAmB,EAAG,KAAK;EAC7C,8GAA+C;IAC3C,YAAY,EAAG,gBAAyB;IACxC,UAAU,EAAG,kBAA2B;IACxC,mBAAmB,EAAG,6BAA6B;IACnD,sIAAO;MACH,YAAY,EAAG,gBAA2B;MAC1C,UAAU,EAAG,kBAA6B;EAIlD,mCAAoB;IAChB,KAAK,EAAG,OAAqC;IAC7C,yCAAO;MAAC,KAAK,EAAG,OAAuC;EAIvD,iBAAM;IAAC,SAAS,EAAG,KAAmB;EAAtC,iBAAM;IAAC,SAAS,EAAG,KAAmB;EAAtC,iBAAM;IAAC,SAAS,EAAG,KAAmB;EAAtC,iBAAM;IAAC,SAAS,EAAG,KAAmB;EAAtC,iBAAM;IAAC,SAAS,EAAG,GAAmB;EAG1C,oCAAK;IACD,OAAO,EAAG,OAAO;EAGrB,iEAAkB;IACd,QAAQ,EAAG,QAAQ;IACnB,IAAI,EAAG,GAAG;IACV,KAAK,EAAG,IAAI;EAEhB,4CAAa;IACT,QAAQ,EAAG,MAAM;IACjB,OAAO,EAAG,IAAI;IACd,cAAc,EAAG,GAAG;IAxFxB,UAAU,EACN,gHAIuB;IAqFvB,oDAAG;MACC,IAAI,EAAG,IAAI;MACX,UAAU,EAAG,MAAM;EAG3B,qBAAM;IACF,GAAG,EAAG,GAAG;IACT,MAAM,EC1FG,GAAG;ID2FZ,OAAO,EAAG,EAAE;IACZ,wBAAE;MACE,MAAM,EAAG,QAAQ;MACjB,OAAO,EAAG,GAAG;MACb,SAAS,EAAG,GAAG;MACf,SAAS,EAAG,MAAM;MAClB,+BAAM;QAAC,MAAM,EAAG,KAAyB;MACzC,4BAAG;QACC,KAAK,EAAG,IAAI;QACZ,MAAM,EAAG,KAAyB;QAClC,mCAAM;UAAC,OAAO,EAAG,IAAI;MAEzB,oCAAS;QACL,SAAS,EAAG,KAAyB;QACrC,MAAM,EAAG,cAAiE;MAE9E,iCAAM;QACF,OAAO,EAAG,YAAY;QACtB,cAAc,EAAG,GAAG;EAIhC,mBAAI;IACA,GAAG,EClHM,GAAG;IDmHZ,MAAM,EClHG,KAAK;IDmHd,OAAO,EAAG,KAAK;IACf,OAAO,EAAG,EAAE;IACZ,QAAQ,EAAG,IAAI;IACf,UAAU,EAAG,UAAU;EAE3B,qBAAM;IACF,MAAM,EAAG,GAAG;IACZ,MAAM,EC1HG,KAAK;ID2Hd,OAAO,EAAG,EAAE;EAiBhB,yBAAU;IACN,KAAK,EAAG,IAAI;IACZ,UAAU,EAAG,MAAM;IACnB,4BAAE;MACE,eAAe,EAAG,IAAI;MACtB,MAAM,EAAG,GAAG;MACZ,OAAO,EAAG,GAAG;IAEjB,4BAAE;MACE,OAAO,EAAG,YAAY;MACtB,MAAM,EAAG,QAAQ;EAIzB,wBAAS;IACL,OAAO,EAAG,IAAI;IACd,cAAc,EAAG,GAAG;IACpB,eAAe,EAAG,MAAM;IACxB,QAAQ,EAAG,QAAQ;IACnB,IAAI,EAAG,GAAG;IACV,MAAM,EAAG,GAAG;IACZ,KAAK,EAAG,IAAI;IACZ,UAAU,EAAG,MAAM;IACnB,OAAO,EAAG,SAAS;IACnB,WAAW,EAAG,GAAG;IACjB,SAAS,EAAG,KAAK;IACjB,UAAU,EAAG,UAAU;EAG3B,uBAAQ;IACJ,OAAO,EAAG,IAAI;IACd,cAAc,EAAG,GAAG;IACpB,UAAU,EAAG,MAAM;IACnB,MAAM,EAAG,QAAQ;IACjB,UAAU,EAAG,MAAM;IACnB,UAAU,EAAG,UAAU;IACvB,4BAAI;MACA,IAAI,EAAG,IAAI;MACX,UAAU,EAAG,MAAM;IAEvB,2BAAG;MAAC,cAAc,EAAG,MAAM;IAC3B,2BAAG;MACC,KAAK,EAAG,IAAI;MACZ,MAAM,EAAG,KAAK;MACd,MAAM,EAAG,SAAS;;ADpM9B,+BAA6B;EAAC,SAAS,EAAG,KAAK",
"sources": ["PythonMapper.scss","../../../AnP/Public/scss/AnP.common.scss","../../../AnP/Public/scss/AnP.settings.scss"],
"names": [],
"file": "PythonMapper.css"
}

View File

@ -0,0 +1,10 @@
@import "../../../AnP/Public/scss/AnP.settings.scss";
$color-primary : #459;
$color-secondary : #BA5;
@import "../../../AnP/Public/scss/AnP.common.scss";
.python-mapper{
@include main_web;
}
.python-mapper h1 .image+span{font-size : 3.1em;}

View File

@ -0,0 +1,15 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from Abstracts.Applications import ApplicationsAbstract
from Abstracts.AnPMap import AnP, Optional, Any
from os.path import abspath as path_absolute
from os.path import dirname as directory_name
class PythonMapper(ApplicationsAbstract):
def __init__(self, anp:AnP|None, inputs:Optional[dict[str, Any|None]|tuple|list] = None) -> None:
super().__init__(anp, "python_mapper", anp.path.get_parent(path_absolute(directory_name(__file__))), {
**anp.get_dictionary(inputs),
"python_mapper_default_settings_files" : "/JSON/PythonMapper.py.settings.json"
})

780
Python/PythonMapper.py Normal file
View File

@ -0,0 +1,780 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from inspect import FrameInfo
from typing import Any, Optional
from os.path import dirname as directory_name
from os.path import abspath as path_absolute
from os.path import exists as path_exists
from threading import Thread
from json import loads as json_decode
from time import sleep
import random
from re import compile as RECompile
from re import Pattern as REPattern
from re import Match as REMatch
from re import MULTILINE as RE_MULTILINE
from time import time as timestamp
from signal import SIGINT as SIGNAL_INTERRUPTION
from signal import signal as signal_method
from inspect import stack as get_stack
from traceback import format_stack as trace_format_stack
from traceback import extract_tb as extract_traceback
import datetime
from io import TextIOWrapper
class PythonMapper:
class Settings:
random_wait_time_in_use:int = 500
project_process_timer:int = 30000
process_subtimer:int = 100
process_time:int = 1000
print_format:str = "[{type}] {yyyy}{mm}{dd} {hh}{ii}{ss}.{nnn} [{line}]{file}({method}): {message}"
exception_format:int = " '{file}({method})[{line}]'{lines}\n\n{exception_message}"
rest_time_per_process_file:int = 10
tabulation_character:str = " "
class CodeBlock:
def __init__(self):
self.class_data:str = ""
self.class_code:list[PythonMapper.CodeBlock] = []
self.methods:list[str] = []
self.static_variables:list[str] = []
self.object_variables:list[str] = []
self.constructor:str = ""
class ClassData:
def __init__(self, class_name:str, spaces:int) -> None:
self.object_done:list[str] = []
self.static_done:list[str] = []
self.spaces:int = spaces
self.class_name:str = class_name
self.code:PythonMapper.CodeBlock = PythonMapper.CodeBlock()
class SearchData:
def __init__(self) -> None:
self.levels:list[PythonMapper.ClassData] = [PythonMapper.ClassData("ROOT", 0)]
self.i:int = 0
class Project:
methods:dict[str, REPattern] = {
"class_item" : RECompile(r'^([ \t]*)class[ \t]+([a-zA-Z0-9_]+)(#[^\:]+)?(?=\:)', RE_MULTILINE),
"method" : RECompile(r'^([ \t]*\@[^\r\n]+(\n|\r\n))*([ \t]*)def[ \t]+(_?[^_][a-zA-Z0-9_]*|__init__)(#[^\:]+)(?=\:)', RE_MULTILINE),
"object_variable" : RECompile(r'^[ \t]+(self[ \t]*\.[ \t]*(_?[^_][a-zA-Z0-9_]*)([ \t]*\:[^\=\r\n]+)?)([ \t]*=|[\r\n]|$)', RE_MULTILINE),
"static_variable" : RECompile(r'^([ \t]*)(_?[^_][a-zA-Z0-9]*)([ \t]*\:[^\r\n\=]+)?(?=[ \t]*\=)(?!\=)', RE_MULTILINE)
}
re_unclean_code:REPattern = RECompile(r'(?<!\\)("{3}((?!"{3})(.|[\r\n]))*"{3}|\'{3}((?!\'{3})(.|[\r\n]))*\'{3})|"((?!")(.|\\\\.))*"|\'((?!\')(.|\\\\.))*\'|\[((?![\[\]])(.|[\r\n]))*\]|\(((?![\(\)])(.|[\r\n]))*\)|\{((?![\{\}])(.|[\r\n]))*\}')
re_clean_code:REPattern = RECompile(r'\#{3}UNCLEAN([0-9]+)KEY#{3}')
def __init__(self, parent:Any, name:str, inputs:dict[str, str|list[str]|int]) -> None:
self.parent:PythonMapper = parent
self.name:str = name
self.timer:int = inputs["timer"] if "timer" in inputs else PythonMapper.Settings.project_process_timer
self.rest_timer:int = (
inputs["rest_timer"] if "rest_timer" in inputs else
inputs["rest"] if "rest" in inputs else
PythonMapper.Settings.rest_time_per_process_file
)
self.path:str = inputs["path"]
self.files:tuple[str] = tuple(inputs["files"])
self.map:str = inputs["map"]
self.__cache:dict[str, str] = {}
self.in_use:bool = False
self.__last_time:int = 0
self.__data:list[PythonMapper.CodeBlock|None] = []
self.dependences:list[str|list[str, str|list[str]]|list[str, str, str]|list[str]] = inputs["dependences"] if "dependences" in inputs else []
self.definitions:list[str] = inputs["definitions"] if "definitions" in inputs else []
self.tabulation:str = inputs["tabulation"] if "tabulation" in inputs else PythonMapper.Settings.tabulation_character
if len(self.definitions):
has_new_type:bool = False
dependence:str|list[str, str|list[str]]|list[str, str, str]|list[str]
for dependence in self.dependences:
if isinstance(dependence, list) and len(dependence) > 1 and dependence[0] == "typing" and (dependence[1] == "NewType" if isinstance(dependence[1], str) else "NewType" in dependence[1]):
has_new_type = True
break
if not has_new_type:
self.dependences += [["typing", "NewType"]]
def process(self) -> None:
time:int = PythonMapper.time()
if time - self.__last_time >= self.timer:
self.__update_cache() and self.__process_cache_file()
self.__last_time = time
def __process_cache_level(self, block:Any, level:int) -> str:
white_spaces:str = ""
code:str = ""
subblock:PythonMapper.CodeBlock
method:str
variable:str
has_class:bool = block.class_data != ""
block:PythonMapper.CodeBlock = block
for _ in range(level - 1):
white_spaces += self.tabulation
if has_class:
code += "\n\n" + white_spaces + block.class_data + ":"
white_spaces += self.tabulation
for subblock in block.class_code:
code += self.__process_cache_level(subblock, level + 1)
if len(block.static_variables):
code += "\n"
for variable in block.static_variables:
code += "\n" + white_spaces + variable + " = None"
if has_class:
l:int = len(block.object_variables)
if l or block.constructor:
tabulation:str = white_spaces + self.tabulation
code += "\n\n" + white_spaces + (block.constructor + ":" if block.constructor else "def __init__(self):")
if l:
for variable in block.object_variables:
code += "\n" + tabulation + variable + " = None"
else:
code += "\n" + tabulation + "pass"
for method in block.methods:
code += "\n\n" + white_spaces + method + ":pass"
return code
def __process_cache_file(self) -> None:
# b:PythonMapper.CodeBlock
# for i, block in enumerate(self.__data):
# print([i, [b.class_data for b in block.class_code]])
# return
code:str = (
"#!/usr/bin/env python\n" +
"# -*- coding: utf-8 -*-"
)
block:PythonMapper.CodeBlock
if len(self.dependences):
dependence:str|list[str, str|list[str]]|list[str, str, str]|list[str]
code += "\n"
for dependence in self.dependences:
if isinstance(dependence, str):
if " " in dependence:
code += "\n" + dependence
continue
dependence = [dependence]
l:int = len(dependence)
if l == 1:
code += "\nimport " + (dependence[0] if isinstance(dependence[0], str) else ", ".join(dependence[0]))
elif l == 2:
code += "\nfrom " + dependence[0] + " import " + (dependence[1] if isinstance(dependence[1], str) else ", ".join(dependence[1]))
elif l == 3:
code += "\nfrom " + dependence[0] + " import " + dependence[1] + " as " + dependence[2]
if len(self.definitions):
definition:str
code += "\n"
for definition in self.definitions:
code += "\n" + (definition if "=" in definition or " " in definition else definition + " = NewType(\"" + definition + "\", Any)")
for block in self.__data:
code += self.__process_cache_level(block, 0)
self.parent.save_file(self.path + '/' + self.map, code)
def __update_cache(self) -> bool:
i:int
file:str
has_changes:bool = False
for i, file in enumerate(self.files):
if not self.parent._working:
break
error:int
data:int
path:str = self.path + '/' + file
data, error = self.parent.load_file(path)
if not error and (path not in self.__cache or data != self.__cache[path]):
self.__cache[path] = data
self.__process_code(path, data, i)
if not has_changes:
has_changes = True
sleep(self.rest_timer / 1000.0)
return has_changes
@staticmethod
def unclean_code(code:str) -> tuple[str, tuple[str]]:
blocks:tuple[str] = tuple()
i:int = 0
while True:
matches:REMatch = PythonMapper.Project.re_unclean_code.search(code)
if not matches:
break
position:tuple[int, int] = matches.span()
blocks += (code[position[0]:position[1]],)
code = code[:position[0]] + "###UNCLEAN"+ str(i) + "KEY###" + code[position[1]:]
i += 1
return (code, blocks)
@staticmethod
def clean_code(code:str, blocks:tuple[str]) -> str:
while True:
matches:REMatch = PythonMapper.Project.re_clean_code.search(code)
if not matches:
break
position:tuple[int, int] = matches.span()
code = code[:position[0]] + blocks[int(matches.group(1))] + code[position[1]:]
return code
@staticmethod
def get_group(code:str, pattern:REPattern) -> list[REMatch|None, list[int, int], bool]:
matches:REMatch|None = pattern.search(code)
position:int = list(matches.span()) if matches else [-1, -1]
ok:bool = matches != None and position[0] >= 0
return [matches, position, ok]
def __process_code(self, path:str, code:str, k:int) -> None:
blocks:tuple[str]
l:int = len(code)
sets:dict[str, list[REMatch|None, int, bool]] = {}
data:PythonMapper.SearchData = PythonMapper.SearchData()
code, blocks = PythonMapper.Project.unclean_code(code)
self.parent._print("info", "The code with '{length}' characters from file '{path}' was uncleaned with '{l}' items.", {
"length" : l,
"path" : path,
"l" : len(blocks)
})
while True:
selected:str = ""
i:int = -1
key:str
pattern:REPattern
has_next:bool = False
matches:REMatch
ok:bool
span:list[int, int]
position:list[int, int]
for key, pattern in PythonMapper.Project.methods.items():
if key not in sets:
sets[key] = PythonMapper.Project.get_group(code, pattern)
matches, span, ok = sets[key]
if not ok:
continue
if span[0] < 0:
matches, span, ok = sets[key] = PythonMapper.Project.get_group(code, pattern)
if ok and (i < 0 or span[0] < i):
i = span[0]
selected = key
if not has_next:
has_next = True
if not has_next:
break
matches, span, ok = sets[selected]
getattr(PythonMapper.Project, selected)(code, PythonMapper.Project.clean_code(code[span[0]:span[1]], blocks).strip(), data, matches)
# getattr(PythonMapper.Project, selected)(code, code[span[0]:span[1]], data, matches)
code = code[span[1]:]
if not code:
break
for key, (matches, position, ok) in sets.items():
if ok:
sets[key][1] = [i - span[1] for i in position]
if k == len(self.__data):
self.__data += [None]
while data.i:
data.i -= 1
data.levels[data.i].code.class_code += [data.levels[data.i + 1].code]
self.__data[k] = data.levels[0].code
@staticmethod
def set_level(data:Any, spaces:int) -> bool:
data:PythonMapper.SearchData = data
if spaces > data.levels[data.i].spaces:
if data.i and data.levels[data.i].spaces == data.levels[data.i - 1].spaces:
data.levels[data.i].spaces = spaces
else:
i:int = len(data.levels)
while data.levels[data.i].spaces > spaces:
data.i -= 1
data.levels[data.i].code.class_code += [data.levels[data.i + 1].code]
i -= 1
data.levels = data.levels[:i]
return data.levels[data.i].spaces == spaces
@classmethod
def class_item(self, code:str, fragment:str, data:Any, matches:REMatch):
data:PythonMapper.SearchData = data
if self.set_level(data, len(matches.group(1))):
data.levels += [PythonMapper.ClassData(matches.group(2), len(matches.group(1)))]
data.i += 1
data.levels[data.i].code.class_data = fragment
# print(["class_item", fragment])
@classmethod
def method(self, code:str, fragment:str, data:Any, matches:REMatch):
data:PythonMapper.SearchData = data
name:str = matches.group(4)
if self.set_level(data, len(matches.group(3))):
if name == "__init__" and not data.levels[data.i].code.constructor and "@" not in fragment[:fragment.index("__init__")]:
data.levels[data.i].code.constructor = fragment
else:
data.levels[data.i].code.methods += [fragment]
# print(["method", fragment])
@classmethod
def object_variable(self, code:str, fragment:str, data:Any, matches:REMatch):
name:str = matches.group(1)
data:PythonMapper.SearchData = data
if name in data.levels[data.i].object_done:
return
data.levels[data.i].object_done += [name]
fragment = (fragment[:-1] if fragment[-1] == "=" else fragment).strip()
data.levels[data.i].code.object_variables += [fragment]
# print(["object_variable", fragment])
@classmethod
def static_variable(self, code:str, fragment:str, data:Any, matches:REMatch):
name:str = matches.group(2)
data:PythonMapper.SearchData = data
if not self.set_level(data, len(matches.group(1))) or name in data.levels[data.i].static_done:
return
data.levels[data.i].static_done += [name]
data.levels[data.i].code.static_variables += [fragment]
# print(["static_variable", data.i, name, len(matches.group(1)), fragment])
# print(["static_variable", fragment])
re_string_variables:REPattern = RECompile(r'\{([^\{\}]+)\}')
re_break_lines:REPattern = RECompile(r'\r\n|[\r\n]')
re_exception_line:REPattern = RECompile(r'^\s*File "([^"]+)", line ([0-9]+), in ([^\n]+)(.*|[\r\n]*)*$')
def __init__(self, inputs:dict[str, Any|None]) -> None:
key:str
self.__inputs:dict[str, Any|None] = inputs
self.__projects:dict[str, PythonMapper.Project] = {}
self.__thread:Thread = Thread(target = self.__process_projects)
self.__root_path:str = path_absolute(directory_name(__file__))
self.__root_path_l:int = len(self.__root_path) + 1
self.__files_projects:tuple[str] = (self.__root_path + "/../JSON/PythonMapper.py.projects.secrets.json",)
self._working:bool = True
self.__last_process_try:int = 0
signal_method(SIGNAL_INTERRUPTION, self.signal_handler)
for key in ("projects_files", "projects_file", "project_file"):
if key in inputs:
if isinstance(inputs[key], str):
self.__files_projects += (inputs[key],)
elif isinstance(inputs[key], list):
self.__files_projects += tuple(inputs[key])
elif isinstance(inputs[key], tuple):
self.__files_projects += inputs[key]
self.update_projects()
self.__thread.start()
# print(self.__projects)
def signal_handler(self, signal_id:int, frame:Any) -> None:
self.stop()
print("The PythonMapper was stopped successfully.")
def stop(self) -> None:
if self._working:
self._working = False
@staticmethod
def string_variables(string:str, variables:Optional[dict[str, Any|None]] = {}) -> str:
def callback(matches:REMatch) -> str:
key:str = matches.group(1)
return str(variables[key]) if key in variables else matches.group(0)
return PythonMapper.re_string_variables.sub(callback, string)
def get_action_data(self, i:int = 1) -> dict[str, str|int]:
stack:FrameInfo = get_stack()[1 + i]
return {
"file" : stack.filename[self.__root_path_l:],
"method" : stack.function,
"line" : stack.lineno
}
def _print(self, _type:str, message:str, variables:Optional[dict[str, Any|None]] = None, i:Optional[int] = 1) -> None:
type_l:int = len(_type)
date:datetime.datetime = datetime.datetime.now()
own:dict[str, Any|None] = {
"type" : " "[int(type_l / 2):] + _type[0:4].upper() + " "[int((type_l + 1) / 2):],
**self.get_action_data(i)
}
key:str
for key in ("year", "month", "day", "hour", "minute", "second"):
k:str = "i" if key == "minute" else key[0]
own[key] = own[k] = getattr(date, key) % 100
own[k + k] = ("00" + str(own[k]))[-2:]
own["year"] = own["yyyy"] = date.year
own["milliseconds"] = own["n"] = int(date.microsecond / 1000)
own["nnn"] = ("000" + str(own["n"]))[-3:]
variables = {**own, **variables}
variables["message"] = PythonMapper.string_variables(message + (
PythonMapper.Settings.exception_format if variables["type"] == "EXCE" else
"{list}" if variables["type"] == "ERRO" else
""), variables)
print(PythonMapper.string_variables(PythonMapper.Settings.print_format, variables))
def validate(self,
error:int,
messages:Optional[tuple[str]] = tuple(),
variables:Optional[dict[str, Any|None]] = {},
error_message:Optional[str|None] = None,
ok_message:Optional[str] = None
):
if error:
if error_message:
list_messages:str = ""
i:int = 0
l:int = len(messages)
while 1 << i <= error:
if error & 1 << i:
list_messages += PythonMapper.string_variables("\n - [{i}] {message}", {
"i" : i,
"message" : PythonMapper.string_variables(messages[i], variables) if i < l else "error_message_" + str(i)
})
i += 1
self._print("error", error_message, {
**variables,
"list" : list_messages,
"code" : error
})
return False
ok_message and self._print("ok", ok_message, variables)
return True
def exception(self,
exception:Exception,
message:Optional[str|list|tuple] = None,
variables:Optional[dict[str, Any]|list|tuple] = None,
i:Optional[int] = 1
) -> None:
lines:list[str]|None = extract_traceback(exception.__traceback__).format()
line_matches:REMatch[str]|None = self.re_exception_line.match(lines[-1])
key:str
value:Any|None
block:str|None
data:dict[str, Any|None] = {
**{key : value for subset in (variables if isinstance(variables, (list, tuple)) else (variables,)) for key, value in (subset if isinstance(subset, dict) else {}).items()},
**self.get_action_data(1),
"lines" : "",
"exception_message" : str(exception),
"method" : line_matches.group(3),
"line" : line_matches.group(2),
"file" : line_matches.group(1)[self.__root_path_l:]
}
for block in trace_format_stack()[:-2] + lines:
if block:
data["lines"] += "\n " + self.re_break_lines.split(block.strip())[0]
data["end"] = PythonMapper.string_variables(PythonMapper.Settings.exception_format, data)
message and self._print("exception", message, data, i + 1)
def load_file(self, path:str) -> tuple[str|None, int]:
error:int = (
1 << 0 if path == None else
1 << 1 if not isinstance(path, str) else
1 << 2 if not path else
1 << 3 if not path_exists(path) else
0) << 0
data:str|None = None
if not error:
opened:TextIOWrapper[Any]
try:
with open(path, 'r') as opened:
data = opened.read()
except Exception as exception:
error |= 1 << 0
self.exception(exception, "There was an exception trying load file '{path}'.", {
"path" : path[self.__root_path_l:] if self.__root_path in path else path
})
self.validate(
error,
(
"exception",
"path_null",
"path_not_string",
"path_empty",
"path_not_exists"
),
{
"path" : path[self.__root_path_l:] if self.__root_path in path else path
},
"There was any error with code '{code}' trying load the file '{path}'.",
"The file '{path}' was loaded successfully."
)
return data, error
def save_file(self, path:str, content:str) -> int:
error:int = (
((
1 << 0 if path == None else
1 << 1 if not isinstance(path, str) else
1 << 2 if not path else
# 1 << 3 if not path_exists(path) else
0) << 0) |
((
1 << 0 if content == None else
1 << 1 if not isinstance(content, str) else
# 1 << 2 if not content else
0) << 4) |
0) << 1
if not error:
opened:TextIOWrapper[Any]
try:
with open(path, "w") as opened:
opened.write(content)
except Exception as exception:
error |= 1 << 0
self.exception(exception, "There was an exception trying save file '{path}' with {bytes} bytes of String data.", {
"path" : path,
"bytes" : len(content)
})
self.validate(
error,
(
"exception",
"path_null",
"path_not_string",
"path_empty",
"path_not_exists"
"content_null",
"content_not_string",
"content_empty"
),
{
"path" : path,
"bytes" : len(content) if isinstance(content, str) else -1
},
"There was any error with code '{code}' trying save file '{path}' with {bytes} bytes of String data.",
"The file '{path}' was write with {bytes} bytes of String data successfully."
)
return error
def __load_projects_file(self, path:str) -> int:
error:int
data:str|None
data, error = self.load_file(path)
error <<= 3
if data:
try:
project_key:str
project_data:dict[str, str|list[str]]
projects:dict[str, dict[str, str|list[str]]] = json_decode(data)
for project_key, project_data in projects.items():
if project_key in self.__projects:
while self.__projects[project_key]["in_use"]:
if not self._working:
error |= 1 << 1
break
sleep((random.random() * PythonMapper.Settings.random_wait_time_in_use) / 1000.0)
if self._working:
del self.__projects[project_key]
if not self._working:
error |= 1 << 1
break
try:
self.__projects[project_key] = PythonMapper.Project(self, project_key, project_data)
except Exception as exception:
error |= 1 << 2
self.exception(exception, "There was an exception trying load the project '{key}' from '{path}'.", {
"path" : path[self.__root_path_l:] if self.__root_path in path else path,
"key" : project_key
})
if project_key in self.__projects:
del self.__projects[project_key]
except Exception as exception:
error |= 1 << 0
self.exception(exception, "There was an exception trying load the projects from file '{path}'.", {
"path" : path[self.__root_path_l:] if self.__root_path in path else path
})
self.validate(
error,
(
"exception",
"not_working",
"project_building_exception",
"load_exception",
"path_null",
"path_not_string",
"path_empty",
"path_not_exists"
),
{
"path" : path[self.__root_path_l:] if self.__root_path in path else path
},
"There was any error with code '{code}' trying loading the projects of file '{path}'.",
"The projects of file '{path}' was loaded successfully."
)
return error
def update_projects(self) -> int:
error:int = 0
for file in self.__files_projects:
if self.__load_projects_file(file):
error |= 1 << 1
self.validate(
error,
(
"exception",
"load_projects_errors"
),
{},
"There was any error with code '{code}' trying update the projects.",
"The projects was updated successfully."
)
return error
@staticmethod
def time() -> int:
return int(timestamp() * 1000)
def __process_projects(self) -> None:
while self._working:
time:int = PythonMapper.time()
if time - self.__last_process_try >= PythonMapper.Settings.process_time:
project:PythonMapper.Project
for project in self.__projects.values():
project.process()
self.__last_process_try = time
sleep(PythonMapper.Settings.process_subtimer / 1000.0)

6
Python/run.py Normal file
View File

@ -0,0 +1,6 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from PythonMapper import PythonMapper
python_mapper:PythonMapper = PythonMapper({})

View File

@ -1,3 +1,7 @@
# PythonMapper
Python Mapper is a very simple project with a mapping Python files in one unique non functional Python file target. This unique file help to IDE helping the developer.
Python Mapper is a very simple project with a mapping Python files in one unique non functional Python file target. This unique file help to IDE helping the developer. For more info of this project, documentation, etc. You could visit its official Website:
- https://pythonpmapper.k3y.pw/
> **WARNING**: This project was hosted in an own creator server that it will down all nights for break of him.

3
Tools/run.sh Executable file
View File

@ -0,0 +1,3 @@
#!/bin/bash
directory=`dirname $(readlink -f "$0")`
python3 $directory/../Python/run.py;

3
Tools/sass.sh Executable file
View File

@ -0,0 +1,3 @@
#!/bin/bash
directory=`dirname $(readlink -f "$0")`
sass $directory/../Public/scss/PythonMapper.scss ../Public/scss/PythonMapper.css;

1
version Normal file
View File

@ -0,0 +1 @@
0.0.1.0