From ca4be018f3a03e94889c221d27b6f3551d2bd301 Mon Sep 17 00:00:00 2001 From: Kelvin Carvalho Da Silva Date: Fri, 30 May 2025 11:27:09 -0300 Subject: [PATCH 1/2] Adds Cursor rules for Mercado Pago Python SDK Introduces a comprehensive set of Cursor rules for the Mercado Pago Python SDK, defining project structure, coding conventions, development practices, testing guidelines, documentation standards, dependency management, security measures, performance optimizations, version control procedures, code quality tools, internationalization considerations, and maintenance practices. --- .cursor/rules/rules.mdc | 333 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 333 insertions(+) create mode 100644 .cursor/rules/rules.mdc diff --git a/.cursor/rules/rules.mdc b/.cursor/rules/rules.mdc new file mode 100644 index 0000000..d1cbb53 --- /dev/null +++ b/.cursor/rules/rules.mdc @@ -0,0 +1,333 @@ +--- +description: +globs: +alwaysApply: true +--- +# Mercado Pago Python SDK - Cursor Rules + +## Visão Geral do Projeto +Este é o SDK oficial do Mercado Pago para Python, uma biblioteca de processamento de pagamentos que segue as melhores práticas Python (PEP 8, PEP 257) e convenções da comunidade. O SDK é distribuído como um pacote Python e segue uma arquitetura modular com clara separação de responsabilidades. + +## Estrutura e Organização do Projeto + +### Estrutura de Diretórios Principal +``` +mercadopago/ # Pacote principal +├── __init__.py # Inicialização do pacote +├── sdk.py # Classe principal do SDK +├── core/ # Funcionalidades principais +│ ├── __init__.py +│ ├── base_client.py # Cliente base abstrato +│ └── base_resource.py # Recurso base abstrato +├── resources/ # Recursos da API +│ ├── __init__.py +│ ├── payment.py +│ └── order.py +├── http/ # Manipulação HTTP +│ ├── __init__.py +│ ├── http_client.py +│ └── response.py +├── config/ # Configurações +│ ├── __init__.py +│ └── config.py +└── examples/ # Exemplos de uso +tests/ # Testes automatizados +docs/ # Documentação +``` + +## Convenções de Nomenclatura + +### Classes e Módulos +- **Clientes**: `{Resource}Client` (ex: `PaymentClient`, `OrderClient`) +- **Recursos**: `{Resource}` (ex: `Payment`, `Order`) +- **Configuração**: `Config`, `Settings` +- **Exceções**: `{Type}Error` (ex: `ValidationError`, `APIError`) + +### Métodos e Variáveis +- Usar **snake_case** para nomes de métodos e variáveis +- Métodos privados começam com underscore +- Constantes em **SCREAMING_SNAKE_CASE** +- Variáveis de instância sem prefixo especial + +### Arquivos e Diretórios +- Arquivos em **snake_case.py** +- Um módulo por arquivo +- Nomes de arquivo devem corresponder ao módulo principal +- Testes em `test_*.py` + +## Padrões de Código + +### Estilo Python +- Seguir PEP 8 (Guia de Estilo) +- Seguir PEP 257 (Docstrings) +- Usar Black para formatação +- Usar isort para imports +- Usar pylint/flake8 para linting +- Linhas com máximo de 88 caracteres (Black default) + +### Padrões de Cliente +```python +from typing import Dict, Optional + +class PaymentClient(BaseClient): + """Cliente para operações de pagamento.""" + + def create(self, payment_data: Dict, options: Optional[Dict] = None) -> Payment: + """Cria um novo pagamento. + + Args: + payment_data: Dados do pagamento + options: Opções adicionais + + Returns: + Payment: O pagamento criado + + Raises: + ValidationError: Se os dados forem inválidos + APIError: Se houver erro na API + """ + return self.post('/v1/payments', data=payment_data, options=options) +``` + +### Padrões de Recurso +```python +from dataclasses import dataclass +from typing import Optional + +@dataclass +class Payment: + """Representa um pagamento.""" + + id: int + status: str + description: Optional[str] = None + + @property + def is_approved(self) -> bool: + """Verifica se o pagamento foi aprovado.""" + return self.status == 'approved' +``` + +## Práticas de Desenvolvimento + +### Geral +- Usar type hints (PEP 484) +- Preferir dataclasses para modelos +- Usar async/await para operações I/O +- Seguir princípios SOLID +- Documentar com docstrings + +### Tratamento de Erros +```python +class APIError(Exception): + """Erro retornado pela API.""" + + def __init__(self, message: str, status_code: int, details: Dict): + super().__init__(message) + self.status_code = status_code + self.details = details +``` + +### Logging +```python +import logging +from typing import Any + +logger = logging.getLogger(__name__) + +def process_payment(payment_data: Dict[str, Any]) -> None: + """Processa um pagamento com logging apropriado.""" + try: + logger.info("Iniciando processamento de pagamento", extra={"payment_id": payment_data.get("id")}) + # Processamento + logger.info("Pagamento processado com sucesso") + except Exception as e: + logger.error("Erro no processamento do pagamento", exc_info=True) + raise +``` + +## Testes + +### Estrutura de Testes +- Usar pytest como framework +- Organizar testes espelhando a estrutura do código +- Usar fixtures para setup comum +- Implementar testes unitários e de integração + +### Padrões de Teste +```python +import pytest +from unittest.mock import Mock + +def test_payment_creation(): + """Testa a criação de um pagamento.""" + client = PaymentClient(Mock()) + payment_data = {"amount": 100} + + result = client.create(payment_data) + + assert result.id is not None + assert result.status == "pending" + +@pytest.mark.asyncio +async def test_async_payment_creation(): + """Testa a criação assíncrona de um pagamento.""" + client = AsyncPaymentClient(Mock()) + payment_data = {"amount": 100} + + result = await client.create(payment_data) + + assert result.id is not None +``` + +## Documentação + +### Docstrings +- Usar formato Google para docstrings +- Documentar todos os módulos, classes e métodos públicos +- Incluir exemplos de uso +- Documentar tipos com type hints + +```python +def create_payment(amount: float, currency: str = "BRL") -> Payment: + """Cria um novo pagamento. + + Args: + amount: O valor do pagamento + currency: A moeda do pagamento (default: BRL) + + Returns: + Payment: O pagamento criado + + Raises: + ValidationError: Se o valor for negativo + + Example: + >>> payment = create_payment(100.0) + >>> print(payment.status) + 'pending' + """ +``` + +## Gerenciamento de Dependências + +### pyproject.toml +```toml +[tool.poetry] +name = "mercadopago" +version = "2.0.0" +description = "Mercado Pago Python SDK" + +[tool.poetry.dependencies] +python = "^3.7" +requests = "^2.25.0" +pydantic = "^1.8.0" + +[tool.poetry.dev-dependencies] +pytest = "^6.2.0" +black = "^21.5b2" +pylint = "^2.8.0" +``` + +### Compatibilidade +- Suportar Python 3.7+ +- Especificar versões de dependências +- Usar Poetry para gerenciamento +- Testar com diferentes versões Python + +## Segurança + +### Práticas +- Validar todas as entradas +- Sanitizar dados sensíveis +- Usar HTTPS +- Implementar rate limiting +- Seguir OWASP guidelines + +### Dados Sensíveis +```python +import os +from typing import Optional + +class Credentials: + """Gerencia credenciais de forma segura.""" + + def __init__(self): + self._access_token: Optional[str] = None + + @property + def access_token(self) -> str: + """Obtém o token de acesso de forma segura.""" + if not self._access_token: + self._access_token = os.environ.get("MP_ACCESS_TOKEN") + return self._access_token +``` + +## Performance + +### Otimizações +- Usar connection pooling +- Implementar caching +- Otimizar imports +- Usar async/await para I/O + +### Concorrência +```python +import asyncio +from typing import List + +async def process_payments(payments: List[Dict]) -> List[Payment]: + """Processa múltiplos pagamentos concorrentemente.""" + tasks = [process_payment(p) for p in payments] + return await asyncio.gather(*tasks) +``` + +## Controle de Versão + +### Git +- Commits atômicos +- Mensagens descritivas +- Feature branches +- Pull requests + +### Releases +- Semantic Versioning +- CHANGELOG.md +- Release tags +- Documentação de breaking changes + +## Qualidade de Código + +### Ferramentas +- Black para formatação +- Pylint para linting +- Mypy para type checking +- Coverage.py para cobertura + +### CI/CD +- Testes automatizados +- Verificação de tipos +- Análise de código +- Deploy automático + +## Internacionalização + +### i18n +- Usar gettext +- Strings externalizadas +- Suporte a múltiplos idiomas +- Formatação local-aware + +## Manutenção + +### Práticas +- Refatoração contínua +- Remoção de código morto +- Atualização de dependências +- Documentação atualizada + +### Monitoramento +- Logging estruturado +- Métricas de performance +- Rastreamento de erros +- Health checks \ No newline at end of file From c766bef91d548886bd91097dea6a1bf878e6bcd7 Mon Sep 17 00:00:00 2001 From: Manoel Vitor Marcelino Dos Santos Date: Tue, 8 Jul 2025 11:25:06 -0300 Subject: [PATCH 2/2] Ai-Fest PL feat: Updating Curso rules and reorganize folder structure - Update Curso rules to reflect new guidelines - Implement a new folder structure for better organization - Create specific task files for order contract updates --- .cursor/rules/{rules.mdc => architecture.mdc} | 0 .cursor/rules/role_playing.mdc | 86 ++++++++++++++++++ .cursor/tasks/order_request_update.md | 88 +++++++++++++++++++ .cursor/tasks/order_response_update.md | 81 +++++++++++++++++ 4 files changed, 255 insertions(+) rename .cursor/rules/{rules.mdc => architecture.mdc} (100%) create mode 100644 .cursor/rules/role_playing.mdc create mode 100644 .cursor/tasks/order_request_update.md create mode 100644 .cursor/tasks/order_response_update.md diff --git a/.cursor/rules/rules.mdc b/.cursor/rules/architecture.mdc similarity index 100% rename from .cursor/rules/rules.mdc rename to .cursor/rules/architecture.mdc diff --git a/.cursor/rules/role_playing.mdc b/.cursor/rules/role_playing.mdc new file mode 100644 index 0000000..9deefa2 --- /dev/null +++ b/.cursor/rules/role_playing.mdc @@ -0,0 +1,86 @@ +--- +description: +globs: +alwaysApply: false +--- +Você é um especialista em desenvolvimento de software em Python, arquitetura de software e em todas as habilidades envolvidas na construção de software, seja para projetos pequenos ou sistemas de grande escala. + +Sua tarefa será desenvolver novas features e resolver eventuais bugs encontrados quando solicitado. + +Seu raciocínio deve ser minucioso, e não há problema se for muito longo. Você pode pensar passo a passo antes e depois de cada ação que decidir tomar. + +Você DEVE iterar e continuar trabalhando até que o problema seja totalmente resolvido. + +Você já possui tudo o que precisa para resolver o problema com o código-fonte disponível. Quero que você resolva o problema completamente de forma autônoma antes de retornar para mim. + +Só encerre sua ação quando tiver certeza de que o problema foi resolvido. Analise o problema passo a passo e certifique-se de verificar se as suas alterações estão corretas. NUNCA termine sua ação sem ter solucionado o problema, e, caso diga que fará uma chamada de ferramenta (tool call), tenha certeza de REALMENTE fazer essa chamada em vez de encerrar a ação. + +Utilize a Internet para buscar documentações necessárias em caso de dúvidas de implementação. + +Por padrão, sempre utilize a última versão das bibliotecas e dependências que você for instalar. + +Tome o tempo que for necessário e pense cuidadosamente em cada etapa – lembre-se de checar sua solução de forma rigorosa e ficar atento a edge cases, especialmente em relação às alterações realizadas. Sua solução deve ser perfeita. Caso contrário, continue trabalhando nela. Ao final, você deve testar seu código rigorosamente utilizando as ferramentas e regras fornecidas, e repetir os testes várias vezes para capturar todos os edge cases. Se a solução não estiver robusta, itere mais até deixá-la perfeita. Não testar seu código de forma suficientemente rigorosa é a PRINCIPAL causa de falha nesse tipo de tarefa; certifique-se de tratar todos os casos de borda e execute todos os testes existentes, se disponíveis. + +Você DEVE planejar extensivamente antes de cada chamada de função e refletir profundamente sobre os resultados das chamadas anteriores. NÃO realize todo o processo apenas fazendo chamadas de funções, pois isso pode prejudicar sua capacidade de resolver o problema com discernimento. + +# Workflow + +## Estratégia de para desenvolvimento em Alto Nível + +1. Compreenda o problema profundamente. Entenda cuidadosamente o problema apresentado e pense de forma crítica sobre o que é necessário. +2. Verifique se existem pastas chamadas "docs", arquivos README ou outros artefatos que possam ser usados como documentação para entender melhor o projeto, seus objetivos e as decisões técnicas e de produto. Também procure por arquivos individuais referentes ADRs, PRDs, RFCs, documentos de System Design, entre outros, que possam. Se existirem, leia esses artefatos completamente antes de seguir para o próximo passo. +3. Investigue a base de código. Explore os arquivos relevantes, procure por funções-chave e obtenha contexto. +4. Desenvolva um plano de ação claro, passo a passo. Divida em formato de tarefas gerenciáveis e incrementais. +5. Implemente o desenvolvimento de forma incremental. Faça alterações pequenas e testáveis no código. +6. Em caso de erros ou falhas, faça o debug conforme necessário. Utilize técnicas de depuração para isolar e resolver problemas. +7. Teste frequentemente. Execute scripts de testes para verificar se o sistema está funcionando. Esses scripts podem ser testes automatizados ou mesmo scripts avulsos criados exatamente para simular a aplicação. +8. Em caso de bugs, itere até que a causa raiz esteja corrigida e todos os testes passem. +9. Em caso de interrupção pelo usuário com alguma solicitação ou sugestão, entenda sua instrução, contexto, realize a ação solicitada, entenda passo a passo como essa solicitação pode ter impactado suas tarefas e plano de ação. Atualize seu plano de ação e tarefas e continue da onde parou sem voltar a dar o controle ao usuário. +10. Em caso de interrupção pelo usuário com alguma dúvida, de sempre uma explicação clara passo a passo. Após a explicação, pergunte ao usuário se você deve continuar sua tarefa da onde parou. Caso positivo, continue o desenvolvimento da tarefa de forma autônoma sem voltar o controle ao usuário. + +Consulte as seções detalhadas abaixo para mais informações sobre cada etapa. + +## 1. Compreensão Profunda do Problema + +Leia cuidadosamente o problema e pense bastante em um plano de solução antes de começar a codificar. + +## 2. Investigação da Base de Código + +- Explore toda a documentação disponível, lendo e compreendendo cada arquivo para entender o software e seus objetivos passo a passo. Normalmente as documentações podem estar em pastas como docs ou arquivos @Readme.md +- Explore os arquivos e diretórios relevantes. +- Procure funções, classes ou variáveis-chave relacionadas a sua tarefa +- Leia e compreenda trechos relevantes de código. +- Valide e atualize continuamente seu entendimento à medida que obtém mais contexto. + +## 3. Desenvolvimento de um plano de ação + +- Crie um plano de ação claro do que deve ser feito +- Baseado no plano de ação, esboce uma sequência de passos específicos, simples e verificáveis no formato de tarefas + +## 4. Realização de Alterações no Código + +- Antes de fazer qualquer alteração, siga as diretrizes de engenharia se elas estiverem disponíveis na documentação. Também verifique a pasta `.cursor/rules` e siga estritamente as regras ali descritas. +- Antes de editar, sempre leia o conteúdo ou a seção relevante do arquivo para garantir o contexto completo. +- Inicie o desenvolvimento baseado no plano de ação e suas tarefas, passo a passo. +- Antes de ir para a próxima tarefa, garanta que a anterior não gerou bugs ou quebrou os testes. +- Em caso de interrupção pelo usuário, entenda sua instrução, entenda seu contexto, realize a ação solicitada, porém, volte a tarefa continuando da onde estava parado. +- Faça alterações de código apenas se tiver alta confiança de que elas podem resolver o problema. +- Ao debugar, busque identificar a causa raiz em vez de apenas tratar sintomas. +- Faça debugging pelo tempo que for necessário até identificar a causa e a solução. +- Use instruções de impressão, logs ou códigos temporários para inspecionar o estado do programa, incluindo mensagens descritivas ou mensagens de erro para entender o que está acontecendo. Após isso, não esqueça de remover esses logs, instruções e mensagens descritivas que utilizou para entender o problema. +- Para testar hipóteses, adicione declarações ou funções de teste. +- Reavalie seus pressupostos caso comportamentos inesperados ocorram. +- NUNCA crie scripts e arquivos totalmente isolados no projeto apenas para executar testes, provas de conceito, incluindo arquivos .sh, makefiles, entre outros. +- NUNCA faça upgrade ou altere versões de bibliotecas e/ou frameworks utilizados no projeto, mesmo que você não esteja encontrando uma solução. +- Quando for instalar uma dependência utilize sempre sua última versão. Caso ache necessário, consulte a @web para garantir que você realmente está utilizando a última versão. +- Utilize sempre boas práticas de desenvolvimento, como SOLID, Clean Code. +- Evite ao máximo criar complexidades desnecessárias. Mantenha sempre o código simples, claro, objetivo e expressivo. Evite a criação demasiada de Interfaces, porém, não deixe de utilizá-las, principalmente em casos de alto acoplamento entre componentes. + +## 5. Ao responder perguntas técnicas, você: + +- Fornece explicações claras e detalhadas +- Compartilha exemplos de código práticos quando apropriado +- Considera as melhores práticas atuais da indústria +- Menciona possíveis armadilhas ou problemas comuns +- Sugere alternativas quando relevante + diff --git a/.cursor/tasks/order_request_update.md b/.cursor/tasks/order_request_update.md new file mode 100644 index 0000000..1e60817 --- /dev/null +++ b/.cursor/tasks/order_request_update.md @@ -0,0 +1,88 @@ +Com base no JSON fornecido abaixo, execute as seguintes etapas: + +**1. Identificação de Classes Candidatas** +- Localize todos os arquivos que contenham o nome Order e estejam relacionados a "Order". Podem ser arquivos ou pastas, e também podem conter "Create" no nome e/ou terminar com "Request" (exemplo: `Order`,`Request`,`OrderRequest`, `CreateOrderRequest`, `Create_Order`). +- Analise todos os arquivos relacionados + +**2. Análise de Compatibilidade** +- Para cada arquivo identificado no passo 1, determine qual classe possui a estrutura mais semelhante ao contrato definido pelo JSON fornecido. +- Utilize critérios como número de propriedades correspondentes, tipos de dados, e similaridade de nomenclatura. + +**3. Seleção e Verificação** +- Escolha a classe que mais se assemelha ao contrato JSON. +- Realize uma análise mais profunda para confirmar se ela realmente representa o contrato JSON desejado. + +**4. Revisão de Propriedades** +- Liste as propriedades presentes no JSON que estão ausentes na classe selecionada. + +**5. Atualização da Classe** Se a classe identificada no passo 3 estiver desatualizada em relação ao JSON fornecido, atualize-a: + - **Adicione propriedades ausentes:** Inclua todas as propriedades presentes no JSON que não existem na classe. + - **Siga o padrão e regras:** Assegure que as novas propriedades sigam o mesmo padrão de nomenclatura, tipagem e documentação (se houver) utilizado na classe existente. + - **Não remova as propriedades obsoletas:** Marque como obsoletas (nos comentários) as propriedades da classe que não estão no JSON, mas não as remova. + +**6. Registro de Alterações** +- Se o arquivo já existir, atuialize, se não crie um arquivo de log chamado `CHANGELOG_ORDER_REQUEST.md`, documentando todas as alterações com comparações divido entre "antes" e "depois". +- Adicione o Json de Exemplo ao log para documentação. + +## JSON exemplo +{ + "type": "online", + "total_amount": "1000.00", + "external_reference": "ext_ref_1234", + "capture_mode": "automatic_async", + "transactions": { + "payments": [ + { + "amount": "1000.00", + "expiration_time": "P1D", + "payment_method": { + "id": "master", + "type": "credit_card", + "token": "677859ef5f18ea7e3a87c41d02c3fbe3", + "installments": 1, + "statement_descriptor": "LOJA X" + } + } + ] + }, + "processing_mode": "automatic", + "description": "some description", + "payer": { + "entity_type": "individual", + "email": "test_123@testuser.com", + "first_name": "John", + "last_name": "Doe", + "identification": { + "type": "CPF", + "number": "15635614680" + }, + "phone": { + "area_code": "55", + "number": "99999999999" + }, + "address": { + "street_name": "R. Ângelo Piva", + "street_number": "144", + "zip_code": "06210110", + "neighborhood": "Presidente Altino", + "city": "Osasco", + "state": "SP", + "complement": "303" + } + }, + "marketplace": "NONE", + "marketplace_fee": "10.00", + "items": [ + { + "title": "Some item title", + "unit_price": "1000.00", + "quantity": 1, + "description": "Some item description", + "external_code": "item_external_code", + "category_id": "category_id", + "type": "item type", + "picture_url": "https://mysite.com/img/item.jpg" + } + ], + "expiration_time": "P3D" +} \ No newline at end of file diff --git a/.cursor/tasks/order_response_update.md b/.cursor/tasks/order_response_update.md new file mode 100644 index 0000000..5f5e769 --- /dev/null +++ b/.cursor/tasks/order_response_update.md @@ -0,0 +1,81 @@ +Com base no JSON fornecido abaixo, execute as seguintes etapas: + +**1. Identificação de Classes Candidatas** +- Localize todos os arquivos relacionados a "Order" que terminem com "Request" (exemplo: `Response`,`OrderResponse`, `CreateOrderResponse`). +- Analise todos os arquivos relacionados + +**2. Análise de Compatibilidade** +- Para cada arquivo identificado no passo 1, determine qual classe possui a estrutura mais semelhante ao contrato definido pelo JSON fornecido. +- Utilize critérios como número de propriedades correspondentes, tipos de dados, e similaridade de nomenclatura. + +**3. Seleção e Verificação** +- Escolha a classe que mais se assemelha ao contrato JSON. +- Realize uma análise mais profunda para confirmar se ela realmente representa o contrato JSON desejado. + +**4. Revisão de Propriedades** +- Liste as propriedades presentes no JSON que estão ausentes na classe selecionada. + +**5. Atualização da Classe** Se a classe identificada no passo 3 estiver desatualizada em relação ao JSON fornecido, atualize-a: + - **Adicione propriedades ausentes:** Inclua todas as propriedades presentes no JSON que não existem na classe. + - **Siga o padrão e regras:** Assegure que as novas propriedades sigam o mesmo padrão de nomenclatura, tipagem e documentação (se houver) utilizado na classe existente. + - **Não remova as propriedades obsoletas:** Marque como obsoletas (nos comentários) as propriedades da classe que não estão no JSON, mas não as remova. + +**6. Registro de Alterações** +- Se o arquivo já existir, atuialize, se não crie um arquivo de log chamado `CHANGELOG_ORDER_RESPONSE.md`, documentando todas as alterações com comparações divido entre "antes" e "depois". +- Adicione o Json de Exemplo ao log para documentação. + +## JSON exemplo +{ + "id": "ORD01HRYFWNYRE1MR1E60MW3X0T2P", + "type": "online", + "processing_mode": "automatic", + "external_reference": "ext_ref_1234", + "description": "some description", + "marketplace": "NONE", + "marketplace_fee": "10.00", + "total_amount": "1000.00", + "total_paid_amount": "1000.00", + "country_code": "BRA", + "user_id": "1245621468", + "status": "processed", + "status_detail": "accredited", + "capture_mode": "automatic_async", + "created_date": "2024-11-21T14:19:14.727Z", + "last_updated_date": "2024-11-21T14:19:18.489Z", + "integration_data": { + "application_id": "130106526144588" + }, + "transactions": { + "payments": [ + { + "id": "PAY01JD7HETD7WX4W31VA60R1KC8E", + "amount": "1000.00", + "paid_amount": "1000.00", + "expiration_time": "P1D", + "date_of_expiration": "2024-01-01T00:00:00.000-03:00", + "reference_id": "22dvqmsf4yc", + "status": "processed", + "status_detail": "accredited", + "payment_method": { + "id": "master", + "type": "credit_card", + "token": "677859ef5f18ea7e3a87c41d02c3fbe3", + "statement_descriptor": "LOJA X", + "installments": 1 + } + } + ] + }, + "items":[ + { + "external_code": "item_external_code", + "category_id": "category_id", + "title": "Some item title", + "description": "Some item description", + "unit_price": "1000.00", + "type": "item type", + "picture_url": "https://mysite.com/img/item.jpg", + "quantity": 1 + } + ] +} \ No newline at end of file