Pular para o conteúdo

Resolução de módulos

O algoritmo exato: as cinco formas de pedir um módulo, e a ordem em que a linguagem procura cada uma.

"Module not found" é uma das mensagens mais frustrantes que existem, e quase sempre porque o algoritmo de busca é folclore. Aqui ele é curto o bastante para caber numa página — e é uma implementação só, em resolucao.py, usada pelo interpretador e pelo analisador.

As cinco formas#

O que você escreveResolve contra
Arcane.Matha biblioteca padrão
Python.numpya ponte para o Python (não passa pela busca em disco)
./util, ../lib/utila pasta do arquivo que escreve o import
sub.moduloa pasta do arquivo, depois o diretório atual
validadorforge_modules/, subindo até achar um forge.toml

Relativo resolve a partir do arquivo, nunca do diretório de onde se rodou. É o que permite mover a pasta inteira sem quebrar nada, e o que torna a leitura do arquivo suficiente para saber o que ele importa.

A ordem, para um caminho relativo#

adopt ./util procura, nesta ordem:

text
./util               (o caminho exato, se for um arquivo)
./util.df
./util/main.df
./util/src/main.df

A ordem importa porque um arquivo e uma pasta com o mesmo nome podem coexistir. Sem ela declarada, a escolha dependeria da ordem em que o sistema de arquivos devolve os nomes.

A ordem, para um nome pontilhado#

adopt sub.modulo troca o ponto por separador de pasta — e só aqui, depois de o caso relativo ter sido descartado:

text
<pasta do arquivo>/sub/modulo.df
<pasta do arquivo>/sub/modulo/main.df
<pasta do arquivo>/sub/modulo/src/main.df
<diretório atual>/sub/modulo.df
<diretório atual>/sub/modulo/main.df
<diretório atual>/sub/modulo/src/main.df

Hífen num caminho relativo#

adopt ./minha-lib as L funciona, e não é óbvio que devesse: o lexer entrega o hífen como operador de subtração. O segmento de caminho cola -, . e dígitos ao nome exigindo adjacência de coluna — sem essa guarda, a - b viraria um arquivo chamado a-b.

Um pacote se importa pelo próprio nome#

O teste de uma biblioteca escreve adopt validador, e não adopt ../src/main, porque precisa exercitá-la pelo caminho que um usuário usaria. A busca sobe até o forge.toml mais próximo e olha o forge_modules/ dali.

text
meu-projeto/
  forge.toml              o que você pediu      (versionado)
  forge.lock              o que foi instalado   (versionado)
  forge_modules/          os pacotes            (NÃO versionado)
  src/main.df

Quando não acha#

A mensagem nomeia o que foi procurado, e não só o que faltou — um "não encontrado" sem a lista de tentativas obriga a adivinhar qual das cinco formas a linguagem achou que você estava usando.

O dataforge deps mostra o grafo de imports do projeto e acusa ciclo, usando o mesmo resolucao.py. Ele já teve uma terceira cópia da regra — uma expressão regular que começava em [A-Za-z_], de modo que ./vizinho nunca casava — e dizia "0 arquivos com imports próprios" em todo projeto do repositório.

Por onde seguir#