Skip to content

Commit

Permalink
Fixed settings
Browse files Browse the repository at this point in the history
  • Loading branch information
xfenix committed Oct 12, 2023
1 parent 6133f41 commit 813d830
Show file tree
Hide file tree
Showing 4 changed files with 132 additions and 82 deletions.
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,15 @@ Also it supports feature called «user dictionaries» — user can add his own w
### Config options
You can change config of the service by changing the environment variables. Here is a list of them:
* `SPELLCHECK_SENTRY_DSN` Sentry DSN for integration. Empty field disables integration. Default value is ``.
* `SPELLCHECK_API_KEY` define api key for users dictionaries mostly. Please, provide, if you want to enable user dictionaries API. Default value is ``. Restrictions is `[BeforeValidator(func=<function _warn_about_empty_api_key at 0x1028aad40>)]`
* `SPELLCHECK_API_KEY` define api key for users dictionaries mostly. Please, provide, if you want to enable user dictionaries API. Default value is ``.
* `SPELLCHECK_ENABLE_CORS` enable CORS for all endpoints. In docker container this option is disabled. Default value is `True`.
* `SPELLCHECK_STRUCTURED_LOGGING` enables structured (json) logging. Default value is `True`.
* `SPELLCHECK_WORKERS` define application server workers count. If you plan to use k8s and only scale with replica sets, you might want to reduce this value to `1`. Default value is `8`. Restrictions is `[typing.Annotated[int, None, Interval(gt=0, ge=None, lt=301, le=None), None]]`
* `SPELLCHECK_PORT` binding port. Default value is `10113`. Restrictions is `[typing.Annotated[int, None, Interval(gt=1023, ge=None, lt=65536, le=None), None]]`
* `SPELLCHECK_CACHE_SIZE` define LRU cache size for misspelled word/suggestions cache. Any value less than `1` makes the cache size unlimited, so be careful with this option. Default value is `10000`. Restrictions is `[BeforeValidator(func=<function _warn_about_poor_lru_cache_size at 0x100f97490>)]`
* `SPELLCHECK_API_PREFIX` define all API's URL prefix. Default value is `/api/`. Restrictions is `[BeforeValidator(func=<function SettingsOfMicroservice.<lambda> at 0x102ab4f70>)]`
* `SPELLCHECK_WORKERS` define application server workers count. If you plan to use k8s and only scale with replica sets, you might want to reduce this value to `1`. Default value is `8`. Restrictions: `Gt(gt=0)`, `Lt(lt=301)`
* `SPELLCHECK_PORT` binding port. Default value is `10113`. Restrictions: `Gt(gt=1023)`, `Lt(lt=65536)`
* `SPELLCHECK_CACHE_SIZE` define LRU cache size for misspelled word/suggestions cache. Any value less than `1` makes the cache size unlimited, so be careful with this option. Default value is `10000`.
* `SPELLCHECK_API_PREFIX` define all API's URL prefix. Default value is `/api/`.
* `SPELLCHECK_DOCS_URL` define documentation (swagger) URL prefix. Default value is `/docs/`.
* `SPELLCHECK_MAX_SUGGESTIONS` defines how many maximum suggestions for each word will be available. `None` means unlimitied. Default value is `None`. Restrictions is `[typing.Optional[typing.Annotated[int, None, Interval(gt=0, ge=None, lt=None, le=None), None]]]`
* `SPELLCHECK_MAX_SUGGESTIONS` defines how many maximum suggestions for each word will be available. 0 means unlimitied. Default value is `0`. Restrictions: `Ge(ge=0)`
* `SPELLCHECK_DICTIONARIES_PATH` define directory where user dicts is stored. This is inner directory in the docker image, please map it to volume as it shown in the quickstart part of this readme. Default value is `/data`.
* `SPELLCHECK_DICTIONARIES_STORAGE_PROVIDER` define wich engine will store user dictionaries. Default value is `StorageProviders.FILE`.
* `SPELLCHECK_DICTIONARIES_DISABLED` switches off user dictionaries API no matter what. Default value is `False`.
Expand Down
9 changes: 8 additions & 1 deletion scripts/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,14 @@ def _update_readme() -> None:
f"Default value is `{field_properties.default}`.",
]
if field_properties.metadata:
one_row_parts.append(f"Restrictions is `{field_properties.metadata}`")
validators_buf: list[str] = []
for one_obj in field_properties.metadata:
restriction_stringified: typing.Final = str(one_obj)
if any(("BeforeValidator" in restriction_stringified, "StringConstraints" in restriction_stringified)):
continue
validators_buf.append(f"`{restriction_stringified}`")
if validators_buf:
one_row_parts.append(f"Restrictions: {', '.join(validators_buf)}")
pack_of_readme_lines.append(" ".join(one_row_parts))
automatic_config_readme: str = "* " + "\n* ".join(pack_of_readme_lines)
new_content = re.sub(
Expand Down
189 changes: 115 additions & 74 deletions whole_app/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,97 +62,138 @@ class StorageProviders(enum.Enum):


class SettingsOfMicroservice(BaseSettings):
app_title: typing.Literal["Spellcheck API"] = "Spellcheck API"
service_name: typing.Literal["spellcheck-microservice"] = "spellcheck-microservice"
sentry_dsn: str = pydantic.Field(
"",
description="Sentry DSN for integration. Empty field disables integration",
)
app_title: str = "Spellcheck API"
service_name: str = "spellcheck-microservice"
sentry_dsn: typing.Annotated[
str,
pydantic.Field(
description="Sentry DSN for integration. Empty field disables integration",
),
pydantic.StringConstraints(
strip_whitespace=True,
),
] = ""
api_key: typing.Annotated[
str,
pydantic.BeforeValidator(_warn_about_empty_api_key),
] = pydantic.Field(
"",
description=(
"define api key for users dictionaries mostly. "
"Please, provide, if you want to enable user dictionaries API"
),
)
api_key_header_name: str = "Api-Key"
enable_cors: bool = pydantic.Field(
default=True,
description="enable CORS for all endpoints. In docker container this option is disabled",
)
structured_logging: bool = pydantic.Field(
default=True,
description="enables structured (json) logging",
)
workers: typing.Annotated[int, pydantic.conint(gt=0, lt=301)] = pydantic.Field(
8,
description=(
"define application server workers count. "
"If you plan to use k8s and only scale with replica sets, you might want to reduce this value to `1`"
),
)
port: typing.Annotated[int, pydantic.conint(gt=1_023, lt=65_536)] = pydantic.Field(
10_113,
description="binding port",
)
pydantic.Field(
description=(
"define api key for users dictionaries mostly. "
"Please, provide, if you want to enable user dictionaries API"
),
),
] = ""
api_key_header_name: typing.Annotated[
str,
pydantic.StringConstraints(
strip_whitespace=True,
),
] = "Api-Key"
enable_cors: typing.Annotated[
bool,
pydantic.Field(
description="enable CORS for all endpoints. In docker container this option is disabled",
),
] = True
structured_logging: typing.Annotated[
bool,
pydantic.Field(
description="enables structured (json) logging",
),
] = True
workers: typing.Annotated[
int,
pydantic.Field(
gt=0,
lt=301,
description=(
"define application server workers count. "
"If you plan to use k8s and only scale with replica sets, you might want to reduce this value to `1`"
),
),
] = 8
port: typing.Annotated[
int,
pydantic.Field(
gt=1_023,
lt=65_536,
description="binding port",
),
] = 10_113
cache_size: typing.Annotated[
int,
pydantic.BeforeValidator(_warn_about_poor_lru_cache_size),
] = pydantic.Field(
10_000,
description=(
"define LRU cache size for misspelled word/suggestions cache. "
"Any value less than `1` makes the cache size unlimited, so be careful with this option"
pydantic.Field(
description=(
"define LRU cache size for misspelled word/suggestions cache. "
"Any value less than `1` makes the cache size unlimited, so be careful with this option"
),
),
)
] = 10_000
api_prefix: typing.Annotated[
str,
pydantic.StringConstraints(
strip_whitespace=True,
),
pydantic.BeforeValidator(
lambda possible_value: f"/{possible_value.strip('/')}",
),
] = pydantic.Field("/api/", description="define all API's URL prefix")
docs_url: str = pydantic.Field(
"/docs/",
description="define documentation (swagger) URL prefix",
)
pydantic.Field(description="define all API's URL prefix"),
] = "/api/"
docs_url: typing.Annotated[
str,
pydantic.StringConstraints(
strip_whitespace=True,
),
pydantic.Field(
description="define documentation (swagger) URL prefix",
),
] = "/docs/"
max_suggestions: typing.Annotated[
int | None,
pydantic.conint(gt=0) | None,
] = pydantic.Field(
None,
description="defines how many maximum suggestions for each word will be available. `None` means unlimitied",
)
dictionaries_path: pathlib.Path = pydantic.Field(
pathlib.Path("/data/"),
description=(
"define directory where user dicts is stored. "
"This is inner directory in the docker image, please map it to volume as it "
"shown in the quickstart part of this readme"
),
)
dictionaries_storage_provider: StorageProviders = pydantic.Field(
StorageProviders.FILE,
description="define wich engine will store user dictionaries",
)
dictionaries_disabled: bool = pydantic.Field(
default=False,
description="switches off user dictionaries API no matter what",
)
int,
pydantic.Field(
ge=0,
description="defines how many maximum suggestions for each word will be available. 0 means unlimitied",
),
] = 0
dictionaries_path: typing.Annotated[
pathlib.Path,
pydantic.Field(
description=(
"define directory where user dicts is stored. "
"This is inner directory in the docker image, please map it to volume as it "
"shown in the quickstart part of this readme"
),
),
] = pathlib.Path("/data/")
dictionaries_storage_provider: typing.Annotated[
StorageProviders,
pydantic.Field(
description="define wich engine will store user dictionaries",
),
] = StorageProviders.FILE
dictionaries_disabled: typing.Annotated[
bool,
pydantic.Field(
description="switches off user dictionaries API no matter what",
),
] = False
current_version: typing.Annotated[
str,
pydantic.BeforeValidator(_parse_version_from_local_file),
] = ""
username_min_length: int = pydantic.Field(
3,
description="minimum length of username",
)
username_max_length: int = pydantic.Field(
60,
description="maximum length of username",
)
username_min_length: typing.Annotated[
int,
pydantic.Field(
description="minimum length of username",
),
] = 3
username_max_length: typing.Annotated[
int,
pydantic.Field(
description="maximum length of username",
),
] = 60
username_regex: str = r"^[a-zA-Z0-9-_]*$"

class Config:
Expand Down
4 changes: 3 additions & 1 deletion whole_app/spell.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,9 @@ def get_memorized_suggestions(word_spellcheck_result: SpellChecker) -> list[str]
misspelled_suggestions = word_spellcheck_result.suggest()
_MISSPELED_CACHE[word_spellcheck_result.word] = misspelled_suggestions
return (
misspelled_suggestions[: SETTINGS.max_suggestions] if SETTINGS.max_suggestions else misspelled_suggestions
misspelled_suggestions[: SETTINGS.max_suggestions]
if SETTINGS.max_suggestions > 0
else misspelled_suggestions
)

def run_check(self: "SpellCheckService") -> list[models.OneCorrection]:
Expand Down

0 comments on commit 813d830

Please sign in to comment.