graphtik


Namegraphtik JSON
Version 10.5.0 PyPI version JSON
download
home_pagehttp://github.com/pygraphkit/graphtik
SummaryA Python lib for solving & executing graphs of functions, with `pandas` in mind
upload_time2023-04-25 21:27:37
maintainer
docs_urlNone
authorKostis Anagnostopoulos, Huy Nguyen, Arel Cordero, Pierre Garrigues, Rob Hess, Tobi Baumgartner, Clayton Mellina
requires_python>=3.6
licenseApache-2.0
keywords graph computation graph dag directed acyclic graph executor scheduler etl workflow pipeline
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI
coveralls test coverage No coveralls.
            Graphtik
========

|pypi-version| |gh-version| (build-version: x.x.x, build-date: 2023-04-25T21:27:33.616654)
|python-ver| |dev-status|
|ci-status| |doc-status| |cover-status| |codestyle| |proj-lic|

|gh-watch| |gh-star| |gh-fork| |gh-issues|

.. epigraph::

    It's a DAG all the way down!

    |sample-plot|

Computation graphs for Python & Pandas
--------------------------------------

**Graphtik** is a library to compose, solve, execute & plot *graphs of python functions*
(a.k.a pipelines) that consume and populate named data
(a.k.a dependencies), whose names may be nested (such as. *pandas* dataframe columns),
based on whether values for those dependencies exist in the inputs or
have been calculated earlier.

In mathematical terms, given:

- a partially populated data-tree, and
- a set of functions operating on (consuming/producing) branches of the data tree,

*graphtik* collects a subset of functions in a graph that when executed
consume & produce as many values as possible in the data-tree.

|usage-overview|

- Its primary use case is building flexible algorithms for data science/machine learning projects.
- It should be extendable to implement the following:

  - an `IoC dependency resolver <https://en.wikipedia.org/wiki/Dependency_injection>`_
    (e.g. Java Spring, Google Guice);
  - an executor of interdependent tasks based on files (e.g. GNU Make);
  - a custom ETL engine;
  - a spreadsheet calculation engine.

*Graphtik* `sprang <https://docs.google.com/spreadsheets/d/1HPgtg2l6v3uDS81hLOcFOZxIBLCnHGrcFOh3pFRIDio/edit#gid=0>`_
from `Graphkit`_ (summer 2019, v1.2.2) to `experiment
<https://github.com/yahoo/graphkit/issues/>`_ with Python 3.6+ features,
but has diverged significantly with enhancements ever since.

.. _features:

Features
--------

- Deterministic pre-decided `execution plan` (unless *partial-outputs* or
  *endured operations* defined, see below).
- Can assemble existing functions without modifications into `pipeline`\s.
- `dependency` resolution can bypass calculation cycles based on data given and asked.
- Support functions with `optional <optionals>` input args and/or `varargs <varargish>`.
- Support functions with `partial outputs`; keep working even if certain `endured` operations fail.
- Facilitate trivial `conveyor operation`\s and `alias` on `provides`.
- Support cycles, by annotating repeated updates of `dependency` values as `sideffects`,
  (e.g. to add columns into *pandas.DataFrame*\s).
- `Hierarchical dependencies <subdoc>` may access data values deep in `solution`
  with `json pointer path` expressions.
- Hierarchical dependencies annotated as `implicit` imply which subdoc dependency
  the function reads or writes in the parent-doc.
- `Merge <operation merging>` or `nest <operation nesting>` sub-pipelines.
- Early `eviction` of intermediate results from `solution`, to optimize memory footprint.
- Solution tracks all intermediate `overwritten <overwrite>` values for the same dependency.
- Elaborate `Graphviz`_ plotting with configurable `plot theme`\s.
- Integration with Sphinx sites with the new *graphtik* directive.
- Authored with *debugging* in mind.
- Parallel execution (but underdeveloped & DEPRECATED).

Anti-features
^^^^^^^^^^^^^

- It's not meant to follow complex conditional logic based on `dependency` values
  (though it does support that to `a limited degree <partial outputs>`).

- It's not an orchestrator for long-running tasks, nor a calendar scheduler -
  `Apache Airflow <https://airflow.apache.org/>`_, `Dagster
  <https://github.com/dagster-io/dagster>`_ or `Luigi <https://luigi.readthedocs.io/>`_
  may help for that.

- It's not really a parallelizing optimizer, neither a map-reduce framework - look
  additionally at `Dask <https://dask.org/>`_, `IpyParallel
  <https://ipyparallel.readthedocs.io/en/latest/>`_, `Celery
  <https://docs.celeryproject.org/en/stable/getting-started/introduction.html>`_,
  Hive, Pig, Hadoop, etc.

- It's not a stream/batch processor, like Spark, Storm, Fink, Kinesis,
  because it pertains function-call semantics, calling only once each function
  to process data-items.

Differences with *schedula*
%%%%%%%%%%%%%%%%%%%%%%%%%%%

`schedula <https://schedula.readthedocs.io/>`_ is a powerful library written roughly
for the same purpose, and works differently along these lines
(ie features below refer to *schedula*):

- terminology (<graphtik> := <schedula>):

  - pipeline := dispatcher
  - plan := workflow
  - solution := solution

- Dijkstra planning runs while calling operations:

  - Powerful & flexible (ie all operations are dynamic, *domains* are possible, etc).
  - Supports *weights*.
  - Cannot pre-calculate & cache execution plans (slow).

- Calculated values are stored inside a graph (mimicking the structure of the functions):

  - graph visualizations absolutely needed to inspect & debug its solutions.
  - graphs imply complex pre/post processing & traversal algos
      (vs constructing/traversing data-trees).

- Reactive plotted diagrams, web-server runs behind the scenes.
- Operation graphs are stackable:

  - plotted nested-graphs support drill-down.
  - *graphtik* emulates that with data/operation names (`operation nesting`),
    but always a unified graph is solved at once,
    bc it is impossible to dress *nesting-funcs* as a *python-funcs* and pre-solve plan
    (*schedula* does not pre-solve plan, Dijkstra runs all the time).
    See TODO about plotting such nested graphs.

- *Schedula* does not calculate all possible values (ie no `overwrite`\s).
- *Schedula* computes precedence based on weights and lexicographical order of function name.

  - Re-inserting operation does not overrides its current function - must remove it first.
  - *graphtik* precedence based insertion order during `composition`.

- Virtual *start* and *end* data-nodes needed for Dijkstra to solve the dag.
- No domains (execute-time conditionals deciding whether a function must run).
- Probably *recompute* is more straightforward in *graphtik*.
- TODO: more differences with *schedula* exist.

Quick start
-----------
Here’s how to install:

::

   pip install graphtik

OR with various "extras" dependencies, such as, for plotting::

   pip install graphtik[plot]

. Tip::
    Supported extras:

    **plot**
        for plotting with `Graphviz`_,
    **matplot**
        for plotting in *maplotlib* windows
    **sphinx**
        for embedding plots in *sphinx*\-generated sites,
    **test**
        for running *pytest*\s,
    **dill**
        may help for pickling `parallel` tasks - see `marshalling` term
        and ``set_marshal_tasks()`` configuration.
    **all**
        all of the above, plus development libraries, eg *black* formatter.
    **dev**
        like *all*

Let's build a *graphtik* computation graph that produces x3 outputs
out of 2 inputs `α` and `β`:

- `α x β`
- `α - αxβ`
- `|α - αxβ| ^ 3`

..

>>> from graphtik import compose, operation
>>> from operator import mul, sub

>>> @operation(name="abs qubed",
...            needs=["α-α×β"],
...            provides=["|α-α×β|³"])
... def abs_qubed(a):
...     return abs(a) ** 3

Compose the ``abs_qubed`` function along the ``mul`` & ``sub``  built-ins
into a computation graph:

>>> graphop = compose("graphop",
...     operation(needs=["α", "β"], provides=["α×β"])(mul),
...     operation(needs=["α", "α×β"], provides=["α-α×β"])(sub),
...     abs_qubed,
... )
>>> graphop
Pipeline('graphop', needs=['α', 'β', 'α×β', 'α-α×β'],
                    provides=['α×β', 'α-α×β', '|α-α×β|³'],
                    x3 ops: mul, sub, abs qubed)

Run the graph and request all of the outputs
(notice that unicode characters work also as Python identifiers):

>>> graphop(α=2, β=5)
{'α': 2, 'β': 5, 'α×β': 10, 'α-α×β': -8, '|α-α×β|³': 512}

... or request a subset of outputs:

>>> solution = graphop.compute({'α': 2, 'β': 5}, outputs=["α-α×β"])
>>> solution
{'α-α×β': -8}

... and plot the results (if in *jupyter*, no need to create the file):

>>> solution.plot('executed_3ops.svg')  # doctest: +SKIP

|sample-sol|

|plot-legend|

.. |sample-plot| image:: docs/source/images/sample.svg
    :alt: sample graphtik plot
    :width: 380px
    :align: middle
.. |usage-overview| image:: docs/source/images/GraphkitUsageOverview.svg
    :alt: Usage overview of graphtik library
    :width: 640px
    :align: middle
.. |sample-sol| image:: docs/source/images/executed_3ops.svg
    :alt: sample graphtik plot
    :width: 380px
    :align: middle
.. |plot-legend| image:: docs/source/images/GraphtikLegend.svg
    :alt: graphtik legend
    :align: middle


.. _Graphkit: https://github.com/yahoo/graphkit
.. _Graphviz: https://graphviz.org
.. _badges_substs:

.. |ci-status| image:: https://github.com/pygraphkit/graphtik/actions/workflows/ci.yaml/badge.svg
    :alt: GitHub Actions CI testing ok? (Linux)
    :target: https://github.com/pygraphkit/graphtik/actions

.. |doc-status| image:: https://img.shields.io/readthedocs/graphtik?branch=master
    :alt: ReadTheDocs ok?
    :target: https://graphtik.readthedocs.org

.. |cover-status| image:: https://img.shields.io/codecov/c/github/pygraphkit/graphtik
    :target: https://codecov.io/gh/pygraphkit/graphtik

.. |gh-version| image::  https://img.shields.io/github/v/release/pygraphkit/graphtik?label=GitHub%20release&include_prereleases
    :target: https://github.com/pygraphkit/graphtik/releases
    :alt: Latest release in GitHub

.. |pypi-version| image::  https://img.shields.io/pypi/v/graphtik?label=PyPi%20version
    :target: https://pypi.python.org/pypi/graphtik/
    :alt: Latest version in PyPI

.. |python-ver| image:: https://img.shields.io/pypi/pyversions/graphtik?label=Python
    :target: https://pypi.python.org/pypi/graphtik/
    :alt: Supported Python versions of latest release in PyPi

.. |dev-status| image:: https://img.shields.io/pypi/status/graphtik
    :target: https://pypi.python.org/pypi/graphtik/
    :alt: Development Status

.. |codestyle| image:: https://img.shields.io/badge/code%20style-black-black
    :target: https://github.com/ambv/black
    :alt: Code Style

.. |gh-watch| image:: https://img.shields.io/github/watchers/pygraphkit/graphtik?style=social
    :target: https://github.com/pygraphkit/graphtik
    :alt: Github watchers

.. |gh-star| image:: https://img.shields.io/github/stars/pygraphkit/graphtik?style=social
    :target: https://github.com/pygraphkit/graphtik
    :alt: Github stargazers

.. |gh-fork| image:: https://img.shields.io/github/forks/pygraphkit/graphtik?style=social
    :target: https://github.com/pygraphkit/graphtik
    :alt: Github forks

.. |gh-issues| image:: http://img.shields.io/github/issues/pygraphkit/graphtik?style=social
    :target: https://github.com/pygraphkit/graphtik/issues
    :alt: Issues count

.. |proj-lic| image:: https://img.shields.io/pypi/l/graphtik
    :target:  https://www.apache.org/licenses/LICENSE-2.0
    :alt: Apache License, version 2.0

            

Raw data

            {
    "_id": null,
    "home_page": "http://github.com/pygraphkit/graphtik",
    "name": "graphtik",
    "maintainer": "",
    "docs_url": null,
    "requires_python": ">=3.6",
    "maintainer_email": "",
    "keywords": "graph,computation graph,DAG,directed acyclic graph,executor,scheduler,etl,workflow,pipeline",
    "author": "Kostis Anagnostopoulos, Huy Nguyen, Arel Cordero, Pierre Garrigues, Rob Hess, Tobi Baumgartner, Clayton Mellina",
    "author_email": "ankostis@gmail.com",
    "download_url": "https://files.pythonhosted.org/packages/7f/00/a579f9350ef68660b84e4b49123cd4f1c7b54ab0ebd55b9d2a0f6cfd77a7/graphtik-10.5.0.tar.gz",
    "platform": "Windows",
    "description": "Graphtik\n========\n\n|pypi-version| |gh-version| (build-version: x.x.x, build-date: 2023-04-25T21:27:33.616654)\n|python-ver| |dev-status|\n|ci-status| |doc-status| |cover-status| |codestyle| |proj-lic|\n\n|gh-watch| |gh-star| |gh-fork| |gh-issues|\n\n.. epigraph::\n\n    It's a DAG all the way down!\n\n    |sample-plot|\n\nComputation graphs for Python & Pandas\n--------------------------------------\n\n**Graphtik** is a library to compose, solve, execute & plot *graphs of python functions*\n(a.k.a pipelines) that consume and populate named data\n(a.k.a dependencies), whose names may be nested (such as. *pandas* dataframe columns),\nbased on whether values for those dependencies exist in the inputs or\nhave been calculated earlier.\n\nIn mathematical terms, given:\n\n- a partially populated data-tree, and\n- a set of functions operating on (consuming/producing) branches of the data tree,\n\n*graphtik* collects a subset of functions in a graph that when executed\nconsume & produce as many values as possible in the data-tree.\n\n|usage-overview|\n\n- Its primary use case is building flexible algorithms for data science/machine learning projects.\n- It should be extendable to implement the following:\n\n  - an `IoC dependency resolver <https://en.wikipedia.org/wiki/Dependency_injection>`_\n    (e.g. Java Spring, Google Guice);\n  - an executor of interdependent tasks based on files (e.g. GNU Make);\n  - a custom ETL engine;\n  - a spreadsheet calculation engine.\n\n*Graphtik* `sprang <https://docs.google.com/spreadsheets/d/1HPgtg2l6v3uDS81hLOcFOZxIBLCnHGrcFOh3pFRIDio/edit#gid=0>`_\nfrom `Graphkit`_ (summer 2019, v1.2.2) to `experiment\n<https://github.com/yahoo/graphkit/issues/>`_ with Python 3.6+ features,\nbut has diverged significantly with enhancements ever since.\n\n.. _features:\n\nFeatures\n--------\n\n- Deterministic pre-decided `execution plan` (unless *partial-outputs* or\n  *endured operations* defined, see below).\n- Can assemble existing functions without modifications into `pipeline`\\s.\n- `dependency` resolution can bypass calculation cycles based on data given and asked.\n- Support functions with `optional <optionals>` input args and/or `varargs <varargish>`.\n- Support functions with `partial outputs`; keep working even if certain `endured` operations fail.\n- Facilitate trivial `conveyor operation`\\s and `alias` on `provides`.\n- Support cycles, by annotating repeated updates of `dependency` values as `sideffects`,\n  (e.g. to add columns into *pandas.DataFrame*\\s).\n- `Hierarchical dependencies <subdoc>` may access data values deep in `solution`\n  with `json pointer path` expressions.\n- Hierarchical dependencies annotated as `implicit` imply which subdoc dependency\n  the function reads or writes in the parent-doc.\n- `Merge <operation merging>` or `nest <operation nesting>` sub-pipelines.\n- Early `eviction` of intermediate results from `solution`, to optimize memory footprint.\n- Solution tracks all intermediate `overwritten <overwrite>` values for the same dependency.\n- Elaborate `Graphviz`_ plotting with configurable `plot theme`\\s.\n- Integration with Sphinx sites with the new *graphtik* directive.\n- Authored with *debugging* in mind.\n- Parallel execution (but underdeveloped & DEPRECATED).\n\nAnti-features\n^^^^^^^^^^^^^\n\n- It's not meant to follow complex conditional logic based on `dependency` values\n  (though it does support that to `a limited degree <partial outputs>`).\n\n- It's not an orchestrator for long-running tasks, nor a calendar scheduler -\n  `Apache Airflow <https://airflow.apache.org/>`_, `Dagster\n  <https://github.com/dagster-io/dagster>`_ or `Luigi <https://luigi.readthedocs.io/>`_\n  may help for that.\n\n- It's not really a parallelizing optimizer, neither a map-reduce framework - look\n  additionally at `Dask <https://dask.org/>`_, `IpyParallel\n  <https://ipyparallel.readthedocs.io/en/latest/>`_, `Celery\n  <https://docs.celeryproject.org/en/stable/getting-started/introduction.html>`_,\n  Hive, Pig, Hadoop, etc.\n\n- It's not a stream/batch processor, like Spark, Storm, Fink, Kinesis,\n  because it pertains function-call semantics, calling only once each function\n  to process data-items.\n\nDifferences with *schedula*\n%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\n`schedula <https://schedula.readthedocs.io/>`_ is a powerful library written roughly\nfor the same purpose, and works differently along these lines\n(ie features below refer to *schedula*):\n\n- terminology (<graphtik> := <schedula>):\n\n  - pipeline := dispatcher\n  - plan := workflow\n  - solution := solution\n\n- Dijkstra planning runs while calling operations:\n\n  - Powerful & flexible (ie all operations are dynamic, *domains* are possible, etc).\n  - Supports *weights*.\n  - Cannot pre-calculate & cache execution plans (slow).\n\n- Calculated values are stored inside a graph (mimicking the structure of the functions):\n\n  - graph visualizations absolutely needed to inspect & debug its solutions.\n  - graphs imply complex pre/post processing & traversal algos\n      (vs constructing/traversing data-trees).\n\n- Reactive plotted diagrams, web-server runs behind the scenes.\n- Operation graphs are stackable:\n\n  - plotted nested-graphs support drill-down.\n  - *graphtik* emulates that with data/operation names (`operation nesting`),\n    but always a unified graph is solved at once,\n    bc it is impossible to dress *nesting-funcs* as a *python-funcs* and pre-solve plan\n    (*schedula* does not pre-solve plan, Dijkstra runs all the time).\n    See TODO about plotting such nested graphs.\n\n- *Schedula* does not calculate all possible values (ie no `overwrite`\\s).\n- *Schedula* computes precedence based on weights and lexicographical order of function name.\n\n  - Re-inserting operation does not overrides its current function - must remove it first.\n  - *graphtik* precedence based insertion order during `composition`.\n\n- Virtual *start* and *end* data-nodes needed for Dijkstra to solve the dag.\n- No domains (execute-time conditionals deciding whether a function must run).\n- Probably *recompute* is more straightforward in *graphtik*.\n- TODO: more differences with *schedula* exist.\n\nQuick start\n-----------\nHere\u2019s how to install:\n\n::\n\n   pip install graphtik\n\nOR with various \"extras\" dependencies, such as, for plotting::\n\n   pip install graphtik[plot]\n\n. Tip::\n    Supported extras:\n\n    **plot**\n        for plotting with `Graphviz`_,\n    **matplot**\n        for plotting in *maplotlib* windows\n    **sphinx**\n        for embedding plots in *sphinx*\\-generated sites,\n    **test**\n        for running *pytest*\\s,\n    **dill**\n        may help for pickling `parallel` tasks - see `marshalling` term\n        and ``set_marshal_tasks()`` configuration.\n    **all**\n        all of the above, plus development libraries, eg *black* formatter.\n    **dev**\n        like *all*\n\nLet's build a *graphtik* computation graph that produces x3 outputs\nout of 2 inputs `\u03b1` and `\u03b2`:\n\n- `\u03b1 x \u03b2`\n- `\u03b1 - \u03b1x\u03b2`\n- `|\u03b1 - \u03b1x\u03b2| ^ 3`\n\n..\n\n>>> from graphtik import compose, operation\n>>> from operator import mul, sub\n\n>>> @operation(name=\"abs qubed\",\n...            needs=[\"\u03b1-\u03b1\u00d7\u03b2\"],\n...            provides=[\"|\u03b1-\u03b1\u00d7\u03b2|\u00b3\"])\n... def abs_qubed(a):\n...     return abs(a) ** 3\n\nCompose the ``abs_qubed`` function along the ``mul`` & ``sub``  built-ins\ninto a computation graph:\n\n>>> graphop = compose(\"graphop\",\n...     operation(needs=[\"\u03b1\", \"\u03b2\"], provides=[\"\u03b1\u00d7\u03b2\"])(mul),\n...     operation(needs=[\"\u03b1\", \"\u03b1\u00d7\u03b2\"], provides=[\"\u03b1-\u03b1\u00d7\u03b2\"])(sub),\n...     abs_qubed,\n... )\n>>> graphop\nPipeline('graphop', needs=['\u03b1', '\u03b2', '\u03b1\u00d7\u03b2', '\u03b1-\u03b1\u00d7\u03b2'],\n                    provides=['\u03b1\u00d7\u03b2', '\u03b1-\u03b1\u00d7\u03b2', '|\u03b1-\u03b1\u00d7\u03b2|\u00b3'],\n                    x3 ops: mul, sub, abs qubed)\n\nRun the graph and request all of the outputs\n(notice that unicode characters work also as Python identifiers):\n\n>>> graphop(\u03b1=2, \u03b2=5)\n{'\u03b1': 2, '\u03b2': 5, '\u03b1\u00d7\u03b2': 10, '\u03b1-\u03b1\u00d7\u03b2': -8, '|\u03b1-\u03b1\u00d7\u03b2|\u00b3': 512}\n\n... or request a subset of outputs:\n\n>>> solution = graphop.compute({'\u03b1': 2, '\u03b2': 5}, outputs=[\"\u03b1-\u03b1\u00d7\u03b2\"])\n>>> solution\n{'\u03b1-\u03b1\u00d7\u03b2': -8}\n\n... and plot the results (if in *jupyter*, no need to create the file):\n\n>>> solution.plot('executed_3ops.svg')  # doctest: +SKIP\n\n|sample-sol|\n\n|plot-legend|\n\n.. |sample-plot| image:: docs/source/images/sample.svg\n    :alt: sample graphtik plot\n    :width: 380px\n    :align: middle\n.. |usage-overview| image:: docs/source/images/GraphkitUsageOverview.svg\n    :alt: Usage overview of graphtik library\n    :width: 640px\n    :align: middle\n.. |sample-sol| image:: docs/source/images/executed_3ops.svg\n    :alt: sample graphtik plot\n    :width: 380px\n    :align: middle\n.. |plot-legend| image:: docs/source/images/GraphtikLegend.svg\n    :alt: graphtik legend\n    :align: middle\n\n\n.. _Graphkit: https://github.com/yahoo/graphkit\n.. _Graphviz: https://graphviz.org\n.. _badges_substs:\n\n.. |ci-status| image:: https://github.com/pygraphkit/graphtik/actions/workflows/ci.yaml/badge.svg\n    :alt: GitHub Actions CI testing ok? (Linux)\n    :target: https://github.com/pygraphkit/graphtik/actions\n\n.. |doc-status| image:: https://img.shields.io/readthedocs/graphtik?branch=master\n    :alt: ReadTheDocs ok?\n    :target: https://graphtik.readthedocs.org\n\n.. |cover-status| image:: https://img.shields.io/codecov/c/github/pygraphkit/graphtik\n    :target: https://codecov.io/gh/pygraphkit/graphtik\n\n.. |gh-version| image::  https://img.shields.io/github/v/release/pygraphkit/graphtik?label=GitHub%20release&include_prereleases\n    :target: https://github.com/pygraphkit/graphtik/releases\n    :alt: Latest release in GitHub\n\n.. |pypi-version| image::  https://img.shields.io/pypi/v/graphtik?label=PyPi%20version\n    :target: https://pypi.python.org/pypi/graphtik/\n    :alt: Latest version in PyPI\n\n.. |python-ver| image:: https://img.shields.io/pypi/pyversions/graphtik?label=Python\n    :target: https://pypi.python.org/pypi/graphtik/\n    :alt: Supported Python versions of latest release in PyPi\n\n.. |dev-status| image:: https://img.shields.io/pypi/status/graphtik\n    :target: https://pypi.python.org/pypi/graphtik/\n    :alt: Development Status\n\n.. |codestyle| image:: https://img.shields.io/badge/code%20style-black-black\n    :target: https://github.com/ambv/black\n    :alt: Code Style\n\n.. |gh-watch| image:: https://img.shields.io/github/watchers/pygraphkit/graphtik?style=social\n    :target: https://github.com/pygraphkit/graphtik\n    :alt: Github watchers\n\n.. |gh-star| image:: https://img.shields.io/github/stars/pygraphkit/graphtik?style=social\n    :target: https://github.com/pygraphkit/graphtik\n    :alt: Github stargazers\n\n.. |gh-fork| image:: https://img.shields.io/github/forks/pygraphkit/graphtik?style=social\n    :target: https://github.com/pygraphkit/graphtik\n    :alt: Github forks\n\n.. |gh-issues| image:: http://img.shields.io/github/issues/pygraphkit/graphtik?style=social\n    :target: https://github.com/pygraphkit/graphtik/issues\n    :alt: Issues count\n\n.. |proj-lic| image:: https://img.shields.io/pypi/l/graphtik\n    :target:  https://www.apache.org/licenses/LICENSE-2.0\n    :alt: Apache License, version 2.0\n",
    "bugtrack_url": null,
    "license": "Apache-2.0",
    "summary": "A Python lib for solving & executing graphs of functions, with `pandas` in mind",
    "version": "10.5.0",
    "split_keywords": [
        "graph",
        "computation graph",
        "dag",
        "directed acyclic graph",
        "executor",
        "scheduler",
        "etl",
        "workflow",
        "pipeline"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "62e4e114627ea89216fa1f74c9daec32861d948ada3beae87c7068df6daca3f3",
                "md5": "4653d0f229806b2aad52b75ca8e65b73",
                "sha256": "d20a87139c9473cef50ac77f9ffea66e93a74d54e53345e9cbd43957f3cb76db"
            },
            "downloads": -1,
            "filename": "graphtik-10.5.0-py2.py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "4653d0f229806b2aad52b75ca8e65b73",
            "packagetype": "bdist_wheel",
            "python_version": "py2.py3",
            "requires_python": ">=3.6",
            "size": 122309,
            "upload_time": "2023-04-25T21:27:36",
            "upload_time_iso_8601": "2023-04-25T21:27:36.115893Z",
            "url": "https://files.pythonhosted.org/packages/62/e4/e114627ea89216fa1f74c9daec32861d948ada3beae87c7068df6daca3f3/graphtik-10.5.0-py2.py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "7f00a579f9350ef68660b84e4b49123cd4f1c7b54ab0ebd55b9d2a0f6cfd77a7",
                "md5": "f8adfe860b486af096818b247d6fbf05",
                "sha256": "890075835194f66a4f036085c338890356ec112b07adb4829b7613bc0a5bda3b"
            },
            "downloads": -1,
            "filename": "graphtik-10.5.0.tar.gz",
            "has_sig": false,
            "md5_digest": "f8adfe860b486af096818b247d6fbf05",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.6",
            "size": 188301,
            "upload_time": "2023-04-25T21:27:37",
            "upload_time_iso_8601": "2023-04-25T21:27:37.595084Z",
            "url": "https://files.pythonhosted.org/packages/7f/00/a579f9350ef68660b84e4b49123cd4f1c7b54ab0ebd55b9d2a0f6cfd77a7/graphtik-10.5.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2023-04-25 21:27:37",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "github_user": "pygraphkit",
    "github_project": "graphtik",
    "travis_ci": true,
    "coveralls": false,
    "github_actions": true,
    "lcname": "graphtik"
}
        
Elapsed time: 0.05927s