Skip to main content

A Rust HTTP server for Python applications

Project description

granian

The Rust HTTP server for Python


Granian is a Rust HTTP server for Python applications built on top of Hyper and Tokio.

Rationale

The main reasons behind Granian design are:

  • Have a single, correct HTTP implementation, supporting versions 1, 2 (and eventually 3)
  • Provide a single package for several platforms
  • Avoid the usual Gunicorn + uvicorn + http-tools dependency composition on unix systems
  • Provide stable performance when compared to existing alternatives

Adopting Granian would thus be a good choice when:

  • wanting a modern, single dependency to serve both ASGI and WSGI applications
  • looking for the most performant way to serve your Python application under HTTP/2
  • you need great concurrency capabilities, especially with websockets
  • you care about throughput more than everything else

On the other hand, Granian won't be the ideal option if:

  • you want a pure Python solution
  • you need advanced debugging features
  • your application relies on trio or gevent
  • you're looking for ASGI extensions not (yet) implemented

Features

  • Supports ASGI/3, RSGI and WSGI interface applications
  • HTTP/1 and HTTP/2 protocols
  • HTTPS and mTLS
  • Websockets
  • Direct static files serving
  • ASGI pathsend extension

Quickstart

You can install Granian using pip:

$ pip install granian

ASGI

Create an application in your main.py:

async def app(scope, receive, send):
    assert scope['type'] == 'http'

    await send({
        'type': 'http.response.start',
        'status': 200,
        'headers': [
            [b'content-type', b'text/plain'],
        ],
    })
    await send({
        'type': 'http.response.body',
        'body': b'Hello, world!',
    })

and serve it using Granian CLI:

$ granian --interface asgi main:app

RSGI

Create an application your main.py:

async def app(scope, proto):
    assert scope.proto == 'http'

    proto.response_str(
        status=200,
        headers=[
            ('content-type', 'text/plain')
        ],
        body="Hello, world!"
    )

and serve it using Granian CLI:

$ granian --interface rsgi main:app

WSGI

Create an application your main.py:

def app(environ, start_response):
    start_response('200 OK', [('content-type', 'text/plain')])
    return [b"Hello, world!"]

and serve it using Granian CLI:

$ granian --interface wsgi main:app

Extra dependencies

Mind that Granian also provides several extra dependencies you might be interested into, in particular:

  • dotenv (allows to load environment files)
  • pname (allows to customize processes' names)
  • reload (adds reload on changes functionality)
  • rloop
  • uvloop
  • winloop

You can combine the above extras to suit your needs, eg:

$ pip install granian[pname,uvloop]

For further information, check the options below.

Options

You can check all the options provided by Granian with the --help command:

$ granian --help
Usage: granian [OPTIONS] APP

  APP  Application target to serve.  [required]

Options:
  --host TEXT                     Host address to bind to  [env var:
                                  GRANIAN_HOST; default: (127.0.0.1)]
  --port INTEGER                  Port to bind to.  [env var: GRANIAN_PORT;
                                  default: 8000]
  --uds PATH                      Unix Domain Socket to bind to.  [env var:
                                  GRANIAN_UDS]
  --uds-permissions OCTAL INTEGER
                                  Unix Domain Socket file permissions  [env
                                  var: GRANIAN_UDS_PERMISSIONS]
  --interface [asgi|asginl|rsgi|wsgi]
                                  Application interface type  [env var:
                                  GRANIAN_INTERFACE; default: (rsgi)]
  --http [auto|1|2]               HTTP version  [env var: GRANIAN_HTTP;
                                  default: (auto)]
  --ws / --no-ws                  Enable websockets handling  [env var:
                                  GRANIAN_WEBSOCKETS; default: (enabled)]
  --workers INTEGER RANGE         Number of worker processes  [env var:
                                  GRANIAN_WORKERS; default: 1; x>=1]
  --blocking-threads INTEGER RANGE
                                  Number of blocking threads (per worker)
                                  [env var: GRANIAN_BLOCKING_THREADS; x>=1]
  --blocking-threads-idle-timeout DURATION
                                  The maximum amount of time in seconds (or a
                                  human-readable duration) an idle blocking
                                  thread will be kept alive  [env var:
                                  GRANIAN_BLOCKING_THREADS_IDLE_TIMEOUT;
                                  default: 30; 5<=x<=600]
  --runtime-threads INTEGER RANGE
                                  Number of runtime threads (per worker)  [env
                                  var: GRANIAN_RUNTIME_THREADS; default: 1;
                                  x>=1]
  --runtime-blocking-threads INTEGER RANGE
                                  Number of runtime I/O blocking threads (per
                                  worker)  [env var:
                                  GRANIAN_RUNTIME_BLOCKING_THREADS; x>=1]
  --runtime-mode [auto|mt|st]     Runtime mode to use (single/multi threaded)
                                  [env var: GRANIAN_RUNTIME_MODE; default:
                                  (auto)]
  --loop [auto|asyncio|rloop|uvloop|winloop]
                                  Event loop implementation  [env var:
                                  GRANIAN_LOOP; default: (auto)]
  --task-impl [asyncio|rust]      Async task implementation to use  [env var:
                                  GRANIAN_TASK_IMPL; default: (asyncio)]
  --backlog INTEGER RANGE         Maximum number of connections to hold in
                                  backlog (globally)  [env var:
                                  GRANIAN_BACKLOG; default: 1024; x>=128]
  --backpressure INTEGER RANGE    Maximum number of requests to process
                                  concurrently (per worker)  [env var:
                                  GRANIAN_BACKPRESSURE; default:
                                  (backlog/workers); x>=1]
  --http1-buffer-size INTEGER RANGE
                                  Sets the maximum buffer size for HTTP/1
                                  connections  [env var:
                                  GRANIAN_HTTP1_BUFFER_SIZE; default: 417792;
                                  x>=8192]
  --http1-header-read-timeout INTEGER RANGE
                                  Sets a timeout (in milliseconds) to read
                                  headers  [env var:
                                  GRANIAN_HTTP1_HEADER_READ_TIMEOUT; default:
                                  30000; 1<=x<=60000]
  --http1-keep-alive / --no-http1-keep-alive
                                  Enables or disables HTTP/1 keep-alive  [env
                                  var: GRANIAN_HTTP1_KEEP_ALIVE; default:
                                  (enabled)]
  --http1-pipeline-flush / --no-http1-pipeline-flush
                                  Aggregates HTTP/1 flushes to better support
                                  pipelined responses (experimental)  [env
                                  var: GRANIAN_HTTP1_PIPELINE_FLUSH; default:
                                  (disabled)]
  --http2-adaptive-window / --no-http2-adaptive-window
                                  Sets whether to use an adaptive flow control
                                  for HTTP2  [env var:
                                  GRANIAN_HTTP2_ADAPTIVE_WINDOW; default:
                                  (disabled)]
  --http2-initial-connection-window-size INTEGER RANGE
                                  Sets the max connection-level flow control
                                  for HTTP2  [env var: GRANIAN_HTTP2_INITIAL_C
                                  ONNECTION_WINDOW_SIZE; default: 1048576;
                                  x>=1024]
  --http2-initial-stream-window-size INTEGER RANGE
                                  Sets the `SETTINGS_INITIAL_WINDOW_SIZE`
                                  option for HTTP2 stream-level flow control
                                  [env var:
                                  GRANIAN_HTTP2_INITIAL_STREAM_WINDOW_SIZE;
                                  default: 1048576; x>=1024]
  --http2-keep-alive-interval INTEGER RANGE
                                  Sets an interval (in milliseconds) for HTTP2
                                  Ping frames should be sent to keep a
                                  connection alive  [env var:
                                  GRANIAN_HTTP2_KEEP_ALIVE_INTERVAL;
                                  1<=x<=60000]
  --http2-keep-alive-timeout DURATION
                                  Sets a timeout (in seconds or a human-
                                  readable duration) for receiving an
                                  acknowledgement of the HTTP2 keep-alive ping
                                  [env var: GRANIAN_HTTP2_KEEP_ALIVE_TIMEOUT;
                                  default: 20; x>=1]
  --http2-max-concurrent-streams INTEGER RANGE
                                  Sets the SETTINGS_MAX_CONCURRENT_STREAMS
                                  option for HTTP2 connections  [env var:
                                  GRANIAN_HTTP2_MAX_CONCURRENT_STREAMS;
                                  default: 200; x>=10]
  --http2-max-frame-size INTEGER RANGE
                                  Sets the maximum frame size to use for HTTP2
                                  [env var: GRANIAN_HTTP2_MAX_FRAME_SIZE;
                                  default: 16384; x>=1024]
  --http2-max-headers-size INTEGER RANGE
                                  Sets the max size of received header frames
                                  [env var: GRANIAN_HTTP2_MAX_HEADERS_SIZE;
                                  default: 16777216; x>=1]
  --http2-max-send-buffer-size INTEGER RANGE
                                  Set the maximum write buffer size for each
                                  HTTP/2 stream  [env var:
                                  GRANIAN_HTTP2_MAX_SEND_BUFFER_SIZE; default:
                                  409600; x>=1024]
  --log / --no-log                Enable logging  [env var:
                                  GRANIAN_LOG_ENABLED; default: (enabled)]
  --log-level [critical|error|warning|warn|info|debug|notset]
                                  Log level  [env var: GRANIAN_LOG_LEVEL;
                                  default: (info)]
  --log-config FILE               Logging configuration file (json)  [env var:
                                  GRANIAN_LOG_CONFIG]
  --access-log / --no-access-log  Enable access log  [env var:
                                  GRANIAN_LOG_ACCESS_ENABLED; default:
                                  (disabled)]
  --access-log-fmt TEXT           Access log format  [env var:
                                  GRANIAN_LOG_ACCESS_FMT]
  --ssl-certificate FILE          SSL certificate file  [env var:
                                  GRANIAN_SSL_CERTIFICATE]
  --ssl-keyfile FILE              SSL key file (PKCS#8 format only)  [env var:
                                  GRANIAN_SSL_KEYFILE]
  --ssl-keyfile-password TEXT     SSL key password  [env var:
                                  GRANIAN_SSL_KEYFILE_PASSWORD]
  --ssl-protocol-min [tls1.2|tls1.3]
                                  Set the minimum supported protocol for SSL
                                  connections.  [env var:
                                  GRANIAN_SSL_PROTOCOL_MIN; default: (tls1.3)]
  --ssl-ca FILE                   Root SSL cerificate file for client
                                  verification  [env var: GRANIAN_SSL_CA]
  --ssl-crl FILE                  SSL CRL file(s)  [env var: GRANIAN_SSL_CRL]
  --ssl-client-verify / --no-ssl-client-verify
                                  Verify clients SSL certificates  [env var:
                                  GRANIAN_SSL_CLIENT_VERIFY; default:
                                  (disabled)]
  --url-path-prefix TEXT          URL path prefix the app is mounted on  [env
                                  var: GRANIAN_URL_PATH_PREFIX]
  --respawn-failed-workers / --no-respawn-failed-workers
                                  Enable workers respawn on unexpected exit
                                  [env var: GRANIAN_RESPAWN_FAILED_WORKERS;
                                  default: (disabled)]
  --respawn-interval FLOAT        The number of seconds to sleep between
                                  workers respawn  [env var:
                                  GRANIAN_RESPAWN_INTERVAL; default: 3.5]
  --rss-sample-interval DURATION  The sample rate in seconds (or a human-
                                  readable duration) for the resource monitor
                                  [env var: GRANIAN_RSS_SAMPLE_INTERVAL;
                                  default: 30; 1<=x<=300]
  --rss-samples INTEGER RANGE     The number of consecutive samples to
                                  consider a worker over resource limit  [env
                                  var: GRANIAN_RSS_SAMPLES; default: 1; x>=1]
  --workers-lifetime DURATION     The maximum amount of time in seconds (or a
                                  human-readable duration) a worker will be
                                  kept alive before respawn  [env var:
                                  GRANIAN_WORKERS_LIFETIME; x>=60]
  --workers-max-rss INTEGER RANGE
                                  The maximum amount of memory (in MiB) a
                                  worker can consume before respawn  [env var:
                                  GRANIAN_WORKERS_MAX_RSS; x>=1]
  --workers-kill-timeout DURATION
                                  The amount of time in seconds (or a human-
                                  readable duration) to wait for killing
                                  workers that refused to gracefully stop
                                  [env var: GRANIAN_WORKERS_KILL_TIMEOUT;
                                  default: (disabled); 1<=x<=1800]
  --factory / --no-factory        Treat target as a factory function, that
                                  should be invoked to build the actual target
                                  [env var: GRANIAN_FACTORY; default:
                                  (disabled)]
  --working-dir DIRECTORY         Set the working directory  [env var:
                                  GRANIAN_WORKING_DIR]
  --env-files FILE                Environment file(s) to load (requires
                                  granian[dotenv] extra)  [env var:
                                  GRANIAN_ENV_FILES]
  --static-path-route TEXT        Route(s) for static file serving  [env var:
                                  GRANIAN_STATIC_PATH_ROUTE; default:
                                  (/static)]
  --static-path-mount DIRECTORY   Path(s) to mount for static file serving
                                  [env var: GRANIAN_STATIC_PATH_MOUNT]
  --static-path-dir-to-file TEXT  Serve the specified file as the index for
                                  directory listings  [env var:
                                  GRANIAN_STATIC_PATH_DIR_TO_FILE]
  --static-path-expires DURATION  Cache headers expiration (in seconds or a
                                  human-readable duration) for static file
                                  serving. 0 to disable.  [env var:
                                  GRANIAN_STATIC_PATH_EXPIRES; default: 86400;
                                  x>=0]
  --metrics / --no-metrics        Enable the prometheus metrics exporter.
                                  [env var: GRANIAN_METRICS_ENABLED; default:
                                  (disabled)]
  --metrics-scrape-interval DURATION
                                  Configure the interval for metrics
                                  collection.  [env var:
                                  GRANIAN_METRICS_SCRAPE_INTERVAL; default:
                                  15; 1<=x<=60]
  --metrics-address TEXT          Metrics exporter host address to bind to
                                  [env var: GRANIAN_METRICS_ADDRESS; default:
                                  (127.0.0.1)]
  --metrics-port INTEGER          Metrics exporter port to bind to.  [env var:
                                  GRANIAN_METRICS_PORT; default: 9090]
  --reload / --no-reload          Enable auto reload on application's files
                                  changes (requires granian[reload] extra)
                                  [env var: GRANIAN_RELOAD; default:
                                  (disabled)]
  --reload-paths PATH             Paths to watch for changes  [env var:
                                  GRANIAN_RELOAD_PATHS; default: (Working
                                  directory)]
  --reload-ignore-dirs TEXT       Names of directories to ignore changes for.
                                  Extends the default list of directories to
                                  ignore in watchfiles' default filter  [env
                                  var: GRANIAN_RELOAD_IGNORE_DIRS]
  --reload-ignore-patterns TEXT   File/directory name patterns (regex) to
                                  ignore changes for. Extends the default list
                                  of patterns to ignore in watchfiles' default
                                  filter  [env var:
                                  GRANIAN_RELOAD_IGNORE_PATTERNS]
  --reload-ignore-paths PATH      Absolute paths to ignore changes for  [env
                                  var: GRANIAN_RELOAD_IGNORE_PATHS]
  --reload-tick INTEGER RANGE     The tick frequency (in milliseconds) the
                                  reloader watch for changes  [env var:
                                  GRANIAN_RELOAD_TICK; default: 50;
                                  50<=x<=5000]
  --reload-ignore-worker-failure / --no-reload-ignore-worker-failure
                                  Ignore worker failures when auto reload is
                                  enabled  [env var:
                                  GRANIAN_RELOAD_IGNORE_WORKER_FAILURE;
                                  default: (disabled)]
  --process-name TEXT             Set a custom name for processes (requires
                                  granian[pname] extra)  [env var:
                                  GRANIAN_PROCESS_NAME]
  --pid-file FILE                 A path to write the PID file to  [env var:
                                  GRANIAN_PID_FILE]
  --version                       Show the version and exit.
  --help                          Show this message and exit.

Human-readable durations

Whenever Granian accepts a duration, it can be specified either as sole number, in which case it is interpreted as a number of seconds, or using one of the following suffixes:

suffix meaning
s seconds (same as no suffix)
m minutes
h hours
d days

Logging

Despite being a Rust project, Granian is a good Python citizen and uses the standard library's logging module to produce logs. This means you can freely configure your logging level and format using the standard idioms you probably familiar with.

As many other web servers, Granian uses two different loggers, specifically:

  • the _granian logger for runtime messages
  • the granian.access logger for access logs

Access log format

The access log format can be configured by specifying the atoms (see below) to include in a specific format. By default Granian will use [%(time)s] %(addr)s - "%(method)s %(path)s %(protocol)s" %(status)d %(dt_ms).3f as the format.

Access log atoms

The following atoms are available for use:

identifier description
addr Client remote address
time Datetime of the request
dt_ms Request duration in ms
status HTTP response status
path Request path (without query string)
query_string Request query string
method Request HTTP method
scheme Request scheme
protocol HTTP protocol version

Workers and threads

Granian offers different options to configure the number of workers and threads to be run, in particular:

  • workers: the total number of processes holding a dedicated Python interpreter that will run the application
  • blocking threads: the number of threads per worker interacting with the Python interpreter
  • runtime threads: the number of Rust threads per worker that will perform network I/O
  • runtime blocking threads: the number of Rust threads per worker involved in blocking operations. The main role of these threads is dealing with blocking I/O – like file system operations.

In general, Granian will try its best to automatically pick proper values for the threading configuration, leaving to you the responsibility to choose the number of workers you need.
There is no golden rule here, as these numbers will vastly depend both on your application behavior and the deployment target, but we can list some suggestions:

  • matching the amount of CPU cores for the workers is generally the best starting point; on containerized environments like docker or k8s is best to have 1 worker per container though and scale your containers using the relevant orchestrator;
  • the default number of runtime threads and runtime blocking threads is fine for the vast majority of applications out there; you might want to increase the first for applications dealing with several concurrently opened websockets or if you primarily use HTTP/2, and lowering the second only if you serve the same few files to a lot of connections;

In regards of blocking threads, the option is irrelevant on asynchronous protocols, as all the interop will happen with the AsyncIO event loop which will also be the one holding the GIL for the vast majority of the time, and thus the value is fixed to a single thread; on synchronous protocols like WSGI instead, it will be the maximum amount of threads interacting – and thus trying to acquire the GIL – with your application code. All those threads will be spawned on-demand depending on the amount of concurrency, and they'll be shutdown after the amount of inactivity time specified with the relevant setting.
In general, and unless you have a very specific use-case to do so (for example, if your application have an average millisecond response, a very limited amount of blocking threads usually delivers better throughput) you should avoid to tune this threadpool size and configure a backpressure value that suits your needs instead. In that regards, please check the next section.

Also, you should generally avoid to configure workers and threads based on numbers suggested for other servers, as Granian architecture is quite different from projects like Gunicorn or Uvicorn.

Backpressure

Since Granian runs a separated Rust runtime aside of your application that will handle I/O and "send work" to the Python interpreter, a mechanism to avoid pushing more work that what the Python interpreter can actually do is provided: backpressure.

Backpressure in Granian operates at the single worker's connections accept loop, practically interrupting the loop in case too many requests are waiting to be processed down the line. You can think of it as a secondary backlog, handled by Granian itself in addition to the network stack one provided by the OS kernel (and configured with apposite parameter).

While on asynchronous protocols, the default value for the backpressure should work fine for the vast majority of applications, as work will be handled and suspended by the AsyncIO event loop, on synchronous protocols there's no way to predict the amount of interrupts (and thus GIL releases) your application would do on a single request, and thus you should configure a value that makes sense in your environment. For example, if your WSGI application never does I/O within a request-reponse flow, then you can't really go beyond serial, and thus any backpressure value above 2 wouldn't probably make any difference, as all the requests will just be waiting to acquire the GIL in order to be processed. On the other hand, if your application makes external network requests within the standard request-response flow, a large backpressure can help, as during the time spent on those code paths you can still process other requests. Another example would be if your application communicate with a database, and you have a limited amount of connections that can be opened to that database: in this case setting the backpressure to that value would definitely be the best option.

In general, think of backpressure as the maximum amount of concurrency you want to handle (per worker) in your application, after which Granian will halt and wait before pushing more work.

Warning: since backpressure interacts with the accept loop, it will limit connections, not the single requests. Keep-alive connections will handle multiple requests within a single connection, but Granian won't count those requests in the actual pressure. This also means, if you typically have several long-running keep-alive connections to your service (for example, if you run behind a reverse proxy), a backpressure value can prevent Granian to accept new connections once the amount of keep-alive connections reaches that limit. Under this circumstances, you want to ensure the configured backpressure is higher than the expected amount of keep-alive connections, and if you're trying to limit the concurrency, it's probably better to configure the blocking threads number rather than the backpressure itself.

Runtime mode

Granian offers two different runtime threading paradigms, due to the fact the runtime can be multi-threaded – in opposition to what happens in Python event-loop which can only run as a single thread.

Given you specify N threads with the relevant option, in st mode Granian will spawn N single-threaded Rust runtimes, while in mt mode Granian will spawn a single multi-threaded runtime with N threads.

Benchmarks suggests st mode to be more efficient with a small amount of processes, while mt mode seems to scale more efficiently where you have a large number of CPUs. Real performance will though depend on specific application code, and thus your mileage might vary.

By default (auto mode), Granian will pick the best option based on the rest of its configuration.

Metrics

Granian exposes the following runtime metrics in Prometheus format. All the metrics are prefixed with granian_, and the ones marked with worker scope are tagged with a worker label containing the worker ID.

metric name type unit scope description
workers_spawns counter absolute number global Number of times Granian spawned a worker
workers_respawns_for_err counter absolute number global Number of times Granian respawned a worker due to an error
workers_respawns_for_lifetime counter absolute number global Number of times Granian respawned a worker due to exceeding lifetime
workers_respawns_for_rss counter absolute number global Number of times Granian respawned a worker due to exceeding resources usage
workers_respawns_for_lifetime counter absolute number global Number of times Granian respawned a worker due to exceeding lifetime
worker_lifetime counter seconds worker Current lifetime of the worker
connections_active gauge absolute number worker Number of active connections
connections_handled counter absolute number worker Number of accepted connections
connections_err gauge absolute number worker Number of failed connections
requests_handled counter absolute number worker Number of processed requests
static_requests_handled counter absolute number worker Number of processed requests for static files
static_requests_err counter absolute number worker Number of requests for static files resulted in a non 200 response code
blocking_threads gauge absolute number worker Current number of blocking threads in the pool (on async protocols this is always 1)
blocking_queue gauge absolute number worker Number of pending tasks for the blocking threadpool
blocking_idle_cumulative counter microseconds worker Cumulative idle time spent in the blocking threadpool
blocking_busy_cumulative counter microseconds worker Cumulative busy time spent in the blocking threadpool
py_wait_cumulative counter microseconds worker Cumulative time spent waiting on GIL (on the free-threaded build this is always 0)

Static files

Granian offers the ability to offload static files serving directly to the server, without calling your Python application in the process.

The --static-path-route and --static-path-mount options accept multiple values, thus you can serve an arbitrary number of static locations in your application, the only condition being the number of routes and mounts specified should be the same:

$ granian \
    --static-path-route /static \
    --static-path-mount assets/static \
    --static-path-route /media \
    --static-path-mount assets/media \
    package:app

Serving a specific file for directory listings

Granian also provides the option to rewrite a static location pointing to a directory to a file contained in such directory. This allows you to serve, for example, an index.html file in the static path tree:

$ granian \
    --static-path-route /docs \
    --static-path-mount generated/docs \
    --static-path-dir-to-file index.html \
    package:app

Note: while Granian performs a rewrite on the target directory, the file will still be served if the request path points to it directly (in the example above, requests pointing to /docs/somefolder and /docs/somefolder/index.html will both respond with the contents of index.html – if present). Also, the option will enable this behavior on all the static paths defined.

Proxies and forwarded headers

Since none of the supported applications protocols define a strategy for proxies' forwarded headers, Granian doesn't provide any option to configure its behaviour around them.

What Granian provides instead, for contexts in which is being run behind a reverse proxy, are wrappers you can use on top of your application, in order to alter the request scope based on the headers forwarded by the proxy itself. You can find such wrappers in the granian.utils.proxies module:

from granian.utils.proxies import wrap_asgi_with_proxy_headers, wrap_wsgi_with_proxy_headers

async def my_asgi_app(scope, receive, send):
    ...

def my_wsgi_app(environ, start_response):
    ...

my_asgi_app = wrap_asgi_with_proxy_headers(my_asgi_app, trusted_hosts="1.2.3.4")
my_wsgi_app = wrap_wsgi_with_proxy_headers(my_wsgi_app, trusted_hosts="1.2.3.4")

With these wrappers, Granian will use:

and replace the relevant request scope attributes with these values.

Since altering the request scope based on values from headers is security-sensitive, Granian will check the request is coming from a trusted host as specified by the trusted_hosts argument. By default this value is set to 127.0.0.1, which means Granian will only intercept those headers if the proxy resides on the same machine, but most likely that's not the case in a production environment: you should thus provide the correct set of addresses to the wrappers.

The trusted_hosts argument accepts either a string or a list of strings, where valid values are IP addresses (for example, 192.0.2.1 or fd12:3456:789a::1) and CIDR ranges (for example, 192.0.2.0/24 or 2001:db8:abcd::/48). The special catch-all value "*" (or ["*"]) will make Granian trust all hosts and effectively disable the security check.

Free-threaded Python

Warning: free-threaded Python support is still experimental and highly discouraged in production environments.

Since version 2.0 Granian supports free-threaded Python. While the installation process remains the same, as wheels for the free-threaded version are published separately, here we list some key differences from the GIL version.

  • Workers are threads instead of separated processes, so there will always be a single Python interpreter running
  • The application is thus loaded a single time and shared between workers
  • In asynchronous protocols like ASGI and RSGI each worker runs its own AsyncIO event loop like the GIL version, but the loop will run in the worker thread instead of the Python main thread

Note: if for any reason the GIL gets enabled on the free-threaded build, Granian will refuse to start. This means you can't use the free-threaded build on GIL enabled interpreters.

While for asynchronous protocols nothing really changes in terms of workers and threads configuration, as the scaling will be still driven by the number of AsyncIO event loops running (so the same rules for GIL workers apply), on synchronous protocols like WSGI every GIL-related limitation is theoretically absent.
While the general rules in terms of I/O-bound vs CPU-bound load still apply, at the time being there's not enough data to make suggestions in terms of workers and threads tuning in the free-threaded Python land, and thus you will need to experiment with those values depending on your specific workload.

Customising Granian

Running Granian directly from Python instead of its CLI gives you access to some customization interfaces that let you alter its standard behaviour.

AsyncIO event loop initialization

As soon as you run Granian directly from Python instead of its CLI, you can customise the default event loop initialisation policy by overwriting the auto policy. Let's say, for instance, you want to use the selector event loop on Windows:

import asyncio
from granian import Granian, loops

@loops.register('auto')
def build_loop():
    asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
    return asyncio.new_event_loop()


Granian(...).serve()

Hooks

Granian provides hooks registration interfaces to run code during specific phases of its lifecycle. Specifically, you have the following methods available:

  • on_startup
  • on_shutdown
  • on_reload

The mentioned methods accept a callable with no arguments that will be invoked during the relevant lifecycle phases. You can register your hooks simply passing them to the relevant method:

from granian import Granian

def my_hook():
    print("hello from reload!")

server = Granian(...)
server.on_reload(my_hook)

Embedding Granian in your project

For projects requiring advance lifecycle management, or implementing their own process management strategy, Granian provides an embeddable server implementation, which provides async interfaces and won't spawn workers as processes or threads, but will run them as AsyncIO tasks.

Warning: the embeddable server is still experimental.

Note: the embeddable server only supports async protocols, thus WSGI is not supported. It's also limited to a single worker, as it runs over an existing event loop.

To embed Granian in your project, you can import the server from the relevant module:

from granian.server.embed import Server

server = Server(my_app, interface="asgi")

async def my_main():
    await server.serve()

Note: as you might already figured out, the embed server accepts the application object as its first argument, instead of the import target string of the standard servers.

Given the serve method is now async, the embeddable server also provides two methods to manage its lifecycle, specifically:

  • stop
  • reload

The idea is that you can spawn the server as a task, and later on interact with it in your own process loop:

async def my_main():
    server_task = asyncio.create_task(server.serve())
    await my_logic()
    server.stop()
    await server_task

Project status

Granian is being actively maintained and is compatible with Python 3.10 and above versions.

Granian follows a semantic versioning scheme for its releases, with a {major}.{minor}.{patch} scheme for versions numbers, where:

  • major versions might introduce breaking changes
  • minor versions introduce new features and backward compatible changes
  • patch versions only introduce bug and security fixes

Mind that bug and security fixes are usually provided for the latest minor version only.

Granian is used in production by projects like paperless-ngx, reflex, searxng and Weblate, and by companies like Microsoft, Mozilla and Sentry.

License

Granian is released under the BSD License.

Project details


Download files

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

Source Distribution

granian-2.7.6.tar.gz (128.7 kB view details)

Uploaded Source

Built Distributions

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

granian-2.7.6-pp311-pypy311_pp73-win_amd64.whl (4.0 MB view details)

Uploaded PyPyWindows x86-64

granian-2.7.6-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl (7.0 MB view details)

Uploaded PyPymusllinux: musl 1.1+ x86-64

granian-2.7.6-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl (7.4 MB view details)

Uploaded PyPymusllinux: musl 1.1+ ARMv7l

granian-2.7.6-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl (7.1 MB view details)

Uploaded PyPymusllinux: musl 1.1+ ARM64

granian-2.7.6-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl (7.1 MB view details)

Uploaded PyPymanylinux: glibc 2.28+ ARM64

granian-2.7.6-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (6.9 MB view details)

Uploaded PyPymanylinux: glibc 2.17+ x86-64

granian-2.7.6-pp311-pypy311_pp73-macosx_11_0_arm64.whl (6.2 MB view details)

Uploaded PyPymacOS 11.0+ ARM64

granian-2.7.6-pp311-pypy311_pp73-macosx_10_12_x86_64.whl (6.5 MB view details)

Uploaded PyPymacOS 10.12+ x86-64

granian-2.7.6-cp314-cp314t-win_amd64.whl (4.0 MB view details)

Uploaded CPython 3.14tWindows x86-64

granian-2.7.6-cp314-cp314t-musllinux_1_1_x86_64.whl (6.9 MB view details)

Uploaded CPython 3.14tmusllinux: musl 1.1+ x86-64

granian-2.7.6-cp314-cp314t-musllinux_1_1_armv7l.whl (7.4 MB view details)

Uploaded CPython 3.14tmusllinux: musl 1.1+ ARMv7l

granian-2.7.6-cp314-cp314t-musllinux_1_1_aarch64.whl (7.0 MB view details)

Uploaded CPython 3.14tmusllinux: musl 1.1+ ARM64

granian-2.7.6-cp314-cp314t-manylinux_2_28_aarch64.whl (6.8 MB view details)

Uploaded CPython 3.14tmanylinux: glibc 2.28+ ARM64

granian-2.7.6-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (6.7 MB view details)

Uploaded CPython 3.14tmanylinux: glibc 2.17+ x86-64

granian-2.7.6-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (7.2 MB view details)

Uploaded CPython 3.14tmanylinux: glibc 2.17+ ARMv7l

granian-2.7.6-cp314-cp314t-manylinux_2_12_i686.manylinux2010_i686.whl (6.3 MB view details)

Uploaded CPython 3.14tmanylinux: glibc 2.12+ i686

granian-2.7.6-cp314-cp314t-macosx_11_0_arm64.whl (6.0 MB view details)

Uploaded CPython 3.14tmacOS 11.0+ ARM64

granian-2.7.6-cp314-cp314t-macosx_10_12_x86_64.whl (6.4 MB view details)

Uploaded CPython 3.14tmacOS 10.12+ x86-64

granian-2.7.6-cp314-cp314-win_amd64.whl (4.1 MB view details)

Uploaded CPython 3.14Windows x86-64

granian-2.7.6-cp314-cp314-musllinux_1_1_x86_64.whl (7.1 MB view details)

Uploaded CPython 3.14musllinux: musl 1.1+ x86-64

granian-2.7.6-cp314-cp314-musllinux_1_1_armv7l.whl (7.4 MB view details)

Uploaded CPython 3.14musllinux: musl 1.1+ ARMv7l

granian-2.7.6-cp314-cp314-musllinux_1_1_aarch64.whl (7.2 MB view details)

Uploaded CPython 3.14musllinux: musl 1.1+ ARM64

granian-2.7.6-cp314-cp314-manylinux_2_28_aarch64.whl (7.2 MB view details)

Uploaded CPython 3.14manylinux: glibc 2.28+ ARM64

granian-2.7.6-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (7.0 MB view details)

Uploaded CPython 3.14manylinux: glibc 2.17+ x86-64

granian-2.7.6-cp314-cp314-manylinux_2_17_i686.manylinux2014_i686.whl (6.5 MB view details)

Uploaded CPython 3.14manylinux: glibc 2.17+ i686

granian-2.7.6-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (7.3 MB view details)

Uploaded CPython 3.14manylinux: glibc 2.17+ ARMv7l

granian-2.7.6-cp314-cp314-macosx_11_0_arm64.whl (6.2 MB view details)

Uploaded CPython 3.14macOS 11.0+ ARM64

granian-2.7.6-cp314-cp314-macosx_10_12_x86_64.whl (6.5 MB view details)

Uploaded CPython 3.14macOS 10.12+ x86-64

granian-2.7.6-cp313-cp313t-win_amd64.whl (4.0 MB view details)

Uploaded CPython 3.13tWindows x86-64

granian-2.7.6-cp313-cp313t-musllinux_1_1_x86_64.whl (6.9 MB view details)

Uploaded CPython 3.13tmusllinux: musl 1.1+ x86-64

granian-2.7.6-cp313-cp313t-musllinux_1_1_armv7l.whl (7.4 MB view details)

Uploaded CPython 3.13tmusllinux: musl 1.1+ ARMv7l

granian-2.7.6-cp313-cp313t-musllinux_1_1_aarch64.whl (7.1 MB view details)

Uploaded CPython 3.13tmusllinux: musl 1.1+ ARM64

granian-2.7.6-cp313-cp313t-manylinux_2_28_aarch64.whl (6.8 MB view details)

Uploaded CPython 3.13tmanylinux: glibc 2.28+ ARM64

granian-2.7.6-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (6.7 MB view details)

Uploaded CPython 3.13tmanylinux: glibc 2.17+ x86-64

granian-2.7.6-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (7.2 MB view details)

Uploaded CPython 3.13tmanylinux: glibc 2.17+ ARMv7l

granian-2.7.6-cp313-cp313t-manylinux_2_12_i686.manylinux2010_i686.whl (6.3 MB view details)

Uploaded CPython 3.13tmanylinux: glibc 2.12+ i686

granian-2.7.6-cp313-cp313t-macosx_11_0_arm64.whl (6.1 MB view details)

Uploaded CPython 3.13tmacOS 11.0+ ARM64

granian-2.7.6-cp313-cp313t-macosx_10_12_x86_64.whl (6.3 MB view details)

Uploaded CPython 3.13tmacOS 10.12+ x86-64

granian-2.7.6-cp313-cp313-win_amd64.whl (4.1 MB view details)

Uploaded CPython 3.13Windows x86-64

granian-2.7.6-cp313-cp313-musllinux_1_1_x86_64.whl (7.0 MB view details)

Uploaded CPython 3.13musllinux: musl 1.1+ x86-64

granian-2.7.6-cp313-cp313-musllinux_1_1_armv7l.whl (7.4 MB view details)

Uploaded CPython 3.13musllinux: musl 1.1+ ARMv7l

granian-2.7.6-cp313-cp313-musllinux_1_1_aarch64.whl (7.2 MB view details)

Uploaded CPython 3.13musllinux: musl 1.1+ ARM64

granian-2.7.6-cp313-cp313-manylinux_2_28_aarch64.whl (7.2 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.28+ ARM64

granian-2.7.6-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (6.9 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.17+ x86-64

granian-2.7.6-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl (6.5 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.17+ i686

granian-2.7.6-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (7.2 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.17+ ARMv7l

granian-2.7.6-cp313-cp313-macosx_11_0_arm64.whl (6.2 MB view details)

Uploaded CPython 3.13macOS 11.0+ ARM64

granian-2.7.6-cp313-cp313-macosx_10_12_x86_64.whl (6.5 MB view details)

Uploaded CPython 3.13macOS 10.12+ x86-64

granian-2.7.6-cp312-cp312-win_amd64.whl (4.1 MB view details)

Uploaded CPython 3.12Windows x86-64

granian-2.7.6-cp312-cp312-musllinux_1_1_x86_64.whl (7.0 MB view details)

Uploaded CPython 3.12musllinux: musl 1.1+ x86-64

granian-2.7.6-cp312-cp312-musllinux_1_1_armv7l.whl (7.4 MB view details)

Uploaded CPython 3.12musllinux: musl 1.1+ ARMv7l

granian-2.7.6-cp312-cp312-musllinux_1_1_aarch64.whl (7.2 MB view details)

Uploaded CPython 3.12musllinux: musl 1.1+ ARM64

granian-2.7.6-cp312-cp312-manylinux_2_28_aarch64.whl (7.2 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.28+ ARM64

granian-2.7.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (6.9 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ x86-64

granian-2.7.6-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl (6.5 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ i686

granian-2.7.6-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (7.2 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ ARMv7l

granian-2.7.6-cp312-cp312-macosx_11_0_arm64.whl (6.2 MB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

granian-2.7.6-cp312-cp312-macosx_10_12_x86_64.whl (6.5 MB view details)

Uploaded CPython 3.12macOS 10.12+ x86-64

granian-2.7.6-cp311-cp311-win_amd64.whl (4.0 MB view details)

Uploaded CPython 3.11Windows x86-64

granian-2.7.6-cp311-cp311-musllinux_1_1_x86_64.whl (7.0 MB view details)

Uploaded CPython 3.11musllinux: musl 1.1+ x86-64

granian-2.7.6-cp311-cp311-musllinux_1_1_armv7l.whl (7.3 MB view details)

Uploaded CPython 3.11musllinux: musl 1.1+ ARMv7l

granian-2.7.6-cp311-cp311-musllinux_1_1_aarch64.whl (7.2 MB view details)

Uploaded CPython 3.11musllinux: musl 1.1+ ARM64

granian-2.7.6-cp311-cp311-manylinux_2_28_aarch64.whl (7.1 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.28+ ARM64

granian-2.7.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (7.0 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.17+ x86-64

granian-2.7.6-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl (6.5 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.17+ i686

granian-2.7.6-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (7.2 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.17+ ARMv7l

granian-2.7.6-cp311-cp311-macosx_11_0_arm64.whl (6.2 MB view details)

Uploaded CPython 3.11macOS 11.0+ ARM64

granian-2.7.6-cp311-cp311-macosx_10_12_x86_64.whl (6.5 MB view details)

Uploaded CPython 3.11macOS 10.12+ x86-64

granian-2.7.6-cp310-cp310-win_amd64.whl (4.0 MB view details)

Uploaded CPython 3.10Windows x86-64

granian-2.7.6-cp310-cp310-musllinux_1_1_x86_64.whl (7.0 MB view details)

Uploaded CPython 3.10musllinux: musl 1.1+ x86-64

granian-2.7.6-cp310-cp310-musllinux_1_1_armv7l.whl (7.3 MB view details)

Uploaded CPython 3.10musllinux: musl 1.1+ ARMv7l

granian-2.7.6-cp310-cp310-musllinux_1_1_aarch64.whl (7.1 MB view details)

Uploaded CPython 3.10musllinux: musl 1.1+ ARM64

granian-2.7.6-cp310-cp310-manylinux_2_28_aarch64.whl (7.1 MB view details)

Uploaded CPython 3.10manylinux: glibc 2.28+ ARM64

granian-2.7.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (7.0 MB view details)

Uploaded CPython 3.10manylinux: glibc 2.17+ x86-64

granian-2.7.6-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl (6.5 MB view details)

Uploaded CPython 3.10manylinux: glibc 2.17+ i686

granian-2.7.6-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (7.2 MB view details)

Uploaded CPython 3.10manylinux: glibc 2.17+ ARMv7l

granian-2.7.6-cp310-cp310-macosx_11_0_arm64.whl (6.2 MB view details)

Uploaded CPython 3.10macOS 11.0+ ARM64

granian-2.7.6-cp310-cp310-macosx_10_12_x86_64.whl (6.5 MB view details)

Uploaded CPython 3.10macOS 10.12+ x86-64

File details

Details for the file granian-2.7.6.tar.gz.

File metadata

  • Download URL: granian-2.7.6.tar.gz
  • Upload date:
  • Size: 128.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for granian-2.7.6.tar.gz
Algorithm Hash digest
SHA256 52c8eaa5bdd636535c4c50b62591420612297f38151786cffd8c8cd39c738da3
MD5 7a4fa7fe8d1a25da2eb39af9b36c8de0
BLAKE2b-256 5c4b7c27442d6377607bec0802dcc1ee73554f1b3982ed6fca3dab253bee55d4

See more details on using hashes here.

File details

Details for the file granian-2.7.6-pp311-pypy311_pp73-win_amd64.whl.

File metadata

File hashes

Hashes for granian-2.7.6-pp311-pypy311_pp73-win_amd64.whl
Algorithm Hash digest
SHA256 378bd11f4c29abfc5f9851ed66294246d9780e3023a4257cc7d854b5717fc9fb
MD5 478aa8ca5455d7d224ef7bdae2559559
BLAKE2b-256 a6ea5ffbaf30f362dd372e6ca2ce663d12da7cf4ab4510f7512fb0e6a9b86d08

See more details on using hashes here.

File details

Details for the file granian-2.7.6-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl.

File metadata

File hashes

Hashes for granian-2.7.6-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 d0446e02ff9f09c8b9f58f1a5fa68b65d4074dd9c30bb114cc2a0f85d99fd1e2
MD5 b495a08868bd468a6bc383f47e88dd8a
BLAKE2b-256 b0d67bc0da726092a53f3385faca77820726ede03247328b30d82e4e1a1f00d7

See more details on using hashes here.

File details

Details for the file granian-2.7.6-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl.

File metadata

File hashes

Hashes for granian-2.7.6-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl
Algorithm Hash digest
SHA256 8299b0d6b40695489134b6e3fcd0b8e218fa8ed106cd24feb7c087f784b0628d
MD5 ea957105ec8e086ddeb7577162aada5a
BLAKE2b-256 3e574d68444563e018cf817e9ddb3b1e6fbcfa5ccb66a2338f3ef8e7885c31a9

See more details on using hashes here.

File details

Details for the file granian-2.7.6-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl.

File metadata

File hashes

Hashes for granian-2.7.6-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl
Algorithm Hash digest
SHA256 7134e556f3ace7c24cfa9fd1f02806a97de1bbd6d010f406f07b5e26b68b5c27
MD5 5b35a1575cc17c61f0983f390e13a321
BLAKE2b-256 2f53fceafccca5596a99dd7473175ee1335768c7a5e97d0bd3c6d078d75238ad

See more details on using hashes here.

File details

Details for the file granian-2.7.6-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for granian-2.7.6-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 d22f4b3d9959d3319643c3818a698eea883fe921f98440d825717d73c4e02fd0
MD5 b18ed82302ce100cbb1579e2074e411b
BLAKE2b-256 47ab9027c0456d28ac89983384f5cfd7cffde35319de2834f3021bfd8f131b7e

See more details on using hashes here.

File details

Details for the file granian-2.7.6-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for granian-2.7.6-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 277ba2ac559e6076fa28ba044974454473e1f020529dc1c65d501d326c7500af
MD5 ae1198eaf2d1eac9e19df0ffd8a895da
BLAKE2b-256 5ec1c3a4397aba2dc4990aa930cf52cbc36d04ba292eab770a9d6ae62a635f6f

See more details on using hashes here.

File details

Details for the file granian-2.7.6-pp311-pypy311_pp73-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for granian-2.7.6-pp311-pypy311_pp73-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 c0902fd91455e581de1096f7f79142ca2a06d019871721005df476bec5bfffd4
MD5 78b55007b704e8ffc6a1ad5edc60cabc
BLAKE2b-256 1c5eb3f789a1576b523f494f321b360d12ce290df8b13165e05aa35b52544c47

See more details on using hashes here.

File details

Details for the file granian-2.7.6-pp311-pypy311_pp73-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for granian-2.7.6-pp311-pypy311_pp73-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 3725497cfb19cd4bd2cb05fada5419bb309fb79a96748e379f7a58d5312402ef
MD5 7bbcbdacabf152fb92ada82970dd50c6
BLAKE2b-256 c253d8154fc25038672daefbab99f9d719befac36fdba4a4c150b628e860ef9f

See more details on using hashes here.

File details

Details for the file granian-2.7.6-cp314-cp314t-win_amd64.whl.

File metadata

  • Download URL: granian-2.7.6-cp314-cp314t-win_amd64.whl
  • Upload date:
  • Size: 4.0 MB
  • Tags: CPython 3.14t, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for granian-2.7.6-cp314-cp314t-win_amd64.whl
Algorithm Hash digest
SHA256 2744c81401641b77d5a2957a683cdc21ef053fb74defa0f53b60cfc1134d2115
MD5 25dc5cb0a99121190fe8394a702b47ee
BLAKE2b-256 1f024f0ef1d8c86a2b23926853791ee54df8d97a70fe2ec027c1be0b0cddc40f

See more details on using hashes here.

File details

Details for the file granian-2.7.6-cp314-cp314t-musllinux_1_1_x86_64.whl.

File metadata

File hashes

Hashes for granian-2.7.6-cp314-cp314t-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 535fe238f8a4d148a0d9bd9d28afb6eb6ab94f955de1d156d568258e5cd9dfb6
MD5 bed782429fe9a0eaac316a4bb9c02a57
BLAKE2b-256 4c6f2052643f726ee53bc9e66eec08cd69b622b88b0c60b435f245109b74b631

See more details on using hashes here.

File details

Details for the file granian-2.7.6-cp314-cp314t-musllinux_1_1_armv7l.whl.

File metadata

File hashes

Hashes for granian-2.7.6-cp314-cp314t-musllinux_1_1_armv7l.whl
Algorithm Hash digest
SHA256 a7364881df5a26e3df8ec1e22e02230b02817cb5585112182749fb4a5069146d
MD5 7a874b84b5386593dd07ae65487ce379
BLAKE2b-256 de3c1a4d2439ae4c1b86c69373a32b306da9e4f053f0ca6313a2b0709d604e8e

See more details on using hashes here.

File details

Details for the file granian-2.7.6-cp314-cp314t-musllinux_1_1_aarch64.whl.

File metadata

File hashes

Hashes for granian-2.7.6-cp314-cp314t-musllinux_1_1_aarch64.whl
Algorithm Hash digest
SHA256 ae666a6a3703986231b93df7fc44a4bca9ddb6283685eda07dc8e1235d7b05e5
MD5 44b09772018c62957384f13dbc6f9dc9
BLAKE2b-256 fbefd8299ddca1c687d8009624b7944e5840f2773f728f9f2e0eac301fc04f6d

See more details on using hashes here.

File details

Details for the file granian-2.7.6-cp314-cp314t-manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for granian-2.7.6-cp314-cp314t-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 403e08987177fde21c54ad5129693045ea4c7dae47b664fcdd0afb406828d6ad
MD5 b3d900f3a091b847638eeab231494dde
BLAKE2b-256 7cb0ce1fe2b72d43b4375df6fa3f011401815a2fa294f7140a77cc1000a0e004

See more details on using hashes here.

File details

Details for the file granian-2.7.6-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for granian-2.7.6-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 7538056d589455d4fa56fee7380857e672c3684f0ab8227a6407678e62da8b32
MD5 b1f2881ecb95a04820fe94a0662199fd
BLAKE2b-256 2d4170d618ecd24493101f22e003a8172f038ed7dc2135a3dc7938bb8ecca0bb

See more details on using hashes here.

File details

Details for the file granian-2.7.6-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl.

File metadata

File hashes

Hashes for granian-2.7.6-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl
Algorithm Hash digest
SHA256 a6de1316d1194a7dd759a8ca2bf0072e9a03c4f3021eca196aa0a41c1bcc6c4c
MD5 f4ee069e6971eb3372db356f39e1b0da
BLAKE2b-256 5dccc7e04b205f0c668fe68c21a8bfaaf775a6ec4067425cd694a947e19f7f9e

See more details on using hashes here.

File details

Details for the file granian-2.7.6-cp314-cp314t-manylinux_2_12_i686.manylinux2010_i686.whl.

File metadata

File hashes

Hashes for granian-2.7.6-cp314-cp314t-manylinux_2_12_i686.manylinux2010_i686.whl
Algorithm Hash digest
SHA256 f43853e0f5be5e4c4e1b1f8bc58fa05feedfe622154faed84823b878d1b39d00
MD5 9f98d1d00a96f265f9c645f6c84927e0
BLAKE2b-256 7d1ae48b29e7b0bc53498ad6d85b7fbff0d0601289fb6284e1ad89c5e565dc23

See more details on using hashes here.

File details

Details for the file granian-2.7.6-cp314-cp314t-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for granian-2.7.6-cp314-cp314t-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 41394d5fd17623e10deb1ed54bde3395609ac9037774586d49c66793777fd5fe
MD5 a7f46a2ee9717e03b93ebe2d2532f677
BLAKE2b-256 257ffeb6c399056662597c05322fdaa7680f02ca1c308511d961c40ee3da2e8d

See more details on using hashes here.

File details

Details for the file granian-2.7.6-cp314-cp314t-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for granian-2.7.6-cp314-cp314t-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 75e1d9e47585eb1616664daced55271bd2d948ef5406d4fed0f909bb718a8a7f
MD5 c0cf9e6ecaa2d4f2ef22f66783950344
BLAKE2b-256 1882335d6f8f41caee1f88c1d81c942318c58ad956c002dd0385b5fd1ef0576b

See more details on using hashes here.

File details

Details for the file granian-2.7.6-cp314-cp314-win_amd64.whl.

File metadata

  • Download URL: granian-2.7.6-cp314-cp314-win_amd64.whl
  • Upload date:
  • Size: 4.1 MB
  • Tags: CPython 3.14, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for granian-2.7.6-cp314-cp314-win_amd64.whl
Algorithm Hash digest
SHA256 7c7b2643518369fed9442c727d28345c1d8f28f3b800966b49fd426ef46fc318
MD5 d1bf5ce6a66889e7efeb5fcaa6403e75
BLAKE2b-256 b7c02508d9a8c10f910b86c88af31e5ddce5a3be6eebe92e3938887e3a23291b

See more details on using hashes here.

File details

Details for the file granian-2.7.6-cp314-cp314-musllinux_1_1_x86_64.whl.

File metadata

File hashes

Hashes for granian-2.7.6-cp314-cp314-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 58d33829649384f537f9c326688acf7ce9df9fc1044f4fad90058c71505cd51f
MD5 75444ae4632cc2b9015853d97366b64d
BLAKE2b-256 45b6e0ba4b1e2a99c16affaa98a6617e16f2165ed8278b03a57987df9bf381fa

See more details on using hashes here.

File details

Details for the file granian-2.7.6-cp314-cp314-musllinux_1_1_armv7l.whl.

File metadata

File hashes

Hashes for granian-2.7.6-cp314-cp314-musllinux_1_1_armv7l.whl
Algorithm Hash digest
SHA256 a05a6c908ad3d98c2e3986f52f60083471a6304d63955465bca957d40fc55671
MD5 4b4ab290724602df212ff8e32a43ccc3
BLAKE2b-256 441b510d0c76c21ed188b281e243ef7d89efa79d6324b2d6962094651dc9c366

See more details on using hashes here.

File details

Details for the file granian-2.7.6-cp314-cp314-musllinux_1_1_aarch64.whl.

File metadata

File hashes

Hashes for granian-2.7.6-cp314-cp314-musllinux_1_1_aarch64.whl
Algorithm Hash digest
SHA256 e3a9ef405e37fd78a753acbd4751f35a08a860d5572a6644aa5d7442fe1b3dc2
MD5 01910f7de34192698fda29392610b385
BLAKE2b-256 c3077c6d26e9b5e2dc694857bb2367ad19e155df97a3126b4a42f8d2da719ff5

See more details on using hashes here.

File details

Details for the file granian-2.7.6-cp314-cp314-manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for granian-2.7.6-cp314-cp314-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 76a4f7ddacee73cf3c8baa06ebfcea1e591185687c45cdae6df7992578135f58
MD5 8d3d69f66c6277dca402b14eafcb5027
BLAKE2b-256 5c636b8d2169d8094b5bdc01b0d108e1c2091bf3dba3f098ae8f57913f1a0cf8

See more details on using hashes here.

File details

Details for the file granian-2.7.6-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for granian-2.7.6-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 3fa6ebbad188f581f264f5b4f2e1bb2f3fa3b8b830d66703b225b4bc3ad9302a
MD5 cfc9e6d6176b81396a600e1bd0a6b9d3
BLAKE2b-256 93bb036c2b53f765842deaf64a3376310d129671e38d36e93b4b4531f91b1c7b

See more details on using hashes here.

File details

Details for the file granian-2.7.6-cp314-cp314-manylinux_2_17_i686.manylinux2014_i686.whl.

File metadata

File hashes

Hashes for granian-2.7.6-cp314-cp314-manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 1f6b57ff48757a76b4c1253e892a5d55108fe868085b6edfe5ddb008d6b93e17
MD5 c47ef9bc56adac017ceee1462889ed29
BLAKE2b-256 ff4b64d0874c83d975ca7acf97f23f4d888a675d11d782d8af74bb4e8b41d528

See more details on using hashes here.

File details

Details for the file granian-2.7.6-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl.

File metadata

File hashes

Hashes for granian-2.7.6-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl
Algorithm Hash digest
SHA256 e2b284d7f5a1080fd50d5b0f3f335dc34a9cc5ebe3cafc291d25eea174d8c178
MD5 ee0be699e7e8513dda3f33904645aeec
BLAKE2b-256 cf793cc94f59fcc14d00c96800aa4d9385e91c051b0140a94fca7a6adcf2f5ec

See more details on using hashes here.

File details

Details for the file granian-2.7.6-cp314-cp314-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for granian-2.7.6-cp314-cp314-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 0ba744daf241cdb52abf7ff1a5e3d53b04d470d4166880789ccfe3605cee5d52
MD5 9d0f5f495511a200a9c9a4a9d242bcc7
BLAKE2b-256 ea5df8a55dfc0de7263e7806726e87b6da725e7b0c11ebb12d95b5300141c3cf

See more details on using hashes here.

File details

Details for the file granian-2.7.6-cp314-cp314-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for granian-2.7.6-cp314-cp314-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 3e8929e235c80d8aa11fc502a4632d7fbb29ff7b4cbd17e5a05f7afc2e38de32
MD5 fc9e5b71f67dad2e8266294cd083b485
BLAKE2b-256 b6b93cd193896669cf737bfc099eb30459bfc3494a66c33f8a768e98563a513b

See more details on using hashes here.

File details

Details for the file granian-2.7.6-cp313-cp313t-win_amd64.whl.

File metadata

  • Download URL: granian-2.7.6-cp313-cp313t-win_amd64.whl
  • Upload date:
  • Size: 4.0 MB
  • Tags: CPython 3.13t, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for granian-2.7.6-cp313-cp313t-win_amd64.whl
Algorithm Hash digest
SHA256 01a389fe9eb11a2e8b23720915df25d4fa6aaf08337d32b9f7515ef02d888c39
MD5 87135ee797ff23275169efc8477e63bd
BLAKE2b-256 85eb2508242883d8cbcffaac0f433245c83cbb56727ea3883cb021f8bc9224bc

See more details on using hashes here.

File details

Details for the file granian-2.7.6-cp313-cp313t-musllinux_1_1_x86_64.whl.

File metadata

File hashes

Hashes for granian-2.7.6-cp313-cp313t-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 0ee043d48e3a9f8a4cba8b9bc0326591e5428f546724feee29f14146fe6595f3
MD5 e74d626755f5bbf8c31a5ec714fe20fe
BLAKE2b-256 5cc2491a6bd46817a48541cc894c27dc6ae138ef5f3ad852bc41729825b177b0

See more details on using hashes here.

File details

Details for the file granian-2.7.6-cp313-cp313t-musllinux_1_1_armv7l.whl.

File metadata

File hashes

Hashes for granian-2.7.6-cp313-cp313t-musllinux_1_1_armv7l.whl
Algorithm Hash digest
SHA256 29cc78dacb2046c78d061d6c3bfefac83150851837ddb3110359b0dd6e2db50b
MD5 6a8fabfbfcc77df4742b628373278660
BLAKE2b-256 9379ac4b3e7942d3184716890d2b670b953764c560a940e436bf92eafabb194c

See more details on using hashes here.

File details

Details for the file granian-2.7.6-cp313-cp313t-musllinux_1_1_aarch64.whl.

File metadata

File hashes

Hashes for granian-2.7.6-cp313-cp313t-musllinux_1_1_aarch64.whl
Algorithm Hash digest
SHA256 f3c044d191e2c03fff43af1b1b0ef8325e1763cf385ff47f9ce7d15b053bb3a2
MD5 9af6fa3f9ed44a10c24b041f200cefba
BLAKE2b-256 75e658a72f2f1a3a12565e26bf404f9f4ba3595062cb95c4dbd54ff69837fdfd

See more details on using hashes here.

File details

Details for the file granian-2.7.6-cp313-cp313t-manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for granian-2.7.6-cp313-cp313t-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 8ce9cf7a999a9e8ce3981810c676233554515ce2e8f1797ed68dd568685b4db7
MD5 8fe8bff23314acaf73848148248faa3d
BLAKE2b-256 0ef0f08aec40227e9deffd66437b003e14138f7a68d75417c95fb70eb32a52ee

See more details on using hashes here.

File details

Details for the file granian-2.7.6-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for granian-2.7.6-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 6e8495d70361dc6aef300e2be03257dd8d29412673cb4892ff5ab931dfe58572
MD5 d213e8b27b6e36b83e0f0e3135c0fc32
BLAKE2b-256 8cc12182a311b747af48215ada0d71e693a0aaa3acc7b44c54d43197dd41cd53

See more details on using hashes here.

File details

Details for the file granian-2.7.6-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl.

File metadata

File hashes

Hashes for granian-2.7.6-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl
Algorithm Hash digest
SHA256 98fb26c008b336d33f9f9a5120010baaedd75961d69f9f29bdeadd36ee248fcb
MD5 47d24696aa262aaf9f832c235b5b0abb
BLAKE2b-256 d3d520e52813cc4123f03ebbe15f87d94bfb00ed6597aab3d0c24688fb9fd5d1

See more details on using hashes here.

File details

Details for the file granian-2.7.6-cp313-cp313t-manylinux_2_12_i686.manylinux2010_i686.whl.

File metadata

File hashes

Hashes for granian-2.7.6-cp313-cp313t-manylinux_2_12_i686.manylinux2010_i686.whl
Algorithm Hash digest
SHA256 cfe099f5ebb71447979d4c78dcede61291f2a4bc61ff96311f6693dc0936ef05
MD5 1886d732679c76faeb80b2bb98d734e2
BLAKE2b-256 2f720d31b3fd13d1ad530c1b01b5e54ba01020d2d6f99db59656a9c7428f9a6f

See more details on using hashes here.

File details

Details for the file granian-2.7.6-cp313-cp313t-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for granian-2.7.6-cp313-cp313t-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 653f8f5fbb1089f72e277a3509e1d3a41fcb1b92bffb3338f77233df406afb22
MD5 490e9930d74875f3c60878a275035e0e
BLAKE2b-256 6645ee34fc633aa1d5b86f37e470ac8a5d1c48a87f5645c5dde7d2ba66e8b83b

See more details on using hashes here.

File details

Details for the file granian-2.7.6-cp313-cp313t-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for granian-2.7.6-cp313-cp313t-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 8d79d0f1ea456dc69fdb0320a6787a5c3639a37285d8d99c18004dcfb3f50ce7
MD5 b4c7df32c8c8de941ade5aff0272deee
BLAKE2b-256 d2f92e3d235a1b069e064605e9cceee37601ba41acafeff72f882955931f446b

See more details on using hashes here.

File details

Details for the file granian-2.7.6-cp313-cp313-win_amd64.whl.

File metadata

  • Download URL: granian-2.7.6-cp313-cp313-win_amd64.whl
  • Upload date:
  • Size: 4.1 MB
  • Tags: CPython 3.13, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for granian-2.7.6-cp313-cp313-win_amd64.whl
Algorithm Hash digest
SHA256 291c2d358ceb7cb8185366d6c9055697e68fa4a26addbc1b7e5bd6ba38033f5d
MD5 c152d751f2326535a3f4cc9128a840c7
BLAKE2b-256 0229802e081046bfd9b9196b0756f22b494b4469e554fb0b7bc2ddf906a9415b

See more details on using hashes here.

File details

Details for the file granian-2.7.6-cp313-cp313-musllinux_1_1_x86_64.whl.

File metadata

File hashes

Hashes for granian-2.7.6-cp313-cp313-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 20fb3cc9437130f1cf6eff86abc8cd3d9c955ee7b1d9a6b12de1fb54525448cf
MD5 ae70ba50203a8a754f4888661fa204bc
BLAKE2b-256 1137ec09ad3557e4284aeef01882a25a3ac211dbc0040ac8aa083bcb7f926c2e

See more details on using hashes here.

File details

Details for the file granian-2.7.6-cp313-cp313-musllinux_1_1_armv7l.whl.

File metadata

File hashes

Hashes for granian-2.7.6-cp313-cp313-musllinux_1_1_armv7l.whl
Algorithm Hash digest
SHA256 4f6ad35673ba7108411ac817bfaba2bc1500f88de293380858ed792a34f233dc
MD5 f5803f8d92e6c5e1062e449e5a72ff16
BLAKE2b-256 0126c2003a760e53a4f16b1c46a555a3b4d1b0468b3f9cddac23e39365226c85

See more details on using hashes here.

File details

Details for the file granian-2.7.6-cp313-cp313-musllinux_1_1_aarch64.whl.

File metadata

File hashes

Hashes for granian-2.7.6-cp313-cp313-musllinux_1_1_aarch64.whl
Algorithm Hash digest
SHA256 9545a200992721f2a05a3d6f2ce58d11ae61925e9fa2857ea900fc5d32762b70
MD5 78e6f5047ff55c5f6974bac0e74a495b
BLAKE2b-256 d430200a1973e8ce5e2457c75083709229c1363cb2bc3e24d9527e7b8fcac0b7

See more details on using hashes here.

File details

Details for the file granian-2.7.6-cp313-cp313-manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for granian-2.7.6-cp313-cp313-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 425156ebaa2ad7215f7522501487fa4d676d0f04cde40a987732df4646b9266d
MD5 845e10f3fedf79a0b9cebe6e05c08063
BLAKE2b-256 c62b61d7c3bce38de50b8259360256c6f7d2b0841e5039e65e98a08695502e59

See more details on using hashes here.

File details

Details for the file granian-2.7.6-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for granian-2.7.6-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 20d6e64c449025074f056ad86b0e16ea4a48ec2745596fa084c995ba514dd64b
MD5 c28ac83d60b879c99ab29a8c3701ad57
BLAKE2b-256 810d0c710584c8aa9036e7213e192f3f541d9bb6cfacfaf003af5c0e13609ed1

See more details on using hashes here.

File details

Details for the file granian-2.7.6-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl.

File metadata

File hashes

Hashes for granian-2.7.6-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 bc95fb353fa9e12888678c81625824f320c68697e86564ab1942910426842cd7
MD5 f9994d6ed13898b41b24567604010bc2
BLAKE2b-256 444d4743aa06d8a98d368ced0721a41ece254016bc8da0a56156911c99596043

See more details on using hashes here.

File details

Details for the file granian-2.7.6-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl.

File metadata

File hashes

Hashes for granian-2.7.6-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl
Algorithm Hash digest
SHA256 08e2fd9f734db178f02e3c0ebe55e4424405c33ac00de4463631f7d459267fb9
MD5 ada5999d41b18595b227a262162b7a3e
BLAKE2b-256 f6282e851e4ca9a841f924de3028094336b6b2b7702188d00f260479571ed993

See more details on using hashes here.

File details

Details for the file granian-2.7.6-cp313-cp313-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for granian-2.7.6-cp313-cp313-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 2079df78961f5bb0032ee86463fd0305f2c62469c7ea9207439c237729440d27
MD5 0a510d851a79e445cb4fde5883cca74f
BLAKE2b-256 58e0db5fb23bf4ef94e0832c901350203ee4bcc74c68000364c75f01f89dc166

See more details on using hashes here.

File details

Details for the file granian-2.7.6-cp313-cp313-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for granian-2.7.6-cp313-cp313-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 6ebda7740ae13d1da82456d7f8166d90aa4dc92b9e114b64d8298cc0666e975a
MD5 dae03d3dad602086a7d1dd4c72582d01
BLAKE2b-256 bb01d8c4ff585c6dfd656771b5aec0d55d19cb1173886ae3c3e373b88ff1af67

See more details on using hashes here.

File details

Details for the file granian-2.7.6-cp312-cp312-win_amd64.whl.

File metadata

  • Download URL: granian-2.7.6-cp312-cp312-win_amd64.whl
  • Upload date:
  • Size: 4.1 MB
  • Tags: CPython 3.12, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for granian-2.7.6-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 0bd61ffa236d4e6b0c1cbadae7024bee5a19faeaa24626cb32914fab7b5818d9
MD5 df0805aa851f8bfa8a993b7ea4fdde0e
BLAKE2b-256 600fd5ad50d5ea6b8bb46db953512f64145b1455b4360420c363ef2353899650

See more details on using hashes here.

File details

Details for the file granian-2.7.6-cp312-cp312-musllinux_1_1_x86_64.whl.

File metadata

File hashes

Hashes for granian-2.7.6-cp312-cp312-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 8432a9adfbdb7ba4ee9897e78d684a30c7c0b6587f696e3dcbaf3fb93aa363e5
MD5 4e379841bfb33b16a12ea794787388c0
BLAKE2b-256 54918c77d5939e0f1145f622002aad0693b7fd3f724dff7e75b5c9994b9b46dc

See more details on using hashes here.

File details

Details for the file granian-2.7.6-cp312-cp312-musllinux_1_1_armv7l.whl.

File metadata

File hashes

Hashes for granian-2.7.6-cp312-cp312-musllinux_1_1_armv7l.whl
Algorithm Hash digest
SHA256 9d92c4f10127203436e774c1fbd05ab8c0a1b1233fc62469ca3d4c38d6c9f645
MD5 2a0c97096abe657afbcc88a8385a7092
BLAKE2b-256 93fffaab106b4696577b735ce7ea046b788fc00b319efcff7cd84b2f66a18db4

See more details on using hashes here.

File details

Details for the file granian-2.7.6-cp312-cp312-musllinux_1_1_aarch64.whl.

File metadata

File hashes

Hashes for granian-2.7.6-cp312-cp312-musllinux_1_1_aarch64.whl
Algorithm Hash digest
SHA256 0fd714f9a5fda9c33d8a7cefaf85be0b7b07758ef707b73eb4a06e38048c2a32
MD5 90f4f4599ea9a7ec8912bdca373e12de
BLAKE2b-256 d89b166fd5cbe00f67d8723b11183b7f6e2e44fccf52939856563751501fabeb

See more details on using hashes here.

File details

Details for the file granian-2.7.6-cp312-cp312-manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for granian-2.7.6-cp312-cp312-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 81b696751078ffb8be5927f13689f2714985a6a3cfbbdf6be97f583b482aa963
MD5 1d9836235bea33f09ea7f8e91116b59f
BLAKE2b-256 47daeb71362ee17b5f0f9dfc8fc38c05a16482a4e59ff234bf875cba455e0f8d

See more details on using hashes here.

File details

Details for the file granian-2.7.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for granian-2.7.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 3415f110355f58e9520b0f5ef78ac5047a143482e1ee5bd63ee1e558dcb363af
MD5 437caf92d9c56fe38065e30bb7c773f1
BLAKE2b-256 73d0fa26ec8d287e396eeefcd914a165fe589502bd64baef0dbca79215363d28

See more details on using hashes here.

File details

Details for the file granian-2.7.6-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl.

File metadata

File hashes

Hashes for granian-2.7.6-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 0576859f46b462e8a46bed56ad10ee8fc06d44910735836c6c64eaec3330e1c2
MD5 b4b1dae176e37c04919ada2f8847904b
BLAKE2b-256 dabb66a5f3894ee2c6d9ef20487a5a07d6d4d0bfa385f672a4845af2bed176b1

See more details on using hashes here.

File details

Details for the file granian-2.7.6-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl.

File metadata

File hashes

Hashes for granian-2.7.6-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl
Algorithm Hash digest
SHA256 239bd4738ef21fa1f7ac09e69ba8c221bf219f0ed65c398d9aa50da490fed98d
MD5 0725c1690c2f38d67804c53b67beb536
BLAKE2b-256 0bca424492b9f5874957d02f0df3e5410a6ca8e465d880dd3dd02ff68232b7ea

See more details on using hashes here.

File details

Details for the file granian-2.7.6-cp312-cp312-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for granian-2.7.6-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 42ed56bd83fc9fe7ef944523c353d8eb377f7bded0cba7e45637d7dcd4d4bb51
MD5 a992c88083d61ed9cfbbfc461756cc1c
BLAKE2b-256 aff2eac07051c5f3acf31fe3151282f5b61de6b23ed614e5bcdc9a44a29bbd83

See more details on using hashes here.

File details

Details for the file granian-2.7.6-cp312-cp312-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for granian-2.7.6-cp312-cp312-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 3aec59c6864af5b26e46b217ba4ab7631313a1fc61976ee46b1eb2de18e6a1b4
MD5 1fa19c4fac07af4e91453afb2ec86685
BLAKE2b-256 0d9dbf53ea626e2f0388bf3fcf2cc056964ad3835b9d2b498aef4bfdf82ed82b

See more details on using hashes here.

File details

Details for the file granian-2.7.6-cp311-cp311-win_amd64.whl.

File metadata

  • Download URL: granian-2.7.6-cp311-cp311-win_amd64.whl
  • Upload date:
  • Size: 4.0 MB
  • Tags: CPython 3.11, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for granian-2.7.6-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 3db581ad3616d05065c48604987670ce08a825ec019183f7b3bce6d6fb147086
MD5 0d9108db584ff5fa3d8bc012834e1c4c
BLAKE2b-256 77276e087a206b2c90d8365ed653a1040d6811b66d50cc371863109aff9e2197

See more details on using hashes here.

File details

Details for the file granian-2.7.6-cp311-cp311-musllinux_1_1_x86_64.whl.

File metadata

File hashes

Hashes for granian-2.7.6-cp311-cp311-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 a96ef130bb6e31a7f45d62f82189514e29c07ae28fb5df5f7661c6941e2d9ff5
MD5 296c7dadb09cb52898659900f583650a
BLAKE2b-256 b01d84ae22620bd14d33b90585de6c1423d267995cf0293fa9a06a56a972cce6

See more details on using hashes here.

File details

Details for the file granian-2.7.6-cp311-cp311-musllinux_1_1_armv7l.whl.

File metadata

File hashes

Hashes for granian-2.7.6-cp311-cp311-musllinux_1_1_armv7l.whl
Algorithm Hash digest
SHA256 6f322a0cf606a0831b9f70fcc4a265b45d7459d63e60d8da78f20b27f005994c
MD5 bf9d6cb183864ff4308dad32cade01f5
BLAKE2b-256 6a52eb5a661b7a69b59da6e4594784585bfa334ff1b42edfb45637ba3e98ca6c

See more details on using hashes here.

File details

Details for the file granian-2.7.6-cp311-cp311-musllinux_1_1_aarch64.whl.

File metadata

File hashes

Hashes for granian-2.7.6-cp311-cp311-musllinux_1_1_aarch64.whl
Algorithm Hash digest
SHA256 2a4d1eed6d63d54da2c71b2a748121b2c03756bee67e73f8d4b11a0a891602bb
MD5 88bba9982e625d8f69201fd2c8703a36
BLAKE2b-256 acd52af09a49f766d6c13938018138edcf33390ebe52ddc73333cd69a0c15542

See more details on using hashes here.

File details

Details for the file granian-2.7.6-cp311-cp311-manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for granian-2.7.6-cp311-cp311-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 d35342a96d84bb6b07226a71adf27e88a7b3d63e08ed78505d045e55f1584f39
MD5 48d027897e371d76e9ee244184fa9e23
BLAKE2b-256 888f6d34025970dc8777ec8af6b666a1e0f25e17c15b035fa6b82b78de5454ec

See more details on using hashes here.

File details

Details for the file granian-2.7.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for granian-2.7.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 cd1fb44a1460675179219305ce9f42df6734005e45a7326813347664f698b8a7
MD5 f70cc1c4973af600f49ddac9fdf0e6f3
BLAKE2b-256 58c0322c68f4bd6cb22f2cc735aa9349c578c6e3081d5dfa68e0a73be8247cd0

See more details on using hashes here.

File details

Details for the file granian-2.7.6-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl.

File metadata

File hashes

Hashes for granian-2.7.6-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 917e498c37cd8c592a669ffb72b46c99596cebe6cec9a7054f5c3de439141528
MD5 4d9874b3c65a79c2f1ebd1d9a9e67bcc
BLAKE2b-256 25a3a53d2e3b2c1ddb961a82dfef374e06ceb99155be17730362ba52d23fe60e

See more details on using hashes here.

File details

Details for the file granian-2.7.6-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl.

File metadata

File hashes

Hashes for granian-2.7.6-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl
Algorithm Hash digest
SHA256 7d7039487a32489add74c1ac70e578171fd6e4a16b4cc074334de736c663a27f
MD5 b2bbeb1c936b1be15807c08449ba6c85
BLAKE2b-256 b4edd2e56e1a2fb7308682058a876cfdeca8b5ff72b79f5f53b14307960800b3

See more details on using hashes here.

File details

Details for the file granian-2.7.6-cp311-cp311-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for granian-2.7.6-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 1049d39b1fd7c312d8b44f355b2fd9122ae1cd625f26c7d10a644838020f869b
MD5 a9f9375c06f5283be4c280993295ca1f
BLAKE2b-256 a4d88abb0a0e97df07c6326616b2d1404ed9f01564745be361ab01903dafb98c

See more details on using hashes here.

File details

Details for the file granian-2.7.6-cp311-cp311-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for granian-2.7.6-cp311-cp311-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 ccc0164a876cfa2bdb043327bc7b8e7b7bb2be2c3ad26b0577a135c2e37a8efe
MD5 f6946407332d5e082e85c4dc869cae22
BLAKE2b-256 bfaacf5c290175664187c7fbc2136bfab5afdceae0f6f336b1304d45c6a0e4c9

See more details on using hashes here.

File details

Details for the file granian-2.7.6-cp310-cp310-win_amd64.whl.

File metadata

  • Download URL: granian-2.7.6-cp310-cp310-win_amd64.whl
  • Upload date:
  • Size: 4.0 MB
  • Tags: CPython 3.10, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for granian-2.7.6-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 a6f336063455d03b1630cf0aade843dc993b06b75468f24b1c8ca1736a668721
MD5 50704628e99f64f67d5bb0ecdeb7a728
BLAKE2b-256 389b72cd54ba515e0cb99ccd67c36292be447049ec37935db39b4c7d05e6516f

See more details on using hashes here.

File details

Details for the file granian-2.7.6-cp310-cp310-musllinux_1_1_x86_64.whl.

File metadata

File hashes

Hashes for granian-2.7.6-cp310-cp310-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 a276cc778eea48bb77511c3af692e3867fcf6fb0baa4a1b927a44914a8c83871
MD5 cb4750023bd01fde06ad0d5034a39a59
BLAKE2b-256 96168ea6465450a04dc7311294f60937982a2add13fc7658a3ae3b5ab2752dae

See more details on using hashes here.

File details

Details for the file granian-2.7.6-cp310-cp310-musllinux_1_1_armv7l.whl.

File metadata

File hashes

Hashes for granian-2.7.6-cp310-cp310-musllinux_1_1_armv7l.whl
Algorithm Hash digest
SHA256 9bbc43f89c405a92e387a793fc200e7ba4d4545f10f7cc3da7d0c670b0bedd86
MD5 33901b2b2c2727fd378ecdcdf8f30863
BLAKE2b-256 a924783857683e3757b2e76d734c8d149a65cc477d015b9e801f0d7ad246f058

See more details on using hashes here.

File details

Details for the file granian-2.7.6-cp310-cp310-musllinux_1_1_aarch64.whl.

File metadata

File hashes

Hashes for granian-2.7.6-cp310-cp310-musllinux_1_1_aarch64.whl
Algorithm Hash digest
SHA256 4f2ee93a182964175f50248ffef0bc85afc2222afd1ba48dba02f41e1d6a76c9
MD5 590610f91264de5b245830756cc77e65
BLAKE2b-256 a324e69f53861efae1f033f7f105becb380653e40694650b819bec88261fe9c0

See more details on using hashes here.

File details

Details for the file granian-2.7.6-cp310-cp310-manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for granian-2.7.6-cp310-cp310-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 ccb5513ba67b7f67127f3d206d7f70d72368d309dd257bec08b50456820b1d66
MD5 15e3a4f2d381e3c4e1d87bed3e7deae7
BLAKE2b-256 379514701c4c23a909b5b3c2c65a4598970877858f1c99032b0c0662ee1aa0d1

See more details on using hashes here.

File details

Details for the file granian-2.7.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for granian-2.7.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 c81b73ecbc37e3fe63019138c58e6c06b45de90c16bfeb422edb030d8f791da9
MD5 50d14c41edb08e9e3a65d143598a5353
BLAKE2b-256 2802e74650b0195e9b601debd942eded1a9355e33e11107c28420532c0b57e17

See more details on using hashes here.

File details

Details for the file granian-2.7.6-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl.

File metadata

File hashes

Hashes for granian-2.7.6-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 86a57851521ec793d72ec767e8ee4fcd94802eed5347a1b0884eb9971f202545
MD5 f0b097e3f347dd243fc5ec2d4b876834
BLAKE2b-256 5f8d0a8f2b41d11a47ef0e62fa4cafa1ee3ee7d6d196c1fa7adb80d29865ae96

See more details on using hashes here.

File details

Details for the file granian-2.7.6-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl.

File metadata

File hashes

Hashes for granian-2.7.6-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl
Algorithm Hash digest
SHA256 68000b5e3c4e3d571256206cb862b42250020295ee853667fad843c0e0cfd79c
MD5 75fd9cd2440d41dad4a6c280cdea1fa0
BLAKE2b-256 0caddc781fedf6427e663a9cca67e948867b13465757f27f0ba7390c1badb835

See more details on using hashes here.

File details

Details for the file granian-2.7.6-cp310-cp310-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for granian-2.7.6-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 17562a05eca26cd54331caabd2f9ca37b48b87efdb304e4fdeba9d6e3032dd7b
MD5 fd8414255c4c24133651af41ebf1a16d
BLAKE2b-256 807d47a5e00fd3412f1a51643e4a186bb8de980725381b1a9d33735fa986cb0b

See more details on using hashes here.

File details

Details for the file granian-2.7.6-cp310-cp310-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for granian-2.7.6-cp310-cp310-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 b1e4fa382176eab0d73d19770ab2299e150fb1980a9c053284dd8c124a32aae7
MD5 cce04a07020e3c185f35d7276683cbed
BLAKE2b-256 19af50bea2dff351ecbd3561a3a1832c3518df647a60585fd01213fb3dc073fa

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