Skip to main content

A dependency injection library for Python, Optimized for serverless applications

Project description

Ididi

codecov PyPI version Python Version License Downloads

A type-based, full-fledged dependency injection library.

ididi is 100% test covered and strictly typed.

coverage droped as pytest-cov does not work well with cython, but tests are still there.

📚 Docs: : https://raceychan.github.io/ididi


Install

ididi requires python >= 3.9

pip install ididi

To view viusal dependency graph, install graphviz

pip install ididi[graphviz]

Features

  • Powerful: Ididi does what alternatives do, and also provides features that others don't.
  • Performant: almost as fast as hard-coded factories, one of the fastest dependency injection framework available.
  • Noninvasive: No / minial changes to your existing code
  • Smart: inject dependency based on type hints, with strong support to typing module.
  • Correct, strictly typed, well-organized exceptions, well-formatted and detail-rich error messages

TypingSupport

ididi has strong support to typing module, includes:

  • TypedDict
  • Unpack
  • NewType
  • Annotated
  • Literal
  • Optional
  • Union

...and more.

Check out tests/features/test_typing_support.py for examples.

Usage

Quick Start

from typing import AsyncGenerator
from ididi import use, entry

async def conn_factory(engine: AsyncEngine) -> AsyncGenerator[AsyncConnection, None]:
    async with engine.begin() as conn:
        yield conn

class UnitOfWork:
    def __init__(self, conn: AsyncConnection=use(conn_factory)):
        self._conn = conn

@entry
async def main(command: CreateUser, uow: UnitOfWork):
    await uow.execute(build_query(command))

# note uow is automatically injected here
await main(CreateUser(name='user'))

To resolve AsyncConnection outside of entry function

from ididi import Graph

dg = Graph()

async with dg.ascope():
    conn = await scope.resolve(conn_factory)

Key Concepts

Marks

ididi provides two marks, use and Ignore, they are convenient shortcut for Graph.node. Technically, they are just metadata carried by typing.Annotated, and should work fine with other Annotated metadata.

use

You can use Graph.node to register a dependent with its factory, here we register dependent Database with its factory db_factory. This means whenver we call dg.resolve(Database), db_factory will be call.

def db_factory() -> Database:
    return Database()

dg = Graph()
dg.node(db_factory)

Alternatively, you can annotate it inside __init__, this allow you to instantiate Graph in a lazy manner.

from ididi import use
class Repository:
    def __init__(self, db: Annotated[Database, use(db_factory)]):
        ...

Ignore

ididi takes a "resolve by default" approach, for dependencies you would like ididi to ignore, you can config ididi to ignore them.

  • Ignore at Graph level
from datetime import datetime
from pathlib import Path

dg = Graph(ignore=(datetime, Path))
  • Ignore at Node level
dg = Graph()
class Clock:
    def __init__(self, dt: datetime): ...

dg.node(Clock, ignore=datetime)

Alternatively, you can mark a dependency using ididi.Ignore,

from ididi import Ignore

class Clock:
    def __init__(self, dt: Ignore[datetime]): ...

Function dependency

Declear a function as a dependency by using Ignore to annotate its return type.

@dataclass
class User:
    name: str
    role: str

def get_user(config: Config) -> Ignore[User]:
    assert isinstance(config, Config)
    return User("user", "admin")

def validate_admin(
    user: Annotated[User, use(get_user)], service: UserService
) -> Ignore[str]:
    assert user.role == "admin"
    assert isinstance(service, UserService)
    return "ok"

class Route:
    def __init__(self, validte_permission: Annotated[str, use(validate_admin)]):
        assert validte_permission == "ok"

assert dg.resolve(validate_admin) == "ok"
assert isinstance(dg.resolve(Route), Route)

Since get_user returns Ignore[User] instead of User, it won't be used as factory to resolve User.

Dependency factory

from ididi import use
from typing import NewType
from datetime import datetime, timezone

UserID = NewType("UserID", str)

def utc_factory() -> datetime:
    return datetime.now(timezone.utc)

def user_id_factory() -> UserID:
    return UserID(str(uuid4()))

class User:
    def __init__(self, user_id: UserID, created_at: Annotated[datetime, use(utc_factory)]):
        self.user_id = user_id
        self.created_at = created_at

user = ididi.resolve(User)
assert user.created_at.tzinfo == timezone.utc

[!TIP] Graph.node accepts a wide arrange of types, such as dependent class, sync/async facotry, sync/async resource factory, with typing support.

Scope

Scope is a temporary view of the graph specialized for handling resources.

In a nutshell:

  • Scope can access(read-only) registered singletons and resolved instances of its parent graph
  • Dependents registered/resolved in a scope will stay in the scope.
  • its parent graph can't access its registered singletons and resolved resources.

Using Scope to manage resources

  • Infinite number of nested scope
  • Parent scope can be accssed by its child scopes(within the same context)
  • Resources will be shared across dependents only withint the same scope
  • Resources will be automatically closed when the scope is exited.
  • Classes that implment contextlib.AbstractContextManager or contextlib.AbstractAsyncContextManager are also considered to be resources and can/should be resolved within scope.
  • Scopes are separated by context

[!TIP] If you have two call stack of a1 -> b1 and a2 -> b2, Here a1 and a2 are two calls to the same function a, then, in b1, you can only access scope created by the a1, not a2.

This is particularly useful when you try to separate resources by route, endpoint, request, etc.

Async scope

@dg.node
def get_resource() -> ty.Generator[Resource, None, None]:
    res = Resource()
    with res:
        yield res

@dg.node
async def get_asyncresource() -> ty.Generator[AsyncResource, None, None]:
    res = AsyncResource()
    async with res:
        yield res


with dg.scope() as scope:
    resource = scope.resolve(Resource)

# For async generator
async with dg.ascope() as scope:
    resource = await scope.resolve(AsyncResource)

[!TIP] dg.node will leave your class/factory untouched, i.e., you can use it as a function. e.g. dg.node(get_resource, reuse=False)

Contexted Scope

You can use dg.use_scope to retrive most recent scope, context-wise, this allows your to have access the scope without passing it around, e.g.

async def service_factory():
    async with dg.ascope() as scope:
        service = scope.resolve(Service)
        yield service

@app.get("users")
async def get_user(service: Service = Depends(service_factory))
    await service.create_user(...)

Then somewhere deep in your service.create_user call stack

async def create_and_publish():
    uow = dg.use_scope().resolve(UnitOfWork)
    async with uow.trans():
        user_repo.add_user(user)
        event_store.add(user_created_event)

Here dg.use_scope() would return the same scope you created in your service_factory.

Named Scope

You can create infinite level of scopes by assigning hashable name to scopes

# at the top most entry of a request
async with dg.ascope(request_id) as scope:
    ...

now scope with name request_id is accessible everywhere within the request context

request_scope = dg.use_scope(request_id)

[!NOTE] Two or more scopes with the same name would follow most recent rule.

Nested Nmaed Scope

async with dg.ascope(app_name) as app_scope:
    async with dg.ascope(router_name) as router_scope:
        async with dg.ascope(endpoint_name) as endpoint_scope:
            async with dg.ascope(user_id) as user_scope:
                async with dg.ascope(request_id) as request_scope:
                    ...

For any functions called within the request_scope, you can get the most recent scope with dg.use_scope(), or its parent scopes, i.e. dg.use_scope(app_name) to get app_scope.

Testing

Override class dependency resolution

You can control how ididi resolve a dependency during testing, by register the test double of the dependency using

  • Graph.override
  • entry.replace

Example: For the following dependent

class UserRepository:
    def __init__(self, db: DataBase):
        self.db=db

dg = Graph()
assert isinstance(dg.resolve(UserRepository).db, DataBase)

in you test file,

class FakeDB(DataBase): ...

def db_factory() -> DataBase:
    return FakeDB()


def test_resolve():
    dg = Graph()
    assert isinstance(dg.resolve(db_factory).db, DataBase)

    dg.override(DataBase, db_factory)
    assert isinstance(dg.resolve(UserRepository).db, FakeDB)

Use Graph.override to replace DataBase with its test double.

Override entry dependency resolution

async def test_entry_replace():
    @ididi.entry
    async def create_user(
        user_name: str, user_email: str, service: UserService
    ) -> UserService:
        return service

    class FakeUserService(UserService): ...

    create_user.replace(UserService, FakeUserService)

    res = await create_user("user", "user@email.com")
    assert isinstance(res, FakeUserService)

Use entryfunc.replace to replace a dependency with its test double.

Graph.override vs entry.replace

Graph.override applies to the whole graph, entry.replace applies to only the entry function.

More

For more detailed information, check out Documentation

  • Tutorial

  • Usage of factory

  • Visualize the dependency graph

  • Circular Dependency Detection

  • Error context

Project details


Release history Release notifications | RSS feed

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ididi-1.5.3.tar.gz (522.6 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

ididi-1.5.3-cp313-cp313-musllinux_1_2_x86_64.whl (3.0 MB view details)

Uploaded CPython 3.13musllinux: musl 1.2+ x86-64

ididi-1.5.3-cp313-cp313-musllinux_1_2_i686.whl (2.9 MB view details)

Uploaded CPython 3.13musllinux: musl 1.2+ i686

ididi-1.5.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (2.8 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.17+ x86-64

ididi-1.5.3-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl (2.7 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.17+ i686manylinux: glibc 2.5+ i686

ididi-1.5.3-cp312-cp312-musllinux_1_2_x86_64.whl (3.0 MB view details)

Uploaded CPython 3.12musllinux: musl 1.2+ x86-64

ididi-1.5.3-cp312-cp312-musllinux_1_2_i686.whl (2.9 MB view details)

Uploaded CPython 3.12musllinux: musl 1.2+ i686

ididi-1.5.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (2.8 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ x86-64

ididi-1.5.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl (2.7 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ i686manylinux: glibc 2.5+ i686

ididi-1.5.3-cp311-cp311-musllinux_1_2_x86_64.whl (2.9 MB view details)

Uploaded CPython 3.11musllinux: musl 1.2+ x86-64

ididi-1.5.3-cp311-cp311-musllinux_1_2_i686.whl (2.8 MB view details)

Uploaded CPython 3.11musllinux: musl 1.2+ i686

ididi-1.5.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (2.9 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.17+ x86-64

ididi-1.5.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl (2.8 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.17+ i686manylinux: glibc 2.5+ i686

ididi-1.5.3-cp310-cp310-musllinux_1_2_x86_64.whl (2.7 MB view details)

Uploaded CPython 3.10musllinux: musl 1.2+ x86-64

ididi-1.5.3-cp310-cp310-musllinux_1_2_i686.whl (2.6 MB view details)

Uploaded CPython 3.10musllinux: musl 1.2+ i686

ididi-1.5.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (2.7 MB view details)

Uploaded CPython 3.10manylinux: glibc 2.17+ x86-64

ididi-1.5.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl (2.6 MB view details)

Uploaded CPython 3.10manylinux: glibc 2.17+ i686manylinux: glibc 2.5+ i686

ididi-1.5.3-cp39-cp39-musllinux_1_2_x86_64.whl (2.7 MB view details)

Uploaded CPython 3.9musllinux: musl 1.2+ x86-64

ididi-1.5.3-cp39-cp39-musllinux_1_2_i686.whl (2.6 MB view details)

Uploaded CPython 3.9musllinux: musl 1.2+ i686

ididi-1.5.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (2.7 MB view details)

Uploaded CPython 3.9manylinux: glibc 2.17+ x86-64

ididi-1.5.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl (2.6 MB view details)

Uploaded CPython 3.9manylinux: glibc 2.17+ i686manylinux: glibc 2.5+ i686

File details

Details for the file ididi-1.5.3.tar.gz.

File metadata

  • Download URL: ididi-1.5.3.tar.gz
  • Upload date:
  • Size: 522.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.9.0

File hashes

Hashes for ididi-1.5.3.tar.gz
Algorithm Hash digest
SHA256 75a33d24a2e9188cb122bfb7de9bf55a45eb4033f94ea1fe0de0d54a00dcdc71
MD5 bce4096e796216f060ff8322a44968e8
BLAKE2b-256 11daa2bca7f16370a4b865b357e745ac7a87631b92183e700cb65ff9e496c13e

See more details on using hashes here.

File details

Details for the file ididi-1.5.3-cp313-cp313-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for ididi-1.5.3-cp313-cp313-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 6585d4e1105a5210151241404876cbc7db14abc78add374acac83a491ed2b586
MD5 6c36cf0cfe488e7c0136f714c6121ed6
BLAKE2b-256 26d89d9207a3d93b67cada1f29dc766dba3489c3017c85d2605ee43aaa7ccdbb

See more details on using hashes here.

File details

Details for the file ididi-1.5.3-cp313-cp313-musllinux_1_2_i686.whl.

File metadata

File hashes

Hashes for ididi-1.5.3-cp313-cp313-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 dba285533d73754782ef40f70cd621cde77544426ff48025bb65256c797f1878
MD5 6242fb72033a27d58902d66144c4f413
BLAKE2b-256 67b8a51ff16f16c3b27aca5cc0757f9a280845f75327c3e78d11c9abafc91e33

See more details on using hashes here.

File details

Details for the file ididi-1.5.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for ididi-1.5.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 e82806566f3cc3770ef08f446fb6a97d9946d80371f051a2aaa564eac03ce5a2
MD5 f03343ffe08c7131b4167d4642dab3f9
BLAKE2b-256 2fe67e9bad736ad1f32fc818e15d84c3ad7c92938742caf21c7cfec78feeed1e

See more details on using hashes here.

File details

Details for the file ididi-1.5.3-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl.

File metadata

File hashes

Hashes for ididi-1.5.3-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 b2f7ea21ebe0f8cb3409f8892199f0227aa7110e5a104b7af6fc5ce592fa847d
MD5 2a310fa6ce03486d6b7b4175201d34e2
BLAKE2b-256 0e328375ddecfc7fd3133545565680f42242391aa6db4eeb4add5041163bf9b0

See more details on using hashes here.

File details

Details for the file ididi-1.5.3-cp312-cp312-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for ididi-1.5.3-cp312-cp312-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 58301564cb98461eb3ca0a7761934206534af4c68be975ff70b94c91d4c460d2
MD5 4a8033d0e87bfb031041b2e27815f9fc
BLAKE2b-256 d1d5bbe0692749b43383dcbed84828c9648dfe7a407118a6310d18aa991697a6

See more details on using hashes here.

File details

Details for the file ididi-1.5.3-cp312-cp312-musllinux_1_2_i686.whl.

File metadata

File hashes

Hashes for ididi-1.5.3-cp312-cp312-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 df69c121756ed3208c2ecfef60682e11e6eacc4719a44ce435c97deac5ce5417
MD5 8d4ab873ebe2feeaa57345acdbecd1e8
BLAKE2b-256 5cea2efe6e50f047b23359011787ab9fefd3968ba00e1dfc3c0b12933966e4d7

See more details on using hashes here.

File details

Details for the file ididi-1.5.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for ididi-1.5.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 ad0b3a8ea3dd741cc959adbbd80212615411e5ffcc5927a511f388798e4a89ea
MD5 b6ac8245ca4e03b56b7dc8837082af0e
BLAKE2b-256 beadeaadcb2b50e61c8c9d8655ac5777963a79574ec2a49ba9545b57744f6b1e

See more details on using hashes here.

File details

Details for the file ididi-1.5.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl.

File metadata

File hashes

Hashes for ididi-1.5.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 873b801c022c9980088c6d2df0a3a2b8b3a72196606a9cf12b6484d7c60fd480
MD5 4d6f23e6a726227a2f14a83ddd7b71c9
BLAKE2b-256 264553e0209e61207457106359735d95f8f7103377ede657124aeba26777c09f

See more details on using hashes here.

File details

Details for the file ididi-1.5.3-cp311-cp311-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for ididi-1.5.3-cp311-cp311-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 1151cb5abd6f2c15ac1d681abca300ce490dc7e5946b63c2c007d3b92a1ca1ab
MD5 046db4bc95a11ffdbedd2ff84c256621
BLAKE2b-256 8fef3aa92132bb19ca1a365d51f6f14f573966ac23753bf9d852617fbe5bb6c4

See more details on using hashes here.

File details

Details for the file ididi-1.5.3-cp311-cp311-musllinux_1_2_i686.whl.

File metadata

File hashes

Hashes for ididi-1.5.3-cp311-cp311-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 a7037248f871ab344424e407de7e751fe4b4d6ef9ba7357b887643172ff48ee8
MD5 3b9dcbcb1c740996949f20aa1c1cbfd9
BLAKE2b-256 f21b7d24662d961d879b3c40cf6118ea43b4c010c056fa14325e70ede78b53d7

See more details on using hashes here.

File details

Details for the file ididi-1.5.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for ididi-1.5.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 18af35f2ee847cc1ba313d199e5e7f1897a7bb6cd50692a9196f6a1cce2dd930
MD5 6ad38f198251e23393f9e495a5d9aab9
BLAKE2b-256 b003569470f4b5f973bb055c2f5fb2a5eba347474a7d777373cd444215562d63

See more details on using hashes here.

File details

Details for the file ididi-1.5.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl.

File metadata

File hashes

Hashes for ididi-1.5.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 df63fb14a037b32a3b9a6a03d9e819283af920b798e39d43865bf13547eb9fc3
MD5 7004e528ddf8d99622e9ed223294116a
BLAKE2b-256 b86253c526f9672d40b3acbbd90e1e55869d81424ecf0c067ff6adbf0ad25a22

See more details on using hashes here.

File details

Details for the file ididi-1.5.3-cp310-cp310-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for ididi-1.5.3-cp310-cp310-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 e7ea5bb19a4c75873a5782ce6a27f4bd7839bcb14f6ae00d116c2fe5637f4f33
MD5 d24c2762bffc7920c00c80fca37c3a50
BLAKE2b-256 7003751f790f7eb749a789395383f447d052a21484cc971c8ea4b310b730333f

See more details on using hashes here.

File details

Details for the file ididi-1.5.3-cp310-cp310-musllinux_1_2_i686.whl.

File metadata

File hashes

Hashes for ididi-1.5.3-cp310-cp310-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 88183272d8135a677729a77885ee6c5fc4f9edb0d6d7b39f12344e1b564b477c
MD5 f8a6fe43493b9ef00294cf4b040fbad1
BLAKE2b-256 0e5633b3022824797a366436b64526004a63d8017bd783d83a0d2ae37e005bb0

See more details on using hashes here.

File details

Details for the file ididi-1.5.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for ididi-1.5.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 e6b1dc6b71fe2c72e07428e40af239134e3b1f198e8afe3063761c3f111ab112
MD5 04cc8e5d7b5a9a5684fabed7d2a14019
BLAKE2b-256 1df4e901208c8c5ad98c4ae3c584db36813de34acb23db2d6005afc11a82de06

See more details on using hashes here.

File details

Details for the file ididi-1.5.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl.

File metadata

File hashes

Hashes for ididi-1.5.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 f4d92d777b60999f083d1fa8ad20d2f05f9230c9023e8de91884e6c88c7ccb59
MD5 1d923f3a785a1283ae6d48a5f37151ed
BLAKE2b-256 00ded129f5f0a9b13e72af5533214be6748e76ea6f6ac19282e7b7f45b34555b

See more details on using hashes here.

File details

Details for the file ididi-1.5.3-cp39-cp39-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for ididi-1.5.3-cp39-cp39-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 35d7a3a8146bd589a9b3a67454978ec107a6174d0a29e4c9392a08640527faff
MD5 7e139e83ef6347a61b0e79e5a3c07c56
BLAKE2b-256 b06d8bdc8328cdcc1538b13e1eabd1c30e663a635e952c6c536f39280ea1e4c0

See more details on using hashes here.

File details

Details for the file ididi-1.5.3-cp39-cp39-musllinux_1_2_i686.whl.

File metadata

  • Download URL: ididi-1.5.3-cp39-cp39-musllinux_1_2_i686.whl
  • Upload date:
  • Size: 2.6 MB
  • Tags: CPython 3.9, musllinux: musl 1.2+ i686
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.9.0

File hashes

Hashes for ididi-1.5.3-cp39-cp39-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 bbe9d3f5eb8cba8ca6b417d175878ee2eaa27676004a5f3af6afa99d2e24ef52
MD5 65007714a6e0da1de952b42b67bac0ba
BLAKE2b-256 49cb2166d47e87865ff9e497dd284badcedc789e4b369a58b1d45735795d264c

See more details on using hashes here.

File details

Details for the file ididi-1.5.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for ididi-1.5.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 4f152e047a5d184b19e2c678d3a4e01250291a93862d414c23933fb726f87ac3
MD5 f82014f04413856bef84f0e1a6991c73
BLAKE2b-256 eee493a61884b41d92566e1c0d3ee16cdaf807b9b3daa6228ecb8d6b6fcb98e2

See more details on using hashes here.

File details

Details for the file ididi-1.5.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl.

File metadata

File hashes

Hashes for ididi-1.5.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 9dc74aee5128ff6b146981605712e514fcce4b65bf15ad1d908a15bc5a38d004
MD5 96adc888431f94156535a3fe423491b2
BLAKE2b-256 b10ebeb09d2ab681725aa5f975e1aa3602d02b233349d1464036202956a8086b

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page