Skip to content

refactor: migração de pkg_resources para pkg_resources_fixer#1107

Merged
robertatakenaka merged 9 commits intoscieloorg:masterfrom
robertatakenaka:fix_compatibilidade_com_setuptools_mais_recente
Feb 16, 2026
Merged

refactor: migração de pkg_resources para pkg_resources_fixer#1107
robertatakenaka merged 9 commits intoscieloorg:masterfrom
robertatakenaka:fix_compatibilidade_com_setuptools_mais_recente

Conversation

@robertatakenaka
Copy link
Copy Markdown
Member

📝 Descrição do Pull Request

Título: refactor: migração de pkg_resources para pkg_resources_fixer

O que foi feito?

Esta alteração visa substituir o uso direto da biblioteca pkg_resources (que pode ser lenta ou apresentar problemas de compatibilidade em certos ambientes) pelo utilitário interno pkg_resources_fixer.

A refatoração padroniza a forma como o sistema obtém a versão do pacote packtools e como carrega os entry points dos plugins.

Principais Mudanças:

  • packtools/catalogs/: Substituição do iter_entry_points padrão pelo get_iter_entry_points customizado para carregamento de catálogos.
  • packtools/htmlgenerator.py: Atualização da captura da versão do sistema via pkg_resources_fixer.get_version.
  • packtools/package_optimiser.py: Limpeza de imports e atualização da lógica de versão.
  • packtools/stylechecker.py: Migração da CLI para usar o novo utilitário de versão.
  • packtools/webapp/config/: Simplificação drástica da lógica de configuração da Webapp, removendo blocos try/except desnecessários para a detecção da versão.

Impacto Técnico:

  1. Performance: O pkg_resources original é conhecido por fazer varreduras pesadas no disco; o uso do fixer tende a ser mais eficiente.
  2. Robustez: Centraliza a lógica de descoberta de pacotes em um único ponto do projeto.

Como testar?

  1. Execute o stylechecker via CLI: python -m packtools.stylechecker --version.
  2. Verifique se o htmlgenerator e o package_optimiser ainda exibem a versão correta.
  3. Inicie a aplicação web e valide se a constante PACKTOOLS_VERSION no arquivo de config está sendo preenchida corretamente.

Copilot AI review requested due to automatic review settings February 13, 2026 19:39
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Este PR refatora a obtenção de versão do pacote e o carregamento de entry points para substituir o uso direto de pkg_resources por um utilitário interno (pkg_resources_fixer), com foco em desempenho e centralização dessa lógica.

Changes:

  • Adiciona packtools/pkg_resources_fixer.py com helpers para obter versão e iterar entry points.
  • Atualiza CLIs (stylechecker, htmlgenerator, package_optimiser) para usar o novo helper de versão.
  • Simplifica webapp/config/default.py e migra o carregamento de plugins de catálogos para o novo helper.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
packtools/pkg_resources_fixer.py Introduz helpers get_version e get_iter_entry_points para substituir pkg_resources.
packtools/webapp/config/default.py Troca lógica de detecção de versão por chamada direta ao helper.
packtools/stylechecker.py Ajusta versão exibida na CLI para usar o novo helper.
packtools/htmlgenerator.py Ajusta versão exibida na CLI para usar o novo helper.
packtools/package_optimiser.py Ajusta versão exibida na CLI para usar o novo helper.
packtools/catalogs/init.py Troca iter_entry_points por wrapper para carregamento de plugins de catálogos.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packtools/stylechecker.py Outdated
Comment on lines 162 to 163
packtools_version = packtools.pkg_resources_fixer.get_version('packtools')

Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

packtools is imported, but packtools.pkg_resources_fixer is not. Accessing packtools.pkg_resources_fixer.get_version(...) will raise AttributeError unless the submodule is imported first. Prefer from packtools.pkg_resources_fixer import get_version (or import packtools.pkg_resources_fixer as pkg_resources_fixer) and then call it; also ensure the result is a non-None string because argparse's action='version' will error if version is None.

Copilot uses AI. Check for mistakes.
Comment thread packtools/htmlgenerator.py Outdated
Comment on lines 78 to 79
packtools_version = packtools.pkg_resources_fixer.get_version('packtools')

Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

packtools is imported, but the pkg_resources_fixer submodule is not. packtools.pkg_resources_fixer.get_version(...) will raise AttributeError unless you import the submodule (or import get_version directly). Also make sure the returned value can’t be None, since argparse's version action expects a string.

Copilot uses AI. Check for mistakes.
Comment thread packtools/package_optimiser.py Outdated
Comment on lines 15 to 16
packtools_version = packtools.pkg_resources_fixer.get_version("packtools")

Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

packtools is imported, but the pkg_resources_fixer submodule is never imported. Calling packtools.pkg_resources_fixer.get_version(...) will raise AttributeError unless you import packtools.pkg_resources_fixer (or import get_version directly). Additionally, argparse's version action requires a string; if get_version returns None this will crash.

Copilot uses AI. Check for mistakes.
Comment thread packtools/catalogs/__init__.py Outdated
"""
from pkg_resources import iter_entry_points
for entry_point in iter_entry_points(group=self.group_name, name=None):
from pkg_resources_fixer import get_iter_entry_points
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This import is likely incorrect: pkg_resources_fixer is a module under packtools/, so importing it as a top-level module (from pkg_resources_fixer ...) will fail with ModuleNotFoundError in most installations. Use an absolute import (from packtools.pkg_resources_fixer import get_iter_entry_points) or a relative import (from ..pkg_resources_fixer ...).

Suggested change
from pkg_resources_fixer import get_iter_entry_points
from ..pkg_resources_fixer import get_iter_entry_points

Copilot uses AI. Check for mistakes.
Comment thread packtools/pkg_resources_fixer.py Outdated
Comment on lines +58 to +61
return entry_points(group=group)
except ImportError:
from pkg_resources import iter_entry_points
return iter_entry_points(group=group, name=None) No newline at end of file
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

importlib.metadata.entry_points() in Python 3.9 does not accept the group= keyword, so entry_points(group=group) will raise TypeError (and won’t be caught by the current except ImportError). Also, the name parameter is ignored in both the importlib and pkg_resources branches (name=None is hard-coded). Update this helper to support Python 3.9’s API (entry_points().get(group, []) / .select(...) depending on the returned type) and to filter by name when provided.

Suggested change
return entry_points(group=group)
except ImportError:
from pkg_resources import iter_entry_points
return iter_entry_points(group=group, name=None)
eps = entry_points()
# Python 3.9+ stdlib / backport style: EntryPoints object with .select(...)
if hasattr(eps, "select"):
select_kwargs = {"group": group}
if name is not None:
select_kwargs["name"] = name
return eps.select(**select_kwargs)
# Mapping style: {'group': [EntryPoint, ...], ...}
group_eps = eps.get(group, [])
if name is not None:
return [ep for ep in group_eps if getattr(ep, "name", None) == name]
return group_eps
except ImportError:
from pkg_resources import iter_entry_points
return iter_entry_points(group=group, name=name)

Copilot uses AI. Check for mistakes.
Comment on lines +3 to +34
def get_version(package_name):
"""
Get the version of a package.

Args:
package_name (str): The name of the package.

Returns:
str: The version of the package.

# Antes
from pkg_resources import get_distribution
version = get_distribution("meu-pacote").version

# Depois
from importlib.metadata import version
version = version("meu-pacote")
"""
try:
from importlib.metadata import version
return version(package_name)
except ImportError:
import pkg_resources
try:
return pkg_resources.get_distribution(package_name).version
except pkg_resources.DistributionNotFound:
return None
except Exception:
return None


def get_iter_entry_points(group, name=None):
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New helper module is introduced without automated tests. Adding unit tests for get_version (including the PackageNotFound case) and get_iter_entry_points (including the Python 3.9-compatible code path) would help prevent regressions, since these functions affect multiple CLIs and plugin loading.

Copilot uses AI. Check for mistakes.
Comment on lines +10 to +12
Returns:
str: The version of the package.

Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Docstring says Returns: str, but the function can return None (e.g., when the package isn’t found or on exceptions). Update the docstring/type hint to reflect an optional return, or adjust the implementation to always return a string (e.g., 'unknown').

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +21 to +24
try:
from importlib.metadata import version
return version(package_name)
except ImportError:
Copy link

Copilot AI Feb 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

get_version() can return None (e.g., when importlib.metadata.version() raises PackageNotFoundError), but several CLIs pass its result to argparse's action='version', which can crash when version is not a string. Consider returning a guaranteed string (for example, falling back to packtools.__version__ when querying packtools, or to a sentinel like 'unknown') and update the docstring/return contract accordingly (it currently says it returns str).

Copilot uses AI. Check for mistakes.
Comment on lines +34 to +37
def get_iter_entry_points(group, name=None):
"""
Get the entry points for a given group and name.

Copy link

Copilot AI Feb 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This new compatibility layer is core to version reporting and plugin discovery, but there are no accompanying tests validating behavior across the supported Python versions (3.9+), especially around entry_points() API differences and PackageNotFoundError handling. Adding focused unit tests (with monkeypatching/mocking for importlib.metadata) would help prevent regressions in CLI --version and catalog plugin loading.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 6 out of 6 changed files in this pull request and generated 4 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +22 to +31
from importlib.metadata import version
return version(package_name)
except ImportError:
import pkg_resources
try:
return pkg_resources.get_distribution(package_name).version
except pkg_resources.DistributionNotFound:
return None
except Exception:
return None
Copy link

Copilot AI Feb 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

get_version() catches a broad Exception and returns None, which can hide unexpected failures (e.g., packaging/metadata issues) and make debugging harder. It would be safer to only catch the specific “package not found” exception from importlib.metadata.version (and possibly pkg_resources.DistributionNotFound) while letting other exceptions surface or be logged.

Suggested change
from importlib.metadata import version
return version(package_name)
except ImportError:
import pkg_resources
try:
return pkg_resources.get_distribution(package_name).version
except pkg_resources.DistributionNotFound:
return None
except Exception:
return None
from importlib.metadata import version, PackageNotFoundError
try:
return version(package_name)
except PackageNotFoundError:
return None
except ImportError:
import pkg_resources
try:
return pkg_resources.get_distribution(package_name).version
except pkg_resources.DistributionNotFound:
return None

Copilot uses AI. Check for mistakes.
Comment thread packtools/stylechecker.py
exit_status = 0

packtools_version = pkg_resources.get_distribution('packtools').version
packtools_version = get_version('packtools')
Copy link

Copilot AI Feb 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

packtools_version may become None if distribution metadata isn’t available, but argparse’s action="proxy.php?url=https%3A%2F%2Fgithub.com%2Fversion" expects a string and can crash when formatting the version output. Consider falling back to packtools.__version__ (or a string like "unknown") when get_version('packtools') returns None to keep --version working reliably.

Suggested change
packtools_version = get_version('packtools')
packtools_version = get_version('packtools') or getattr(packtools, '__version__', None) or 'unknown'
packtools_version = str(packtools_version)

Copilot uses AI. Check for mistakes.
def main():

packtools_version = pkg_resources.get_distribution('packtools').version
packtools_version = get_version('packtools')
Copy link

Copilot AI Feb 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

packtools_version may become None if distribution metadata isn’t available, but argparse’s action="proxy.php?url=https%3A%2F%2Fgithub.com%2Fversion" expects a string and can crash when formatting the version output. Consider falling back to packtools.__version__ (or a string like "unknown") when get_version('packtools') returns None to keep --version working reliably.

Suggested change
packtools_version = get_version('packtools')
packtools_version = get_version('packtools')
if packtools_version is None:
packtools_version = getattr(packtools, '__version__', 'unknown')

Copilot uses AI. Check for mistakes.
def main():

packtools_version = pkg_resources.get_distribution("packtools").version
packtools_version = get_version("packtools")
Copy link

Copilot AI Feb 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

packtools_version may become None if distribution metadata isn’t available, but argparse’s action="proxy.php?url=https%3A%2F%2Fgithub.com%2Fversion" expects a string and can crash when formatting the version output. Consider falling back to packtools.__version__ (or a string like "unknown") when get_version('packtools') returns None to keep --version working reliably.

Suggested change
packtools_version = get_version("packtools")
packtools_version = get_version("packtools") or getattr(packtools, "__version__", "unknown")

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.


except ImportError:
from pkg_resources import iter_entry_points
return iter_entry_points(group=group, name=None) No newline at end of file
Copy link

Copilot AI Feb 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The name parameter is hardcoded to None in the fallback call to iter_entry_points, but it should pass through the name parameter from the function signature. This means the name filtering functionality will not work when falling back to pkg_resources. Change name=None to name=name to preserve the intended behavior.

Suggested change
return iter_entry_points(group=group, name=None)
return iter_entry_points(group=group, name=name)

Copilot uses AI. Check for mistakes.
Comment on lines +22 to +33
from importlib.metadata import version
return version(package_name)
except ImportError:
import pkg_resources
try:
return pkg_resources.get_distribution(package_name).version
except pkg_resources.DistributionNotFound:
return None
except Exception:
return None


Copy link

Copilot AI Feb 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The exception handling uses an overly broad except Exception that may hide unexpected errors. In Python 3.8+, importlib.metadata.version() raises PackageNotFoundError when a package is not found. For better error clarity and to avoid masking bugs, consider explicitly catching PackageNotFoundError from importlib.metadata instead of the generic Exception.

Suggested change
from importlib.metadata import version
return version(package_name)
except ImportError:
import pkg_resources
try:
return pkg_resources.get_distribution(package_name).version
except pkg_resources.DistributionNotFound:
return None
except Exception:
return None
from importlib.metadata import version, PackageNotFoundError
try:
return version(package_name)
except PackageNotFoundError:
return None
except ImportError:
import pkg_resources
try:
return pkg_resources.get_distribution(package_name).version
except pkg_resources.DistributionNotFound:
return None

Copilot uses AI. Check for mistakes.

except ImportError:
from pkg_resources import iter_entry_points
return iter_entry_points(group=group, name=None) No newline at end of file
Copy link

Copilot AI Feb 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new pkg_resources_fixer.py module lacks test coverage. Given that this codebase has comprehensive automated testing (as evidenced by the extensive test suite), adding tests for both get_version() and get_iter_entry_points() would ensure the migration from pkg_resources works correctly across different Python versions and edge cases (e.g., missing packages, various entry point configurations).

Suggested change
return iter_entry_points(group=group, name=None)
return iter_entry_points(group=group, name=name)

Copilot uses AI. Check for mistakes.
@robertatakenaka robertatakenaka merged commit 5c786fa into scieloorg:master Feb 16, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants