portugython 0.4.1__tar.gz → 0.5.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.
- {portugython-0.4.1 → portugython-0.5.0}/CHANGELOG.md +32 -1
- {portugython-0.4.1 → portugython-0.5.0}/PKG-INFO +64 -68
- {portugython-0.4.1 → portugython-0.5.0}/README.md +62 -66
- {portugython-0.4.1 → portugython-0.5.0}/portugython/__init__.py +2 -1
- portugython-0.5.0/portugython/_codec.py +99 -0
- {portugython-0.4.1 → portugython-0.5.0}/portugython/_importador.py +2 -0
- portugython-0.5.0/portugython/chaves.py +31 -0
- portugython-0.5.0/portugython-codec.pth +1 -0
- {portugython-0.4.1 → portugython-0.5.0}/pyproject.toml +5 -2
- portugython-0.5.0/tests/exemplo_codec.ptpy +22 -0
- portugython-0.5.0/tests/test_codec.py +245 -0
- {portugython-0.4.1 → portugython-0.5.0}/tests/test_portugython.py +1 -1
- {portugython-0.4.1 → portugython-0.5.0}/.gitignore +0 -0
- {portugython-0.4.1 → portugython-0.5.0}/LICENSE +0 -0
- {portugython-0.4.1 → portugython-0.5.0}/portugython/abstrato.py +0 -0
- {portugython-0.4.1 → portugython-0.5.0}/portugython/aleatorio.py +0 -0
- {portugython-0.4.1 → portugython-0.5.0}/portugython/argumentos.py +0 -0
- {portugython-0.4.1 → portugython-0.5.0}/portugython/assincronico.py +0 -0
- {portugython-0.4.1 → portugython-0.5.0}/portugython/bisecao.py +0 -0
- {portugython-0.4.1 → portugython-0.5.0}/portugython/calendario.py +0 -0
- {portugython-0.4.1 → portugython-0.5.0}/portugython/caminho.py +0 -0
- {portugython-0.4.1 → portugython-0.5.0}/portugython/classe_dados.py +0 -0
- {portugython-0.4.1 → portugython-0.5.0}/portugython/codificacao.py +0 -0
- {portugython-0.4.1 → portugython-0.5.0}/portugython/colecoes.py +0 -0
- {portugython-0.4.1 → portugython-0.5.0}/portugython/compressao.py +0 -0
- {portugython-0.4.1 → portugython-0.5.0}/portugython/configuracao.py +0 -0
- {portugython-0.4.1 → portugython-0.5.0}/portugython/contexto.py +0 -0
- {portugython-0.4.1 → portugython-0.5.0}/portugython/copia.py +0 -0
- {portugython-0.4.1 → portugython-0.5.0}/portugython/csv_pt.py +0 -0
- {portugython-0.4.1 → portugython-0.5.0}/portugython/depuracao.py +0 -0
- {portugython-0.4.1 → portugython-0.5.0}/portugython/enumeracao.py +0 -0
- {portugython-0.4.1 → portugython-0.5.0}/portugython/estatistica.py +0 -0
- {portugython-0.4.1 → portugython-0.5.0}/portugython/estrutura.py +0 -0
- {portugython-0.4.1 → portugython-0.5.0}/portugython/expressao.py +0 -0
- {portugython-0.4.1 → portugython-0.5.0}/portugython/formatacao.py +0 -0
- {portugython-0.4.1 → portugython-0.5.0}/portugython/funcional.py +0 -0
- {portugython-0.4.1 → portugython-0.5.0}/portugython/hash_pt.py +0 -0
- {portugython-0.4.1 → portugython-0.5.0}/portugython/identificador.py +0 -0
- {portugython-0.4.1 → portugython-0.5.0}/portugython/iteradores.py +0 -0
- {portugython-0.4.1 → portugython-0.5.0}/portugython/json.py +0 -0
- {portugython-0.4.1 → portugython-0.5.0}/portugython/matematica.py +0 -0
- {portugython-0.4.1 → portugython-0.5.0}/portugython/py.typed +0 -0
- {portugython-0.4.1 → portugython-0.5.0}/portugython/rede.py +0 -0
- {portugython-0.4.1 → portugython-0.5.0}/portugython/registro.py +0 -0
- {portugython-0.4.1 → portugython-0.5.0}/portugython/serializacao.py +0 -0
- {portugython-0.4.1 → portugython-0.5.0}/portugython/sistema.py +0 -0
- {portugython-0.4.1 → portugython-0.5.0}/portugython/soquete.py +0 -0
- {portugython-0.4.1 → portugython-0.5.0}/portugython/subprocesso.py +0 -0
- {portugython-0.4.1 → portugython-0.5.0}/portugython/tempo.py +0 -0
- {portugython-0.4.1 → portugython-0.5.0}/portugython/threads.py +0 -0
- {portugython-0.4.1 → portugython-0.5.0}/portugython/tipagem.py +0 -0
- {portugython-0.4.1 → portugython-0.5.0}/portugython/transpilador.py +0 -0
- {portugython-0.4.1 → portugython-0.5.0}/tests/__init__.py +0 -0
- {portugython-0.4.1 → portugython-0.5.0}/tests/ola_mundo.ptpy +0 -0
- {portugython-0.4.1 → portugython-0.5.0}/tests/test_importador.py +0 -0
- {portugython-0.4.1 → portugython-0.5.0}/tests/test_submodulos.py +0 -0
- {portugython-0.4.1 → portugython-0.5.0}/tests/test_transpilador.py +0 -0
|
@@ -1,6 +1,37 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
## 0.
|
|
3
|
+
## 0.5.0 (2026-06-26)
|
|
4
|
+
|
|
5
|
+
Adiciona **codec de fonte `portugues`**: a forma mais natural de escrever Python em português.
|
|
6
|
+
|
|
7
|
+
Adicione `# -*- coding: portugues -*-` ao topo de qualquer arquivo `.py` e escreva
|
|
8
|
+
Python com palavras-chave em português diretamente. Não é necessária nenhuma ferramenta
|
|
9
|
+
extra além do Python padrão.
|
|
10
|
+
|
|
11
|
+
Exemplo completo:
|
|
12
|
+
|
|
13
|
+
```python
|
|
14
|
+
# -*- coding: portugues -*-
|
|
15
|
+
de chaves importe *
|
|
16
|
+
|
|
17
|
+
defina fatorial(n):
|
|
18
|
+
se n <= 1:
|
|
19
|
+
retorne 1
|
|
20
|
+
senao:
|
|
21
|
+
retorne n * fatorial(n - 1)
|
|
22
|
+
|
|
23
|
+
para i em intervalo(1, 6):
|
|
24
|
+
escreva(f"{i}! = {fatorial(i)}")
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Novos módulos:
|
|
28
|
+
|
|
29
|
+
- `portugython._codec`: codec `portugues` que traduz palavras-chave antes do parse;
|
|
30
|
+
registrado automaticamente via `portugython-codec.pth` ao instalar.
|
|
31
|
+
- `portugython.chaves`: re-exporta todos os identificadores em português do
|
|
32
|
+
portugython para uso com `from chaves import *`.
|
|
33
|
+
|
|
34
|
+
|
|
4
35
|
|
|
5
36
|
Corrige acentuação em toda a documentação (README, CHANGELOG, docstrings).
|
|
6
37
|
Sem alterações na API ou no código.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: portugython
|
|
3
|
-
Version: 0.
|
|
4
|
-
Summary:
|
|
3
|
+
Version: 0.5.0
|
|
4
|
+
Summary: Escreva Python em Português: codec de sintaxe, módulos e funções traduzidos
|
|
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
|
|
@@ -31,7 +31,7 @@ Description-Content-Type: text/markdown
|
|
|
31
31
|
[](https://pypi.org/project/portugython/)
|
|
32
32
|
[](https://opensource.org/licenses/MIT)
|
|
33
33
|
|
|
34
|
-
Escreva Python em Português. Portugython traduz funções, tipos e módulos da biblioteca padrão do Python para nomes em português.
|
|
34
|
+
Escreva Python em Português. Portugython traduz funções, tipos e módulos da biblioteca padrão do Python para nomes em português, e inclui um **codec de sintaxe** que permite escrever palavras-chave (`se`, `para`, `defina`, etc.) nativamente em qualquer arquivo `.py`.
|
|
35
35
|
|
|
36
36
|
## Instalação
|
|
37
37
|
|
|
@@ -39,7 +39,59 @@ Escreva Python em Português. Portugython traduz funções, tipos e módulos da
|
|
|
39
39
|
pip install portugython
|
|
40
40
|
```
|
|
41
41
|
|
|
42
|
-
|
|
42
|
+
O codec é registrado automaticamente ao instalar. Basta adicionar `# -*- coding: portugues -*-` ao topo do arquivo.
|
|
43
|
+
|
|
44
|
+
## Uso: Python em Português nativo
|
|
45
|
+
|
|
46
|
+
```python
|
|
47
|
+
# -*- coding: portugues -*-
|
|
48
|
+
de chaves importe *
|
|
49
|
+
|
|
50
|
+
defina fatorial(n):
|
|
51
|
+
se n <= 1:
|
|
52
|
+
retorne 1
|
|
53
|
+
senao:
|
|
54
|
+
retorne n * fatorial(n - 1)
|
|
55
|
+
|
|
56
|
+
defina verificar_primo(n):
|
|
57
|
+
se n < 2:
|
|
58
|
+
retorne Falso
|
|
59
|
+
para i em intervalo(2, n):
|
|
60
|
+
se n % i == 0:
|
|
61
|
+
retorne Falso
|
|
62
|
+
retorne Verdadeiro
|
|
63
|
+
|
|
64
|
+
primos = [x para x em intervalo(2, 20) se verificar_primo(x)]
|
|
65
|
+
escreva("Primos:", primos)
|
|
66
|
+
|
|
67
|
+
para n em intervalo(1, 6):
|
|
68
|
+
escreva(f"{n}! = {fatorial(n)}")
|
|
69
|
+
|
|
70
|
+
tente:
|
|
71
|
+
resultado = 10 / 0
|
|
72
|
+
exceto ZeroDivisionError como err:
|
|
73
|
+
escreva("Erro capturado:", err)
|
|
74
|
+
finalmente:
|
|
75
|
+
escreva("Pronto!")
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Salve como `programa.py` e execute com `python programa.py`. Nenhuma ferramenta extra necessária.
|
|
79
|
+
|
|
80
|
+
> **Nota sobre palavras ambíguas**: `e`, `ou`, `de`, `com`, `em` são palavras-chave
|
|
81
|
+
> reservadas em arquivos com `# -*- coding: portugues -*-`. Evite usá-las como
|
|
82
|
+
> nomes de variáveis (use `err` em vez de `e` para exceções, por exemplo).
|
|
83
|
+
|
|
84
|
+
## Como funciona
|
|
85
|
+
|
|
86
|
+
O codec `portugues` é registrado automaticamente via `portugython-codec.pth` ao instalar
|
|
87
|
+
o pacote. Quando Python encontra `# -*- coding: portugues -*-`, chama o codec para
|
|
88
|
+
decodificar o arquivo antes de parsear, traduzindo palavras-chave em português para
|
|
89
|
+
Python padrão de forma transparente.
|
|
90
|
+
|
|
91
|
+
O módulo `chaves` exporta todos os aliases de funções em português (`escreva`, `leia`,
|
|
92
|
+
`intervalo`, `tamanho`, `Lista`, `Dicionario`, etc.) para uso direto via `from chaves import *`.
|
|
93
|
+
|
|
94
|
+
## Uso básico sem codec
|
|
43
95
|
|
|
44
96
|
```python
|
|
45
97
|
from portugython import *
|
|
@@ -281,84 +333,28 @@ if email.encontrar("contato@example.com"):
|
|
|
281
333
|
| `filtro(f, it)` | `list(filter(f, it))` |
|
|
282
334
|
| `reduzido(f, it)` | `functools.reduce(f, it)` |
|
|
283
335
|
|
|
284
|
-
## Transpilador
|
|
336
|
+
## Transpilador (API programática)
|
|
285
337
|
|
|
286
|
-
|
|
287
|
-
(palavras-chave) para português. Isso permite escrever programas Python
|
|
288
|
-
inteiramente em português.
|
|
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
|
|
338
|
+
Além do codec, `portugython.transpilador` expõe funções para tradução programática:
|
|
299
339
|
|
|
300
340
|
```python
|
|
301
341
|
from portugython import traduzir, executar_texto, executar_arquivo
|
|
302
342
|
|
|
303
|
-
#
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
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)
|
|
343
|
+
# Ver o Python equivalente
|
|
344
|
+
print(traduzir("se x > 0:\n retorne x"))
|
|
345
|
+
# if x > 0:
|
|
346
|
+
# return x
|
|
317
347
|
|
|
318
348
|
# Executar diretamente
|
|
319
349
|
executar_texto("para i em intervalo(3):\n escreva(i)")
|
|
320
350
|
|
|
321
351
|
# Executar um arquivo .ptpy
|
|
322
|
-
executar_arquivo("
|
|
352
|
+
executar_arquivo("programa.ptpy")
|
|
323
353
|
```
|
|
324
354
|
|
|
325
|
-
|
|
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
|
-
```
|
|
355
|
+
## Tabela de palavras-chave
|
|
358
356
|
|
|
359
|
-
### Tabela de palavras-chave
|
|
360
357
|
|
|
361
|
-
| Português | Python | | Português | Python |
|
|
362
358
|
|-----------|--------|-|-----------|--------|
|
|
363
359
|
| `se` | `if` | | `senao` | `else` |
|
|
364
360
|
| `senaose` | `elif` | | `para` | `for` |
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
[](https://pypi.org/project/portugython/)
|
|
5
5
|
[](https://opensource.org/licenses/MIT)
|
|
6
6
|
|
|
7
|
-
Escreva Python em Português. Portugython traduz funções, tipos e módulos da biblioteca padrão do Python para nomes em português.
|
|
7
|
+
Escreva Python em Português. Portugython traduz funções, tipos e módulos da biblioteca padrão do Python para nomes em português, e inclui um **codec de sintaxe** que permite escrever palavras-chave (`se`, `para`, `defina`, etc.) nativamente em qualquer arquivo `.py`.
|
|
8
8
|
|
|
9
9
|
## Instalação
|
|
10
10
|
|
|
@@ -12,7 +12,59 @@ Escreva Python em Português. Portugython traduz funções, tipos e módulos da
|
|
|
12
12
|
pip install portugython
|
|
13
13
|
```
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
O codec é registrado automaticamente ao instalar. Basta adicionar `# -*- coding: portugues -*-` ao topo do arquivo.
|
|
16
|
+
|
|
17
|
+
## Uso: Python em Português nativo
|
|
18
|
+
|
|
19
|
+
```python
|
|
20
|
+
# -*- coding: portugues -*-
|
|
21
|
+
de chaves importe *
|
|
22
|
+
|
|
23
|
+
defina fatorial(n):
|
|
24
|
+
se n <= 1:
|
|
25
|
+
retorne 1
|
|
26
|
+
senao:
|
|
27
|
+
retorne n * fatorial(n - 1)
|
|
28
|
+
|
|
29
|
+
defina verificar_primo(n):
|
|
30
|
+
se n < 2:
|
|
31
|
+
retorne Falso
|
|
32
|
+
para i em intervalo(2, n):
|
|
33
|
+
se n % i == 0:
|
|
34
|
+
retorne Falso
|
|
35
|
+
retorne Verdadeiro
|
|
36
|
+
|
|
37
|
+
primos = [x para x em intervalo(2, 20) se verificar_primo(x)]
|
|
38
|
+
escreva("Primos:", primos)
|
|
39
|
+
|
|
40
|
+
para n em intervalo(1, 6):
|
|
41
|
+
escreva(f"{n}! = {fatorial(n)}")
|
|
42
|
+
|
|
43
|
+
tente:
|
|
44
|
+
resultado = 10 / 0
|
|
45
|
+
exceto ZeroDivisionError como err:
|
|
46
|
+
escreva("Erro capturado:", err)
|
|
47
|
+
finalmente:
|
|
48
|
+
escreva("Pronto!")
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Salve como `programa.py` e execute com `python programa.py`. Nenhuma ferramenta extra necessária.
|
|
52
|
+
|
|
53
|
+
> **Nota sobre palavras ambíguas**: `e`, `ou`, `de`, `com`, `em` são palavras-chave
|
|
54
|
+
> reservadas em arquivos com `# -*- coding: portugues -*-`. Evite usá-las como
|
|
55
|
+
> nomes de variáveis (use `err` em vez de `e` para exceções, por exemplo).
|
|
56
|
+
|
|
57
|
+
## Como funciona
|
|
58
|
+
|
|
59
|
+
O codec `portugues` é registrado automaticamente via `portugython-codec.pth` ao instalar
|
|
60
|
+
o pacote. Quando Python encontra `# -*- coding: portugues -*-`, chama o codec para
|
|
61
|
+
decodificar o arquivo antes de parsear, traduzindo palavras-chave em português para
|
|
62
|
+
Python padrão de forma transparente.
|
|
63
|
+
|
|
64
|
+
O módulo `chaves` exporta todos os aliases de funções em português (`escreva`, `leia`,
|
|
65
|
+
`intervalo`, `tamanho`, `Lista`, `Dicionario`, etc.) para uso direto via `from chaves import *`.
|
|
66
|
+
|
|
67
|
+
## Uso básico sem codec
|
|
16
68
|
|
|
17
69
|
```python
|
|
18
70
|
from portugython import *
|
|
@@ -254,84 +306,28 @@ if email.encontrar("contato@example.com"):
|
|
|
254
306
|
| `filtro(f, it)` | `list(filter(f, it))` |
|
|
255
307
|
| `reduzido(f, it)` | `functools.reduce(f, it)` |
|
|
256
308
|
|
|
257
|
-
## Transpilador
|
|
309
|
+
## Transpilador (API programática)
|
|
258
310
|
|
|
259
|
-
|
|
260
|
-
(palavras-chave) para português. Isso permite escrever programas Python
|
|
261
|
-
inteiramente em português.
|
|
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
|
|
311
|
+
Além do codec, `portugython.transpilador` expõe funções para tradução programática:
|
|
272
312
|
|
|
273
313
|
```python
|
|
274
314
|
from portugython import traduzir, executar_texto, executar_arquivo
|
|
275
315
|
|
|
276
|
-
#
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
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)
|
|
316
|
+
# Ver o Python equivalente
|
|
317
|
+
print(traduzir("se x > 0:\n retorne x"))
|
|
318
|
+
# if x > 0:
|
|
319
|
+
# return x
|
|
290
320
|
|
|
291
321
|
# Executar diretamente
|
|
292
322
|
executar_texto("para i em intervalo(3):\n escreva(i)")
|
|
293
323
|
|
|
294
324
|
# Executar um arquivo .ptpy
|
|
295
|
-
executar_arquivo("
|
|
325
|
+
executar_arquivo("programa.ptpy")
|
|
296
326
|
```
|
|
297
327
|
|
|
298
|
-
|
|
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
|
-
```
|
|
328
|
+
## Tabela de palavras-chave
|
|
331
329
|
|
|
332
|
-
### Tabela de palavras-chave
|
|
333
330
|
|
|
334
|
-
| Português | Python | | Português | Python |
|
|
335
331
|
|-----------|--------|-|-----------|--------|
|
|
336
332
|
| `se` | `if` | | `senao` | `else` |
|
|
337
333
|
| `senaose` | `elif` | | `para` | `for` |
|
|
@@ -4,6 +4,7 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
from functools import reduce as _reduce
|
|
6
6
|
|
|
7
|
+
import portugython._codec # registra o codec 'portugues' automaticamente # noqa: F401
|
|
7
8
|
from portugython._importador import (
|
|
8
9
|
desinstalar,
|
|
9
10
|
instalar,
|
|
@@ -19,7 +20,7 @@ from portugython.transpilador import (
|
|
|
19
20
|
traduzir_para_portugues,
|
|
20
21
|
)
|
|
21
22
|
|
|
22
|
-
__version__ = "0.
|
|
23
|
+
__version__ = "0.5.0"
|
|
23
24
|
|
|
24
25
|
# Instala o gancho de importação automaticamente
|
|
25
26
|
instalar()
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"""_codec - codec 'portugues' que habilita sintaxe Python em português.
|
|
2
|
+
|
|
3
|
+
Quando registrado, qualquer arquivo com:
|
|
4
|
+
|
|
5
|
+
# -*- coding: portugues -*-
|
|
6
|
+
|
|
7
|
+
pode usar palavras-chave em português diretamente. Python chama este codec
|
|
8
|
+
para decodificar o código-fonte antes de parsear, então a tradução é
|
|
9
|
+
transparente para o interpretador.
|
|
10
|
+
|
|
11
|
+
O codec é registrado automaticamente ao importar portugython, e também
|
|
12
|
+
via o arquivo portugython-codec.pth instalado em site-packages (que
|
|
13
|
+
registra o codec ao iniciar o Python, antes de qualquer código do usuário).
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
from __future__ import annotations
|
|
17
|
+
|
|
18
|
+
import codecs
|
|
19
|
+
import encodings.utf_8
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def _decode(input_bytes: bytes, errors: str = "strict") -> tuple[str, int]:
|
|
23
|
+
"""Decodifica bytes de fonte Python em português para Python padrão.
|
|
24
|
+
|
|
25
|
+
Chamado pelo Python quando encontra '# -*- coding: portugues -*-'.
|
|
26
|
+
|
|
27
|
+
Args:
|
|
28
|
+
input_bytes: Bytes do arquivo-fonte.
|
|
29
|
+
errors: Política de tratamento de erros de encoding.
|
|
30
|
+
|
|
31
|
+
Returns:
|
|
32
|
+
Tupla (código_python_str, bytes_consumidos).
|
|
33
|
+
"""
|
|
34
|
+
from portugython.transpilador import traduzir # noqa: PLC0415
|
|
35
|
+
|
|
36
|
+
fonte = input_bytes.decode("utf-8", errors)
|
|
37
|
+
return traduzir(fonte), len(input_bytes)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class _DecodificadorIncremental(codecs.BufferedIncrementalDecoder):
|
|
41
|
+
"""Decodificador incremental necessário pela interface de codecs."""
|
|
42
|
+
|
|
43
|
+
def _buffer_decode(
|
|
44
|
+
self, entrada: bytes, erros: str, final: bool
|
|
45
|
+
) -> tuple[str, int]:
|
|
46
|
+
return _decode(entrada, erros)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class _LeitorFluxo(codecs.StreamReader):
|
|
50
|
+
"""Leitor de fluxo necessário pela interface de codecs."""
|
|
51
|
+
|
|
52
|
+
def decode(self, entrada: bytes, erros: str = "strict") -> tuple[str, int]:
|
|
53
|
+
return _decode(entrada, erros)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
_CODEC_INFO = codecs.CodecInfo(
|
|
57
|
+
name="portugues",
|
|
58
|
+
encode=encodings.utf_8.encode,
|
|
59
|
+
decode=_decode,
|
|
60
|
+
incrementaldecoder=_DecodificadorIncremental,
|
|
61
|
+
streamreader=_LeitorFluxo,
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
_NOMES_CODEC: frozenset[str] = frozenset(
|
|
65
|
+
("portugues", "portugues_br", "pt_br", "português", "português_br")
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def _buscar_codec(nome: str) -> codecs.CodecInfo | None:
|
|
70
|
+
"""Função de busca registrada no sistema de codecs do Python.
|
|
71
|
+
|
|
72
|
+
Args:
|
|
73
|
+
nome: Nome do codec solicitado pelo Python.
|
|
74
|
+
|
|
75
|
+
Returns:
|
|
76
|
+
CodecInfo se o nome for 'portugues', None caso contrário.
|
|
77
|
+
"""
|
|
78
|
+
if nome.replace("-", "_").lower() in _NOMES_CODEC:
|
|
79
|
+
return _CODEC_INFO
|
|
80
|
+
return None
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def registrar() -> None:
|
|
84
|
+
"""Registra o codec 'portugues' no sistema de codecs do Python.
|
|
85
|
+
|
|
86
|
+
Após registrar, arquivos com '# -*- coding: portugues -*-'
|
|
87
|
+
podem usar palavras-chave em português nativamente.
|
|
88
|
+
|
|
89
|
+
Chamado automaticamente ao importar portugython e pelo arquivo
|
|
90
|
+
portugython-codec.pth no arranque do Python.
|
|
91
|
+
|
|
92
|
+
Example:
|
|
93
|
+
from portugython._codec import registrar
|
|
94
|
+
registrar()
|
|
95
|
+
"""
|
|
96
|
+
codecs.register(_buscar_codec)
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
registrar()
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"""chaves - exporta todos os identificadores em português do portugython.
|
|
2
|
+
|
|
3
|
+
Uso típico junto com o codec 'portugues':
|
|
4
|
+
|
|
5
|
+
# -*- coding: portugues -*-
|
|
6
|
+
de chaves importe *
|
|
7
|
+
|
|
8
|
+
se 4 > 5:
|
|
9
|
+
passe
|
|
10
|
+
senao:
|
|
11
|
+
escreva("correto!")
|
|
12
|
+
|
|
13
|
+
defina fatorial(n):
|
|
14
|
+
se n <= 1:
|
|
15
|
+
retorne 1
|
|
16
|
+
senao:
|
|
17
|
+
retorne n * fatorial(n - 1)
|
|
18
|
+
|
|
19
|
+
para i em intervalo(1, 6):
|
|
20
|
+
escreva(f"{i}! = {fatorial(i)}")
|
|
21
|
+
|
|
22
|
+
Também pode ser importado com a sintaxe Python padrão:
|
|
23
|
+
|
|
24
|
+
# -*- coding: portugues -*-
|
|
25
|
+
from chaves import *
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
from portugython import * # noqa: F401, F403
|
|
29
|
+
from portugython import __all__ # noqa: F401
|
|
30
|
+
|
|
31
|
+
__all__ = list(__all__)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import portugython._codec
|
|
@@ -4,8 +4,8 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "portugython"
|
|
7
|
-
version = "0.
|
|
8
|
-
description = "
|
|
7
|
+
version = "0.5.0"
|
|
8
|
+
description = "Escreva Python em Português: codec de sintaxe, módulos e funções traduzidos"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = {text = "MIT"}
|
|
11
11
|
requires-python = ">=3.10"
|
|
@@ -29,6 +29,9 @@ classifiers = [
|
|
|
29
29
|
Homepage = "https://github.com/spacemany2k38/portugython"
|
|
30
30
|
"Bug Tracker" = "https://github.com/spacemany2k38/portugython/issues"
|
|
31
31
|
|
|
32
|
+
[tool.hatch.build.targets.wheel]
|
|
33
|
+
force-include = {"portugython-codec.pth" = "portugython-codec.pth"}
|
|
34
|
+
|
|
32
35
|
[project.scripts]
|
|
33
36
|
ptpy = "portugython.transpilador:_main"
|
|
34
37
|
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# -*- coding: portugues -*-
|
|
2
|
+
de chaves importe *
|
|
3
|
+
|
|
4
|
+
defina fatorial(n):
|
|
5
|
+
se n <= 1:
|
|
6
|
+
retorne 1
|
|
7
|
+
senao:
|
|
8
|
+
retorne n * fatorial(n - 1)
|
|
9
|
+
|
|
10
|
+
defina verificar_primo(n):
|
|
11
|
+
se n < 2:
|
|
12
|
+
retorne Falso
|
|
13
|
+
para i em intervalo(2, n):
|
|
14
|
+
se n % i == 0:
|
|
15
|
+
retorne Falso
|
|
16
|
+
retorne Verdadeiro
|
|
17
|
+
|
|
18
|
+
resultados = []
|
|
19
|
+
para n em intervalo(1, 6):
|
|
20
|
+
resultados.adicione(fatorial(n))
|
|
21
|
+
|
|
22
|
+
primos = [x para x em intervalo(2, 20) se verificar_primo(x)]
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
"""Testes para o codec 'portugues' e o módulo chaves."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import codecs
|
|
6
|
+
import sys
|
|
7
|
+
import textwrap
|
|
8
|
+
|
|
9
|
+
# ---------------------------------------------------------------------------
|
|
10
|
+
# Testes do codec
|
|
11
|
+
# ---------------------------------------------------------------------------
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def test_codec_registrado():
|
|
15
|
+
"""O codec 'portugues' deve estar disponível após importar portugython."""
|
|
16
|
+
import portugython # noqa: F401
|
|
17
|
+
|
|
18
|
+
info = codecs.lookup("portugues")
|
|
19
|
+
assert info.name == "portugues"
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def test_codec_decodifica_se():
|
|
23
|
+
info = codecs.lookup("portugues")
|
|
24
|
+
codigo = b"se x > 0: passar"
|
|
25
|
+
resultado, _ = info.decode(codigo)
|
|
26
|
+
assert "if" in resultado
|
|
27
|
+
assert "pass" in resultado
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def test_codec_decodifica_para():
|
|
31
|
+
info = codecs.lookup("portugues")
|
|
32
|
+
codigo = b"para i em intervalo(3): passar"
|
|
33
|
+
resultado, _ = info.decode(codigo)
|
|
34
|
+
assert "for" in resultado
|
|
35
|
+
assert "in" in resultado
|
|
36
|
+
assert "pass" in resultado
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def test_codec_decodifica_defina_retorne():
|
|
40
|
+
info = codecs.lookup("portugues")
|
|
41
|
+
codigo = b"defina f(x):\n retorne x * 2"
|
|
42
|
+
resultado, _ = info.decode(codigo)
|
|
43
|
+
assert "def f(x):" in resultado
|
|
44
|
+
assert "return x * 2" in resultado
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def test_codec_preserva_strings():
|
|
48
|
+
info = codecs.lookup("portugues")
|
|
49
|
+
codigo = b'x = "se para enquanto defina"'
|
|
50
|
+
resultado, _ = info.decode(codigo)
|
|
51
|
+
assert '"se para enquanto defina"' in resultado
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def test_codec_preserva_comentarios():
|
|
55
|
+
info = codecs.lookup("portugues")
|
|
56
|
+
codigo = b"# se para enquanto\nx = 1"
|
|
57
|
+
resultado, _ = info.decode(codigo)
|
|
58
|
+
assert "# se para enquanto" in resultado
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def test_codec_encode_utf8():
|
|
62
|
+
"""Encode deve ser UTF-8 normal (sem transformação)."""
|
|
63
|
+
info = codecs.lookup("portugues")
|
|
64
|
+
texto = "olá mundo"
|
|
65
|
+
codificado, _ = info.encode(texto)
|
|
66
|
+
assert codificado == texto.encode("utf-8")
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
# ---------------------------------------------------------------------------
|
|
70
|
+
# Testes do módulo chaves
|
|
71
|
+
# ---------------------------------------------------------------------------
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def test_chaves_importavel():
|
|
75
|
+
from chaves import Falso, Nenhum, Verdadeiro, escreva, intervalo # noqa: F401
|
|
76
|
+
|
|
77
|
+
assert escreva is print
|
|
78
|
+
assert intervalo is range
|
|
79
|
+
assert Verdadeiro is True
|
|
80
|
+
assert Falso is False
|
|
81
|
+
assert Nenhum is None
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def test_chaves_tem_all():
|
|
85
|
+
import chaves
|
|
86
|
+
|
|
87
|
+
assert hasattr(chaves, "__all__")
|
|
88
|
+
assert len(chaves.__all__) > 20
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def test_chaves_escreva(capsys):
|
|
92
|
+
from chaves import escreva
|
|
93
|
+
|
|
94
|
+
escreva("olá do chaves")
|
|
95
|
+
assert "olá do chaves" in capsys.readouterr().out
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def test_chaves_lista_classe():
|
|
99
|
+
from chaves import Lista, tamanho
|
|
100
|
+
|
|
101
|
+
lista = Lista([1, 2, 3])
|
|
102
|
+
lista.adicione(4)
|
|
103
|
+
assert tamanho(lista) == 4
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def test_chaves_tamanho():
|
|
107
|
+
from chaves import tamanho
|
|
108
|
+
|
|
109
|
+
assert tamanho([1, 2, 3]) == 3
|
|
110
|
+
assert tamanho("abc") == 3
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
# ---------------------------------------------------------------------------
|
|
114
|
+
# Testes de execução com codec via arquivo .ptpy
|
|
115
|
+
# ---------------------------------------------------------------------------
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def test_arquivo_ptpy_com_declaracao_codec(tmp_path, capsys):
|
|
119
|
+
"""Arquivo com # -*- coding: portugues -*- é executado com palavras-chave em PT."""
|
|
120
|
+
arquivo = tmp_path / "teste.ptpy"
|
|
121
|
+
arquivo.write_text(
|
|
122
|
+
textwrap.dedent("""
|
|
123
|
+
# -*- coding: portugues -*-
|
|
124
|
+
de chaves importe *
|
|
125
|
+
|
|
126
|
+
defina quadrado(n):
|
|
127
|
+
retorne n * n
|
|
128
|
+
|
|
129
|
+
para i em intervalo(1, 4):
|
|
130
|
+
escreva(quadrado(i))
|
|
131
|
+
""").strip(),
|
|
132
|
+
encoding="utf-8",
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
from portugython.transpilador import executar_arquivo
|
|
136
|
+
|
|
137
|
+
executar_arquivo(arquivo)
|
|
138
|
+
saida = capsys.readouterr().out
|
|
139
|
+
assert "1" in saida
|
|
140
|
+
assert "4" in saida
|
|
141
|
+
assert "9" in saida
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
def test_ptpy_se_senao(tmp_path, capsys):
|
|
145
|
+
arquivo = tmp_path / "cond.ptpy"
|
|
146
|
+
arquivo.write_text(
|
|
147
|
+
textwrap.dedent("""
|
|
148
|
+
# -*- coding: portugues -*-
|
|
149
|
+
de chaves importe *
|
|
150
|
+
|
|
151
|
+
x = 10
|
|
152
|
+
se x > 5:
|
|
153
|
+
escreva("grande")
|
|
154
|
+
senaose x == 5:
|
|
155
|
+
escreva("exato")
|
|
156
|
+
senao:
|
|
157
|
+
escreva("pequeno")
|
|
158
|
+
""").strip(),
|
|
159
|
+
encoding="utf-8",
|
|
160
|
+
)
|
|
161
|
+
from portugython.transpilador import executar_arquivo
|
|
162
|
+
|
|
163
|
+
executar_arquivo(arquivo)
|
|
164
|
+
assert "grande" in capsys.readouterr().out
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
def test_ptpy_tente_exceto(tmp_path, capsys):
|
|
168
|
+
arquivo = tmp_path / "erro.ptpy"
|
|
169
|
+
arquivo.write_text(
|
|
170
|
+
textwrap.dedent("""
|
|
171
|
+
# -*- coding: portugues -*-
|
|
172
|
+
de chaves importe *
|
|
173
|
+
|
|
174
|
+
tente:
|
|
175
|
+
levante ValueError("teste")
|
|
176
|
+
exceto ValueError como err:
|
|
177
|
+
escreva("capturado:", err)
|
|
178
|
+
finalmente:
|
|
179
|
+
escreva("pronto")
|
|
180
|
+
""").strip(),
|
|
181
|
+
encoding="utf-8",
|
|
182
|
+
)
|
|
183
|
+
from portugython.transpilador import executar_arquivo
|
|
184
|
+
|
|
185
|
+
executar_arquivo(arquivo)
|
|
186
|
+
saida = capsys.readouterr().out
|
|
187
|
+
assert "capturado" in saida
|
|
188
|
+
assert "pronto" in saida
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
def test_ptpy_enquanto(tmp_path, capsys):
|
|
192
|
+
arquivo = tmp_path / "loop.ptpy"
|
|
193
|
+
arquivo.write_text(
|
|
194
|
+
textwrap.dedent("""
|
|
195
|
+
# -*- coding: portugues -*-
|
|
196
|
+
de chaves importe *
|
|
197
|
+
|
|
198
|
+
i = 0
|
|
199
|
+
enquanto i < 3:
|
|
200
|
+
escreva(i)
|
|
201
|
+
i = i + 1
|
|
202
|
+
""").strip(),
|
|
203
|
+
encoding="utf-8",
|
|
204
|
+
)
|
|
205
|
+
from portugython.transpilador import executar_arquivo
|
|
206
|
+
|
|
207
|
+
executar_arquivo(arquivo)
|
|
208
|
+
saida = capsys.readouterr().out
|
|
209
|
+
assert "0" in saida
|
|
210
|
+
assert "2" in saida
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
# ---------------------------------------------------------------------------
|
|
214
|
+
# Testes de importação via hook (.ptpy como módulo)
|
|
215
|
+
# ---------------------------------------------------------------------------
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
def test_importar_modulo_ptpy(tmp_path):
|
|
219
|
+
"""Módulos .ptpy podem ser importados via import normal com o hook ativo."""
|
|
220
|
+
import portugython # garante hook ativo # noqa: F401
|
|
221
|
+
|
|
222
|
+
modulo_py = tmp_path / "meu_modulo.ptpy"
|
|
223
|
+
modulo_py.write_text(
|
|
224
|
+
textwrap.dedent("""
|
|
225
|
+
de chaves importe *
|
|
226
|
+
|
|
227
|
+
defina dobrar(x):
|
|
228
|
+
retorne x * 2
|
|
229
|
+
|
|
230
|
+
VALOR = dobrar(21)
|
|
231
|
+
""").strip(),
|
|
232
|
+
encoding="utf-8",
|
|
233
|
+
)
|
|
234
|
+
|
|
235
|
+
sys.path.insert(0, str(tmp_path))
|
|
236
|
+
try:
|
|
237
|
+
if "meu_modulo" in sys.modules:
|
|
238
|
+
del sys.modules["meu_modulo"]
|
|
239
|
+
import meu_modulo # noqa: PLC0415
|
|
240
|
+
|
|
241
|
+
assert meu_modulo.VALOR == 42
|
|
242
|
+
assert meu_modulo.dobrar(5) == 10
|
|
243
|
+
finally:
|
|
244
|
+
sys.path.remove(str(tmp_path))
|
|
245
|
+
sys.modules.pop("meu_modulo", None)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|