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.9.tar.gz (129.8 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.9-pp311-pypy311_pp73-win_amd64.whl (4.1 MB view details)

Uploaded PyPyWindows x86-64

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

Uploaded PyPymusllinux: musl 1.1+ x86-64

granian-2.7.9-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl (7.5 MB view details)

Uploaded PyPymusllinux: musl 1.1+ ARMv7l

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

Uploaded PyPymusllinux: musl 1.1+ ARM64

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

Uploaded PyPymanylinux: glibc 2.28+ ARM64

granian-2.7.9-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (7.0 MB view details)

Uploaded PyPymanylinux: glibc 2.17+ x86-64

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

Uploaded PyPymacOS 11.0+ ARM64

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

Uploaded PyPymacOS 10.12+ x86-64

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

Uploaded CPython 3.14tWindows x86-64

granian-2.7.9-cp314-cp314t-musllinux_1_1_x86_64.whl (7.0 MB view details)

Uploaded CPython 3.14tmusllinux: musl 1.1+ x86-64

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

Uploaded CPython 3.14tmusllinux: musl 1.1+ ARMv7l

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

Uploaded CPython 3.14tmusllinux: musl 1.1+ ARM64

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

Uploaded CPython 3.14tmanylinux: glibc 2.28+ ARM64

granian-2.7.9-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.9-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.9-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.9-cp314-cp314t-macosx_11_0_arm64.whl (6.1 MB view details)

Uploaded CPython 3.14tmacOS 11.0+ ARM64

granian-2.7.9-cp314-cp314t-macosx_10_12_x86_64.whl (6.3 MB view details)

Uploaded CPython 3.14tmacOS 10.12+ x86-64

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

Uploaded CPython 3.14Windows x86-64

granian-2.7.9-cp314-cp314-musllinux_1_1_x86_64.whl (7.0 MB view details)

Uploaded CPython 3.14musllinux: musl 1.1+ x86-64

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

Uploaded CPython 3.14musllinux: musl 1.1+ ARMv7l

granian-2.7.9-cp314-cp314-musllinux_1_1_aarch64.whl (7.1 MB view details)

Uploaded CPython 3.14musllinux: musl 1.1+ ARM64

granian-2.7.9-cp314-cp314-manylinux_2_28_aarch64.whl (7.1 MB view details)

Uploaded CPython 3.14manylinux: glibc 2.28+ ARM64

granian-2.7.9-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.9-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.9-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.9-cp314-cp314-macosx_11_0_arm64.whl (6.2 MB view details)

Uploaded CPython 3.14macOS 11.0+ ARM64

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

Uploaded CPython 3.14macOS 10.12+ x86-64

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

Uploaded CPython 3.13tWindows x86-64

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

Uploaded CPython 3.13tmusllinux: musl 1.1+ x86-64

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

Uploaded CPython 3.13tmusllinux: musl 1.1+ ARMv7l

granian-2.7.9-cp313-cp313t-musllinux_1_1_aarch64.whl (7.0 MB view details)

Uploaded CPython 3.13tmusllinux: musl 1.1+ ARM64

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

Uploaded CPython 3.13tmanylinux: glibc 2.28+ ARM64

granian-2.7.9-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.9-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.9-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.9-cp313-cp313t-macosx_11_0_arm64.whl (6.1 MB view details)

Uploaded CPython 3.13tmacOS 11.0+ ARM64

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

Uploaded CPython 3.13tmacOS 10.12+ x86-64

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

Uploaded CPython 3.13Windows x86-64

granian-2.7.9-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.9-cp313-cp313-musllinux_1_1_armv7l.whl (7.3 MB view details)

Uploaded CPython 3.13musllinux: musl 1.1+ ARMv7l

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

Uploaded CPython 3.13musllinux: musl 1.1+ ARM64

granian-2.7.9-cp313-cp313-manylinux_2_28_aarch64.whl (7.1 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.28+ ARM64

granian-2.7.9-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (7.0 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.17+ x86-64

granian-2.7.9-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl (6.4 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.17+ i686

granian-2.7.9-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.9-cp313-cp313-macosx_11_0_arm64.whl (6.2 MB view details)

Uploaded CPython 3.13macOS 11.0+ ARM64

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

Uploaded CPython 3.13macOS 10.12+ x86-64

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

Uploaded CPython 3.12Windows x86-64

granian-2.7.9-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.9-cp312-cp312-musllinux_1_1_armv7l.whl (7.3 MB view details)

Uploaded CPython 3.12musllinux: musl 1.1+ ARMv7l

granian-2.7.9-cp312-cp312-musllinux_1_1_aarch64.whl (7.1 MB view details)

Uploaded CPython 3.12musllinux: musl 1.1+ ARM64

granian-2.7.9-cp312-cp312-manylinux_2_28_aarch64.whl (7.1 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.28+ ARM64

granian-2.7.9-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (7.0 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ x86-64

granian-2.7.9-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl (6.4 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ i686

granian-2.7.9-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.9-cp312-cp312-macosx_11_0_arm64.whl (6.2 MB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

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

Uploaded CPython 3.12macOS 10.12+ x86-64

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

Uploaded CPython 3.11Windows x86-64

granian-2.7.9-cp311-cp311-musllinux_1_1_x86_64.whl (6.9 MB view details)

Uploaded CPython 3.11musllinux: musl 1.1+ x86-64

granian-2.7.9-cp311-cp311-musllinux_1_1_armv7l.whl (7.4 MB view details)

Uploaded CPython 3.11musllinux: musl 1.1+ ARMv7l

granian-2.7.9-cp311-cp311-musllinux_1_1_aarch64.whl (7.0 MB view details)

Uploaded CPython 3.11musllinux: musl 1.1+ ARM64

granian-2.7.9-cp311-cp311-manylinux_2_28_aarch64.whl (7.0 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.28+ ARM64

granian-2.7.9-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (6.9 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.17+ x86-64

granian-2.7.9-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.9-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.9-cp311-cp311-macosx_11_0_arm64.whl (6.2 MB view details)

Uploaded CPython 3.11macOS 11.0+ ARM64

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

Uploaded CPython 3.11macOS 10.12+ x86-64

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

Uploaded CPython 3.10Windows x86-64

granian-2.7.9-cp310-cp310-musllinux_1_1_x86_64.whl (6.9 MB view details)

Uploaded CPython 3.10musllinux: musl 1.1+ x86-64

granian-2.7.9-cp310-cp310-musllinux_1_1_armv7l.whl (7.4 MB view details)

Uploaded CPython 3.10musllinux: musl 1.1+ ARMv7l

granian-2.7.9-cp310-cp310-musllinux_1_1_aarch64.whl (7.0 MB view details)

Uploaded CPython 3.10musllinux: musl 1.1+ ARM64

granian-2.7.9-cp310-cp310-manylinux_2_28_aarch64.whl (7.0 MB view details)

Uploaded CPython 3.10manylinux: glibc 2.28+ ARM64

granian-2.7.9-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (6.9 MB view details)

Uploaded CPython 3.10manylinux: glibc 2.17+ x86-64

granian-2.7.9-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.9-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.9-cp310-cp310-macosx_11_0_arm64.whl (6.2 MB view details)

Uploaded CPython 3.10macOS 11.0+ ARM64

granian-2.7.9-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.9.tar.gz.

File metadata

  • Download URL: granian-2.7.9.tar.gz
  • Upload date:
  • Size: 129.8 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.9.tar.gz
Algorithm Hash digest
SHA256 096d9a3396b13826bc63d2cf424ed04daf1ea077beed361d48dca2d55cb4b527
MD5 2dc4f3e5d7b3030184f6f82970012023
BLAKE2b-256 b0cc9c752e6173df02c5e37c0df7bffd50c1341109e4b4f8e5073bfd3a72dc82

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.9-pp311-pypy311_pp73-win_amd64.whl
Algorithm Hash digest
SHA256 44564f8d0f2971550285f21ff815e75b0c5761a0230d5ef3f05d8af851628ee6
MD5 61bce7f7eaa944dd9881ef4d1a20ad0e
BLAKE2b-256 8778361ded082262cd1c142bd1cfd591710211148d3ac371eecca81d78c6b803

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.9-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 8adc5757b1f1d3e5ad0f50787f459ea33fb8c4434d3d4c3ad2a0694a761c2ce5
MD5 3df9ef4a693abb4780dc78de63675469
BLAKE2b-256 0d7ff730949f75f3a79993fb7c2255f9f82376ff83f8c13ec724cc92b668a0ab

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.9-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl
Algorithm Hash digest
SHA256 b13dd27d32b4fb2ff8a7fd79f80de78bd706c946a8cb1c6ea8a7b83a56086c5e
MD5 7e745b368157341a624b5e5fc3842a37
BLAKE2b-256 61776b0540cb5e6de8af77b9cb16911dbbd3ba8737943eeb8555bf2fa92b3019

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.9-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl
Algorithm Hash digest
SHA256 22caac0f82396d792860f7f0ab6012231b1578ba7e50427306c4f17d1e146dfb
MD5 18e10fcb42d40d3ba1862bac8d076858
BLAKE2b-256 9b76ac022a2f9bea3df682462941d1a4da73160eb0f29c0a56dd987a8cda5164

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.9-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 332a6111fff536dca96776f33bfec9415bf5b66c53f46604b9f2d2b5b7a6036a
MD5 4558cf96b7ae3198a5728cf1ce38ef46
BLAKE2b-256 fd26e15744979d1788aceaa53a0c0bf9d9988f2a9b7400b8b4ea4dc3fdfca99b

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.9-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 00530458f3cbfcd922cd8b8c2eb2cc17123ff84850de946a4c4839e35e9b74fd
MD5 74c137dcc9d27375a7fa3f78bfbca058
BLAKE2b-256 6e4f1710313a9b545877a61880177a3b909f195ab31bf1504294256a811f866f

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.9-pp311-pypy311_pp73-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 03af38185c3fd321713123fafbeb711ca84a7b221c8d159daa82d7c57cb02141
MD5 c0254e8f6f916a960876aa066b9c9cf1
BLAKE2b-256 915d5cd74e0568e44bfc3dd946cc7cfa050851e94837905229dd84ddf17a8eae

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.9-pp311-pypy311_pp73-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 b87dd3e65a4ce09ae2113b3fa36f741aaa2aa6e4c31f16bf67c64b2b7c3ade02
MD5 d60a61530a7488ffb08d7a873f83510e
BLAKE2b-256 9082d67dff2240a0627fb6bca3f0489d3d05a0083d81610c7efb6be71131b94a

See more details on using hashes here.

File details

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

File metadata

  • Download URL: granian-2.7.9-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.9-cp314-cp314t-win_amd64.whl
Algorithm Hash digest
SHA256 d2cef5a15afee90683944a3b23694e97d75adeafd59ef85ff3896bc9462695d2
MD5 2c85b5188c9486a65ff2a56626cd4a7c
BLAKE2b-256 0a62aa89482ffbc3e56d533cf8c87a91cfb58c486e6a77c522fa34c9f8874113

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.9-cp314-cp314t-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 6c7e3193da47554561142be7a58520b36a01f6a2da57a7bcbe61f970fb53cc0c
MD5 f3ff742e207720ff99b61bf900870448
BLAKE2b-256 c6d94526cc50a1fe3addcc29fe3c7c676d64046f724a4d8e4e29d76ba7dcbe04

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.9-cp314-cp314t-musllinux_1_1_armv7l.whl
Algorithm Hash digest
SHA256 3022cde5c662716db8fe16838ba351e0897768435b9c732afc9a4a7322ed05d5
MD5 935bd164e60f11e54666698f02621038
BLAKE2b-256 923abec3533aaaff69a9a984f3fd578a2ca29548c9d8503770b1ba5c2260aecd

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.9-cp314-cp314t-musllinux_1_1_aarch64.whl
Algorithm Hash digest
SHA256 c6475981a0cbf766575a0146bdbe52439185a5040cef2a3969214ca1ef6a5e18
MD5 0136d1b66df0ea97572379fa069b8b25
BLAKE2b-256 08b28f50b2d83452ee3100fcd1b26a5de5206b8befeb9d36b79e6c20d5f6dacd

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.9-cp314-cp314t-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 f9669323b5cd90be7565711bc75363eccf75b6aecdbb0b286f1a860199ef800c
MD5 d9c7a618ce2edbc8f2d785885b0ef6f1
BLAKE2b-256 020ac0b977247bf3dd4efa92903dd316b8089f7e67cb21922e83cdcdd98201f7

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.9-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 1c254a1b2027612f0df6e47e8059fd304cda287be25421e1dced4d6b56fb054c
MD5 328e6802fa67b6ebd7c5ef0147dd9fbb
BLAKE2b-256 4c4c13bd13b0dcc2697b521e75efbeede7328c0809f3e93e964362fd334c0dd4

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.9-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl
Algorithm Hash digest
SHA256 3e39cdfcd5a0ed8e9e8a5e21cd65085ac3a4c73ac5f258f804aedc729cdfa2bb
MD5 793e507700624c098a0a403fb71c3e54
BLAKE2b-256 050f555c2f436cf386614e8197ffc3a27c6e3a812149fd84367d2f988361b4fe

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.9-cp314-cp314t-manylinux_2_12_i686.manylinux2010_i686.whl
Algorithm Hash digest
SHA256 57edbef65585ac69d6ada7b9d7cb6fcd6ebeb2e663833c246f72d3634851f5ac
MD5 ab9045f4517be3423cbc7fc8d968e2a7
BLAKE2b-256 b560fcc41cd8f394c12785fc2f9d9843ad4329e90a2468d0aaf3474be3255e90

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.9-cp314-cp314t-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 ea97a1928b414a35903667440875e0f0f4d2f7a341e8d198ab57f0b2cb70af28
MD5 408382cf30c2c6b69b17fb367042b5a7
BLAKE2b-256 761c787f63df68e28b9e5793efd80c7ba9e1a0e77663c921525552ac3b0d9305

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.9-cp314-cp314t-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 1a9b34e5d46a48fa6f017d6afa546f4d35aa6a2a10737e9c49c5c9108e6a4280
MD5 03cde4f59724fde87f10135233c79cfe
BLAKE2b-256 11fbaa241630b4e987c0b343d08c71e20a89098f9c863a12842afa19930f82a0

See more details on using hashes here.

File details

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

File metadata

  • Download URL: granian-2.7.9-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.9-cp314-cp314-win_amd64.whl
Algorithm Hash digest
SHA256 74d6e50277621e2faa41931d4ddaeae0735e39a20ebaccc49a2282549a4d5297
MD5 768b4255048bef2bc446b915103a7289
BLAKE2b-256 515cb82a31436c740dd0a87e091998f9c350739cbd260aa3880db6f5418112a7

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.9-cp314-cp314-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 665a82ce3f48a4b5e1f4cc83115d3b9a2647b3f222d072db6716223e6dfc86d2
MD5 e7a2040450621ae034c102903acc6b81
BLAKE2b-256 d8838e5e429ebb1465c998403a60e0078784d28b819954c387a9558d99b6c3c5

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.9-cp314-cp314-musllinux_1_1_armv7l.whl
Algorithm Hash digest
SHA256 e2cf4c926e99718576e4ba201d884a56b0e62d8ede39c7468b26cbe2d98c30e5
MD5 979617e05d02cb632c92668676f38959
BLAKE2b-256 8706432aaa769de91176944d3210734e27c223c77b76da359699067cd90d4c65

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.9-cp314-cp314-musllinux_1_1_aarch64.whl
Algorithm Hash digest
SHA256 33ba7e10bfd30b196b866a9b4b828c9a108a22325936f7d07def89a6b9f21dce
MD5 ba276c40b92180f08828c1dce2ce58ca
BLAKE2b-256 99465200e2b09feae19b7a96371eb2f1523faf2e99aae60584f286db0263cea6

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.9-cp314-cp314-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 e2eb74974682bf8635dff79f356d3fd86193c8c1ebed1baffa75ad1793fddbc7
MD5 65a3924ac4e9303ae51840fed610b2d8
BLAKE2b-256 ab77d595c9698b7799e28c4dc9a3091d30dbea9e20e9e92926e47f9c974b7a77

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.9-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 607a02fbda1905cc0b0764f09fab1d601299e482ebb1d9722e61ca08742fb0df
MD5 2cd176975a26dfaa485c517a831f266c
BLAKE2b-256 9dc580826359e26079665562b362f0a5f05261183a8b423e31c954f110313bb4

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.9-cp314-cp314-manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 d17720e112e40563bfefa7b8031d37372234b568784c07250322887631f168f8
MD5 a9eff8402a5efe163d89870176798412
BLAKE2b-256 bee4ef1ca00cc17664548427908da36d9a16e29e7adb34318d5173d1c00ecd1c

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.9-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl
Algorithm Hash digest
SHA256 1f06eb3a1c5ce9bf050e94f37310a6add0410ddee75fc65563e86d1619eea384
MD5 8ed990cd49bf595e18cbd0e45e556a4d
BLAKE2b-256 b279beaa9a25285aea37b7bf9c2fa7357871b51ae1a7ee79501d570386e188ab

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.9-cp314-cp314-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 554543e1085ff6bf60eb0f0e995a8a412e92165e92113f9bae9e1fdfeec2ca72
MD5 afa5fb16753c20a7efc955f7db261678
BLAKE2b-256 8fac2fdc222d98960c5d0a1d1970ee52f9f4e3a953b2862d7be8fb043e74e0c1

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.9-cp314-cp314-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 17e6975266757b05fd59163a3b5ccd7a9d50c227b13e58b9e5b47eff0609c17f
MD5 9b1d6725518f6d6ff3cadee639e20a0d
BLAKE2b-256 43fab388d36bef00f28f2c99df3ab7a08878116d4d1d654b6f93f7b0ef9cde5b

See more details on using hashes here.

File details

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

File metadata

  • Download URL: granian-2.7.9-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.9-cp313-cp313t-win_amd64.whl
Algorithm Hash digest
SHA256 2836fd595a144be7e70faebddf1ce7b4e0c136a7017d75660b88c8da63c0f0ff
MD5 aa26b2debc20e8e545575ff9b188c9fe
BLAKE2b-256 e4954cbe8728c9e609f33ec676e194a6296cd628bfb9d6c1310f4ab06634f09a

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.9-cp313-cp313t-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 887f0f1e045314044712a2e3799991c7be0ba4129f6806b82e40f502417694d9
MD5 16ab31bd0e075c2049dfb6a896d795f9
BLAKE2b-256 b42f38daac752e7384c5da56803a65428ef29a196df8e436082813b391877ef5

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.9-cp313-cp313t-musllinux_1_1_armv7l.whl
Algorithm Hash digest
SHA256 12da3d84a9dce7706a19f6a98e8f7c3624721ff66bc34a60cfc4d58e2d6593b9
MD5 f95d2fafb36daf6c68b6d7e962f5b6ef
BLAKE2b-256 577cce3d1ef6f8999106a41d828c88f154b6bc6f700950894613e62a3bb46e2e

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.9-cp313-cp313t-musllinux_1_1_aarch64.whl
Algorithm Hash digest
SHA256 73e8fe3d162c66d1eddaee825e59379bbf7a384ff776ae984baf796cf1b81fe3
MD5 7730d0386bbe9c03f510c8fcce2ea0a8
BLAKE2b-256 9e72cbb85914df3e09e9ad6a59406157622a50e64df960e378d1091195a5a0a2

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.9-cp313-cp313t-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 ac516f3cbdce733578ee91a8139d624a1dccf9ab782fb9f3ab58254ebe6c29ad
MD5 e9f023b5e30022a4d20a4e4c297d4156
BLAKE2b-256 aba06cd1b05e0a868b224232fb203838272cdd3165d16338a847f726b21926e2

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.9-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 e155eb6d3c8827ef3821c80ae6a5f7a61f37562d121240128ce099e3db06ad2f
MD5 46aab2c51c3271cb62d12fec465abae3
BLAKE2b-256 29f360413bf1a6f6da32b10a3dcfb45c2d09de2dc2f6829555323239635b6398

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.9-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl
Algorithm Hash digest
SHA256 d019f88e7944c3e3967da833e758c85cb6c35c7a82a8185eba23243b5cf24b7c
MD5 b66ea4a19f77866638cb52e831c1c2f6
BLAKE2b-256 4f3265a9b41f107bf76fd23c6c6102eee6ac1112cb84250408d034517cb415aa

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.9-cp313-cp313t-manylinux_2_12_i686.manylinux2010_i686.whl
Algorithm Hash digest
SHA256 6d08149dfa9777ba281ddf7d7df7ae5473cf6c2fa8815ac33301a24acf33e875
MD5 e63b4090a41041b251b56aa476e3d1ad
BLAKE2b-256 34b3fc344b4bc668d5f4eae9bddbd0eb8f2517214470dd40d178c6c51d14be22

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.9-cp313-cp313t-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 d52c262b5e0d345c0c0684b7536ea42f370a7bbb4720b1b625d60d84d87c81be
MD5 cace80b1c4d9ec735ddbf142ba4c2edc
BLAKE2b-256 c5f308878d6a5b010e39f168b3cffe5011183eab4464a58144ea5711d22d9888

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.9-cp313-cp313t-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 9aa2087ae2103e99ba169f53d718258205bf2ace7df87c9b6dd52e3f71a90335
MD5 fab6885b78c2345467446ea9f900c6a0
BLAKE2b-256 5e7f62673800ed73a85d5b629f493d06a387834196e9463b115ef4fee35d1928

See more details on using hashes here.

File details

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

File metadata

  • Download URL: granian-2.7.9-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.9-cp313-cp313-win_amd64.whl
Algorithm Hash digest
SHA256 e79316015dd68624e021281b3d0e2d9446f04160db4f14140561fe4c0ffeaaa0
MD5 fd3f2f326d7db58938c42870c6006c59
BLAKE2b-256 ba2f51a4db315adbc5e28bf5ac97cb93e04c5e7e6705dc0ef6c8220851453074

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.9-cp313-cp313-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 ed501eafd6cb3c63924466860bf478ad23691d7ad16678b2069e75b5328a074c
MD5 74e9e8582939e589d94c349ed7c58b2c
BLAKE2b-256 c888842e71b39a3a02a16d49b4495c20150055e0888aec6ceb1b965df3a872a5

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.9-cp313-cp313-musllinux_1_1_armv7l.whl
Algorithm Hash digest
SHA256 cae7ccfd34519241e92311e966763650f839b07b1195541cb0f5c180ef22df99
MD5 5ee396c5942a061acda4585178b3d241
BLAKE2b-256 20f7a4dca67e6b68014d548d957735521ce68b2e99a5474722663d048c740063

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.9-cp313-cp313-musllinux_1_1_aarch64.whl
Algorithm Hash digest
SHA256 5dda81fbf58d8f173b9990e6300525359dc2641b88f03bbbe31cc693db5f530b
MD5 a35098e1194c7b8b1b76d36adea52e56
BLAKE2b-256 e236091e26516a7d9093068665dfeffc61dd87c0cb9b9869ffdf452296ab237b

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.9-cp313-cp313-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 18e3f870a8c42500fe6c8d73d24a6888920e2a8740810ef1ddb83b0b67ce643e
MD5 e32a097a8a81e22503b8ea46886bd1e6
BLAKE2b-256 9c1d2a19bce46d187296752c9a54cf833f0472232eb6ad4152e99439163fbd1a

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.9-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 d4ddd82390b6fb9c025007f7ccd92e99d244211898a7851103f28688889dd905
MD5 6cfe639f6d46d38f0f3d98d084a51dad
BLAKE2b-256 25d44afb3e49ca32b7b6528c2cde626ff60d43663c3567b500bcfbe40af3ca73

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.9-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 ff89b203cebba0780efa0360b6e23520323d05f799a610d4a07a5681067b7249
MD5 1501f2a32538b7cd645d41aaac8ccc2b
BLAKE2b-256 67e321e699362e4ecd56d254519d042316444b34c2048e32869101db9bfb6db7

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.9-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl
Algorithm Hash digest
SHA256 64eb08bcf4aca0375fae95a27ca2e78e9dfef7ccae8e12daaac8b2f0bd1cc718
MD5 ca33bce1ddb2f332f63210c02ca629ef
BLAKE2b-256 bfb39f72bd1f36bd3825d35eff3bd8d00c7a01affdec91387fec6e33e314dc6d

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.9-cp313-cp313-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 233baf237d4d3768b4ca6cb6d26546de242e437e1af6050405dcc4673032977f
MD5 a28078c25e308e61d0943916852b604d
BLAKE2b-256 c05e27fe98fabcae553e3f5087b46f3185a257ed9ee5d7f145d2fd03309bcb60

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.9-cp313-cp313-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 23aa08e4d7563f0acb45424676a7d892a146493b5db0895efb5bc8e5121e3051
MD5 92a5555805103b6257e246c12d8812e4
BLAKE2b-256 34c4a66d5c6daf849d012e871ed2684a2e7f81c518ce9f9e827f5900d99d5e7e

See more details on using hashes here.

File details

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

File metadata

  • Download URL: granian-2.7.9-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.9-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 eecd2aa017aa92bc165a9ad33c494e1cfcbfc68a5f055b43e729749899590867
MD5 fbbbf8dc75c5c60ee480887509ec6916
BLAKE2b-256 3e44d71bf6b7e40f9d44f67b9b0ed861fb89d0912daf88cdcb2b7c69feb7f6c2

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.9-cp312-cp312-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 b3000658f76ef2069aee455d3a0835e36fb073e8fd6e95d777cc0179eb97f5b2
MD5 a65c07e57d9b60d6d9d462907043a537
BLAKE2b-256 6de3b3b049d22fc1dedf771410036da06c9bf05f9d24b63474147970ebbb99a0

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.9-cp312-cp312-musllinux_1_1_armv7l.whl
Algorithm Hash digest
SHA256 61270c22d6172fbb6f8e363bad19e8dcaefde27a9b0685bbffaa09835fdf44e3
MD5 edffbc1bf9f1cda97226c12070a9ac1b
BLAKE2b-256 db0125eda803061400b4176d7bb3f144948a065dc76299112ac9ec1d91871cc4

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.9-cp312-cp312-musllinux_1_1_aarch64.whl
Algorithm Hash digest
SHA256 ea963e616edba406969579e296f853bee164db23c1a63b8d2268459797c64810
MD5 aaf37cc74724c43bf4c94d270fb166d3
BLAKE2b-256 6218e6f612945ab888cd7a4ff0d42a51f0d3d274bb1860ef90dfa7386d25ffbb

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.9-cp312-cp312-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 809ec8a9f44c69c49b158811ad78a3195d5e361662ce93dcb7afb848f5f2fd10
MD5 709a153d354a862a9547d8db73dcc857
BLAKE2b-256 7801f6ece64a623e604eac9024751aaf1fab11bf38483a8563a7e009ffa55e00

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.9-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 7a720940970ce47b4b348d4e3c9fefe6ce0a40c46ac851c2e4cc0dcf5bd6e2a7
MD5 2f2d7be07cf703708104c24c8db1c472
BLAKE2b-256 e9c2f38c504bdd150a5f8dc4907309d5467df827401614edabe0d7453e384770

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.9-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 e49f859672fe1e8e062f3be791bec2b3169505719ccf83459ff48aac52ee1d0f
MD5 d4e67ba719b922599526cf3a063dba6b
BLAKE2b-256 f1ed600a820132ce60a987091b8688e60fad3276fd63c1b726c329958d5a4148

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.9-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl
Algorithm Hash digest
SHA256 497c99fc3d4fe0342add24e3c53da78f0d9505ec332dae9075527e00918617d4
MD5 55bf11d8e66e6000b9b0ddcab87d034c
BLAKE2b-256 42e6f580baa79fc38c6d0ac83e6047150e66d842e5b2e393acc5188f356c73e4

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.9-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 3d741def2ad09c8e30880c909023c6d6b78ebe528c5c2e95de8523d967f625f1
MD5 fa451a28dfd46daa47d7c4918b92949b
BLAKE2b-256 686e6e172bad9a56ee79b9eb530dc45f993159872eb948868c6eb529828d46d8

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.9-cp312-cp312-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 e04d86c24948dbf3de0b6b1ac9a9d6c82514f5a6c4f27fe49991e5178a1d0d9f
MD5 bc3cf69ec7c321ced5e03a7cc9b7a5e4
BLAKE2b-256 b87dea14f692056fc08d625aa62b404c10781393f98eadef0208d2fade1f5028

See more details on using hashes here.

File details

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

File metadata

  • Download URL: granian-2.7.9-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.9-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 4918fc299a2b429a92fcee7006c0df63856bcc5e9dfc969be16a04ee1a7b1a81
MD5 a4f7ef7293093ec7e1df54361165bb78
BLAKE2b-256 231bb1f1ae9843c6dfcf623401cd6fea8f90a9de9dad4a01de878534f24a3f31

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.9-cp311-cp311-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 8faaa4e51758cf6d2b3b5b228d1cb9cc4d1be460d59ebb71951435505a2ee48a
MD5 7261863df70fc6ed6bf7d7dc543e63d6
BLAKE2b-256 6451905ecd8596ac85bc3fa6c118ca33ce77ffe0234caa3a6fa5b9ec825b9b96

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.9-cp311-cp311-musllinux_1_1_armv7l.whl
Algorithm Hash digest
SHA256 02bed3191731ff6990308a322fb810890d211f7614d4c67825e92d93be7d2d97
MD5 e00d91f28600ccc4d6ddb738a6f6cc84
BLAKE2b-256 64cc64189390ebdb1b604ee94e39c2f739e35753796c73ed157584cf8d6dc702

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.9-cp311-cp311-musllinux_1_1_aarch64.whl
Algorithm Hash digest
SHA256 331c1050b232ae0366c6e8d26aa4ceb5ad4247216b9c613854c27a8bd14c9205
MD5 4b3e4b9f642664f066aa285104d7b16c
BLAKE2b-256 e5bbf8f6209a71636d1bc0f27ab7f4c6ef2dcbbffcc73fdeebabfc279ea8dcb8

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.9-cp311-cp311-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 cde124d00b8702300779badf9edb757449144a28fdedf6e8ab4d169d54f74fa4
MD5 2e7fa73f31acb0616b8298a783bff102
BLAKE2b-256 db6d23eefe9c3fa664658d0a2c168e4d401c9a306eed5d78456f40a6b4ba93e8

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.9-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 a9395c947ef1884567e63b5c49bd53f4868daf94ac7047d85e73f94efc53c9f4
MD5 7ecc5e09b09b410d4bf7409fdcdeb1db
BLAKE2b-256 27e62825ac380b99ed96c44b745123663f35e194f068d2c989316677f6eec85e

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.9-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 92f9460c68dfc41d57d255baf6dc3b15ade38b1c19fcb40ce1dd3aa74058b530
MD5 9228ecb70f6d8f6fe9d6ca13f6a7fae2
BLAKE2b-256 19450be7994fb5487a82de64cc0b850bf6a03b813b7f31dde8b571bab44d1fdc

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.9-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl
Algorithm Hash digest
SHA256 be49dc58a4220f3af127d26d2ffff58f75afabf7b790681e213bfcb95c51424b
MD5 47ec94856f60d46409a5402137a97ff3
BLAKE2b-256 27e32ec22fe9a560dd7d62cb64ac5b6b9823af427afdc011c22380e22ce055f7

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.9-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 b4dbf1e14f2b381a0a9d043598b8d496956d7e0e89ab43e4c04f415485be85a2
MD5 74a3cced4431dfaa82ac3ee158c8285f
BLAKE2b-256 683843ec59bfec87488db885f8a6b8cba49ffb56ccdf14648dcafa936580810f

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.9-cp311-cp311-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 7edc7c798d01a8afb0ab8925d009a9403ab9585d11d450b8e7c4559d963101f5
MD5 fd4c617d777b81d0b966d0c3d0245d96
BLAKE2b-256 7dc3b448c723ffc5ce1b4405654ad4502b8463ff055c05ff595bcbe726d1c6b1

See more details on using hashes here.

File details

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

File metadata

  • Download URL: granian-2.7.9-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.9-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 5a327625b37c5ba2378b33b902ba4d9127f3c4fe52c9f1c1491774b8cabdc611
MD5 706f11d32e159a54e7834a29501898c0
BLAKE2b-256 89bbfe152a1314346da03884f2c9d88504b3e2f2918d9f16572d98318d6a94f4

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.9-cp310-cp310-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 a6294af0dc726d6ace5cbaa58cd1f5ec2acf633e2a6a5e09ca4d5718e9de2f62
MD5 7c0a36b3ea467fee129836dd4bc27e3f
BLAKE2b-256 1cbe493b0235f3fe93b74a14755aed12b2222e9ea7d483ceeb956665298f2e0b

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.9-cp310-cp310-musllinux_1_1_armv7l.whl
Algorithm Hash digest
SHA256 f1eee5f767d98ec373e50ff36c3f770f6db97e6cf7ed7b6afa367ee443eecffe
MD5 2a7a95a9d739afd44a65241726b7c796
BLAKE2b-256 73c4a56be4dd7119e19a6cacf5a602fd1decafd5069b4e543cd4e0c46acbd96c

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.9-cp310-cp310-musllinux_1_1_aarch64.whl
Algorithm Hash digest
SHA256 ce5599288d31ca20a7b77482486737a5089155aeb7c0730a13878707c9f1eec7
MD5 5f87a5ffe762750c66c0b8d54f13bf66
BLAKE2b-256 5a5c8a71c68d049cea7bdc09f123ee8d79a743594a4289be03f20da449314c09

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.9-cp310-cp310-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 584e00da14d02e616df3af3f138b682af34a35e72e6d556220b214024e1b88db
MD5 d8a4fdc4524534f5f60d50dda31de037
BLAKE2b-256 0c59506e576a937db6ad6c7d2293e6d4ad50e8475e0ca71859be08774c99110e

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.9-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 d14c716a2b1a808b946dca99930f1bb1f1ae1fc3ad7f57c46a936343f35937da
MD5 191210ec5fa19685ae84b8b871768191
BLAKE2b-256 be6a6967ca4eb5f24c59095f0bf6241d01df5e0ce4774085a7ac4c5bf466fe2a

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.9-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 f1c544e76044086d0a33e8c2ae12b3a0f523444fe20247a275e8bb5ff0ce2a9a
MD5 1395ed39275b85766a6d2c08653e0bbc
BLAKE2b-256 9d61322f61795703c07bf80e8232f2c48a16507206aa67ae82a9ed8fb9d8248f

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.9-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl
Algorithm Hash digest
SHA256 e7abd6f7a2ebf96e766bf26c76cf821adca1ac172226d55e705d08c3f005bf0f
MD5 32acc0ae1927784e15f64aa17f7076cb
BLAKE2b-256 8bd21524ed3bb7e4f375b2fe6741ade348f2a5efd4a9fdc2892fa549adbe8e14

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.9-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 06d6956b9e899aade1c86ee8baf92e442fef3bae58584bc95c031d2feb1379d0
MD5 4be70711a12fd8963ca4130f012fcdec
BLAKE2b-256 9c31d2b07484a0f06d9821775b0ff3ecd56113b1b9f7278f0b3dbb7199159e96

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.9-cp310-cp310-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 f84e8650635836c9e4b19c503ba6907d9ec8fcf996a754eea449c2cd9421bb3d
MD5 7c273948eb1ff01573781b00acc8e2c9
BLAKE2b-256 118d909e09ae2317e8d9ea2f17c60460adeb10bb478a6e5d6ec47daab7ad1f8b

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