DisCapTy API (Package)#

Full and complete API of the DisCapTy package.

discapty.captcha module#

class discapty.captcha.Captcha(code: str, captcha_object: discapty.captcha._CR)#

Bases: Generic[discapty.captcha._CR]

Represent a Captcha object.

Changed in version 2.0.0: The Captcha object is no longer what creates the Captcha image, it just is the representation of the Captcha that the user will face.

Changed in version 2.1.0: This class is now a generic class and requires to indicate which type it will receive. (If necessary)

code: str#
captcha_object: discapty.captcha._CR#
type: Type[discapty.captcha._CR]#
check(text: str, *, force_casing: bool = False, remove_spaces: bool = True) bool#

Check if a text is correct against the captcha code.

Parameters
  • text (str) – The answer to check against the Captcha’s code.

  • force_casing (bool) – If True, the casing must be respected. Defaults to False.

  • remove_spaces (bool) – If True, spaces will be removed when checking the answer. Defaults to True.

Returns

True if the answer is correct, False otherwise.

Return type

bool

discapty.captcha_queue module#

class discapty.captcha_queue.CaptchaQueue(generators: Union[discapty.generators.Generator[discapty.captcha_queue._GR], Iterable[discapty.generators.Generator[discapty.captcha_queue._GR]]], *, queue: Optional[Dict[str, discapty.challenge.Challenge[discapty.captcha_queue._GR]]] = None)#

Bases: Generic[discapty.captcha_queue._GR]

A safe handler for taking cares of managing the challenges for the developer.

It basically offers a sane & internal way to manage your captcha using a key-value pair without ever having to touch the challenges/captcha directly.

Parameters
Raises

ValueError – If no generators has been passed.

New in version 2.0.0.

Changed in version 2.1.0: This class is now a generic class and requires to indicate which type it will receive. (If necessary) If the type is not especially indicated in your variable, it should be automatically done.

generators: List[discapty.generators.Generator[discapty.captcha_queue._GR]]#
queue: Dict[str, discapty.challenge.Challenge[discapty.captcha_queue._GR]]#
create_challenge(challenge_id: Optional[str] = None, *, retries: Optional[int] = None, code: Optional[str] = None, code_length: Optional[int] = None) discapty.challenge.Challenge[discapty.captcha_queue._GR]#

Create a challenge for an id. Overwrite the challenge created before, unless the challenge is not fully completed.

Parameters
  • challenge_id (Optional, str) – The id associated to the challenge. If not given, a random id will be generated.

  • retries (Optional, int) – The number of allowed retries. Defaults to 3.

  • code (Optional, str) – The code to use. Defaults to a random code.

  • code_length (Optional, int) – The length of the code to generate if no code is supplied. Defaults to 4.

Returns

The generated challenge.

Return type

discapty.challenge.Challenge

Changed in version 2.1.0: The return type will now be dynamically acquired and adapt to the given generator(s).

get_challenge(challenge_id: str) discapty.challenge.Challenge[discapty.captcha_queue._GR]#

Get the challenge of an id, if it exist.

Parameters

challenge_id (str) – The id associated to the challenge.

Raises

UnexistingChallengeError – If the given id does not have any associated challenge.

Returns

The challenge associated to the id.

Return type

discapty.challenge.Challenge

Changed in version 2.1.0: The return type will now be dynamically acquired and adapt to the given generator(s).

delete_challenge(challenge_id: str) None#

Delete a challenge of an id, if it exist.

Parameters

challenge_id (int) – The id associated to the challenge.

Raises

UnexistingChallengeError – If the given id does not have any associated challenge.

discapty.challenge module#

class discapty.challenge.FailReason(value)#

Bases: enum.Enum

An enum with all possible reasons of failing the captcha.

TOO_MANY_RETRIES = 'Too many retries'#
CANCELLED = 'Challenge has been cancelled'#
class discapty.challenge.States(value)#

Bases: enum.Enum

An enum representing the different states of a challenge.

Available states are:

  • PENDING : The challenge is waiting to begin.

  • WAITING : The challenge is waiting for user’s input.

  • COMPLETED : The challenge has been completed.

  • FAILED : The challenge has been failed without trouble.

  • FAILURE : The challenge has been completed without user’s input and in an unexpected way. (e.g. manually cancelled)

PENDING = 'Pending'#
WAITING = 'Waiting'#
COMPLETED = 'Completed'#
FAILED = 'Failed'#
FAILURE = 'Failure (Unexpected)'#
class discapty.challenge.Challenge(generator: discapty.generators.Generator[discapty.challenge._CR], challenge_id: Optional[str] = None, *, allowed_retries: Optional[int] = None, code: Optional[str] = None, code_length: Optional[int] = None)#

Bases: Generic[discapty.challenge._CR]

Representation of a challenge. A challenge represent the user’s Captcha question-answer he must face.

This class takes cares of:
  • Generating the captcha

  • Verify inputs

  • Manage the “Captcha” object

It frees your mind from managing all the process of a captcha challenge, keeping your code short and easy.

Parameters
  • generator (Subclass of discapty.generators.Generator) – The generator class to use.

  • challenge_id (Optional, str) – The id of the challenge. Can be a string or an id. If none is supplied, a random UUID will be generated.

  • allowed_retries (Optional, int) – The number of retries allowed. Defaults to 3.

  • code (Optional, str) – The code to use. If none is supplied, a random code will be generated.

  • code_length (Optional, int) – The length of the code to generate if no code is supplied. Defaults to 4.

New in version 2.0.0.

Changed in version 2.1.0: This class is now a generic class and requires to indicate which type it will receive. (If necessary) If the type is not especially indicated in your variable, it should be automatically done.

generator: discapty.generators.Generator[discapty.challenge._CR]#

The generator used with this challenge.

code: str#

The clear code.

challenge_id: str#

The ID of this challenge.

allowed_retries: int#

The total allowed retried of this challenge.

failures: int#

The total failures since this challenge has been created.

attempted_tries: int#

The total attempted tried since this challenge has been created.

state: discapty.challenge.States#

The actual state of the challenge.

fail_reason: Optional[str]#

The fail reason, if applicable.

property captcha_object: discapty.challenge._CR#

Get the Captcha object.

Returns

The Captcha object.

Return type

discapty.constants.GeneratorReturnType

property captcha: discapty.captcha.Captcha[discapty.challenge._CR]#

The Captcha class associated to this challenge.

Returns

The Captcha class.

Return type

discapty.captcha.Captcha

property is_completed: bool#

Check if the challenge has been completed or failed.

Returns

If the challenge has been completed or failed.

Return type

bool

property is_correct: Optional[bool]#

Check if the challenge has been completed. If not, return None. If failed, return False.

Returns

If the challenge has been completed with success. If not, return False. If not completed, return None.

Return type

Optional, bool

property is_wrong: Optional[bool]#

Check if the challenge has been failed. If not, return None. If completed, return False.

Returns

If the challenge has been failed. If not, return False. If not completed, return None.

Return type

Optional, bool

begin() discapty.challenge._CR#

Begins the challenge.

Raises
  • AlreadyCompletedError – If the challenge has already been completed. You cannot start a challenge twice, you need to create a new one.

  • AlreadyRunningError – If the challenge is already running.

  • TooManyRetriesError – If the number of failures is greater than the number of retries allowed. In other words, the challenge has failed.

  • ChallengeCompletionError – If the challenge had a failure. Returns the failure’s reason.

Return type

The Captcha object to send to the user.

Changed in version 2.1.0: The return type will now be dynamically acquired and adapt to the given generator.

check(answer: str, *, force_casing: bool = False, remove_spaces: bool = True) bool#

Check an answer. This will always add +1 to attempted_tries and failures if necessary.

Parameters
  • answer (str) – The answer to check against the Captcha’s code.

  • force_casing (bool) – If True, the casing must be respected. Defaults to False.

  • remove_spaces (bool) – If True, spaces will be removed when checking the answer. Defaults to True.

Raises
  • TooManyRetriesError – If the number of failures is greater than the number of retries allowed. We are still adding +1 to the failure even when raising the exception.

  • TypeError – The challenge cannot be edited (State is either not PENDING or not WAITING)

Returns

True if the answer is correct, False otherwise.

Return type

bool

reload(*, increase_attempted_tries: bool = True, increase_failures: bool = False) discapty.challenge._CR#

Reload the Challenge and its code.

This method will create a new random code + captcha object. It will also increase the attempted_tries counter if requested. By defaults, this behavior is executed.

Parameters
  • increase_attempted_tries (bool) – If True, the attempted_tries counter will be increased.

  • increase_failures (bool) – If True, the failures counter will be increased.

Raises

TypeError – If the challenge cannot be edited or is not already running.

Returns

The Captcha object to send to the user.

Return type

discapty.constants.GeneratorReturnType

Changed in version 2.1.0: The return type will now be dynamically acquired and adapt to the given generator.

cancel() None#

Cancel the challenge.

Raises

TypeError – If the challenge cannot be edited.

discapty.constants module#

discapty.errors module#

exception discapty.errors.NonexistingChallengeError#

Bases: KeyError

Raised when trying to get a challenge that does not exist. Subclass of “KeyError” as this error will appear when trying to get the challenge from a dict.

exception discapty.errors.InvalidFontError#

Bases: Exception

Raised when one or more fonts are invalid.

exception discapty.errors.ChallengeCompletionError#

Bases: Exception

Raised when a challenge has an issue regarding its completion.

exception discapty.errors.TooManyRetriesError#

Bases: discapty.errors.ChallengeCompletionError

Raised when a challenge received more retries than allowed.

exception discapty.errors.AlreadyCompletedError#

Bases: discapty.errors.ChallengeCompletionError

Raised when a challenge has already been completed.

exception discapty.errors.AlreadyRunningError#

Bases: discapty.errors.ChallengeCompletionError

Raised when a challenge is already running.

discapty.generators module#

discapty.generators.random() x in the interval [0, 1).#
class discapty.generators.Generator#

Bases: abc.ABC, pydantic.main.BaseModel, Generic[discapty.generators._GR]

Base class for all generators.

A generator is used to especially generate a Captcha object based on a given text. A generator looks like this:

class MyGenerator(Generator[str]):
    def generate(self, text: str) -> str:
        return "+".join(text)

A generator can be supplied with parameters using class’s attributes, for example:

class MyGenerator(Generator[str]):
    separator = "+"

    def generate(self, text: str) -> str:
        return self.separator.join(text)

gen1 = MyGenerator()  # Separator here is "+"
gen2 = MyGenerator(separator="-")  # Separator here is "-"

Here, separator has a default value, which can be overridden by the user, or not. If you wish to create a generator with a required value, you can use “…”, like this:

class MyGenerator(Generator[str]):
    separator: str = ...

    ...

MyGenerator(separator="+")  # Works! 👍
MyGenerator()  # Raises an error! 👎

If you wish to know more on that subject, visit Pydantic’s documentation as this is what Generator uses under the hood. https://pydantic-docs.helpmanual.io/

New in version 2.0.0.

Changed in version 2.1.0: This class is now a generic class, taking as the parameter the type output of “.generate”.

property required_keys: List[str]#

List of all child’s required keys.

Returns

The list of required keys.

Return type

List of str

property optional_keys: List[str]#

List of all child’s optional keys.

Returns

The list of optional keys.

Return type

List of str

abstract generate(text: str) discapty.generators._GR#

A method that needs to be implemented by the child class. This method will return the Captcha that the user has requested. See class’s docstring.

Parameters

text (str) – The text to generate the captcha with.

class discapty.generators.WheezyGenerator(*, fonts: Sequence[Union[pydantic.types.FilePath, str]] = ['/home/docs/checkouts/readthedocs.org/user_builds/discapty/checkouts/latest/discapty/fonts/Roboto-Regular.ttf'], fonts_size: Tuple[int, ...] = (50,), width: int = 300, height: int = 125, background_color: pydantic.color.Color = '#EEEECC', text_color: pydantic.color.Color = '#5C87B2', text_squeeze_factor: float = 0.8, noise_number: int = 30, noise_color: pydantic.color.Color = '#EEEECC', noise_level: int = 2)#

Bases: discapty.generators.Generator[PIL.Image.Image]

A wheezy image Captcha generator. Comes with many customizable settings. Easier to read than Image.

Example: https://imgur.com/a/l9V09PN

fonts: Sequence[Union[pydantic.types.FilePath, str]]#
fonts_size: Tuple[int, ...]#
width: int#
height: int#
background_color: pydantic.color.Color#
text_color: pydantic.color.Color#
text_squeeze_factor: float#
noise_number: int#
noise_color: pydantic.color.Color#
noise_level: int#
classmethod as_many_size_as_fonts(v: Tuple[int, ...], values: Dict[str, Any])#
generate(text: str) PIL.Image.Image#

Generate a wheezy image. See https://imgur.com/a/l9V09PN.

Parameters

text (str) – The text to generate the captcha with.

Returns

The captcha image.

Return type

PIL.Image.Image

class discapty.generators.ImageGenerator(*, fonts: Sequence[Union[pydantic.types.FilePath, str]] = ['/home/docs/checkouts/readthedocs.org/user_builds/discapty/checkouts/latest/discapty/fonts/Roboto-Regular.ttf'], fonts_size: Tuple[int, ...] = (50,), background_color: pydantic.color.Color = '#F7FCFD00', text_color: pydantic.color.Color = '#4712B964', number_of_dots: int = 100, width_of_dots: int = 3, number_of_curves: int = 1, width: int = 300, height: int = 125)#

Bases: discapty.generators.Generator[PIL.Image.Image]

An image Captcha generator. Comes with many customizable settings. More harder than the Wheezy generator.

Example: https://imgur.com/a/wozYgW0

fonts: Sequence[Union[pydantic.types.FilePath, str]]#
fonts_size: Tuple[int, ...]#
background_color: pydantic.color.Color#
text_color: pydantic.color.Color#
number_of_dots: int#
width_of_dots: int#
number_of_curves: int#
width: int#
height: int#
get_truefonts() Tuple[PIL.ImageFont.FreeTypeFont, ...]#
static create_noise_curve(image: PIL.Image.Image, color: pydantic.color.Color, number: int = 1) PIL.Image.Image#
static create_noise_dots(image: PIL.Image.Image, color: pydantic.color.Color, width: int = 3, number: int = 30) PIL.Image.Image#
create_captcha_image(*, chars: str) PIL.Image.Image#
generate(text: str) PIL.Image.Image#

Generate a Captcha image. See https://imgur.com/a/wozYgW0

Parameters

text (str) – The text to generate the captcha with.

Returns

The captcha image.

Return type

PIL.Image.Image

class discapty.generators.TextGenerator(*, separator: Union[str, List[str]] = '\u200b')#

Bases: discapty.generators.Generator[str]

A text-based Captcha generator. Most insecure, but it is the most tricky.

It adds a specific separator between each character of the given text. The default separator is an invisible space. (\u200B)

separator: Union[str, List[str]]#
generate(text: str) str#

Generate a Captcha text.

Parameters

text (str) – The text to generate the captcha with.

Returns

The captcha text.

Return type

str