portugython 0.2.0__tar.gz → 0.4.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. {portugython-0.2.0 → portugython-0.4.0}/CHANGELOG.md +75 -1
  2. {portugython-0.2.0 → portugython-0.4.0}/PKG-INFO +105 -2
  3. {portugython-0.2.0 → portugython-0.4.0}/README.md +103 -0
  4. {portugython-0.2.0 → portugython-0.4.0}/portugython/__init__.py +31 -1
  5. portugython-0.4.0/portugython/_importador.py +200 -0
  6. portugython-0.4.0/portugython/transpilador.py +254 -0
  7. {portugython-0.2.0 → portugython-0.4.0}/pyproject.toml +5 -2
  8. portugython-0.4.0/tests/ola_mundo.ptpy +38 -0
  9. portugython-0.4.0/tests/test_importador.py +170 -0
  10. {portugython-0.2.0 → portugython-0.4.0}/tests/test_portugython.py +1 -1
  11. portugython-0.4.0/tests/test_transpilador.py +310 -0
  12. {portugython-0.2.0 → portugython-0.4.0}/.gitignore +0 -0
  13. {portugython-0.2.0 → portugython-0.4.0}/LICENSE +0 -0
  14. {portugython-0.2.0 → portugython-0.4.0}/portugython/abstrato.py +0 -0
  15. {portugython-0.2.0 → portugython-0.4.0}/portugython/aleatorio.py +0 -0
  16. {portugython-0.2.0 → portugython-0.4.0}/portugython/argumentos.py +0 -0
  17. {portugython-0.2.0 → portugython-0.4.0}/portugython/assincronico.py +0 -0
  18. {portugython-0.2.0 → portugython-0.4.0}/portugython/bisecao.py +0 -0
  19. {portugython-0.2.0 → portugython-0.4.0}/portugython/calendario.py +0 -0
  20. {portugython-0.2.0 → portugython-0.4.0}/portugython/caminho.py +0 -0
  21. {portugython-0.2.0 → portugython-0.4.0}/portugython/classe_dados.py +0 -0
  22. {portugython-0.2.0 → portugython-0.4.0}/portugython/codificacao.py +0 -0
  23. {portugython-0.2.0 → portugython-0.4.0}/portugython/colecoes.py +0 -0
  24. {portugython-0.2.0 → portugython-0.4.0}/portugython/compressao.py +0 -0
  25. {portugython-0.2.0 → portugython-0.4.0}/portugython/configuracao.py +0 -0
  26. {portugython-0.2.0 → portugython-0.4.0}/portugython/contexto.py +0 -0
  27. {portugython-0.2.0 → portugython-0.4.0}/portugython/copia.py +0 -0
  28. {portugython-0.2.0 → portugython-0.4.0}/portugython/csv_pt.py +0 -0
  29. {portugython-0.2.0 → portugython-0.4.0}/portugython/depuracao.py +0 -0
  30. {portugython-0.2.0 → portugython-0.4.0}/portugython/enumeracao.py +0 -0
  31. {portugython-0.2.0 → portugython-0.4.0}/portugython/estatistica.py +0 -0
  32. {portugython-0.2.0 → portugython-0.4.0}/portugython/estrutura.py +0 -0
  33. {portugython-0.2.0 → portugython-0.4.0}/portugython/expressao.py +0 -0
  34. {portugython-0.2.0 → portugython-0.4.0}/portugython/formatacao.py +0 -0
  35. {portugython-0.2.0 → portugython-0.4.0}/portugython/funcional.py +0 -0
  36. {portugython-0.2.0 → portugython-0.4.0}/portugython/hash_pt.py +0 -0
  37. {portugython-0.2.0 → portugython-0.4.0}/portugython/identificador.py +0 -0
  38. {portugython-0.2.0 → portugython-0.4.0}/portugython/iteradores.py +0 -0
  39. {portugython-0.2.0 → portugython-0.4.0}/portugython/json.py +0 -0
  40. {portugython-0.2.0 → portugython-0.4.0}/portugython/matematica.py +0 -0
  41. {portugython-0.2.0 → portugython-0.4.0}/portugython/py.typed +0 -0
  42. {portugython-0.2.0 → portugython-0.4.0}/portugython/rede.py +0 -0
  43. {portugython-0.2.0 → portugython-0.4.0}/portugython/registro.py +0 -0
  44. {portugython-0.2.0 → portugython-0.4.0}/portugython/serializacao.py +0 -0
  45. {portugython-0.2.0 → portugython-0.4.0}/portugython/sistema.py +0 -0
  46. {portugython-0.2.0 → portugython-0.4.0}/portugython/soquete.py +0 -0
  47. {portugython-0.2.0 → portugython-0.4.0}/portugython/subprocesso.py +0 -0
  48. {portugython-0.2.0 → portugython-0.4.0}/portugython/tempo.py +0 -0
  49. {portugython-0.2.0 → portugython-0.4.0}/portugython/threads.py +0 -0
  50. {portugython-0.2.0 → portugython-0.4.0}/portugython/tipagem.py +0 -0
  51. {portugython-0.2.0 → portugython-0.4.0}/tests/__init__.py +0 -0
  52. {portugython-0.2.0 → portugython-0.4.0}/tests/test_submodulos.py +0 -0
@@ -1,6 +1,80 @@
1
1
  # Changelog
2
2
 
3
- ## 0.2.0 (2026-06-26)
3
+ ## 0.4.0 (2026-06-26)
4
+
5
+ Add `transpilador` module: a tokenizer-based source transpiler that
6
+ translates Python keywords to Portuguese, enabling fully Portuguese Python syntax.
7
+
8
+ New module `portugython.transpilador`:
9
+
10
+ - `traduzir(codigo)` - translates Portuguese Python source to valid Python
11
+ - `traduzir_para_portugues(codigo)` - inverse translation
12
+ - `executar_texto(codigo)` - translate and execute a Portuguese Python string
13
+ - `executar_arquivo(caminho)` - translate and execute a `.ptpy` file
14
+ - `mostrar_traducao(codigo)` - print the translated Python source
15
+ - `MAPA_PALAVRAS_CHAVE` - full keyword translation table
16
+ - `PALAVRAS_RESERVADAS` - frozenset of reserved Portuguese keywords
17
+
18
+ Keyword translations (34 keywords):
19
+
20
+ se -> if senaose -> elif senao -> else
21
+ para -> for enquanto -> while parar -> break
22
+ continuar -> continue passar -> pass
23
+ defina -> def classe -> class retorne -> return
24
+ produzca -> yield anonima -> lambda
25
+ importe -> import de -> from como -> as
26
+ tente -> try exceto -> except finalmente -> finally
27
+ levante -> raise com -> with
28
+ nao -> not e -> and ou -> or
29
+ em -> in eh -> is
30
+ excluir -> del afirmar -> assert
31
+ global -> global naolocal -> nonlocal
32
+ assincronico -> async aguardar -> await
33
+ Verdadeiro -> True Falso -> False Nenhum -> None
34
+
35
+ New CLI entry point: `ptpy` runs `.ptpy` files directly:
36
+
37
+ ptpy meu_programa.ptpy
38
+ ptpy -c 'para i em intervalo(3): escreva(i)'
39
+ ptpy --mostrar meu_programa.ptpy # show the translated Python
40
+
41
+ Extended import hook to load `.ptpy` files via the normal import system.
42
+
43
+ Example `.ptpy` program:
44
+
45
+ ```python
46
+ defina fatorial(n):
47
+ se n <= 1:
48
+ retorne 1
49
+ senao:
50
+ retorne n * fatorial(n - 1)
51
+
52
+ para i em intervalo(1, 6):
53
+ escreva(f"{i}! = {fatorial(i)}")
54
+ ```
55
+
56
+
57
+
58
+ Add import hook so all Portuguese module names work as top-level imports.
59
+
60
+ After `import portugython`, the full stdlib-level syntax works:
61
+
62
+ import aleatorio
63
+ from matematica import raiz_quadrada, PI
64
+ from colecoes import Contador, Pilha, Fila
65
+ from tempo import agora, hoje
66
+ from expressao import buscar, encontrar_todos
67
+ from dados import serializar, deserializar # json
68
+ from subprocesso import executar
69
+ from caminho import Caminho
70
+ # ... all 36 modules
71
+
72
+ New exports:
73
+ - `portugython.instalar()` - instala o gancho (chamado automaticamente)
74
+ - `portugython.desinstalar()` - remove o gancho
75
+ - `portugython.listar_modulos()` - retorna o mapa de nomes
76
+
77
+
4
78
 
5
79
  Full stdlib coverage. 36 submodules total, all importable via `from portugython import <modulo>`:
6
80
 
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: portugython
3
- Version: 0.2.0
4
- Summary: A Portuguese translation of the Python functions/modules/packages
3
+ Version: 0.4.0
4
+ Summary: A Portuguese translation of Python: functions, modules and syntax
5
5
  Project-URL: Homepage, https://github.com/spacemany2k38/portugython
6
6
  Project-URL: Bug Tracker, https://github.com/spacemany2k38/portugython/issues
7
7
  Author: Victor Kolis
@@ -281,6 +281,109 @@ if email.encontrar("contato@example.com"):
281
281
  | `filtro(f, it)` | `list(filter(f, it))` |
282
282
  | `reduzido(f, it)` | `functools.reduce(f, it)` |
283
283
 
284
+ ## Transpilador de palavras-chave
285
+
286
+ Portugython inclui um transpilador completo que traduz a sintaxe do Python
287
+ (palavras-chave) para portugues. Isso permite escrever programas Python
288
+ inteiramente em portugues.
289
+
290
+ ### CLI: ptpy
291
+
292
+ ```bash
293
+ ptpy meu_programa.ptpy # executa um arquivo .ptpy
294
+ ptpy -c 'para i em intervalo(3): escreva(i)' # executa inline
295
+ ptpy --mostrar meu_programa.ptpy # imprime o Python equivalente
296
+ ```
297
+
298
+ ### API Python
299
+
300
+ ```python
301
+ from portugython import traduzir, executar_texto, executar_arquivo
302
+
303
+ # Traduzir uma string
304
+ codigo_pt = """
305
+ defina fatorial(n):
306
+ se n <= 1:
307
+ retorne 1
308
+ senao:
309
+ retorne n * fatorial(n - 1)
310
+ """
311
+ print(traduzir(codigo_pt))
312
+ # def fatorial(n):
313
+ # if n <= 1:
314
+ # return 1
315
+ # else:
316
+ # return n * fatorial(n - 1)
317
+
318
+ # Executar diretamente
319
+ executar_texto("para i em intervalo(3):\n escreva(i)")
320
+
321
+ # Executar um arquivo .ptpy
322
+ executar_arquivo("meu_programa.ptpy")
323
+ ```
324
+
325
+ ### Programa completo em portugues (.ptpy)
326
+
327
+ ```python
328
+ # fatorial.ptpy
329
+ importe portugython
330
+
331
+ defina fatorial(n):
332
+ se n <= 1:
333
+ retorne 1
334
+ senao:
335
+ retorne n * fatorial(n - 1)
336
+
337
+ defina verificar_primo(n):
338
+ se n < 2:
339
+ retorne Falso
340
+ para i em intervalo(2, n):
341
+ se n % i == 0:
342
+ retorne Falso
343
+ retorne Verdadeiro
344
+
345
+ primos = [x para x em intervalo(2, 20) se verificar_primo(x)]
346
+ escreva("Primos:", primos)
347
+
348
+ para n em intervalo(1, 8):
349
+ escreva(f"{n}! = {fatorial(n)}")
350
+
351
+ tente:
352
+ resultado = 10 / 0
353
+ exceto ZeroDivisionError como err:
354
+ escreva("Erro capturado:", err)
355
+ finalmente:
356
+ escreva("Pronto!")
357
+ ```
358
+
359
+ ### Tabela de palavras-chave
360
+
361
+ | Portugues | Python | | Portugues | Python |
362
+ |-----------|--------|-|-----------|--------|
363
+ | `se` | `if` | | `senao` | `else` |
364
+ | `senaose` | `elif` | | `para` | `for` |
365
+ | `enquanto` | `while` | | `parar` | `break` |
366
+ | `continuar` | `continue` | | `passar` | `pass` |
367
+ | `defina` | `def` | | `classe` | `class` |
368
+ | `retorne` | `return` | | `produzca` | `yield` |
369
+ | `anonima` | `lambda` | | `importe` | `import` |
370
+ | `de` | `from` | | `como` | `as` |
371
+ | `tente` | `try` | | `exceto` | `except` |
372
+ | `finalmente` | `finally` | | `levante` | `raise` |
373
+ | `com` | `with` | | `nao` | `not` |
374
+ | `e` | `and` | | `ou` | `or` |
375
+ | `em` | `in` | | `eh` | `is` |
376
+ | `excluir` | `del` | | `afirmar` | `assert` |
377
+ | `global` | `global` | | `naolocal` | `nonlocal` |
378
+ | `assincronico` | `async` | | `aguardar` | `await` |
379
+ | `Verdadeiro` | `True` | | `Falso` | `False` |
380
+ | `Nenhum` | `None` | | | |
381
+
382
+ > **Nota**: Palavras como `e`, `ou`, `de`, `com` e `em` sao palavras-chave
383
+ > reservadas no contexto de arquivos `.ptpy`. Evite usa-las como nomes de
384
+ > variaveis nesses arquivos, assim como nao se usa `if` ou `for` como
385
+ > variaveis em Python normal.
386
+
284
387
  ## Contribuir
285
388
 
286
389
  1. Crie um fork deste repositorio
@@ -254,6 +254,109 @@ if email.encontrar("contato@example.com"):
254
254
  | `filtro(f, it)` | `list(filter(f, it))` |
255
255
  | `reduzido(f, it)` | `functools.reduce(f, it)` |
256
256
 
257
+ ## Transpilador de palavras-chave
258
+
259
+ Portugython inclui um transpilador completo que traduz a sintaxe do Python
260
+ (palavras-chave) para portugues. Isso permite escrever programas Python
261
+ inteiramente em portugues.
262
+
263
+ ### CLI: ptpy
264
+
265
+ ```bash
266
+ ptpy meu_programa.ptpy # executa um arquivo .ptpy
267
+ ptpy -c 'para i em intervalo(3): escreva(i)' # executa inline
268
+ ptpy --mostrar meu_programa.ptpy # imprime o Python equivalente
269
+ ```
270
+
271
+ ### API Python
272
+
273
+ ```python
274
+ from portugython import traduzir, executar_texto, executar_arquivo
275
+
276
+ # Traduzir uma string
277
+ codigo_pt = """
278
+ defina fatorial(n):
279
+ se n <= 1:
280
+ retorne 1
281
+ senao:
282
+ retorne n * fatorial(n - 1)
283
+ """
284
+ print(traduzir(codigo_pt))
285
+ # def fatorial(n):
286
+ # if n <= 1:
287
+ # return 1
288
+ # else:
289
+ # return n * fatorial(n - 1)
290
+
291
+ # Executar diretamente
292
+ executar_texto("para i em intervalo(3):\n escreva(i)")
293
+
294
+ # Executar um arquivo .ptpy
295
+ executar_arquivo("meu_programa.ptpy")
296
+ ```
297
+
298
+ ### Programa completo em portugues (.ptpy)
299
+
300
+ ```python
301
+ # fatorial.ptpy
302
+ importe portugython
303
+
304
+ defina fatorial(n):
305
+ se n <= 1:
306
+ retorne 1
307
+ senao:
308
+ retorne n * fatorial(n - 1)
309
+
310
+ defina verificar_primo(n):
311
+ se n < 2:
312
+ retorne Falso
313
+ para i em intervalo(2, n):
314
+ se n % i == 0:
315
+ retorne Falso
316
+ retorne Verdadeiro
317
+
318
+ primos = [x para x em intervalo(2, 20) se verificar_primo(x)]
319
+ escreva("Primos:", primos)
320
+
321
+ para n em intervalo(1, 8):
322
+ escreva(f"{n}! = {fatorial(n)}")
323
+
324
+ tente:
325
+ resultado = 10 / 0
326
+ exceto ZeroDivisionError como err:
327
+ escreva("Erro capturado:", err)
328
+ finalmente:
329
+ escreva("Pronto!")
330
+ ```
331
+
332
+ ### Tabela de palavras-chave
333
+
334
+ | Portugues | Python | | Portugues | Python |
335
+ |-----------|--------|-|-----------|--------|
336
+ | `se` | `if` | | `senao` | `else` |
337
+ | `senaose` | `elif` | | `para` | `for` |
338
+ | `enquanto` | `while` | | `parar` | `break` |
339
+ | `continuar` | `continue` | | `passar` | `pass` |
340
+ | `defina` | `def` | | `classe` | `class` |
341
+ | `retorne` | `return` | | `produzca` | `yield` |
342
+ | `anonima` | `lambda` | | `importe` | `import` |
343
+ | `de` | `from` | | `como` | `as` |
344
+ | `tente` | `try` | | `exceto` | `except` |
345
+ | `finalmente` | `finally` | | `levante` | `raise` |
346
+ | `com` | `with` | | `nao` | `not` |
347
+ | `e` | `and` | | `ou` | `or` |
348
+ | `em` | `in` | | `eh` | `is` |
349
+ | `excluir` | `del` | | `afirmar` | `assert` |
350
+ | `global` | `global` | | `naolocal` | `nonlocal` |
351
+ | `assincronico` | `async` | | `aguardar` | `await` |
352
+ | `Verdadeiro` | `True` | | `Falso` | `False` |
353
+ | `Nenhum` | `None` | | | |
354
+
355
+ > **Nota**: Palavras como `e`, `ou`, `de`, `com` e `em` sao palavras-chave
356
+ > reservadas no contexto de arquivos `.ptpy`. Evite usa-las como nomes de
357
+ > variaveis nesses arquivos, assim como nao se usa `if` ou `for` como
358
+ > variaveis em Python normal.
359
+
257
360
  ## Contribuir
258
361
 
259
362
  1. Crie um fork deste repositorio
@@ -4,7 +4,25 @@ from __future__ import annotations
4
4
 
5
5
  from functools import reduce as _reduce
6
6
 
7
- __version__ = "0.2.0"
7
+ from portugython._importador import (
8
+ desinstalar,
9
+ instalar,
10
+ listar_modulos,
11
+ )
12
+ from portugython.transpilador import (
13
+ MAPA_PALAVRAS_CHAVE,
14
+ PALAVRAS_RESERVADAS,
15
+ executar_arquivo,
16
+ executar_texto,
17
+ mostrar_traducao,
18
+ traduzir,
19
+ traduzir_para_portugues,
20
+ )
21
+
22
+ __version__ = "0.4.0"
23
+
24
+ # Instala o gancho de importacao automaticamente
25
+ instalar()
8
26
 
9
27
  # ---------------------------------------------------------------------------
10
28
  # IO
@@ -490,6 +508,18 @@ def imprima(*args: object, sep: str = " ", fim: str = "\n", **kwargs: object) ->
490
508
  # ---------------------------------------------------------------------------
491
509
  __all__ = [
492
510
  "__version__",
511
+ # Importador
512
+ "instalar",
513
+ "desinstalar",
514
+ "listar_modulos",
515
+ # Transpilador
516
+ "traduzir",
517
+ "traduzir_para_portugues",
518
+ "executar_texto",
519
+ "executar_arquivo",
520
+ "mostrar_traducao",
521
+ "MAPA_PALAVRAS_CHAVE",
522
+ "PALAVRAS_RESERVADAS",
493
523
  # IO
494
524
  "escreva",
495
525
  "leia",
@@ -0,0 +1,200 @@
1
+ """_importador - gancho de importacao que permite importar modulos em Portugues.
2
+
3
+ Quando ativado, permite usar nomes de modulos em Portugues diretamente:
4
+
5
+ import aleatorio
6
+ from matematica import raiz_quadrada
7
+ from colecoes import Contador
8
+
9
+ Tambem permite importar arquivos .ptpy (Python em Portugues):
10
+
11
+ import meu_modulo # carrega meu_modulo.ptpy se existir
12
+ """
13
+
14
+ from __future__ import annotations
15
+
16
+ import importlib
17
+ import importlib.abc
18
+ import importlib.machinery
19
+ import importlib.util
20
+ import sys
21
+ from importlib.machinery import ModuleSpec, SourceFileLoader
22
+ from pathlib import Path
23
+ from typing import Sequence
24
+
25
+ # Mapeamento de nome em Portugues -> caminho completo do modulo portugython
26
+ MAPA_MODULOS: dict[str, str] = {
27
+ # Matematica e ciencia
28
+ "aleatorio": "portugython.aleatorio",
29
+ "matematica": "portugython.matematica",
30
+ "estatistica": "portugython.estatistica",
31
+ # Tipos e estruturas
32
+ "colecoes": "portugython.colecoes",
33
+ "iteradores": "portugython.iteradores",
34
+ "funcional": "portugython.funcional",
35
+ "bisecao": "portugython.bisecao",
36
+ # Tempo e data
37
+ "tempo": "portugython.tempo",
38
+ "calendario": "portugython.calendario",
39
+ # Sistema e IO
40
+ "sistema": "portugython.sistema",
41
+ "caminho": "portugython.caminho",
42
+ "subprocesso": "portugython.subprocesso",
43
+ "soquete": "portugython.soquete",
44
+ "rede": "portugython.rede",
45
+ # Texto e expressoes
46
+ "expressao": "portugython.expressao",
47
+ "formatacao": "portugython.formatacao",
48
+ # Serialization e codificacao
49
+ "serializacao": "portugython.serializacao",
50
+ "codificacao": "portugython.codificacao",
51
+ "compressao": "portugython.compressao",
52
+ "dados": "portugython.json",
53
+ # Concorrencia
54
+ "threads": "portugython.threads",
55
+ "assincronico": "portugython.assincronico",
56
+ # OOP e tipos
57
+ "abstrato": "portugython.abstrato",
58
+ "enumeracao": "portugython.enumeracao",
59
+ "classe_dados": "portugython.classe_dados",
60
+ "tipagem": "portugython.tipagem",
61
+ # Utilitarios
62
+ "registro": "portugython.registro",
63
+ "argumentos": "portugython.argumentos",
64
+ "contexto": "portugython.contexto",
65
+ "copia": "portugython.copia",
66
+ "hash_pt": "portugython.hash_pt",
67
+ "identificador": "portugython.identificador",
68
+ "configuracao": "portugython.configuracao",
69
+ "estrutura": "portugython.estrutura",
70
+ "depuracao": "portugython.depuracao",
71
+ "csv_pt": "portugython.csv_pt",
72
+ }
73
+
74
+
75
+ class _CarregadorAlias(importlib.abc.Loader):
76
+ """Carrega um modulo portugython sob um nome em Portugues."""
77
+
78
+ def __init__(self, modulo_real: str) -> None:
79
+ self._modulo_real = modulo_real
80
+
81
+ def create_module(self, spec: ModuleSpec): # noqa: ANN001
82
+ """Retorna o modulo real (ja carregado ou carregado agora)."""
83
+ return importlib.import_module(self._modulo_real)
84
+
85
+ def exec_module(self, module) -> None: # noqa: ANN001
86
+ """Nao precisa fazer nada: create_module ja retornou o modulo pronto."""
87
+
88
+
89
+ class ImportadorPortugues(importlib.abc.MetaPathFinder):
90
+ """Intercepta imports de nomes em Portugues e redireciona para portugython.*."""
91
+
92
+ def find_spec(
93
+ self,
94
+ fullname: str,
95
+ path: Sequence[str] | None,
96
+ target=None, # noqa: ANN001
97
+ ) -> ModuleSpec | None:
98
+ """Retorna um ModuleSpec para o modulo em Portugues, se mapeado.
99
+
100
+ Args:
101
+ fullname: Nome completo do modulo sendo importado.
102
+ path: Caminho de busca (ignorado aqui).
103
+ target: Modulo alvo (ignorado aqui).
104
+ """
105
+ if fullname in MAPA_MODULOS:
106
+ modulo_real = MAPA_MODULOS[fullname]
107
+ carregador = _CarregadorAlias(modulo_real)
108
+ return ModuleSpec(fullname, carregador)
109
+ return None
110
+
111
+
112
+ _gancho = ImportadorPortugues()
113
+
114
+
115
+
116
+
117
+ def listar_modulos() -> dict[str, str]:
118
+ """Retorna o mapeamento de nomes em Portugues para modulos portugython.
119
+
120
+ Returns:
121
+ Dicionario com nome_portugues -> caminho_modulo.
122
+ """
123
+ return dict(MAPA_MODULOS)
124
+
125
+
126
+ # ---------------------------------------------------------------------------
127
+ # Carregador de arquivos .ptpy
128
+ # ---------------------------------------------------------------------------
129
+
130
+
131
+ class _CarregadorPtpy(SourceFileLoader):
132
+ """Carrega arquivos .ptpy transpilando-os para Python antes da execucao."""
133
+
134
+ def get_data(self, path: str) -> bytes:
135
+ """Le o arquivo .ptpy e retorna o codigo Python traduzido como bytes."""
136
+ from portugython.transpilador import traduzir # noqa: PLC0415
137
+
138
+ codigo_pt = Path(path).read_text(encoding="utf-8")
139
+ codigo_py = traduzir(codigo_pt)
140
+ return codigo_py.encode("utf-8")
141
+
142
+
143
+ class ImportadorPtpy(importlib.abc.MetaPathFinder):
144
+ """Importa arquivos .ptpy (Python em Portugues) de qualquer diretorio
145
+ no sys.path."""
146
+
147
+ def find_spec(
148
+ self,
149
+ fullname: str,
150
+ path: Sequence[str] | None,
151
+ target=None, # noqa: ANN001
152
+ ) -> ModuleSpec | None:
153
+ """Procura um arquivo .ptpy para o modulo solicitado.
154
+
155
+ Args:
156
+ fullname: Nome completo do modulo.
157
+ path: Caminhos de busca.
158
+ target: Modulo alvo (ignorado).
159
+ """
160
+ diretorios = path if path else sys.path
161
+ for diretorio in diretorios:
162
+ candidato = Path(diretorio) / f"{fullname}.ptpy"
163
+ if candidato.exists():
164
+ carregador = _CarregadorPtpy(fullname, str(candidato))
165
+ return ModuleSpec(
166
+ fullname,
167
+ carregador,
168
+ origin=str(candidato),
169
+ )
170
+ return None
171
+
172
+
173
+ _gancho_ptpy = ImportadorPtpy()
174
+
175
+
176
+ def instalar() -> None:
177
+ """Instala o importador de modulos em Portugues no sys.meta_path.
178
+
179
+ Apos chamar esta funcao:
180
+ - Modulos portugython sao importaveis pelo nome em Portugues
181
+ - Arquivos .ptpy sao importaveis via import normal
182
+
183
+ Example:
184
+ import aleatorio
185
+ from matematica import raiz_quadrada, PI
186
+ from colecoes import Contador, Pilha
187
+ from tempo import agora, hoje
188
+ """
189
+ if not any(isinstance(f, ImportadorPortugues) for f in sys.meta_path):
190
+ sys.meta_path.insert(0, _gancho)
191
+ if not any(isinstance(f, ImportadorPtpy) for f in sys.meta_path):
192
+ sys.meta_path.append(_gancho_ptpy)
193
+
194
+
195
+ def desinstalar() -> None:
196
+ """Remove o importador de modulos em Portugues do sys.meta_path."""
197
+ sys.meta_path[:] = [
198
+ f for f in sys.meta_path
199
+ if not isinstance(f, (ImportadorPortugues, ImportadorPtpy))
200
+ ]