Compare commits
16
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
61086e0b9b | ||
|
|
ce53920340 | ||
|
|
78c5c56220 | ||
|
|
873303661a | ||
|
|
0a8775dfc9 | ||
|
|
015eebd6ed | ||
|
|
3df8cfffc7 | ||
|
|
85a1c47c8c | ||
|
|
f91384173b | ||
|
|
f253115e62 | ||
|
|
75c96efc76 | ||
|
|
15a937e39c | ||
|
|
d1deaad03f | ||
|
|
4df2bab348 | ||
|
|
d5b9018ef2 | ||
|
|
b387fec2b3 |
@@ -9,3 +9,4 @@ coverage.xml
|
|||||||
build
|
build
|
||||||
dist
|
dist
|
||||||
.pytest_cache
|
.pytest_cache
|
||||||
|
words.txt
|
||||||
|
|||||||
@@ -18,22 +18,22 @@ OPEN ?= xdg-open
|
|||||||
|
|
||||||
.PHONY: help
|
.PHONY: help
|
||||||
help: ## show this message
|
help: ## show this message
|
||||||
@echo "Usage: $(MAKE) [target1] [target2] ..."
|
echo "Usage: $(MAKE) [target1] [target2] ..."
|
||||||
@echo ""
|
echo ""
|
||||||
@echo "Commands/Targets:"
|
echo "Commands/Targets:"
|
||||||
@cat $(MAKEFILE_LIST) | grep -E '(^[a-zA-Z0-9_%-]+:.*?##.*$$)|(^##)' | awk 'BEGIN {FS = ":.*?## "}{printf "\033[32m%-20s\033[0m %s\n", $$1, $$2}' | sed -e 's/\[32m##/[33m/'
|
cat $(MAKEFILE_LIST) | grep -E '(^[a-zA-Z0-9_%-]+:.*?##.*$$)|(^##)' | awk 'BEGIN {FS = ":.*?## "}{printf "\033[32m%-20s\033[0m %s\n", $$1, $$2}' | sed -e 's/\[32m##/[33m/'
|
||||||
@echo ""
|
echo ""
|
||||||
@echo "Environment:"
|
echo "Environment:"
|
||||||
@cat $(MAKEFILE_LIST) | grep -E '^[a-zA-Z0-9_-]+\s*\??=.*$$' | grep -Eo '^[a-zA-Z0-9_-]+' | xargs -I {} $(MAKE) -s print-{} 2> /dev/null
|
cat $(MAKEFILE_LIST) | grep -E '^[a-zA-Z0-9_-]+\s*\??=.*$$' | grep -Eo '^[a-zA-Z0-9_-]+' | xargs -I {} $(MAKE) -s print-{} 2> /dev/null
|
||||||
|
|
||||||
.PHONY: print-%
|
.PHONY: print-%
|
||||||
print-%:
|
print-%:
|
||||||
@echo -e '\033[32m$*\033[0m = $($*)'
|
echo -e '\033[32m$*\033[0m = $($*)'
|
||||||
|
|
||||||
# FILES
|
# FILES
|
||||||
|
|
||||||
.venv: uv.lock
|
.venv: uv.lock
|
||||||
@$(MAKE) -s uv-sync
|
$(MAKE) -s uv-sync
|
||||||
|
|
||||||
# ACTIONS
|
# ACTIONS
|
||||||
|
|
||||||
@@ -57,7 +57,7 @@ test: unittest ## test project
|
|||||||
|
|
||||||
.PHONY: test-%
|
.PHONY: test-%
|
||||||
test-%: ## test project with specific test
|
test-%: ## test project with specific test
|
||||||
@$(MAKE) -s unittest-$*
|
$(MAKE) -s unittest-$*
|
||||||
|
|
||||||
.PHONY: coverage
|
.PHONY: coverage
|
||||||
coverage: coverage-unittest coverage-xml coverage-report ## test project with coverage
|
coverage: coverage-unittest coverage-xml coverage-report ## test project with coverage
|
||||||
@@ -66,53 +66,61 @@ coverage: coverage-unittest coverage-xml coverage-report ## test project with co
|
|||||||
|
|
||||||
.PHONY: uv-sync
|
.PHONY: uv-sync
|
||||||
uv-sync: ## uv sync
|
uv-sync: ## uv sync
|
||||||
@$(UV) sync --active
|
$(UV) sync --active
|
||||||
|
|
||||||
.PHONY: uv-update
|
.PHONY: uv-update
|
||||||
uv-upgrade: ## uv sync upgrade
|
uv-upgrade: ## uv sync upgrade
|
||||||
@$(UV) sync --active --upgrade
|
$(UV) sync --active --upgrade
|
||||||
|
|
||||||
.PHONY: ruff
|
.PHONY: ruff
|
||||||
ruff: .venv ## ruff check
|
ruff: .venv ## ruff check
|
||||||
@$(RUFF) check
|
$(RUFF) check
|
||||||
|
|
||||||
.PHONY: ruff-fix
|
.PHONY: ruff-fix
|
||||||
ruff-fix: .venv ## ruff check (and fix)
|
ruff-fix: .venv ## ruff check (and fix)
|
||||||
@$(RUFF) check --fix --unsafe-fixes
|
$(RUFF) check --fix --unsafe-fixes
|
||||||
|
|
||||||
.PHONY: ruff-format
|
.PHONY: ruff-format
|
||||||
ruff-format: .venv ## ruff format
|
ruff-format: .venv ## ruff format
|
||||||
@$(RUFF) format
|
$(RUFF) format
|
||||||
|
|
||||||
.PHONY: ruff-format-check
|
.PHONY: ruff-format-check
|
||||||
ruff-format-check: .venv ## ruff format (check only)
|
ruff-format-check: .venv ## ruff format (check only)
|
||||||
@$(RUFF) format --check
|
$(RUFF) format --check
|
||||||
|
|
||||||
.PHONY: ty
|
.PHONY: ty
|
||||||
ty: .venv ## ty check
|
ty: .venv ## ty check
|
||||||
@$(TY) check
|
$(TY) check
|
||||||
|
|
||||||
.PHONY: unittest
|
.PHONY: unittest
|
||||||
unittest: .venv ## unittest
|
unittest: .venv ## unittest
|
||||||
@$(UNITTEST) -v
|
$(UNITTEST) -v
|
||||||
|
|
||||||
.PHONY: unittest-%
|
.PHONY: unittest-%
|
||||||
unittest-%: .venv ## unittest -k [filter]
|
unittest-%: .venv ## unittest -k [filter]
|
||||||
@$(UNITTEST) -v -k $*
|
$(UNITTEST) -v -k $*
|
||||||
|
|
||||||
.PHONY: coverage-unittest
|
.PHONY: coverage-unittest
|
||||||
coverage-unittest: .venv ## coverage run -m unittest
|
coverage-unittest: .venv ## coverage run -m unittest
|
||||||
@$(COVERAGE) run -m unittest -v
|
$(COVERAGE) run -m unittest -v
|
||||||
|
|
||||||
.PHONY: coverage-report
|
.PHONY: coverage-report
|
||||||
coverage-report: .venv ## coverage report
|
coverage-report: .venv ## coverage report
|
||||||
@$(COVERAGE) report
|
$(COVERAGE) report
|
||||||
|
|
||||||
.PHONY: coverage-html
|
.PHONY: coverage-html
|
||||||
coverage-html: .venv ## coverage html
|
coverage-html: .venv ## coverage html
|
||||||
@$(COVERAGE) html
|
$(COVERAGE) html
|
||||||
@$(OPEN) htmlcov/index.html || true
|
$(OPEN) htmlcov/index.html || true
|
||||||
|
|
||||||
.PHONY: coverage-xml
|
.PHONY: coverage-xml
|
||||||
coverage-xml: .venv ## coverage xml
|
coverage-xml: .venv ## coverage xml
|
||||||
@$(COVERAGE) xml
|
$(COVERAGE) xml
|
||||||
|
|
||||||
|
.PHONY: release-%
|
||||||
|
release-%: .venv ## release major/minor/patch
|
||||||
|
$(UV) version --bump=$*
|
||||||
|
git add pyproject.toml uv.lock
|
||||||
|
git commit -m "chore: $$(uv version --short)"
|
||||||
|
git tag "release/$$(uv version --short)" -m "$$(uv version)"
|
||||||
|
$(UV) build
|
||||||
|
|||||||
@@ -23,14 +23,18 @@ uvx --from git+https://git.klemek.fr/klemek/cool-domain cool-domain
|
|||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
```txt
|
```txt
|
||||||
usage: cool-domain [-h] [--count DOMAIN_COUNT] [--lang {english,french}] [--dig | --no-dig] [--debug | --no-debug] [--quiet | --no-quiet]
|
usage: cool-domain [-h] [--count DOMAIN_COUNT] [--words WORD_COUNT] [--lang {english,french,custom}] [--custom-words CUSTOM_WORDS]
|
||||||
[--cache | --no-cache] [--cache-file CACHE_FILE] [--tld-list-uri TLD_LIST_URI]
|
[--dig | --no-dig] [--debug | --no-debug] [--quiet | --no-quiet] [--cache | --no-cache] [--cache-file CACHE_FILE]
|
||||||
|
[--tld-list-uri TLD_LIST_URI]
|
||||||
|
|
||||||
options:
|
options:
|
||||||
-h, --help show this help message and exit
|
-h, --help show this help message and exit
|
||||||
--count DOMAIN_COUNT number of domains to generate (default: 1)
|
--count DOMAIN_COUNT number of domains to generate (default: 1)
|
||||||
--lang {english,french}
|
--words WORD_COUNT number of words per domain (default: 1)
|
||||||
|
--lang {english,french,custom}
|
||||||
word list lang (default: english)
|
word list lang (default: english)
|
||||||
|
--custom-words CUSTOM_WORDS
|
||||||
|
custom word list location (default: words.txt)
|
||||||
--dig, --no-dig check availability with dig (default: true)
|
--dig, --no-dig check availability with dig (default: true)
|
||||||
--debug, --no-debug
|
--debug, --no-debug
|
||||||
--quiet, --no-quiet
|
--quiet, --no-quiet
|
||||||
@@ -40,3 +44,45 @@ options:
|
|||||||
--tld-list-uri TLD_LIST_URI
|
--tld-list-uri TLD_LIST_URI
|
||||||
Top Level Domains list (default: https://publicsuffix.org/list/public_suffix_list.dat)
|
Top Level Domains list (default: https://publicsuffix.org/list/public_suffix_list.dat)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
# Development
|
||||||
|
|
||||||
|
## Updating `tld.txt`
|
||||||
|
|
||||||
|
Go to [tld-list.com](https://tld-list.com) and open console.
|
||||||
|
|
||||||
|
```js
|
||||||
|
async function getValidTlds() {
|
||||||
|
const delay = (millis) =>
|
||||||
|
new Promise((resolve, reject) => {
|
||||||
|
setTimeout((_) => {
|
||||||
|
resolve();
|
||||||
|
}, millis);
|
||||||
|
});
|
||||||
|
|
||||||
|
const sourceData = await (
|
||||||
|
await fetch("https://tld-list.com/tlds-from-a-z")
|
||||||
|
).text();
|
||||||
|
const regexp = /href="\/tld\/([\w\.]+)"/gm;
|
||||||
|
const outTlds = [];
|
||||||
|
let match;
|
||||||
|
|
||||||
|
while ((match = regexp.exec(sourceData)) !== null) {
|
||||||
|
const tld = match[1];
|
||||||
|
await delay(100);
|
||||||
|
console.log(tld);
|
||||||
|
const resp = await fetch(`https://tld-list.com/tld/${tld}`);
|
||||||
|
if (resp.status === 200) {
|
||||||
|
const content = await resp.text();
|
||||||
|
if (!content.includes("Registrars (0)")) {
|
||||||
|
outTlds.push(tld);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return outTlds;
|
||||||
|
}
|
||||||
|
|
||||||
|
const tlds = await getValidTlds();
|
||||||
|
|
||||||
|
console.log(tlds.join(','));
|
||||||
|
```
|
||||||
|
|||||||
+16
-11
@@ -1,25 +1,26 @@
|
|||||||
import logging
|
import logging
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from . import PKG_NAME, PKG_VERSION
|
from cool_domain import PKG_NAME, PKG_VERSION
|
||||||
from .cache import Cache
|
from cool_domain.constants import LANGS
|
||||||
from .constants import LANGS
|
from cool_domain.factory import Factory
|
||||||
from .factory import Factory
|
from cool_domain.logs import setup_logs
|
||||||
from .logs import setup_logs
|
from cool_domain.params import parse_parameters
|
||||||
from .params import parse_parameters
|
from cool_domain.tld_list import TLDList
|
||||||
from .tld_list import TLDList
|
from cool_domain.word_list import WordList
|
||||||
|
|
||||||
|
|
||||||
def main() -> int:
|
def main() -> int:
|
||||||
params = parse_parameters(sys.argv[1:])
|
params = parse_parameters(sys.argv[1:])
|
||||||
setup_logs(params)
|
setup_logs(params)
|
||||||
logging.getLogger().info("%s %s", PKG_NAME, PKG_VERSION)
|
logging.getLogger().info("%s %s", PKG_NAME, PKG_VERSION)
|
||||||
|
langs = LANGS
|
||||||
|
langs["custom"] = WordList("custom", params.custom_words)
|
||||||
with (
|
with (
|
||||||
Cache(filepath=params.cache_file, no_load=params.cache) as cache,
|
TLDList() as tld_list,
|
||||||
TLDList(cache=cache, remote_uri=params.tld_list_uri) as tld_list,
|
langs[params.lang] as word_list,
|
||||||
LANGS[params.lang] as word_list,
|
|
||||||
):
|
):
|
||||||
factory = Factory(tld_list=tld_list, word_list=word_list)
|
factory = Factory(tld_list=tld_list, word_list=word_list, words=params.words)
|
||||||
logging.getLogger().info(
|
logging.getLogger().info(
|
||||||
"Searching %s domain%s", params.count, "s" if params.count > 1 else ""
|
"Searching %s domain%s", params.count, "s" if params.count > 1 else ""
|
||||||
)
|
)
|
||||||
@@ -29,3 +30,7 @@ def main() -> int:
|
|||||||
else:
|
else:
|
||||||
logging.getLogger().info(factory.random_domain())
|
logging.getLogger().info(factory.random_domain())
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
|||||||
@@ -1,48 +0,0 @@
|
|||||||
import json
|
|
||||||
import pathlib
|
|
||||||
import typing
|
|
||||||
|
|
||||||
T = typing.TypeVar("T")
|
|
||||||
|
|
||||||
|
|
||||||
class Cache:
|
|
||||||
__slots__ = ["__data", "__filepath", "__no_load"]
|
|
||||||
|
|
||||||
def __init__(self, filepath: str, no_load: bool) -> None: # noqa: FBT001
|
|
||||||
self.__filepath = pathlib.Path(filepath)
|
|
||||||
self.__no_load = no_load
|
|
||||||
self.__data: dict[str, typing.Any] | None = None
|
|
||||||
|
|
||||||
def load(self) -> None:
|
|
||||||
if not self.__no_load and self.__filepath.exists():
|
|
||||||
self.__data = json.loads(self.__filepath.read_text())
|
|
||||||
else:
|
|
||||||
self.__data = {}
|
|
||||||
|
|
||||||
def write(self) -> None:
|
|
||||||
self.__filepath.write_text(json.dumps(self.__data))
|
|
||||||
|
|
||||||
def __enter__(self) -> typing.Self:
|
|
||||||
self.load()
|
|
||||||
return self
|
|
||||||
|
|
||||||
def __exit__(self, *_: object) -> None:
|
|
||||||
self.write()
|
|
||||||
|
|
||||||
def has(self, key: str) -> bool:
|
|
||||||
return self.__data is not None and key in self.__data
|
|
||||||
|
|
||||||
def get(self, key: str) -> typing.Any:
|
|
||||||
if self.__data is not None and key in self.__data:
|
|
||||||
return self.__data[key]
|
|
||||||
return None
|
|
||||||
|
|
||||||
def set(self, key: str, value: typing.Any) -> None:
|
|
||||||
if self.__data is not None:
|
|
||||||
self.__data[key] = value
|
|
||||||
self.write()
|
|
||||||
|
|
||||||
def get_or_set(self, key: str, callback: typing.Callable[[], T]) -> T:
|
|
||||||
if not self.has(key):
|
|
||||||
self.set(key, callback())
|
|
||||||
return self.get(key)
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
from .word_list import WordList
|
from cool_domain.word_list import WordList
|
||||||
|
|
||||||
LANGS: dict[str, WordList] = {
|
LANGS: dict[str, WordList] = {
|
||||||
"english": WordList("english", "english", "words_alpha.txt"),
|
"english": WordList("english", "english.txt"),
|
||||||
"french": WordList("french", "french", "francais.txt"),
|
"french": WordList("french", "french.txt"),
|
||||||
}
|
}
|
||||||
|
|||||||
Symlink
+1
@@ -0,0 +1 @@
|
|||||||
|
../english/words_alpha.txt
|
||||||
+12
-9
@@ -4,9 +4,8 @@ import shutil
|
|||||||
import subprocess
|
import subprocess
|
||||||
import typing
|
import typing
|
||||||
|
|
||||||
if typing.TYPE_CHECKING:
|
from cool_domain.tld_list import TLDList
|
||||||
from .tld_list import TLDList
|
from cool_domain.word_list import WordList
|
||||||
from .word_list import WordList
|
|
||||||
|
|
||||||
|
|
||||||
class FactoryError(Exception):
|
class FactoryError(Exception):
|
||||||
@@ -14,12 +13,13 @@ class FactoryError(Exception):
|
|||||||
|
|
||||||
|
|
||||||
class Factory:
|
class Factory:
|
||||||
__slots__ = ["__found", "__tld_list", "__word_list", "logger", "logger"]
|
__slots__ = ["__found", "__tld_list", "__word_list", "__words", "logger"]
|
||||||
|
|
||||||
def __init__(self, tld_list: TLDList, word_list: WordList) -> None:
|
def __init__(self, tld_list: TLDList, word_list: WordList, words: int) -> None:
|
||||||
self.logger: logging.Logger = logging.getLogger(self.__class__.__name__)
|
self.logger: logging.Logger = logging.getLogger(self.__class__.__name__)
|
||||||
self.__tld_list = tld_list
|
self.__tld_list = tld_list
|
||||||
self.__word_list = word_list
|
self.__word_list = word_list
|
||||||
|
self.__words = words
|
||||||
self.__found: set[str] = set()
|
self.__found: set[str] = set()
|
||||||
|
|
||||||
def __iter__(self) -> typing.Self:
|
def __iter__(self) -> typing.Self:
|
||||||
@@ -41,10 +41,10 @@ class Factory:
|
|||||||
msg = "dig is not installed"
|
msg = "dig is not installed"
|
||||||
raise FactoryError(msg)
|
raise FactoryError(msg)
|
||||||
try:
|
try:
|
||||||
output = subprocess.check_output([dig_bin, domain, "+short"]) # noqa: S603
|
output = subprocess.check_output([dig_bin, domain, "NS", "+short"]) # noqa: S603
|
||||||
return len(output) == 0
|
return len(output) == 0
|
||||||
except subprocess.CalledProcessError:
|
except subprocess.CalledProcessError:
|
||||||
return True
|
return False
|
||||||
|
|
||||||
def random_domain(self) -> str:
|
def random_domain(self) -> str:
|
||||||
k = 10000
|
k = 10000
|
||||||
@@ -65,12 +65,15 @@ class Factory:
|
|||||||
return domain
|
return domain
|
||||||
|
|
||||||
def __random_domain(self) -> str | None:
|
def __random_domain(self) -> str | None:
|
||||||
word = random.choice(self.__word_list.words) # noqa: S311
|
word = self.__random_word()
|
||||||
for tld in self.__tld_list_shuffled:
|
for tld in self.__tld_list_shuffled:
|
||||||
tld_escaped = tld.replace(".", "")
|
tld_escaped = tld.replace(".", "")
|
||||||
if word.endswith(tld_escaped) and len(word) > len(tld_escaped):
|
if word.endswith(tld_escaped) and len(word) > len(tld_escaped):
|
||||||
domain = word[: -len(tld_escaped)] + "." + tld
|
domain = word[: -len(tld_escaped)] + "." + tld
|
||||||
if domain not in self.__found:
|
if "-." not in domain and domain not in self.__found:
|
||||||
self.__found.add(domain)
|
self.__found.add(domain)
|
||||||
return domain
|
return domain
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def __random_word(self) -> str:
|
||||||
|
return "-".join(random.sample(self.__word_list.words, self.__words))
|
||||||
|
|||||||
Symlink
+1
@@ -0,0 +1 @@
|
|||||||
|
../french/francais.txt
|
||||||
+1
-2
@@ -2,8 +2,7 @@ import enum
|
|||||||
import logging
|
import logging
|
||||||
import typing
|
import typing
|
||||||
|
|
||||||
if typing.TYPE_CHECKING:
|
from cool_domain.params import Parameters
|
||||||
from .params import Parameters
|
|
||||||
|
|
||||||
|
|
||||||
class TermColor(enum.StrEnum):
|
class TermColor(enum.StrEnum):
|
||||||
|
|||||||
+20
-29
@@ -1,12 +1,10 @@
|
|||||||
import argparse
|
import argparse
|
||||||
import dataclasses
|
import dataclasses
|
||||||
import os
|
import os
|
||||||
import pathlib
|
|
||||||
import tempfile
|
|
||||||
import typing
|
import typing
|
||||||
|
|
||||||
from . import PKG_NAME
|
from cool_domain import PKG_NAME
|
||||||
from .constants import LANGS
|
from cool_domain.constants import LANGS
|
||||||
|
|
||||||
|
|
||||||
@dataclasses.dataclass(frozen=True, slots=True)
|
@dataclasses.dataclass(frozen=True, slots=True)
|
||||||
@@ -15,13 +13,13 @@ class Parameters:
|
|||||||
quiet: bool = False
|
quiet: bool = False
|
||||||
cache: bool = True
|
cache: bool = True
|
||||||
count: int = 1
|
count: int = 1
|
||||||
|
words: int = 1
|
||||||
dig: bool = True
|
dig: bool = True
|
||||||
lang: str = "english"
|
lang: str = "english"
|
||||||
cache_file: str = str(pathlib.Path(tempfile.gettempdir()) / ".cool-domain-cache")
|
custom_words: str = "words.txt"
|
||||||
tld_list_uri: str = "https://publicsuffix.org/list/public_suffix_list.dat"
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_namespace(cls, args: argparse.Namespace) -> Parameters:
|
def from_namespace(cls, args: argparse.Namespace) -> "Parameters":
|
||||||
return Parameters(**vars(args))
|
return Parameters(**vars(args))
|
||||||
|
|
||||||
|
|
||||||
@@ -89,7 +87,6 @@ def parse_parameters(args: typing.Sequence[str]) -> Parameters:
|
|||||||
default_values = Parameters()
|
default_values = Parameters()
|
||||||
parser = argparse.ArgumentParser(
|
parser = argparse.ArgumentParser(
|
||||||
PKG_NAME,
|
PKG_NAME,
|
||||||
suggest_on_error=True,
|
|
||||||
)
|
)
|
||||||
__add_arg_int(
|
__add_arg_int(
|
||||||
parser,
|
parser,
|
||||||
@@ -98,11 +95,25 @@ def parse_parameters(args: typing.Sequence[str]) -> Parameters:
|
|||||||
default=default_values.count,
|
default=default_values.count,
|
||||||
help_txt="number of domains to generate",
|
help_txt="number of domains to generate",
|
||||||
)
|
)
|
||||||
|
__add_arg_int(
|
||||||
|
parser,
|
||||||
|
"--words",
|
||||||
|
env_var="WORD_COUNT",
|
||||||
|
default=default_values.words,
|
||||||
|
help_txt="number of words per domain",
|
||||||
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--lang",
|
"--lang",
|
||||||
default=default_values.lang,
|
default=default_values.lang,
|
||||||
help="word list lang (default: english)",
|
help="word list lang (default: english)",
|
||||||
choices=LANGS.keys(),
|
choices=[*list(LANGS.keys()), "custom"],
|
||||||
|
)
|
||||||
|
__add_arg_str(
|
||||||
|
parser,
|
||||||
|
"--custom-words",
|
||||||
|
env_var="CUSTOM_WORDS",
|
||||||
|
default=default_values.custom_words,
|
||||||
|
help_txt="custom word list location",
|
||||||
)
|
)
|
||||||
__add_arg_bool(
|
__add_arg_bool(
|
||||||
parser,
|
parser,
|
||||||
@@ -116,25 +127,5 @@ def parse_parameters(args: typing.Sequence[str]) -> Parameters:
|
|||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--quiet", action=argparse.BooleanOptionalAction, default=default_values.quiet
|
"--quiet", action=argparse.BooleanOptionalAction, default=default_values.quiet
|
||||||
)
|
)
|
||||||
__add_arg_bool(
|
|
||||||
parser,
|
|
||||||
"--cache",
|
|
||||||
default=default_values.cache,
|
|
||||||
help_txt="use cache",
|
|
||||||
)
|
|
||||||
__add_arg_str(
|
|
||||||
parser,
|
|
||||||
"--cache-file",
|
|
||||||
env_var="CACHE_FILE",
|
|
||||||
default=default_values.cache_file,
|
|
||||||
help_txt="cache file location",
|
|
||||||
)
|
|
||||||
__add_arg_str(
|
|
||||||
parser,
|
|
||||||
"--tld-list-uri",
|
|
||||||
env_var="TLD_LIST_URI",
|
|
||||||
default=default_values.tld_list_uri,
|
|
||||||
help_txt="Top Level Domains list",
|
|
||||||
)
|
|
||||||
parsed_args = parser.parse_args(args)
|
parsed_args = parser.parse_args(args)
|
||||||
return Parameters.from_namespace(parsed_args)
|
return Parameters.from_namespace(parsed_args)
|
||||||
|
|||||||
+2598
File diff suppressed because it is too large
Load Diff
+9
-34
@@ -1,54 +1,29 @@
|
|||||||
import http
|
|
||||||
import logging
|
import logging
|
||||||
|
import pathlib
|
||||||
import typing
|
import typing
|
||||||
|
|
||||||
import requests
|
|
||||||
import unidecode
|
|
||||||
|
|
||||||
if typing.TYPE_CHECKING:
|
|
||||||
from .cache import Cache
|
|
||||||
|
|
||||||
|
|
||||||
class TLDError(Exception):
|
class TLDError(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class TLDList:
|
class TLDList:
|
||||||
__slots__ = ["__cache", "__remote_uri", "logger", "tlds"]
|
__slots__ = ["logger", "tlds"]
|
||||||
|
|
||||||
def __init__(self, cache: Cache, remote_uri: str) -> None:
|
def __init__(self) -> None:
|
||||||
self.logger: logging.Logger = logging.getLogger(self.__class__.__name__)
|
self.logger: logging.Logger = logging.getLogger(self.__class__.__name__)
|
||||||
self.tlds: list[str] | None = None
|
self.tlds: list[str] | None = None
|
||||||
self.__cache = cache
|
|
||||||
self.__remote_uri = remote_uri
|
|
||||||
|
|
||||||
def __load_remote(self) -> list[str]:
|
def __load_file(self) -> list[str]:
|
||||||
response = requests.get(self.__remote_uri, timeout=5)
|
|
||||||
if response.status_code != http.HTTPStatus.OK:
|
|
||||||
msg = f"Failed to read {self.__remote_uri}."
|
|
||||||
raise TLDError(msg)
|
|
||||||
raw_lines = response.content.decode().split("\n")
|
|
||||||
out_lines = []
|
out_lines = []
|
||||||
for line in raw_lines:
|
with (pathlib.Path(__file__).parent / "tld.txt").open() as file:
|
||||||
stripped_line = line.strip()
|
for line in file:
|
||||||
if (
|
if len(line.strip()):
|
||||||
len(stripped_line)
|
out_lines += [line.strip()]
|
||||||
and not stripped_line.startswith("//")
|
|
||||||
and not stripped_line.startswith("*")
|
|
||||||
and unidecode.unidecode(stripped_line) == stripped_line
|
|
||||||
):
|
|
||||||
if "." in stripped_line:
|
|
||||||
for other in out_lines:
|
|
||||||
if stripped_line.endswith(other):
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
out_lines += [stripped_line]
|
|
||||||
else:
|
|
||||||
out_lines += [stripped_line]
|
|
||||||
return out_lines
|
return out_lines
|
||||||
|
|
||||||
def load(self) -> None:
|
def load(self) -> None:
|
||||||
self.tlds = self.__cache.get_or_set("tld_list", self.__load_remote)
|
self.tlds = self.__load_file()
|
||||||
self.logger.info("Loaded %d TLD entries", len(self.tlds))
|
self.logger.info("Loaded %d TLD entries", len(self.tlds))
|
||||||
|
|
||||||
def __enter__(self) -> typing.Self:
|
def __enter__(self) -> typing.Self:
|
||||||
|
|||||||
@@ -8,10 +8,10 @@ import unidecode
|
|||||||
class WordList:
|
class WordList:
|
||||||
__slots__ = ["__filepath", "__name", "logger", "words"]
|
__slots__ = ["__filepath", "__name", "logger", "words"]
|
||||||
|
|
||||||
def __init__(self, name: str, path: str, filename: str) -> None:
|
def __init__(self, name: str, path: str) -> None:
|
||||||
self.logger: logging.Logger = logging.getLogger(self.__class__.__name__)
|
self.logger: logging.Logger = logging.getLogger(self.__class__.__name__)
|
||||||
self.__name = name
|
self.__name = name
|
||||||
self.__filepath = pathlib.Path(__file__).parent / ".." / path / filename
|
self.__filepath = pathlib.Path(__file__).parent / path
|
||||||
self.words: list[str] = []
|
self.words: list[str] = []
|
||||||
|
|
||||||
def open(self) -> None:
|
def open(self) -> None:
|
||||||
@@ -22,7 +22,10 @@ class WordList:
|
|||||||
self.logger.info("[%s] Loaded %d words", self.__name, len(self.words))
|
self.logger.info("[%s] Loaded %d words", self.__name, len(self.words))
|
||||||
|
|
||||||
def __escape_word(self, word: str) -> str:
|
def __escape_word(self, word: str) -> str:
|
||||||
return unidecode.unidecode(word.strip()).lower()
|
word = unidecode.unidecode(word.strip()).lower()
|
||||||
|
if " " in word:
|
||||||
|
return ""
|
||||||
|
return word
|
||||||
|
|
||||||
def close(self) -> None:
|
def close(self) -> None:
|
||||||
pass
|
pass
|
||||||
|
|||||||
+2
-3
@@ -1,11 +1,10 @@
|
|||||||
[project]
|
[project]
|
||||||
name = "cool-domain"
|
name = "cool-domain"
|
||||||
version = "1.0.0"
|
version = "1.4.1"
|
||||||
description = "Add your description here"
|
description = "Add your description here"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
requires-python = ">=3.14"
|
requires-python = ">=3.12"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"requests>=2.34.2,<3.0.0",
|
|
||||||
"unidecode>=1.4.0,<2.0.0",
|
"unidecode>=1.4.0,<2.0.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@@ -1,63 +1,12 @@
|
|||||||
version = 1
|
version = 1
|
||||||
revision = 3
|
revision = 3
|
||||||
requires-python = ">=3.14"
|
requires-python = ">=3.12"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "certifi"
|
|
||||||
version = "2026.5.20"
|
|
||||||
source = { registry = "https://pypi.org/simple" }
|
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/f3/ce/ee2ecad540810a79593028e88299baeae54d346cc7a0d94b6199988b89b1/certifi-2026.5.20.tar.gz", hash = "sha256:69dea482ab64caa7b9f6aba1c6bf48bb6a5448d1c0f1b17ab42ad8c763a5344d", size = 135422, upload-time = "2026-05-20T11:46:50.073Z" }
|
|
||||||
wheels = [
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/59/8c/57e832b7af6d7c5abe66eb3fbe3a3a32f4d11ea23a1aa7131371035be991/certifi-2026.5.20-py3-none-any.whl", hash = "sha256:3c52e209ba0a4ad7aebe60436a4ab349c39e1e602e8c134221e546902ad25897", size = 134134, upload-time = "2026-05-20T11:46:48.578Z" },
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "charset-normalizer"
|
|
||||||
version = "3.4.7"
|
|
||||||
source = { registry = "https://pypi.org/simple" }
|
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/e7/a1/67fe25fac3c7642725500a3f6cfe5821ad557c3abb11c9d20d12c7008d3e/charset_normalizer-3.4.7.tar.gz", hash = "sha256:ae89db9e5f98a11a4bf50407d4363e7b09b31e55bc117b4f7d80aab97ba009e5", size = 144271, upload-time = "2026-04-02T09:28:39.342Z" }
|
|
||||||
wheels = [
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/97/c8/c67cb8c70e19ef1960b97b22ed2a1567711de46c4ddf19799923adc836c2/charset_normalizer-3.4.7-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:c36c333c39be2dbca264d7803333c896ab8fa7d4d6f0ab7edb7dfd7aea6e98c0", size = 309234, upload-time = "2026-04-02T09:27:07.194Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/99/85/c091fdee33f20de70d6c8b522743b6f831a2f1cd3ff86de4c6a827c48a76/charset_normalizer-3.4.7-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1c2aed2e5e41f24ea8ef1590b8e848a79b56f3a5564a65ceec43c9d692dc7d8a", size = 208042, upload-time = "2026-04-02T09:27:08.749Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/87/1c/ab2ce611b984d2fd5d86a5a8a19c1ae26acac6bad967da4967562c75114d/charset_normalizer-3.4.7-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:54523e136b8948060c0fa0bc7b1b50c32c186f2fceee897a495406bb6e311d2b", size = 228706, upload-time = "2026-04-02T09:27:09.951Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/a8/29/2b1d2cb00bf085f59d29eb773ce58ec2d325430f8c216804a0a5cd83cbca/charset_normalizer-3.4.7-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:715479b9a2802ecac752a3b0efa2b0b60285cf962ee38414211abdfccc233b41", size = 224727, upload-time = "2026-04-02T09:27:11.175Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/47/5c/032c2d5a07fe4d4855fea851209cca2b6f03ebeb6d4e3afdb3358386a684/charset_normalizer-3.4.7-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bd6c2a1c7573c64738d716488d2cdd3c00e340e4835707d8fdb8dc1a66ef164e", size = 215882, upload-time = "2026-04-02T09:27:12.446Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/2c/c2/356065d5a8b78ed04499cae5f339f091946a6a74f91e03476c33f0ab7100/charset_normalizer-3.4.7-cp314-cp314-manylinux_2_31_armv7l.whl", hash = "sha256:c45e9440fb78f8ddabcf714b68f936737a121355bf59f3907f4e17721b9d1aae", size = 200860, upload-time = "2026-04-02T09:27:13.721Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/0c/cd/a32a84217ced5039f53b29f460962abb2d4420def55afabe45b1c3c7483d/charset_normalizer-3.4.7-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:3534e7dcbdcf757da6b85a0bbf5b6868786d5982dd959b065e65481644817a18", size = 211564, upload-time = "2026-04-02T09:27:15.272Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/44/86/58e6f13ce26cc3b8f4a36b94a0f22ae2f00a72534520f4ae6857c4b81f89/charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:e8ac484bf18ce6975760921bb6148041faa8fef0547200386ea0b52b5d27bf7b", size = 211276, upload-time = "2026-04-02T09:27:16.834Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/8f/fe/d17c32dc72e17e155e06883efa84514ca375f8a528ba2546bee73fc4df81/charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:a5fe03b42827c13cdccd08e6c0247b6a6d4b5e3cdc53fd1749f5896adcdc2356", size = 201238, upload-time = "2026-04-02T09:27:18.229Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/6a/29/f33daa50b06525a237451cdb6c69da366c381a3dadcd833fa5676bc468b3/charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:2d6eb928e13016cea4f1f21d1e10c1cebd5a421bc57ddf5b1142ae3f86824fab", size = 230189, upload-time = "2026-04-02T09:27:19.445Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/b6/6e/52c84015394a6a0bdcd435210a7e944c5f94ea1055f5cc5d56c5fe368e7b/charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:e74327fb75de8986940def6e8dee4f127cc9752bee7355bb323cc5b2659b6d46", size = 211352, upload-time = "2026-04-02T09:27:20.79Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/8c/d7/4353be581b373033fb9198bf1da3cf8f09c1082561e8e922aa7b39bf9fe8/charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:d6038d37043bced98a66e68d3aa2b6a35505dc01328cd65217cefe82f25def44", size = 227024, upload-time = "2026-04-02T09:27:22.063Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/30/45/99d18aa925bd1740098ccd3060e238e21115fffbfdcb8f3ece837d0ace6c/charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:7579e913a5339fb8fa133f6bbcfd8e6749696206cf05acdbdca71a1b436d8e72", size = 217869, upload-time = "2026-04-02T09:27:23.486Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/5c/05/5ee478aa53f4bb7996482153d4bfe1b89e0f087f0ab6b294fcf92d595873/charset_normalizer-3.4.7-cp314-cp314-win32.whl", hash = "sha256:5b77459df20e08151cd6f8b9ef8ef1f961ef73d85c21a555c7eed5b79410ec10", size = 148541, upload-time = "2026-04-02T09:27:25.146Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/48/77/72dcb0921b2ce86420b2d79d454c7022bf5be40202a2a07906b9f2a35c97/charset_normalizer-3.4.7-cp314-cp314-win_amd64.whl", hash = "sha256:92a0a01ead5e668468e952e4238cccd7c537364eb7d851ab144ab6627dbbe12f", size = 159634, upload-time = "2026-04-02T09:27:26.642Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/c6/a3/c2369911cd72f02386e4e340770f6e158c7980267da16af8f668217abaa0/charset_normalizer-3.4.7-cp314-cp314-win_arm64.whl", hash = "sha256:67f6279d125ca0046a7fd386d01b311c6363844deac3e5b069b514ba3e63c246", size = 148384, upload-time = "2026-04-02T09:27:28.271Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/94/09/7e8a7f73d24dba1f0035fbbf014d2c36828fc1bf9c88f84093e57d315935/charset_normalizer-3.4.7-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:effc3f449787117233702311a1b7d8f59cba9ced946ba727bdc329ec69028e24", size = 330133, upload-time = "2026-04-02T09:27:29.474Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/8d/da/96975ddb11f8e977f706f45cddd8540fd8242f71ecdb5d18a80723dcf62c/charset_normalizer-3.4.7-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fbccdc05410c9ee21bbf16a35f4c1d16123dcdeb8a1d38f33654fa21d0234f79", size = 216257, upload-time = "2026-04-02T09:27:30.793Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/e5/e8/1d63bf8ef2d388e95c64b2098f45f84758f6d102a087552da1485912637b/charset_normalizer-3.4.7-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:733784b6d6def852c814bce5f318d25da2ee65dd4839a0718641c696e09a2960", size = 234851, upload-time = "2026-04-02T09:27:32.44Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/9b/40/e5ff04233e70da2681fa43969ad6f66ca5611d7e669be0246c4c7aaf6dc8/charset_normalizer-3.4.7-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a89c23ef8d2c6b27fd200a42aa4ac72786e7c60d40efdc76e6011260b6e949c4", size = 233393, upload-time = "2026-04-02T09:27:34.03Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/be/c1/06c6c49d5a5450f76899992f1ee40b41d076aee9279b49cf9974d2f313d5/charset_normalizer-3.4.7-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6c114670c45346afedc0d947faf3c7f701051d2518b943679c8ff88befe14f8e", size = 223251, upload-time = "2026-04-02T09:27:35.369Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/2b/9f/f2ff16fb050946169e3e1f82134d107e5d4ae72647ec8a1b1446c148480f/charset_normalizer-3.4.7-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:a180c5e59792af262bf263b21a3c49353f25945d8d9f70628e73de370d55e1e1", size = 206609, upload-time = "2026-04-02T09:27:36.661Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/69/d5/a527c0cd8d64d2eab7459784fb4169a0ac76e5a6fc5237337982fd61347e/charset_normalizer-3.4.7-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:3c9a494bc5ec77d43cea229c4f6db1e4d8fe7e1bbffa8b6f0f0032430ff8ab44", size = 220014, upload-time = "2026-04-02T09:27:38.019Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/7e/80/8a7b8104a3e203074dc9aa2c613d4b726c0e136bad1cc734594b02867972/charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8d828b6667a32a728a1ad1d93957cdf37489c57b97ae6c4de2860fa749b8fc1e", size = 218979, upload-time = "2026-04-02T09:27:39.37Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/02/9a/b759b503d507f375b2b5c153e4d2ee0a75aa215b7f2489cf314f4541f2c0/charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:cf1493cd8607bec4d8a7b9b004e699fcf8f9103a9284cc94962cb73d20f9d4a3", size = 209238, upload-time = "2026-04-02T09:27:40.722Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/c2/4e/0f3f5d47b86bdb79256e7290b26ac847a2832d9a4033f7eb2cd4bcf4bb5b/charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:0c96c3b819b5c3e9e165495db84d41914d6894d55181d2d108cc1a69bfc9cce0", size = 236110, upload-time = "2026-04-02T09:27:42.33Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/96/23/bce28734eb3ed2c91dcf93abeb8a5cf393a7b2749725030bb630e554fdd8/charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:752a45dc4a6934060b3b0dab47e04edc3326575f82be64bc4fc293914566503e", size = 219824, upload-time = "2026-04-02T09:27:43.924Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/2c/6f/6e897c6984cc4d41af319b077f2f600fc8214eb2fe2d6bcb79141b882400/charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:8778f0c7a52e56f75d12dae53ae320fae900a8b9b4164b981b9c5ce059cd1fcb", size = 233103, upload-time = "2026-04-02T09:27:45.348Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/76/22/ef7bd0fe480a0ae9b656189ec00744b60933f68b4f42a7bb06589f6f576a/charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ce3412fbe1e31eb81ea42f4169ed94861c56e643189e1e75f0041f3fe7020abe", size = 225194, upload-time = "2026-04-02T09:27:46.706Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/c5/a7/0e0ab3e0b5bc1219bd80a6a0d4d72ca74d9250cb2382b7c699c147e06017/charset_normalizer-3.4.7-cp314-cp314t-win32.whl", hash = "sha256:c03a41a8784091e67a39648f70c5f97b5b6a37f216896d44d2cdcb82615339a0", size = 159827, upload-time = "2026-04-02T09:27:48.053Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/7a/1d/29d32e0fb40864b1f878c7f5a0b343ae676c6e2b271a2d55cc3a152391da/charset_normalizer-3.4.7-cp314-cp314t-win_amd64.whl", hash = "sha256:03853ed82eeebbce3c2abfdbc98c96dc205f32a79627688ac9a27370ea61a49c", size = 174168, upload-time = "2026-04-02T09:27:49.795Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/de/32/d92444ad05c7a6e41fb2036749777c163baf7a0301a040cb672d6b2b1ae9/charset_normalizer-3.4.7-cp314-cp314t-win_arm64.whl", hash = "sha256:c35abb8bfff0185efac5878da64c45dafd2b37fb0383add1be155a763c1f083d", size = 153018, upload-time = "2026-04-02T09:27:51.116Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/db/8f/61959034484a4a7c527811f4721e75d02d653a35afb0b6054474d8185d4c/charset_normalizer-3.4.7-py3-none-any.whl", hash = "sha256:3dce51d0f5e7951f8bb4900c257dad282f49190fdbebecd4ba99bcc41fef404d", size = 61958, upload-time = "2026-04-02T09:28:37.794Z" },
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cool-domain"
|
name = "cool-domain"
|
||||||
version = "1.0.0"
|
version = "1.4.1"
|
||||||
source = { editable = "." }
|
source = { editable = "." }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "requests" },
|
|
||||||
{ name = "unidecode" },
|
{ name = "unidecode" },
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -68,10 +17,7 @@ dev = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[package.metadata]
|
[package.metadata]
|
||||||
requires-dist = [
|
requires-dist = [{ name = "unidecode", specifier = ">=1.4.0,<2.0.0" }]
|
||||||
{ name = "requests", specifier = ">=2.34.2,<3.0.0" },
|
|
||||||
{ name = "unidecode", specifier = ">=1.4.0,<2.0.0" },
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.metadata.requires-dev]
|
[package.metadata.requires-dev]
|
||||||
dev = [
|
dev = [
|
||||||
@@ -79,30 +25,6 @@ dev = [
|
|||||||
{ name = "ty", specifier = ">=0.0.34,<0.0.35" },
|
{ name = "ty", specifier = ">=0.0.34,<0.0.35" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "idna"
|
|
||||||
version = "3.18"
|
|
||||||
source = { registry = "https://pypi.org/simple" }
|
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/cd/63/9496c57188a2ee585e0f1db071d75089a11e98aa86eb99d9d7618fc1edce/idna-3.18.tar.gz", hash = "sha256:ffb385a7e039654cef1ab9ef32c6fafe283c0c0467bba1d9029738ce4a14a848", size = 196711, upload-time = "2026-06-02T14:34:07.794Z" }
|
|
||||||
wheels = [
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/1e/5e/d4e9f1a599fb8e573b7b87160658329fbf28d19eac2718f51fc3def3aa5a/idna-3.18-py3-none-any.whl", hash = "sha256:7f952cbe720b688055e3f87de14f5c3e5fdaa8bc3928985c4077ca689de849a2", size = 65455, upload-time = "2026-06-02T14:34:06.319Z" },
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "requests"
|
|
||||||
version = "2.34.2"
|
|
||||||
source = { registry = "https://pypi.org/simple" }
|
|
||||||
dependencies = [
|
|
||||||
{ name = "certifi" },
|
|
||||||
{ name = "charset-normalizer" },
|
|
||||||
{ name = "idna" },
|
|
||||||
{ name = "urllib3" },
|
|
||||||
]
|
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/ac/c3/e2a2b89f2d3e2179abd6d00ebd70bff6273f37fb3e0cc209f48b39d00cbf/requests-2.34.2.tar.gz", hash = "sha256:f288924cae4e29463698d6d60bc6a4da69c89185ad1e0bcc4104f584e960b9ed", size = 142856, upload-time = "2026-05-14T19:25:27.735Z" }
|
|
||||||
wheels = [
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/a0/f4/c67b0b3f1b9245e8d266f0f112c500d50e5b4e83cb6f3b71b6528104182a/requests-2.34.2-py3-none-any.whl", hash = "sha256:2a0d60c172f83ac6ab31e4554906c0f3b3588d37b5cb939b1c061f4907e278e0", size = 73075, upload-time = "2026-05-14T19:25:26.443Z" },
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ruff"
|
name = "ruff"
|
||||||
version = "0.15.12"
|
version = "0.15.12"
|
||||||
@@ -160,12 +82,3 @@ sdist = { url = "https://files.pythonhosted.org/packages/94/7d/a8a765761bbc0c836
|
|||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/8f/b7/559f59d57d18b44c6d1250d2eeaa676e028b9c527431f5d0736478a73ba1/Unidecode-1.4.0-py3-none-any.whl", hash = "sha256:c3c7606c27503ad8d501270406e345ddb480a7b5f38827eafe4fa82a137f0021", size = 235837, upload-time = "2025-04-24T08:45:01.609Z" },
|
{ url = "https://files.pythonhosted.org/packages/8f/b7/559f59d57d18b44c6d1250d2eeaa676e028b9c527431f5d0736478a73ba1/Unidecode-1.4.0-py3-none-any.whl", hash = "sha256:c3c7606c27503ad8d501270406e345ddb480a7b5f38827eafe4fa82a137f0021", size = 235837, upload-time = "2025-04-24T08:45:01.609Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "urllib3"
|
|
||||||
version = "2.7.0"
|
|
||||||
source = { registry = "https://pypi.org/simple" }
|
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/53/0c/06f8b233b8fd13b9e5ee11424ef85419ba0d8ba0b3138bf360be2ff56953/urllib3-2.7.0.tar.gz", hash = "sha256:231e0ec3b63ceb14667c67be60f2f2c40a518cb38b03af60abc813da26505f4c", size = 433602, upload-time = "2026-05-07T16:13:18.596Z" }
|
|
||||||
wheels = [
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/7f/3e/5db95bcf282c52709639744ca2a8b149baccf648e39c8cc87553df9eae0c/urllib3-2.7.0-py3-none-any.whl", hash = "sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897", size = 131087, upload-time = "2026-05-07T16:13:17.151Z" },
|
|
||||||
]
|
|
||||||
|
|||||||
Reference in New Issue
Block a user