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

Uploaded PyPyWindows x86-64

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

Uploaded PyPymusllinux: musl 1.1+ x86-64

granian-2.7.1-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl (7.3 MB view details)

Uploaded PyPymusllinux: musl 1.1+ ARMv7l

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

Uploaded PyPymusllinux: musl 1.1+ ARM64

granian-2.7.1-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl (7.0 MB view details)

Uploaded PyPymanylinux: glibc 2.28+ ARM64

granian-2.7.1-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.1-pp311-pypy311_pp73-macosx_11_0_arm64.whl (6.1 MB view details)

Uploaded PyPymacOS 11.0+ ARM64

granian-2.7.1-pp311-pypy311_pp73-macosx_10_12_x86_64.whl (6.4 MB view details)

Uploaded PyPymacOS 10.12+ x86-64

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

Uploaded CPython 3.14tWindows x86-64

granian-2.7.1-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.1-cp314-cp314t-musllinux_1_1_armv7l.whl (7.3 MB view details)

Uploaded CPython 3.14tmusllinux: musl 1.1+ ARMv7l

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

Uploaded CPython 3.14tmusllinux: musl 1.1+ ARM64

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

Uploaded CPython 3.14tmanylinux: glibc 2.28+ ARM64

granian-2.7.1-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.1-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (7.1 MB view details)

Uploaded CPython 3.14tmanylinux: glibc 2.17+ ARMv7l

granian-2.7.1-cp314-cp314t-manylinux_2_12_i686.manylinux2010_i686.whl (6.2 MB view details)

Uploaded CPython 3.14tmanylinux: glibc 2.12+ i686

granian-2.7.1-cp314-cp314t-macosx_11_0_arm64.whl (6.1 MB view details)

Uploaded CPython 3.14tmacOS 11.0+ ARM64

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

Uploaded CPython 3.14tmacOS 10.12+ x86-64

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

Uploaded CPython 3.14Windows x86-64

granian-2.7.1-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.1-cp314-cp314-musllinux_1_1_armv7l.whl (7.3 MB view details)

Uploaded CPython 3.14musllinux: musl 1.1+ ARMv7l

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

Uploaded CPython 3.14musllinux: musl 1.1+ ARM64

granian-2.7.1-cp314-cp314-manylinux_2_28_aarch64.whl (7.0 MB view details)

Uploaded CPython 3.14manylinux: glibc 2.28+ ARM64

granian-2.7.1-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.1-cp314-cp314-manylinux_2_17_i686.manylinux2014_i686.whl (6.4 MB view details)

Uploaded CPython 3.14manylinux: glibc 2.17+ i686

granian-2.7.1-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (7.1 MB view details)

Uploaded CPython 3.14manylinux: glibc 2.17+ ARMv7l

granian-2.7.1-cp314-cp314-macosx_11_0_arm64.whl (6.1 MB view details)

Uploaded CPython 3.14macOS 11.0+ ARM64

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

Uploaded CPython 3.14macOS 10.12+ x86-64

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

Uploaded CPython 3.13tWindows x86-64

granian-2.7.1-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.1-cp313-cp313t-musllinux_1_1_armv7l.whl (7.3 MB view details)

Uploaded CPython 3.13tmusllinux: musl 1.1+ ARMv7l

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

Uploaded CPython 3.13tmusllinux: musl 1.1+ ARM64

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

Uploaded CPython 3.13tmanylinux: glibc 2.28+ ARM64

granian-2.7.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (6.8 MB view details)

Uploaded CPython 3.13tmanylinux: glibc 2.17+ x86-64

granian-2.7.1-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (7.1 MB view details)

Uploaded CPython 3.13tmanylinux: glibc 2.17+ ARMv7l

granian-2.7.1-cp313-cp313t-manylinux_2_12_i686.manylinux2010_i686.whl (6.2 MB view details)

Uploaded CPython 3.13tmanylinux: glibc 2.12+ i686

granian-2.7.1-cp313-cp313t-macosx_11_0_arm64.whl (6.0 MB view details)

Uploaded CPython 3.13tmacOS 11.0+ ARM64

granian-2.7.1-cp313-cp313t-macosx_10_12_x86_64.whl (6.4 MB view details)

Uploaded CPython 3.13tmacOS 10.12+ x86-64

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

Uploaded CPython 3.13Windows x86-64

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

Uploaded CPython 3.13musllinux: musl 1.1+ ARMv7l

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

Uploaded CPython 3.13musllinux: musl 1.1+ ARM64

granian-2.7.1-cp313-cp313-manylinux_2_28_aarch64.whl (7.0 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.28+ ARM64

granian-2.7.1-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.1-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.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (7.1 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.17+ ARMv7l

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

Uploaded CPython 3.13macOS 11.0+ ARM64

granian-2.7.1-cp313-cp313-macosx_10_12_x86_64.whl (6.4 MB view details)

Uploaded CPython 3.13macOS 10.12+ x86-64

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

Uploaded CPython 3.12Windows x86-64

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

Uploaded CPython 3.12musllinux: musl 1.1+ ARMv7l

granian-2.7.1-cp312-cp312-musllinux_1_1_aarch64.whl (7.0 MB view details)

Uploaded CPython 3.12musllinux: musl 1.1+ ARM64

granian-2.7.1-cp312-cp312-manylinux_2_28_aarch64.whl (7.0 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.28+ ARM64

granian-2.7.1-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.1-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.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (7.1 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ ARMv7l

granian-2.7.1-cp312-cp312-macosx_11_0_arm64.whl (6.1 MB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

granian-2.7.1-cp312-cp312-macosx_10_12_x86_64.whl (6.4 MB view details)

Uploaded CPython 3.12macOS 10.12+ x86-64

granian-2.7.1-cp311-cp311-win_amd64.whl (4.1 MB view details)

Uploaded CPython 3.11Windows x86-64

granian-2.7.1-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.1-cp311-cp311-musllinux_1_1_armv7l.whl (7.3 MB view details)

Uploaded CPython 3.11musllinux: musl 1.1+ ARMv7l

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

Uploaded CPython 3.11musllinux: musl 1.1+ ARM64

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

Uploaded CPython 3.11manylinux: glibc 2.28+ ARM64

granian-2.7.1-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.1-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl (6.4 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.17+ i686

granian-2.7.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (7.1 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.17+ ARMv7l

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

Uploaded CPython 3.11macOS 11.0+ ARM64

granian-2.7.1-cp311-cp311-macosx_10_12_x86_64.whl (6.4 MB view details)

Uploaded CPython 3.11macOS 10.12+ x86-64

granian-2.7.1-cp310-cp310-win_amd64.whl (4.1 MB view details)

Uploaded CPython 3.10Windows x86-64

granian-2.7.1-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.1-cp310-cp310-musllinux_1_1_armv7l.whl (7.3 MB view details)

Uploaded CPython 3.10musllinux: musl 1.1+ ARMv7l

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

Uploaded CPython 3.10musllinux: musl 1.1+ ARM64

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

Uploaded CPython 3.10manylinux: glibc 2.28+ ARM64

granian-2.7.1-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.1-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl (6.4 MB view details)

Uploaded CPython 3.10manylinux: glibc 2.17+ i686

granian-2.7.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (7.1 MB view details)

Uploaded CPython 3.10manylinux: glibc 2.17+ ARMv7l

granian-2.7.1-cp310-cp310-macosx_11_0_arm64.whl (6.1 MB view details)

Uploaded CPython 3.10macOS 11.0+ ARM64

granian-2.7.1-cp310-cp310-macosx_10_12_x86_64.whl (6.4 MB view details)

Uploaded CPython 3.10macOS 10.12+ x86-64

File details

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

File metadata

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

File hashes

Hashes for granian-2.7.1.tar.gz
Algorithm Hash digest
SHA256 cc79292b24895db9441d32c3a9f11a4e19805d566bc77f9deb7ef18daac62e16
MD5 6bda058d07a7ec5c58ba73b4003ec5bd
BLAKE2b-256 e5e5c3a745a2c60cba6e67c5607fe6e18883fd2b7800fd7215511c526fab3872

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.1-pp311-pypy311_pp73-win_amd64.whl
Algorithm Hash digest
SHA256 a9bb46143d77161065cfe1d662f9a758bb17c7e3a2fde178f0a5aaac3fb3a65b
MD5 f244e8db5afab774f5497c6d25b6caec
BLAKE2b-256 a914c2480b4b4123e22b41bf82fc49e7a3b28cd2274dfa445959a1805f9a603d

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.1-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 47ef955d06c1cdff1aeb3d4d0ada415359a034295d0f162d7c0a0f98d76d4d6c
MD5 d0e2234fb8ac47ba184d1a7f46a4dd68
BLAKE2b-256 a5906bd215ec3567bcc36defb7cb30a3c03f73f2f56f8a8a34148a24008f94b6

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.1-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl
Algorithm Hash digest
SHA256 f4b715653cc9765c1aea629802c862e030482ff847f5d4c03d5f401830ff617c
MD5 75acc4daff50aaec4aab728dd2c8772c
BLAKE2b-256 4782c1fce66ebeb3d681d4405eee78b9159b230558f8bc99e44456541c03fe7b

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.1-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl
Algorithm Hash digest
SHA256 99b24f1241d142bdcb33c5744e7503b358fbcd899c44e4f48464b2bcaca2bd0f
MD5 2911f26c295e74c7470c3c4e4e24d7b7
BLAKE2b-256 91544c4aff8f153c3340d0aa26afbeb3db03bc9d7d914905c47705328c2514a8

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.1-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 32a4414b3ac17eef25d3bc33e2ed4f85150ebed3ef40028d4192bd0a842358c0
MD5 c1cd2d6c6721ef9c7399b625c7b6db4e
BLAKE2b-256 7600b2567a14dd68ae1fee1085d60f9ddaa6e93b155c86893804ed2303228f37

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.1-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 e8272952e6c094cdb24e42c9123eb780e789fe28e3f49a80cfce3df1b080ae2d
MD5 9fcdd63d9a13f8f97f07e20965a59d49
BLAKE2b-256 8640c6bf30ae2f9feb305b454a2a2118e40bec9dac94cc5c23a9d68f2d054f14

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.1-pp311-pypy311_pp73-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 8eeb97b4cc403956cdd782da83d30eddbfb90415e850520b6627d207cf06d8db
MD5 978a9a26f170761f44adb261c3c29781
BLAKE2b-256 f7796d734663ea31a1935ae0d835ba12883cdfe63376593918de84ddf1aa26c2

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.1-pp311-pypy311_pp73-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 97ebda3ae49c181b25b603d32ace5a8d83880c9c52550d3b66a4bf09f3c1b809
MD5 2d58d9a008046ef1af17df40aeb2c3d4
BLAKE2b-256 d77236d03ed914f70c79583542a60cedfeb7bc2ab992ee75ca5725612c1191a4

See more details on using hashes here.

File details

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

File metadata

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

File hashes

Hashes for granian-2.7.1-cp314-cp314t-win_amd64.whl
Algorithm Hash digest
SHA256 d787d9bf1744c275fa60775629e910305aa6395a88a32eea25b0008652ed9fe9
MD5 a732a7a4161230e98b45060b76f706f7
BLAKE2b-256 0cc1d6aa049cdbe15b9ffe7964b01cc50efc8ccc067c3a50da7bc5ced1eaf6a4

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.1-cp314-cp314t-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 874d4eedc527f9c59dd192e263be8047b86759e71ac9552283d010bcea93993b
MD5 f9410a38c6ed533f99fd89643569105d
BLAKE2b-256 d1527fefaf4f1317883e7a5f25a92bca43f914b47d4762ad8f38f48e7e85b2a8

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.1-cp314-cp314t-musllinux_1_1_armv7l.whl
Algorithm Hash digest
SHA256 f2834f178ddbe25f077b28eba3b0e3e3814b17a0fc61fe44c17c270eef37ff54
MD5 b256a9a165623670dbf345b8c16deb66
BLAKE2b-256 c9e4deff2560260ddc9a99315ecb345c93485b0b102708838e7c42837c7a6535

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.1-cp314-cp314t-musllinux_1_1_aarch64.whl
Algorithm Hash digest
SHA256 2cc036b6f7db04ba6750aa86dff17c7930b7f295e4bfc5f35e9231d9f42e8094
MD5 12d1630094e4228578d3f989b9890704
BLAKE2b-256 23002b9655d05f14bee4cd4080f3a18f0f0f4e7014158d7323a1cb0d31ed61cb

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.1-cp314-cp314t-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 ff4aba223bfeca0c6bc8f64ef03d87d04aff36515b2fd91108e5c9f55e67a5ee
MD5 8935cdc91c16bb2d4bd34882ebd6df3f
BLAKE2b-256 e62773655570644b3e727b22e3cf4239eebe90c18d1d3c868fc3d71e4d50dd46

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.1-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 9d12b93e6467fc079b38e104154d5e5625a5e7c6a1776a59039c1e5fb57e0fe3
MD5 f561753f992bdadc410d552cb975fbf4
BLAKE2b-256 d0630c0c0005798c808082ae72b6bc3ccc1282d1b078375b060c5477aabbe407

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.1-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl
Algorithm Hash digest
SHA256 b7f65cd1d46c8ee454b0f29743340bebc170c1da2af83bd759fb02d69c24c7e9
MD5 01355f4331d819eddbdc7fc171c2aea3
BLAKE2b-256 911af317272d59618a846a0c7ea019ab0352d947e8afdae40faea580b98600c7

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.1-cp314-cp314t-manylinux_2_12_i686.manylinux2010_i686.whl
Algorithm Hash digest
SHA256 1d1b5b47a34ab0f47f8bd447894412b4d9bdcb2011fbb9d1b8f7890c8442d233
MD5 86b0f7c59e64b82b829e2ddbfcd3f9d2
BLAKE2b-256 319c438da7d5c66ed2c9df1c5946485e464fd52a420217212e0c9b5bb90f8e93

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.1-cp314-cp314t-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 387c6032d46191deaf18819f15988e98d0f5c85eef09efb28c4c4b7b8b0dc2d2
MD5 4750e35e0b79b4217315af67ed4ac701
BLAKE2b-256 40eabdb388e3e24308e92c370674d225e819eee6740dd440d6450860039b934a

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.1-cp314-cp314t-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 e25c7dedd9325e11bda1d9692f25314791d24ae39b8206fb858f18a57087f2ee
MD5 b7ae9530b014e8a2f7a02249db2807b5
BLAKE2b-256 5c41bd76745d2fd2e2735390037324cb2d2b2f934473d77fb27f176494f5b2f3

See more details on using hashes here.

File details

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

File metadata

  • Download URL: granian-2.7.1-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.7

File hashes

Hashes for granian-2.7.1-cp314-cp314-win_amd64.whl
Algorithm Hash digest
SHA256 089f8a0d6d6a215f6773aa9dfdb56ec349d28840203517e7a7933485b1a1f404
MD5 85598e44c15b6674f096d42cb07c2996
BLAKE2b-256 61eab6901c64cac1fc3b455acdba279d80454fe963eca314ebfaf4e2eec9933c

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.1-cp314-cp314-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 773ff347d4541634e8c50b82b532eefa68c0043cda100bd44712b88565a5495b
MD5 1698b9fda62c003c1ab7dc47a15477d7
BLAKE2b-256 2f3afe283eeb7a2f525472bd6ef2b0c6b7fb95d4369902b75d8e7e252628e62e

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.1-cp314-cp314-musllinux_1_1_armv7l.whl
Algorithm Hash digest
SHA256 1a59ed88c40896db96a973e49a5ba2a2f84d7569c1da8cf11c685d11bffc2ef1
MD5 30b07a0ac8ab79b28b2cd3a2fc588347
BLAKE2b-256 f769c7a5c595313432a5373e6014980a77d8f028f24f31b68406af97ace94fe6

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.1-cp314-cp314-musllinux_1_1_aarch64.whl
Algorithm Hash digest
SHA256 ff063c417ee16fadca3c534e2059a6cf47e1df2607f1c6012be4ea6486b814f5
MD5 be38ab2d647615cf48f71fd154793395
BLAKE2b-256 fac608b9203a4f897a31810bb18344b5ecaf26eb34135916c257c14ec762eb51

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.1-cp314-cp314-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 392f6cc3eb7a5039a815a823c3f468161b4eb179d061450c0ec843cef0eb1b54
MD5 e85c25feec60e5922438e6486b31f4f7
BLAKE2b-256 eb479f07664d847653115b196f70594016de8fd7629e5aa1645d6d20f771cf14

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.1-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 ab94be605aaf90968fd04fb527f1b2790f6815dd0e9690586adb4a9be1f25010
MD5 bc9380c64f890d45d9424cb304c4a47e
BLAKE2b-256 74186e8962f1be1a578841e9c68bb8f3a416c30880003c3180a1e6b852ad1717

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.1-cp314-cp314-manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 d593d80f568b2025a227a9b0bf664db94c9423069b27c120e288a2350507a4d8
MD5 2f707a720293b51b677d1ada384b9785
BLAKE2b-256 ca70edd388b12ebecde4edbbf4d62cd78ed6e5ae0f6b834e88de2fe06e6f948e

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.1-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl
Algorithm Hash digest
SHA256 5c4eaf3b0c1602a2ef75a8e418bb6d2867994e7ac246ea6833f7b812289d038c
MD5 adeeed832e3a5f761f6a1fc451fa5dcd
BLAKE2b-256 cba0fa0b961d7c9b1c2f046a58b85ffe1e7bc5d3a7fcc8c947bdd6fd397a312c

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.1-cp314-cp314-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 ee4b404425a135274ab69513fdc1883ce954beef22113058e6e2a25d89926e68
MD5 cf347e3743434c111cc458893be38022
BLAKE2b-256 e8775248e8cf1c25f080959c0a4e4a8039107b0b2bf67a9fc8904cfe57614a24

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.1-cp314-cp314-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 a677972bb9050ec15896452f2c299b56f15e01212c1185d9373b92348fd88930
MD5 73a4aff22fd6cfd9a13fb7ef7c327de6
BLAKE2b-256 41c1cc5c0abc5c573a8832c584f52c98f7882119fe81d52a49285800e25d993f

See more details on using hashes here.

File details

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

File metadata

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

File hashes

Hashes for granian-2.7.1-cp313-cp313t-win_amd64.whl
Algorithm Hash digest
SHA256 b2cd2118353db7f06fee0aefdada9e109434e030ac2fdc8f691b669787680d2e
MD5 90d04dfb1de0b21287e15167557f7eef
BLAKE2b-256 d311a913af3c65debb5e5d577d3cb5ac988313c05c19fca789e167375ee432df

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.1-cp313-cp313t-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 52163a3b609489bcb614e45811e2a66a6780b1459bbbc29504de13c23a115112
MD5 694ec2070b44ad62a40413b5d09711ab
BLAKE2b-256 ac0075180d71994b87c0b56385c1b60c93b73b8822ed8edba2c63f72b0f836b6

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.1-cp313-cp313t-musllinux_1_1_armv7l.whl
Algorithm Hash digest
SHA256 f787bbcb06ca605ff4161a04078591b2269b628165214ab913084e7fdb5ab9d8
MD5 f3110b36f40e61c31dc30d218bef23b5
BLAKE2b-256 9125389eea98109e4b85e443fae384b30ff67167f27f4df6fb43d26cd151d0dc

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.1-cp313-cp313t-musllinux_1_1_aarch64.whl
Algorithm Hash digest
SHA256 dc51944736d5683b255b7cd33581daf8bc44ae1dab31240e1969eca13d1e75cf
MD5 9d54c7569759de839e900a38eebdf307
BLAKE2b-256 214a619d699acd3cd37de048ab606a85021f5edf42bd54c7f081d20dccd48041

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.1-cp313-cp313t-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 bec493af655645e58e6d89c7e37eb7751e9bf827506286e765d79a5c4ff10a3f
MD5 0f89502c4b2a8fb1218ad813de540c90
BLAKE2b-256 8262d133c36fdab4552db665d6bb2d53ac4834e41a97d8d0244f1aacc03e188f

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 2acc29a3eb9b1b9708355abd5438c216caff4ba4536bc77e46b19e44fb1b37ea
MD5 0d7d8edb882a8fe49083533df9a59c43
BLAKE2b-256 bdd3540a9f816884abf4da62d2e411455968a1ee8e4685243d3dd7fee1cf375f

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.1-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl
Algorithm Hash digest
SHA256 8ebbc04483ada6e1a8a89f055de0b4cad2f90b3cbc94a1ae08fc2b140d905f4b
MD5 5891f10dba7ddd2de24a63e2dc2a5951
BLAKE2b-256 c83a7aaf34391df169d54bcc3bfc32919b58de9b8a9e28e66b4f3276b910ef68

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.1-cp313-cp313t-manylinux_2_12_i686.manylinux2010_i686.whl
Algorithm Hash digest
SHA256 38088f6bd4780b280aae8abf15c2205bdf9066def927f8c9690c13a966519286
MD5 69903837a70e24355b6b85fb8b81b124
BLAKE2b-256 21f6ff76aab55b5a7bdbd20f4f73486fcb5a09440f4fd56bd3dc6266e65dee9a

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.1-cp313-cp313t-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 de9367e2dca2923bf12b52f004ab975ed0de45c8dedddd87993ed9fffabfb0ce
MD5 9946ce0e8394e30a23826692391062d2
BLAKE2b-256 468da8965de519507ba5dfa13af4760b3c1b334e46bf3283eab55f171693de0a

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.1-cp313-cp313t-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 33ed73fe753fcae51a647555614fc67013558a654d323115ab0fbf60aca6c47a
MD5 115392106dd09d5ab62a699406284805
BLAKE2b-256 33a83e0ea25a85a05618363ac9f90eb4e504ccc00e48c64f30cd37ef7046097f

See more details on using hashes here.

File details

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

File metadata

  • Download URL: granian-2.7.1-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.7

File hashes

Hashes for granian-2.7.1-cp313-cp313-win_amd64.whl
Algorithm Hash digest
SHA256 861d69fc3504c891f152585c2109d1eaf791c35392b13ed22c72fb199dc50dfa
MD5 f27328bf337af1d4c6953994d8782749
BLAKE2b-256 191e52173568f8da3a2d50f48eabe1cc19d857586e0878009477ed0c196ebebd

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.1-cp313-cp313-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 af842b07f14d7433774627c16fb0fbcdc9e60587d2d684636d2eba446c343297
MD5 a2c34512fe2a41277fa46865f659ac9b
BLAKE2b-256 0d0f3ddd893a4582943ab21c59853b7a6adae837130445ad64964cd73ea77ce4

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.1-cp313-cp313-musllinux_1_1_armv7l.whl
Algorithm Hash digest
SHA256 a20eaf1b756981caa8c0d6c19c5467e03386aadb07f854b88243218c9db9513b
MD5 331ba1306ab739a6b6b72519daaedd17
BLAKE2b-256 5285dcbc5b860697e1ebf9fa4206d3fba931a2ea2547fb8d2638ad392f4d5a90

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.1-cp313-cp313-musllinux_1_1_aarch64.whl
Algorithm Hash digest
SHA256 bc56766803ec0f958f4f2e3be9f4cb2385f9d6970e34ade6ff5c0ba751a3ce9c
MD5 505756c3f283b3d7332b2aab290808fd
BLAKE2b-256 4e496849f1f784186f41551ceba040e4402d7daa7a9c5c89e0b4c0fb7df5d73e

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.1-cp313-cp313-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 7681e76c61af0dd1e135139f5fa9561ec16fdbac19d0a9fbf4617079b822bf21
MD5 ecb72f7b86f2c5f54611e7c246e24745
BLAKE2b-256 1def379b77fc6f8909ffc4d9397135b122d93446f303f52e428aca1120d79b08

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 de3f44b244600103a3ad6358937a42370b8cc518b7754c740620be681272e0bd
MD5 4385835d12e2f5cc6717c999fe97610f
BLAKE2b-256 5db67a5632e1a206e11ac3470f9ef79b2aadce67d1dfc5cdf75a5fd9795ae0fa

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.1-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 9a68bf02c93c2137c68e2acd1dc68e871f49ce2e61b042fec9a145104daf3d5b
MD5 85913708933f81b70697462ea9649dba
BLAKE2b-256 635efdd4e42c800804cc277f12a3eba51747d100739b8beb0c1a909837670d86

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl
Algorithm Hash digest
SHA256 2079c9c29b65404283ef61ced11905c8491e4bc68a4e3b56c684fe2dab8cf8c2
MD5 effb951707d011033dbb51cf5f580529
BLAKE2b-256 b404432b73f713ebb102e1585f5abec9cb2284d76f4d16df73c24f2e4dcc9cbd

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.1-cp313-cp313-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 78ce501ec337b7db52ba1773c0acf0abd72b3fac71b6b747fe4ae6f38cca0a6b
MD5 04b96e08ae2d59389fbbf7615f0e6b4c
BLAKE2b-256 c25f32f933dac26835ad2f8bc9b4f5762be8f8340318a9bbeca75b32fa6f6195

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.1-cp313-cp313-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 b4f0c807fefedfa58d07c2751cc40471765387d331e70ea7ebd2a2ff5d492ca0
MD5 a0da908fc744eac7619afde778cc100f
BLAKE2b-256 53cee8ae26e248daaa8e782c0e6bce1350759da262f8aa637b8a0036c5455376

See more details on using hashes here.

File details

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

File metadata

  • Download URL: granian-2.7.1-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.7

File hashes

Hashes for granian-2.7.1-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 6cab79a863ccf6f18aa8b5e9261865d87c28574cd85174e8bb1bab873220077d
MD5 aaeb3127b20eac7de0575d4a0548c967
BLAKE2b-256 ca482c89fa53f5cdbc8495f55d587f3fa24f9ff984a8c572dd8930aa991e4301

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.1-cp312-cp312-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 93100bd3185e653c482c2996e11a7ece58ea28e355ef335bb0a30e4851c3ae8c
MD5 a72b55b122b520b1f89d44bcddafc223
BLAKE2b-256 42eecda1e8eb3e7025d82b6594814fc2f95ce252f638691240e4bc523924e204

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.1-cp312-cp312-musllinux_1_1_armv7l.whl
Algorithm Hash digest
SHA256 68a136b5d7ade34f3ee5ee743b2bdd55d6c1f0249c6bfdc8e038c6d0846de61e
MD5 207fdefa32cc973a759464d7d373f688
BLAKE2b-256 d468e0e24673e943fbb2540a7cd68dd3ea10a4cd9db6f538de9cec26b1c54133

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.1-cp312-cp312-musllinux_1_1_aarch64.whl
Algorithm Hash digest
SHA256 cc435c5d1881554bf7eb4e2fe8d2ad7e5052a0bacc7195c477bfc97544c7bf46
MD5 832da2dfef26bb43d4aad9d1c001c235
BLAKE2b-256 afffb17d357d4f1eff19ff45257ea924bb571d4cf2caefccdc8aca8c0b1a3c7a

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.1-cp312-cp312-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 24f09f5dbb9105498e521733e5993135fb276e346ce8f04cead2f4113ca51bba
MD5 fdc2cb30be81ee5722c5e6a50449c34e
BLAKE2b-256 90f5bd0fafc93f01f345ad1ecc70fbb459e452c777fe8b4958020399332b7f03

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 a02a150c6a1ba8a7123634a22c0352a116ea2211e634479e9f64409db72d4489
MD5 cb5da583e18252b632782fdcef66a5d5
BLAKE2b-256 5fef5d6712ad81e85841d4fd5436f5cbfcdb3ac3ddeb9e75953fd6b323bfff64

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.1-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 76b1751c5d5dcc93803e37baf68396dba22d809001037faec4b2df8fdc52af7e
MD5 4902b118068ab2f9e9e2c415a441e6ea
BLAKE2b-256 9b89db6b3504a41e222a1d94417995f73fa17a27dc2fc664c29295dfc34bd64b

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl
Algorithm Hash digest
SHA256 6b1007f1b58e4ace682d424789dd34b63526a482ba3efc01ca18098b65420d6d
MD5 61994a9894e8cab60a7f81d922334b8b
BLAKE2b-256 fe6909eea196a4f9883dad20d4acd645be35242c0004ba4a698f73f9e0fe8291

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.1-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 df3e8f617dc3e21e3a4e543678993e855fb1d008f1207c646d27efd45e45161b
MD5 56dfc6ed5c402f65095bd19bd7b1b05e
BLAKE2b-256 ab38bf86291a04d1d4fd7b469b0134224cdb0cafa4e7cc8de5744f79d045ff5c

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.1-cp312-cp312-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 d603c53a8d7e6243a5c4b9749116143f4a6184033777451ba376b038905ac57f
MD5 4931e3a91ff7b38b4abc3732b8121ef5
BLAKE2b-256 3b2d4a29e3b654ad38b0a7b1fb477a20a1d03b36a40060d15bd98f43654aac3a

See more details on using hashes here.

File details

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

File metadata

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

File hashes

Hashes for granian-2.7.1-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 ba65410b56d951d9aa2e8b0b0f7796431052c43eca2bb8a526a743d2f8aa539f
MD5 b43bf26d0561844c0cafe81086d16c4e
BLAKE2b-256 e3512abe731a4ec42038a0ea24695bd6fd79d4b340797115bd1af40c21cfd1a3

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.1-cp311-cp311-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 98ab412772f2c66260a3535da4101ccc6dd20de30e74a87b32fd7abc729cc14f
MD5 f0b7017b1b1fcb9417b1f87e6d04f22e
BLAKE2b-256 c2bcc9d1dce0b2d11bf76aadd06608d3b01a2b697c030c5ea01474d15e36e2af

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.1-cp311-cp311-musllinux_1_1_armv7l.whl
Algorithm Hash digest
SHA256 025218f8ccc5907bc8277b0df9a60927a5862ee607606cfc970cc404d5346af6
MD5 c2599ccbf885caa55e7d529e14041846
BLAKE2b-256 3062c445c0c96552f11dee49d002d4af32adbeca19b7e8064a1d106952810345

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.1-cp311-cp311-musllinux_1_1_aarch64.whl
Algorithm Hash digest
SHA256 ab6da78f0fcecf9a9177db2d716e50214b540cb1ea77dafc88e35184ca901266
MD5 51c3091a0cf21478fa50b3754e52ef41
BLAKE2b-256 1983f9c3685681aa4b41feb73def9ef63800b6f639629e9b083a0c279583fb92

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.1-cp311-cp311-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 71776d7319906cfc78f723cc38f927ffaf58bcb9b1707fe5d88c3662827aa1f7
MD5 5ea4650b6c1500db9c3a7fdb57c842f9
BLAKE2b-256 5c840d18018b05652991c8502da2cbab6b9b8c234926870d0458d2d7c5124a65

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 c2c445c13fa6fc7235f95c28f2d203369d0c516aba15ba24faad08ca0a095bd0
MD5 ba56818edd6292880b597fe2694c64f8
BLAKE2b-256 37491836d259060ceae6cf1dc7d0c424864786ac028c93aaeed07f6ea9dfcafc

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.1-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 5240510754712cc802ad5a71507f10efdb83a043dbccd351662897f58916a76a
MD5 3702aa0a1906ff3c574283380b54d634
BLAKE2b-256 beac6e142e3a26c3fe90d7e6592256ed4940e696f4430933d597e4014b5ee441

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl
Algorithm Hash digest
SHA256 edf7cbab2c54a3dd10c0f8a737b133cc605b6309acdfe3aa060bc954d7ae13c5
MD5 7526cd17e67a5a09fbc16510e604a894
BLAKE2b-256 2b1b44d8acdfda1a1af2c4fa8ba215912bd78318b59f195c5b7831dab69a7719

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.1-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 b1abc6dfe5d5fb1f2e863200ee9edf749ed82ff9c1361c21483b214a91654879
MD5 5b62199284a5d2ad27242e60c839459d
BLAKE2b-256 e8b6db0b26c9226490fb42d51fa70fd08e8daf5ad9747d60d2dc143dd2517b3d

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.1-cp311-cp311-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 bbcdea802c5a594d204b807de6829a7d4b723c397087857ca4d3a3cf2ac1d16e
MD5 2c9dd8405cc2c6137cd86d47559e72d3
BLAKE2b-256 27fd44b8027007de2558d09ff7ee688229ad5d4f368bb166589a2547926057e4

See more details on using hashes here.

File details

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

File metadata

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

File hashes

Hashes for granian-2.7.1-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 91d7ff9ebd4736da8597c642b3df0e4087aaf0c64f0d15bbe5415e7c2811b599
MD5 04e8b28c804e95b940b23e8f91f696b9
BLAKE2b-256 e0113c7fd79b99a12d5505385a3dcfe899e01ebc46b0219fd319c0716719251b

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.1-cp310-cp310-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 f4008dca32d36089060cfdcf1973db01ee373ffd639433a760cb597a0ea1a29a
MD5 3f7d676dd4ddcb84cc1a46552d7e1b58
BLAKE2b-256 59d489cb7484e1910f77b51be41c8f5d5709dea00d82b6b63bbe15b6ff8f4974

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.1-cp310-cp310-musllinux_1_1_armv7l.whl
Algorithm Hash digest
SHA256 f7133e8553e3b91c9484a69f3d2e040b618ba9fe71e8d0df9781084b41827aca
MD5 20d267adb050fa2181c5f4e4aa26254d
BLAKE2b-256 9cb3f53f1160d5e4c0c00dd38aad793f5b2c1fae191cc180f355be92e39a6485

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.1-cp310-cp310-musllinux_1_1_aarch64.whl
Algorithm Hash digest
SHA256 0eba7a11d2d7283ab59ae2b8fefcc45ff46949313e2f46ff8fbf8d7a6c0115b9
MD5 f8e3193ebc63208dc2cfd433a066ca26
BLAKE2b-256 a598778018938e51e2e43eeaded3cefc5ef595db084a1a24965702ca555ce468

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.1-cp310-cp310-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 9cf191fec7e91287dc7a885edfc82b40cf3b2bef0c4b5aa2209a0fcc31b68e01
MD5 64e538e1042584642ea02470b8d5651b
BLAKE2b-256 b3f127f220de51e3cb37d5e2a0cdfdbe6075a23787d62e9d911eb2786ab14953

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 f3135a9b895585f28ae09162e581f36322adf9d7505e3dad4b705211760f9c9c
MD5 fcefa5b787a53b70e37bf86b4561845e
BLAKE2b-256 766d6d1826de26f1810b9288b961de68032083a067b880029f04ea446241ca52

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.1-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 4e0b168da29737c1c46b5949189c9b35a177d58dce31ae4834870395990350fc
MD5 a08c0930e73b8a716e428ebc30ed9f8a
BLAKE2b-256 2fcd11c1eb0d2a17ecedecc03d503b23011d2ad88e99678edcf1ae80a4961f7d

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl
Algorithm Hash digest
SHA256 abad081f70f09b42fdf4d6063e61e388b1b4051c40103129d6fb649cb2903e3c
MD5 645757e8e075bf11696e0ea6f039fae1
BLAKE2b-256 42b02d5471893d7c35f1b85854b27ddab65743eec66fa94fd80daa7b71ae0330

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.1-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 5597681fb4273f71f48e7c7c639f36fa9b66a8431fccd21f56a723890e624dc4
MD5 d58322cb817470e1f9421cbfb3533642
BLAKE2b-256 711350e910c7b8cc922393f921ef41ca33e3574ccd55d29625eb04177ede8c8d

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for granian-2.7.1-cp310-cp310-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 800140b3cfd80360e82f5fca8e3846deecbe8f8accb2fc4a6ff7af73dcfda001
MD5 339a176ddcbf1227fb142c2510e7271b
BLAKE2b-256 bc0b50d9f2c911742140fc719db522f20ac16b8d33e845704cb9f80948af8596

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