FakeNumDetect
FakeNumDetect é uma biblioteca Python, em desenvolvimento, para apontar indícios de dados numéricos fabricados ou manipulados, combinando testes estatísticos de forense numérica e modelos de Machine Learning.
Projeto de Trabalho de Conclusão de Curso (TCC2, SENAC). O TCC1 definiu a proposta e a fundamentação; o TCC2 é a etapa de implementação e validação experimental.
Importante: um resultado "suspeito" da FakeNumDetect é um indício estatístico que merece investigação, e não uma prova de fraude ou fabricação.
Status do projeto
Em desenvolvimento. o que ja tem hoje:
| Parte | Situação |
|---|---|
| Testes estatísticos: Benford (1º e 2º dígito), GRIM, SPRITE, entropia de Shannon, terminação de dígitos | ✅ implementados e testados |
| Machine Learning: Isolation Forest e Sparse Autoencoder | ✅ implementados, calibrados e avaliados em 4 datasets reais |
| Score de suspeição unificado por registro (0 a 100, pesos calibrados por regressão logística L2) | ✅ implementado (combina Isolation Forest, Sparse Autoencoder e Benford) |
| Análise por coluna com correção de múltiplas comparações (Bonferroni e Benjamini-Hochberg) | ✅ implementada |
Consistência do arredondamento entre colunas comparáveis (comparar_arredondamento) |
✅ implementada; indica que colunas não combinam, mas não qual delas é a fabricada |
| Avaliação: métricas, validação cruzada, Wilcoxon, bootstrap, Friedman | ✅ implementada |
| Relatório em HTML com gráficos (registros e colunas) | ✅ implementado; o PDF é gerado pelo "Imprimir > Salvar como PDF" do navegador |
API única no estilo scikit-learn (fit/detect/report, classe FakeNumDetect) |
✅ implementada; encadeia os módulos no mesmo caminho da validação cruzada |
Empacotamento e integração contínua (pyproject.toml, GitHub Actions em Python 3.10 e 3.13, cobertura mínima de 90%) |
✅ configurados; pacote validado com twine check e testado instalado fora do repositório |
| Publicação no PyPI | ⏳ pacote pronto; falta o envio pela conta da autora |
Como a biblioteca analisa os dados
A FakeNumDetect trabalha em dois níveis:
- Por registro (linha): o score de suspeição unificado combina Isolation Forest, Sparse Autoencoder e um score de Benford por registro. Responde quais linhas são suspeitas.
- Por coluna: Benford e terminação de dígitos são aplicados a cada coluna, com correção para múltiplas comparações. Responde quais colunas parecem ter valores fabricados.
GRIM e SPRITE ficam disponíveis como funções independentes: eles verificam médias e desvios-padrão reportados (por exemplo, numa tabela de um artigo), e não dados brutos. Com as médias publicadas em três artigos de pizza do Cornell Food and Brand Lab, o GRIM concordou com o julgamento de especialistas (van der Zee, Anaya e Brown, 2017) em 96 de 97 médias, e o SPRITE recusou os 13 desvios-padrão que eles apontaram como impossíveis. Num cenário sintético com verdade matemática conhecida (escala de 1 a 5, n de 10 a 50), nenhum dos 400 casos honestos foi acusado, e as duas técnicas pegaram todas as 170 estatísticas retocadas à mão que ficaram impossíveis (85% das 200 simuladas).
A terminação de dígitos também tem um score por registro (terminacao_record_suspicion_score), que compara o último dígito de cada valor com a frequência observada nos dados de referência. Ele não entra no score unificado; foi avaliado à parte e só ajudou nos dados do seguro (ver Principais resultados).
Estrutura do repositório
FakeNumDetect/
├── fakenumdetect/ # código-fonte da biblioteca
│ ├── estatisticas/ # Benford, GRIM, SPRITE, Shannon, terminação de dígitos, análise por coluna
│ ├── ml/ # Isolation Forest e Sparse Autoencoder
│ ├── preprocessamento/ # DatasetBundle, divisões treino/validação/teste, k-fold, carregadores dos datasets
│ ├── pontuacao/ # score de suspeição unificado e ensembles
│ ├── avaliacao/ # métricas, comparação estatística, correção de múltiplas comparações
│ ├── relatorio/ # geração do relatório em HTML
│ ├── api/ # classe FakeNumDetect (fit, detect, report)
│ └── ModuleExcecoes.py # erros com nome próprio da biblioteca
├── tests/ # testes automatizados (pytest), com dados reais em tests/fixtures/
├── experiments/ # scripts que reproduzem os experimentos do TCC2 (e o download verificado dos dados)
├── exemplos/ # notebook de uso (Google Colab ou Jupyter)
├── results/ # resultados dos experimentos (.jsonl)
├── .github/workflows/ # integração contínua (testes e cobertura mínima de 90%)
├── pyproject.toml # empacotamento da biblioteca (versões mínimas)
├── requirements.txt # ambiente exato dos resultados (versões fixas)
└── README.md
As pastas datasets/ e models/ existem localmente e ficam fora do Git.
Instalação
Requer Python 3.10 ou superior (desenvolvido com 3.13).
Depois da publicação no PyPI:
pip install fakenumdetect
Instalação (ambiente de desenvolvimento)
Requer Python 3.10 ou superior (desenvolvido com 3.13).
git clone https://github.com/GiPaiva/FakeNumDetect.git
cd FakeNumDetect
python -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
pip install -r requirements.txt
O requirements.txt fixa as versões exatas do ambiente em que os testes e os resultados de results/ foram gerados (Python 3.13.7), incluindo o PyOD, usado só num experimento. O pyproject.toml, usado por pip install fakenumdetect, aceita versões mais novas, para a biblioteca não entrar em conflito com outros pacotes do projeto de quem a usa.
Para rodar os testes:
python -m pytest -q
Para medir a cobertura de testes da biblioteca (linhas e ramos):
python -m pytest -q --cov=fakenumdetect --cov-branch --cov-report=term-missing
Cobertura atual: 97% (354 testes, medida com o comando acima).
Exemplos de uso
Os exemplos usam arquivos reais que já estão em tests/fixtures/.
Uso rápido: fit, detect e report
from fakenumdetect import FakeNumDetect
from fakenumdetect.preprocessamento.ModuleLoaderADBench import load_adbench
bundle = load_adbench("tests/fixtures/4_breastw.npz")
det = FakeNumDetect().fit(bundle.X_train) # referência: só registros genuínos
res = det.detect(bundle.X_test)
print(res.registros.head(3)) # scores 0 a 100 por técnica, score unificado e sinalização
print(res.registros["sinalizado"].sum(), "de", len(res.registros), "registros sinalizados") # 227 de 328
print(res.colunas["colunas_suspeitas"]) # []
det.report(res, "relatorio.html")
fit(X)recebe dados de referência que você acredita serem genuínos (matriz ouDataFrame, sem valores ausentes). Ele treina o Isolation Forest (com os valores do artigo original: 100 árvores, subamostra de até 256 registros econtamination="auto") e o Sparse Autoencoder, a normalização de cada técnica e o limiar (percentil 95 do score unificado numa parte da referência separada para validação).- Por padrão, as técnicas são combinadas pela média simples. Se você tiver dados rotulados (1 = fabricado, com as duas classes),
fit(X, X_cal=..., y_cal=...)calibra os pesos por regressão logística. detect(X)devolveregistros(umDataFramecom o mesmo índice da entrada),limiar,colunas(análise por coluna) e, comcolunas_comparaveis=[["col_a", "col_b"]],arredondamento(consistência do arredondamento entre essas colunas).report(res, caminho)gera o relatório em HTML.res.laudo["tabela"]: o laudo do lote com as 7 técnicas. Cada uma diz quanto suspeita do lote inteiro (0 a 100) ou por que não se aplica, e a linha "Juntas" combina as que opinaram (correção de Simes). GRIM e SPRITE entram comdet.detect(dados, estatisticas_publicadas=tabela)(colunasmedia,n,dp,minimo,maximo; média e DP como texto). Dois botões de 0 a 5:confianca_referencia(5 = comparar com os dados de referência; 0 = com a Lei de Benford e finais uniformes) erigor(5 = aceita 5% de alarme falso; 0 = 0,1%). Escolha os dois antes de olhar o resultado. No experimento (run_laudo.py), o laudo separou sem erro a fabricação real do seguro, mas não superou a melhor técnica individual nas fabricações simuladas do JarFraud e, com valores inventados, ficou significativamente abaixo do teste de Benford.- Erros de dado têm nome próprio (
EmptyDataError,InsufficientDataError,InvalidDataTypeError,BenfordInapplicableError,NoApplicableTechniqueError), importáveis defakenumdetect. Todos herdam deFakeNumDetectError(e deValueError):except FakeNumDetectErrortrata qualquer problema no dado. - Opcional:
FakeNumDetect(regras_aplicabilidade=True)tira da nota por registro as técnicas que não se aplicam ao tipo de dado (regra do TCC1): o Benford só usa as colunas cujos números variam pelo menos 2 ordens de grandeza, e o Autoencoder exige 2 colunas ou mais. O resultado informa as técnicas usadas e as excluídas (res.tecnicas), e o relatório também. Na validação cruzada, a regra não melhorou a nota em nenhum dos 4 datasets e piorou a média ponderada no AcademicAnomaly; por isso é opção, e não padrão.
Para usar no Google Colab ou no Jupyter, abra o notebook exemplos/uso_fakenumdetect.ipynb: ele instala a biblioteca, roda os três passos com um conjunto de dados real que já vem no scikit-learn, mostra o relatório dentro do notebook e traz uma seção para enviar o seu próprio CSV.
Cuidados, vindos dos experimentos: a referência precisa ser genuína (registros fabricados no treino prejudicam muito o autoencoder); o limiar do percentil 95 sinaliza, por construção, cerca de 5% dos registros genuínos; e os testes de dígitos indicam desvio de uma distribuição de referência, não fabricação.
Teste de Benford em uma coluna
import numpy as np
from fakenumdetect.estatisticas.ModuleBenford import analyze_first_digit
dados = np.load("tests/fixtures/jarfraud_colunas_amostra.npz")
vendas = dados["X"][:, list(dados["feature_names"]).index("sale")]
r = analyze_first_digit(vendas)
print(r["p_value"], r["mad"], r["conformity"]) # p ~0.09, MAD ~0.0035, "close conformity"
print(r["digitos_desviantes"]) # estatística Z por dígito: [{"digito": 7, "direcao": "excesso", ...}]
Análise por coluna com correção de múltiplas comparações
import numpy as np
from fakenumdetect.estatisticas.ModuleAnaliseColunas import analisar_colunas
dados = np.load("tests/fixtures/jarfraud_colunas_amostra.npz")
r = analisar_colunas(dados["X"], list(dados["feature_names"]), correcao="bh")
print(r["colunas_suspeitas"]) # [] : dados contábeis reais seguem Benford
for c in r["colunas"]:
print(c["nome"], c["benford"]["conformidade"], c["suspeita"])
Por padrão, uma coluna só é sinalizada quando o p-valor corrigido é significativo e o MAD indica desvio relevante (faixas de Nigrini). Isso evita sinalizar colunas genuínas em amostras grandes, onde o qui-quadrado rejeita desvios minúsculos. Quando o Benford se aplica, o resultado também lista os dígitos que se afastam do esperado (c["benford"]["digitos_desviantes"], estatística Z de Nigrini com correção BH entre os dígitos); essa lista explica o desvio, mas não decide a suspeita. Cada teste só é aplicado quando faz sentido para a coluna (por exemplo, Benford exige valores que cubram pelo menos duas ordens de grandeza).
Score de suspeição de um registro com Isolation Forest
from fakenumdetect.preprocessamento.ModuleLoaderADBench import load_adbench
from fakenumdetect.ml.ModuleIsolationForest import calibrate_isolation_forest, raw_suspicion_score
bundle = load_adbench("tests/fixtures/4_breastw.npz")
modelo = calibrate_isolation_forest(bundle.X_train, bundle.X_val)["model"]
scores = raw_suspicion_score(modelo, bundle.X_test) # quanto maior, mais suspeito
O fluxo completo do score unificado (normalização de cada técnica para 0 a 100, calibração de pesos e limiar) é o que a classe FakeNumDetect faz; a versão usada na validação cruzada está em experiments/run_kfold_comparacao.py.
Relatório em HTML
import numpy as np
from fakenumdetect.estatisticas.ModuleAnaliseColunas import analisar_colunas
from fakenumdetect.relatorio.ModuleRelatorio import gerar_relatorio_html
dados = np.load("tests/fixtures/jarfraud_colunas_amostra.npz")
analise = analisar_colunas(dados["X"], list(dados["feature_names"]))
gerar_relatorio_html("relatorio.html", analise_colunas=analise)
O relatório também aceita o score unificado de cada registro (scores_registros, escala 0 a 100) e o limiar (limiar_registros). O resultado é um único arquivo HTML, com os gráficos embutidos, que abre em qualquer navegador. Para ver o fluxo inteiro sobre um dataset real (treinar os modelos, calcular o score, analisar as colunas e gerar o relatório):
python experiments/run_relatorio_exemplo.py 4_breastw
O relatório é salvo em results/relatorios/.
Datasets usados nos experimentos
| Dataset | Origem | Onde fica |
|---|---|---|
4_breastw |
ADBench (Han et al., 2022) | tests/fixtures/4_breastw.npz |
AcademicAnomaly |
macrOData | tests/fixtures/AcademicAnomaly.npz |
| FakeData | Bradshaw e Payne (2021), GitHub MSBradshaw/FakeData | baixado para a pasta temporária do sistema |
| JarFraud | Bao et al. (2020), GitHub JarFraud/FraudDetection | baixado para a pasta temporária do sistema |
| Seguro (Shu et al., 2012) | Data Colada #98, ResearchBox #336 (CC BY 4.0) | datasets/seguro_shu2012/ (amostra de 400 linhas em tests/fixtures/shu2012_amostra.xlsx) |
O dataset do seguro é o único com fabricação real e verdade conhecida por coluna: o artigo foi retratado em 2021, e o Data Colada mostrou quais valores foram fabricados (a fonte do Excel separa os registros originais das cópias). Ele é uma validação à parte e não entra no Friedman nem na correção múltipla do estudo principal. Baixe DrivingdataAll with font.xlsx de https://researchbox.org/336 para datasets/seguro_shu2012/.
FakeData e JarFraud são baixados das fontes oficiais automaticamente, na primeira vez em que um experimento precisa deles (experiments/ModuleCacheDados.py). Antes de reaproveitar o arquivo da pasta temporária, o script confere o SHA-256 com o dos arquivos que geraram results/: se o arquivo estiver incompleto, ele é baixado de novo; se o arquivo de origem tiver mudado, o script para com erro, em vez de rodar com outro dado.
Reproduzindo os experimentos
Os scripts gravam resultados em results/*.jsonl acrescentando linhas. Para refazer um experimento do zero, apague antes o .jsonl correspondente. A ordem importa, porque alguns scripts leem resultados de outros:
- Divisão única:
run_isolation_forest_<dataset>.pyerun_autoencoder_<dataset>.py - Escolha da esparsidade do autoencoder:
run_escolha_esparsidade.py <dataset> - Validação cruzada:
run_kfold_comparacao.py <dataset>para os 4 datasets e depoisrun_kfold_comparacao.py friedmanerun_kfold_comparacao.py correcao(Benjamini-Hochberg e Bonferroni sobre as 32 comparações) Regra de aplicabilidade por registro (opcional):run_kfold_comparacao.py aplicabilidade <dataset>para os 4 datasets e depoisrun_kfold_comparacao.py resumo_aplicabilidade. Validação cruzada repetida com 10 sementes (F1, PR-AUC, MCC e especificidade):run_kfold_comparacao.py sementes <dataset>para os 4 datasets e depoisrun_kfold_comparacao.py resumo_sementes. - Sensibilidade (usam os pesos do passo 3):
run_sensibilidade_pesos.py <dataset>erun_sensibilidade_limiar.py <dataset>; sensibilidade do autoencoder à contaminação do treino:run_sensibilidade_contaminacao_ae.py <dataset>e, em seguida, as estratégias de mitigação:run_mitigacao_contaminacao_ae.py <dataset>(só4_breastweAcademicAnomaly) - Análise por coluna:
run_analise_colunas.py descritivo,run_analise_colunas.py injecaoerun_analise_colunas.py z(estatística Z por dígito); aplicabilidade das 7 técnicas em cada base:run_analise_colunas.py tecnicas; checagem do artefato de precisão do FakeData:run_artefato_precisao_fakedata.py - Relatório de exemplo (usa os pesos do passo 3):
run_relatorio_exemplo.py <dataset> - Validação com fabricação real (seguro):
run_seguro_shu2012.py colunaserun_seguro_shu2012.py registro; consistência do arredondamento:run_consistencia_arredondamento.py seguro,alarme_falsoepoder - GRIM e SPRITE com estatísticas publicadas:
run_grim_sprite_pizza.py(lêtests/fixtures/grim_pizza_wansink.csv, não precisa baixar nada) - Laudo do lote com as 7 técnicas:
run_laudo.py seguroerun_laudo.py jarfraud - Terminação de dígitos por registro:
run_terminacao_registro.py <dataset>(aceita tambémshu2012) e depoisrun_terminacao_registro.py resumo - GRIM e SPRITE em cenário sintético:
run_grim_sprite_sintetico.py(não precisa baixar nada) - Custo do critério de escolha da arquitetura do autoencoder:
run_sensibilidade_arquitetura_ae.py <dataset>para os 4 datasets e depoisrun_sensibilidade_arquitetura_ae.py resumo - Referências de comparação (acaso, z-score e PyOD) nos mesmos folds:
run_baselines.py <dataset>para os 4 datasets,run_baselines.py pyod_ae <dataset>(autoencoder do PyOD),run_baselines.py temporal(JarFraud com divisão temporal) e depoisrun_baselines.py resumo. O PyOD só é usado nesse experimento e não é dependência da biblioteca (está norequirements.txt, mas não nopyproject.toml)
Os nomes de dataset aceitos são 4_breastw, AcademicAnomaly, fakedata_real_experiment e jarfraud_full_experiment_clean.
Principais resultados até agora
- Nenhuma técnica isolada funciona bem em todos os domínios: o F1 médio da melhor técnica vai de cerca de 0,93 (breastw) a 0,03 (JarFraud).
- O score unificado ponderado teve o maior F1 médio em 2 dos 4 datasets e ficou ligeiramente abaixo da melhor técnica nos outros 2, mas não superou a melhor técnica individual com significância estatística em nenhum deles. No nível de registro, a hipótese central do TCC recebe apoio parcial, e não confirmação. A conclusão se manteve ao repetir a validação cruzada com 10 sementes.
- A forma de combinar importa: a média ponderada com pesos calibrados foi melhor que a média simples em todos os datasets.
- Na análise por coluna, as regras de aplicabilidade evitam que 100% das colunas sejam sinalizadas por serem de um tipo inadequado, e o critério combinado de p-valor e MAD reduz os falsos positivos para menos de 10%.
- A terminação de dígitos por registro só se aplica a dados com valores grandes (≥ 1000). Nos dados do seguro, onde o sinal da fabricação é a falta do arredondamento humano, ela separou os registros fabricados acima do acaso (PR-AUC 0,334 contra 0,250); no JarFraud, a diferença foi irrelevante, e no breastw e no FakeData ela não se aplica.
A discussão completa, com tabelas e limitações, está no texto do TCC2.
Limitações conhecidas
- A análise foi validada em 4 datasets; em nenhum deles há rótulo de fabricação por coluna, então a análise por coluna foi validada com fabricação simulada sobre dados reais.
- No arquivo do FakeData, as amostras reais têm 2 casas decimais e as fabricadas têm precisão cheia, o que por si só separa as classes. Isolation Forest e Autoencoder não dependem disso (o F1 não muda com os fabricados arredondados), mas o artefato impede validar a análise por coluna com esses rótulos.
- Na única validação com fabricação real e verdade conhecida por coluna (dados do seguro de Shu et al., 2012), os testes de dígitos sinalizaram todas as colunas genuínas e só 5 das 12 fabricadas: os dados genuínos têm arredondamento humano, e os fabricados, gerados por computador, têm dígitos uniformes. No nível de registro, nenhuma técnica distinguiu as cópias (PR-AUC igual ao do acaso). Os testes detectam desvio de uma distribuição de referência, o que não é o mesmo que detectar fabricação. O teste de consistência do arredondamento entre colunas, criado a partir desse caso (e por isso validado em outros dados: alarme falso de 2,3%), pega esse tipo de inconsistência, mas não diz qual coluna é a fabricada e não vê nada quando todas foram fabricadas do mesmo jeito.
- Fabricações pequenas (poucos por cento dos valores de uma coluna) são difíceis de detectar pelos testes de dígitos.
- O SPRITE é uma busca heurística: "não encontrei uma amostra" é indício, e não prova. Nos artigos de pizza, ele não encontrava amostra para um desvio-padrão que uma verificação exata mostrou ser possível; a causa era um defeito no sorteio da busca, já corrigido, e agora ele encontra amostra para os 34 desvios-padrão possíveis. O GRIM arredonda empates exatos (como 2,675) para cima ou para o par, e por isso acusa uma média que os especialistas, mais conservadores, aceitaram.
- Uma coluna inteiramente inventada com valores uniformes pode ser declarada "não aplicável" para Benford e escapar da análise por coluna.
- Na divisão única, a prevalência do teste fica acima da prevalência da base (todas as anomalias vão para o teste), o que infla F1 e PR-AUC; as comparações entre técnicas usam a validação cruzada, que preserva a prevalência.
- Um z-score univariado igualou o score combinado no FakeData, e, no JarFraud com divisão temporal (treino até 2001, teste de 2003 a 2008), nenhuma técnica superou o acaso (
run_baselines.py). - O autoencoder padrão do PyOD superou o autoencoder da FakeNumDetect nas 4 bases e, sozinho, igualou ou superou o score combinado no AcademicAnomaly e no FakeData; a revisão do autoencoder fica como trabalho futuro.
- No FakeData, a validação de cada fold tem só 4 registros, e o limiar no percentil 95 fica instável; ali, o PR-AUC é a métrica confiável.
- A arquitetura e a esparsidade do autoencoder foram calibradas uma vez e reutilizadas em todos os folds da validação cruzada. O Isolation Forest usa os valores do artigo original (100 árvores, subamostra de até 256 registros); uma versão anterior escolhia esses valores e a
contaminationpor um critério sem relação com a detecção, e a troca não mudou nenhuma conclusão. - A arquitetura do autoencoder é escolhida pela menor perda de reconstrução na validação, critério que não mede a detecção e tende a premiar redes maiores. Com as grades usadas, o custo foi desprezível: a diferença média de PR-AUC para a melhor arquitetura da grade ficou abaixo de 0,005 nos 4 datasets (
run_sensibilidade_arquitetura_ae.py). - O autoencoder pode ser muito sensível a registros fabricados que entrem no treino: no AcademicAnomaly, 5% de contaminação derrubou o F1 em 36,5%. As mitigações previstas no TCC1 (mais regularização e ensemble de autoencoders por votação majoritária, disponível em
treinar_ensemble_autoencoders) foram testadas e não resolveram o problema: nenhuma superou o autoencoder original com o treino contaminado. O aparamento iterativo do treino (treinar_autoencoder_aparado, fora do TCC1) foi o melhor com 5% de contaminação (F1 0,453 contra 0,392), mas também ficou longe do critério, porque remove cerca de 9% do treino mesmo quando ele está limpo e custa desempenho no caso sem contaminação (F1 0,617 para 0,491).
Autora
Giovanna Paiva Alves. Desenvolvido como Trabalho de Conclusão de Curso no SENAC.
Licença
MIT. Veja o arquivo LICENSE.
Metadata
Release files for fakenumdetect 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| fakenumdetect-0.1.0.tar.gz | 130.1 kB | Without provenance | Details for fakenumdetect-0.1.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| fakenumdetect-0.1.0-py3-none-any.whl | Python 3 | none | any | Details for fakenumdetect-0.1.0-py3-none-any.whl |
Total release size: 222.9 kB
Release files / fakenumdetect-0.1.0.tar.gz
| Download URL | fakenumdetect-0.1.0.tar.gz |
|---|---|
| Size | 130.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
81326b56c342ec121905aecb3ca5acdb99748b6f2284d1d84b0d63af8eb1be7f
|
|
BLAKE2b-256 checksum How to use checksums |
133fa6f5497f924de7b32e46a5a15d7f8a09ebe96b86bcb7bdd0d9fb2dc6d1df
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.7
|
Release files / fakenumdetect-0.1.0-py3-none-any.whl
| Download URL | fakenumdetect-0.1.0-py3-none-any.whl |
|---|---|
| Size | 92.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
d81df1b09cb805e84af5395894199fae18706bb1109dec1b683cc11cae8bc69b
|
|
BLAKE2b-256 checksum How to use checksums |
e616e10198d4376336e4b3d36682cc77d3e1263e40e7cb37a352318d0298f1ff
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.7
|
Security for fakenumdetect 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.