{ "info": { "author": "Sergey Krilov", "author_email": "", "bugtrack_url": null, "classifiers": [ "License :: OSI Approved :: MIT License", "Programming Language :: Python", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy" ], "description": "\n# rtreelib\n\nPluggable R-tree implementation in pure Python.\n\n## Overview\n\nSince the original R-tree data structure has been initially proposed in 1984, there have been\nmany variations introduced over the years optimized for various use cases [1]. However, when\nworking in Python (one of the most popular languages for spatial data processing), there is\nno easy way to quickly compare how these various implementations behave on real data.\n\nThe aim of this library is to provide a \"pluggable\" R-tree implementation that allows swapping\nout the various strategies for insertion, node deletion, and other behaviors so that their\nimpact can be easily compared (without having to install separate libraries and having to\nmake code changes to accommodate for API differences). Several of the more common R-tree\nvariations will soon be provided as ready-built implementations (see the **Status** section\nbelow).\n\nIn addition, this library also provides utilities for inspecting the R-tree structure. It\nallows creating diagrams (using matplotlib and graphviz) that show the R-tree nodes and\nentries (including all the intermediate, non-leaf nodes), along with plots of their\ncorresponding bounding boxes. It also allows exporting the R-tree to PostGIS so it could\nbe examined using a GIS viewer like QGIS.\n\n## Status\n\nThis library is currently in early development. At this time, only the original Guttman\nstrategy is implemented (insertion only, no deletion), though the framework for swapping\nout the strategies is in place. Note that as additional strategies are implemented, it is\nanticipated that this framework will need to be extended, resulting in breaking changes.\n\nContributions for implementing additional strategies are welcome. See the section on\n**Extending** below.\n\nThere is existing functionality for creating diagrams (explained below), and the ability to\nexport the R-Tree structure to PostGIS is also in the works.\n\n## Setup\n\nThis package is available on PyPI and can be installed using pip:\n\n```\npip install rtreelib\n```\n\nThis package requires Python 3.6+.\n\nThere are additional optional dependencies you can install if you want to be able to\ncreate diagrams or export the R-tree data to PostGIS. See the corresponding sections\nbelow for additional setup information.\n\n## Usage\n\nTo instantiate the default implementation and insert an entry:\n\n```python\nfrom rtreelib import RTree, Rect\n\nt = RTree()\nt.insert('foo', Rect(0, 0, 5, 5))\n```\n\nThe first parameter to the `insert` method represents the data, and can be of any data type\n(though you will want to stick to strings, numbers, and other basic data types that can be\neasily and succintly represented as a string if you want to create diagrams). The second\nparameter represents the minimum bounding rectangle (MBR) of the associated data element.\n\nThe default implementation uses Guttman's original strategies for insertion, node splitting,\nand deletion, as outlined in his paper from 1984 [2]. However, the behavior can be customized\nby either instantiating or inheriting from `RTreeBase` and providing your own implementations\nfor these behaviors. (Eventually this library will also ship with several ready-made\nimplementations.) See the following section for more information.\n\n## Extending\n\nAs noted above, the purpose of this library is to provide a pluggable R-tree implementation\nwhere the various behaviors can be swapped out and customized to allow comparison. To that\nend, this library provides a framework for achieving this.\n\nAs an example, the [`RTreeGuttman`](https://github.com/sergkr/rtreelib/blob/master/rtreelib/strategies/guttman.py)\nclass (aliased as `RTree`) simply inherits from `RTreeBase`, providing an implementation\nfor the `choose_leaf`, `adjust_tree`, and `split_node` behaviors as follows:\n\n```python\nclass RTreeGuttman(RTreeBase[T]):\n \"\"\"R-Tree implementation that uses Guttman's strategies for insertion, splitting, and deletion.\"\"\"\n\n def __init__(self, max_entries: int = DEFAULT_MAX_ENTRIES, min_entries: int = None):\n \"\"\"\n Initializes the R-Tree using Guttman's strategies for insertion, splitting, and deletion.\n :param max_entries: Maximum number of entries per node.\n :param min_entries: Minimum number of entries per node. Defaults to ceil(max_entries/2).\n \"\"\"\n super().__init__(choose_leaf=least_enlargement, adjust_tree=adjust_tree_strategy, split_node=quadratic_split,\n max_entries=max_entries, min_entries=min_entries)\n```\n\nEach behavior should be a function that implements a specific signature and performs a given\ntask. Here are the behaviors that are currently required to be specified:\n\n* **`choose_leaf`**: Strategy used for choosing a leaf node when inserting a new entry.\n * Signature: `(tree: RTreeBase[T], entry: RTreeEntry[T]) \u2192 RTreeNode[T]`\n * Arguments:\n * `tree: RTreeBase[T]`: R-tree instance.\n * `entry: RTreeEntry[T]`: Entry being inserted.\n * Returns: `RTreeNode[T]`\n * This function should return the leaf node where the new entry should be inserted. This\n node may or may not have the capacity for the new entry. If the insertion of the new node\n results in the node overflowing, it will be split according to the strategy defined by\n `split_node`.\n* **`adjust_tree`**: Strategy used for balancing the tree, including propagating node splits,\nupdating bounding boxes on all nodes and entries as necessary, and growing the tree by\ncreating a new root if necessary. This strategy is executed after inserting or deleting an\nentry.\n * Signature: `(tree: RTreeBase[T], node: RTreeNode[T], split_node: RTreeNode[T]) \u2192 None`\n * Arguments:\n * `tree: RTreeBase[T]`: R-tree instance.\n * `node: RTreeNode[T]`: Node where a newly-inserted entry has just been added.\n * `split_node: RTreeNode[T]`: If the insertion of a new entry has caused the node to\n split, this is the newly-created split node. Otherwise, this will be `None`.\n * Returns: `None`\n* **`split_node`**: Strategy used for splitting a node that contains more than the maximum\nnumber of entries. This function should break up the node's entries into two groups,\nassigning one of the groups to be the entries of the original node, and the other to a\nnewly-created neighbor node (which this function should return).\n * Signature: `(tree: RTreeBase[T], node: RTreeNode[T]) \u2192 RTreeNode[T]`\n * Arguments:\n * `tree: RTreeBase[T]`: R-tree instance.\n * `node: RTreeNode[T]`: Overflowing node that needs to be split.\n * Returns: `RTreeNode[T]`\n * This function should return the newly-created split node whose entries are a subset\n of the original node's entries.\n\n## Creating R-tree Diagrams\n\nThis library provides a set of utility functions that can be used to create diagrams of the\nentire R-tree structure, including the root and all intermediate and leaf level nodes and\nentries.\n\nThese features are optional, and the required dependencies are *not* automatically installed\nwhen installing this library. Therefore, you must install them manually. This includes the\nfollowing Python dependencies which can be installed using pip:\n\n```\npip install matplotlib pydot tqdm\n```\n\nThis also includes the following system-level dependencies:\n\n* TkInter\n* Graphviz\n\nOn Ubuntu, these can be installed using:\n\n```\nsudo apt install python3-tk graphviz\n```\n\nOnce the above dependencies are installed, you can create an R-tree diagram as follows:\n\n```python\nfrom rtreelib import RTree, Rect\nfrom rtreelib.util.diagram import create_rtree_diagram\n\n\n# Create an RTree instance with some sample data\nt = RTree(max_entries=4)\nt.insert('a', Rect(0, 0, 3, 3))\nt.insert('b', Rect(2, 2, 4, 4))\nt.insert('c', Rect(1, 1, 2, 4))\nt.insert('d', Rect(8, 8, 10, 10))\nt.insert('e', Rect(7, 7, 9, 9))\n\n# Create a diagram of the R-tree structure\ncreate_rtree_diagram(t)\n```\n\nThis creates a diagram like the following:\n\n![R-tree Diagram](https://github.com/sergkr/rtreelib/blob/master/doc/rtree_diagram.png \"R-tree Diagram\")\n\nThe diagram is created in a temp directory as a PostScript file, and the default viewer\nis automatically launched for convenience. Each box in the main diagram represents a node\n(except at the leaf level, where it represents the leaf entry), and contains a plot that\ndepicts all of the data spatially. The bounding boxes of each node are represented using\ntan rectangles with a dashed outline. The bounding box corresponding to the current node\nis highlighted in pink.\n\nThe bounding boxes for the original data entries themselves are depicted in blue, and are\nlabeled using the value that was passed in to `insert`. At the leaf level, the corresponding\ndata element is highlighted in pink.\n\nThe entries contained in each node are depicted along the bottom of the node's box, and\npoint to either a child node (for non-leaf nodes), or to the data entries (for leaf nodes).\n\nAs can be seen in the above screenshot, the diagram depicts the entire tree structure, which\ncan be quite large depending on the number of nodes and entries. It may also take a while to\ngenerate, since it launches matplotlib to plot the data spatially for each node and entry, and\nthen graphviz to generate the overall diagram. Given the size and execution time required to\ngenerate these diagrams, it's only practical for R-trees containing a relatively small\namount of data (e.g., no more than about a dozen total entries). To analyze the resulting\nR-tree structure when working with a large amount of data, it is recommended to export the\ndata to PostGIS and use a viewer like QGIS (as explained in the following section).\n\n## Exporting to PostGIS\n\nIn addition to creating diagrams, this library also allows exporting R-trees to a\nPostGIS database.\n\nTo do so, you will first need to install the [psycopg2](http://initd.org/psycopg/) driver.\nThis is an optional dependency, so it is not automatically installed when you install\nthis package. Refer to the\n[installation instructions for psycopg2](http://initd.org/psycopg/docs/install.html) to\nensure that you have all the necessary system-wide prerequisites installed (C compiler,\nPython header files, etc.). Then, install `psycopg2` using the following command (passing\nthe `--no-binary` flag to ensure that it is built from source, and also to avoid a console\nwarning when using `psycopg2`):\n\n```\npip install psycopg2 --no-binary psycopg2\n```\n\nOnce `psycopg2` is installed, you should be able to import the functions you need from the\n`rtreelib.pg` module:\n\n```python\nfrom rtreelib.pg import init_db_pool, create_rtree_tables, export_to_postgis\n```\n\nThe subsections below guide you throw how to use this library to export R-trees to the\ndatabase. You will first need to decide on your preferred method for connecting to the\ndatabase, as well as create the necessary tables to store the R-tree data. Once these\nprerequisites are met, exporting the R-tree can be done using a simple function call.\nFinally, this guide shows how you can visualize the exported data using QGIS, a popular\nand freely-available GIS viewer.\n\n### Initializing a Connection Pool\n\nWhen working with the `rtreelib.pg` module, there are three ways of passing database\nconnection information:\n\n1. Initialize a connection pool by calling `init_db_pool`. This allows using the other\nfunctions in this module without having to pass around connection info.\n2. Manually open the connection yourself, and pass in the connection object to the\nfunction.\n3. Pass in keyword arguments that can be used to establish the database connection.\n\nThe first method is generally the easiest - you just have to call it once, and not\nhave to worry about passing in connection information to the other functions. This\nsection explains this method, and the following sections assume that you are using\nit. However, the other methods are also explained later on in this guide.\n\n`init_db_pool` accepts the same parameters as the\n[psycopg2.connect](http://initd.org/psycopg/docs/module.html#psycopg2.connect) function.\nFor example, you can pass in a connection string:\n\n```python\ninit_db_pool(\"dbname=mydb user=postgres password=temp123!\")\n```\n\nAlternatively, using the URL syntax:\n\n```python\ninit_db_pool(\"postgresql://localhost/mydb?user=postgres&password=temp123!\")\n```\n\nOr keyword arguments:\n\n```python\ninit_db_pool(user=\"postgres\", password=\"temp123!\", host=\"localhost\", database=\"mydb\")\n```\n\nNext, before you can export an R-tree, you first need to create a few database\ntables to store the data. The following section explains how to achieve this.\n\n### Creating Tables to Store R-tree Data\n\nWhen exporting an R-tree using this library, the data is populated inside three\ntables:\n\n* `rtree`: This tables simply contains the ID of each R-tree that was exported.\nThis library allows you to export multiple R-trees at once, and they are\ndifferentiated by ID (you can also clear the contents of all tables using\n`clear_rtree_tables`).\n* `rtree_node`: Contains information about each node in the R-tree, including\nits bounding box (as a PostGIS geometry column), a pointer to the parent entry\ncontaining this node, and the level of this node (starting at 0 for the root).\nThe node also contains a reference to the `rtree` that it is a part of.\n* `rtree_entry`: Contains information about each entry in the R-tree, including\nits bounding box (as a PostGIS geometry column) and a pointer to the node\ncontaining this entry. For leaf entries, this also contains the value of the\ndata element.\n\nThese tables can be created using the `create_rtree_tables` function. This is\nsomething you only need to do once.\n\nThis function can be called without any arguments if you have established the\nconnection pool, and your data does not use a spatial reference system (`srid`).\nHowever, generally when working with spatial data, you will have a particular\nSRID that your data is in, in which case you should pass it in to ensure that\nall geometry columns use the correct SRID:\n\n```python\ncreate_rtree_tables(srid=4326)\n```\n\nYou can also choose to create the tables in a different schema (other than `public`):\n\n```python\ncreate_rtree_tables(srid=4326, schema=\"temp\")\n```\n\nHowever, in this case, be sure to pass in the same schema to the other functions in\nthis module.\n\nYou can also pass in a `datatype`, which indicates the type of data stored in the leaf\nentries (i.e., the type of the data you pass in to the `insert` method of `RTree`).\nThis can either be a string containing a PostgreSQL column type:\n\n```python\ncreate_rtree_tables(srid=4326, datatype='VARCHAR(255)')\n```\n\nOr a Python type, in which case an appropriate PostgreSQL data type will be inferred:\n\n```python\ncreate_rtree_tables(srid=4326, datatype=int)\n```\n\nIf you don't pass anything in, or an appropriate PostgreSQL data type cannot be\ndetermined from the Python type, the column type will default to `TEXT`, which allows\nstoring arbitrary-length strings.\n\nWhen passing a string containing a PostgreSQL column type, you also have the option\nof adding a modifier such as `NOT NULL`, or even a foreign key constraint:\n\n```python\ncreate_rtree_tables(srid=4326, datatype='INT REFERENCES my_other_table (my_id_column)')\n```\n\n### Exporting the R-tree\n\nTo export the R-tree once the tables have been created, simply call the\n`export_to_postgis` function, passing in the R-tree instance (and optionally an SRID):\n\n```python\nrtree_id = export_to_postgis(tree, srid=4326)\n```\n\nThis function populates the `rtree`, `rtree_node`, and `rtree_entry` tables with\nthe data from the R-tree, and returns the ID of the newly-inserted R-tree in the\n`rtree` table.\n\nNote that if you used a schema other than `public` when calling\n`create_rtree_tables`, you will need to pass in the same schema when calling\n`export_to_postgis`:\n\n```python\nrtree_id = export_to_postgis(tree, srid=4326, schema='temp')\n```\n\n### Viewing the Data Using QGIS\n\n[QGIS](https://qgis.org/en/site/) is a popular and freely-available GIS viewer which\ncan be used to visualize the exported R-tree data. To do so, launch QGIS and create\na new project. Then, follow these steps to add the exported R-tree data as a layer:\n\n* Go to Layer \u2192 Add Layer \u2192 Add PostGIS Layers\n* Connect to the database where you exported the data\n* Select either the `rtree_node` or `rtree_entry` table, depending on which part of\nthe structure you wish to visualize. For this example, we will be looking at the\nnodes, so select `rtree_node`.\n* Optionally, you can set a layer filter to only include the nodes belonging to a\nparticular tree (if you exported multiple R-trees). To do so, click the\n**Set Filter** button, and enter a filter expression (such as `rtree_id=1`).\n* Click **Add**\n\nAt this point, the layer will be displaying all nodes at every level of the tree,\nwhich may be a bit hard to decipher if you have a lot of data. After adjusting the\nlayer style to make it partially transparent, here is an example of what an R-tree\nwith a couple hundred leaf entries might look like (38 nodes across 3 levels):\n\n![QGIS - All Nodes](https://github.com/sergkr/rtreelib/blob/master/doc/qgis_all_nodes.png)\n\nTo make it easier to understand the structure, it might help to be able to view each\nlevel of the tree independently. To do this, double click the layer in the Layers\npanel, switch to the Style tab, and change the style type at the top from\n\"Single symbol\" (the default) to \"Categorized\". Then in the Column dropdown, select\nthe \"level\" column. You can optionally assign a color ramp or use random colors so\nthat each level gets a different color. Then click **Classify** to automatically\ncreate a separate style for each layer:\n\n![QGIS - Layer Style](https://github.com/sergkr/rtreelib/blob/master/doc/qgis_layer_style.png)\n\nNow in the layers panel, each level will be shown as a separate entry and can be\ntoggled on and off, making it possible to explore the R-tree structure one level\nat a time:\n\n![QGIS - Layers Panel](https://github.com/sergkr/rtreelib/blob/master/doc/qgis_layers_panel.png)\n\nNow, viewing just the nodes at level 1 (the level immediately below the root node),\nit makes it easier to see what the bounding rectangles look like:\n\n![QGIS - Nodes at Level 1](https://github.com/sergkr/rtreelib/blob/master/doc/qgis_level_one_nodes.png)\n\nClearly, using the default Guttman implementation on this particular dataset is\nnon-optimal (depending on the use case), as it resulted in a lot of overlap. This\nimplies, for instance, that a typical query to find the leaf entry for a given\nlocation would require visiting many subtrees.\n\nPerhaps a different R-tree variant would work better on this dataset? This is the\ntype of question that this library is meant to answer.\n\n### Cleaning Up\n\nAs mentioned above, when you call `export_to_postgis`, the existing data in the\ntables is *not* cleared. This allows you to export multiple R-trees at once and\ncompare them side-by-side.\n\nHowever, for simplicity, you may wish to clear out the existing data prior to\nexporting new data. To do so, call `clear_rtree_tables`:\n\n```python\nclear_rtree_tables()\n```\n\nThis will perform a SQL `TRUNCATE` on all R-tree tables.\n\nNote that if you created the tables in a different schema (other than `public`),\nyou will need to pass in that same schema to this function:\n\n```python\nclear_rtree_tables(schema='temp')\n```\n\nYou may also wish to completely drop all the tables that were created by\n`create_rtree_tables`. To do so, call `drop_rtree_tables`:\n\n```python\ndrop_rtree_tables()\n```\n\nAgain, you may need to pass in a schema if it is something other than `public`:\n\n```python\ndrop_rtree_tables(schema='temp')\n```\n\n### Alternate Database Connection Handling Methods\n\nAs mentioned earlier in this guide, instead of initializing a connection pool,\nyou have other options for how to handle establishing database connections when\nusing this library. You can choose to handle opening and closing the connection\nyourself and pass in the connection object; alternatively, you can pass in the\nconnection information as keyword arguments.\n\nTo establish the database connection yourself, the typical usage scenario might\nlook like this:\n\n```python\nimport psycopg2\nfrom rtreelib import RTree, Rect\nfrom rtreelib.pg import init_db_pool, create_rtree_tables, clear_rtree_tables, export_to_postgis, drop_rtree_tables\n\n\n# Create an RTree instance with some sample data\nt = RTree(max_entries=4)\nt.insert('a', Rect(0, 0, 3, 3))\nt.insert('b', Rect(2, 2, 4, 4))\nt.insert('c', Rect(1, 1, 2, 4))\nt.insert('d', Rect(8, 8, 10, 10))\nt.insert('e', Rect(7, 7, 9, 9))\n\n# Export R-tree to PostGIS (using explicit connection)\nconn = None\ntry:\n conn = psycopg2.connect(user=\"postgres\", password=\"temp123!\", host=\"localhost\", database=\"mydb\")\n create_rtree_tables(conn, schema='temp')\n rtree_id = export_to_postgis(t, conn=conn, schema='temp')\n print(rtree_id)\nfinally:\n if conn:\n conn.close()\n```\n\nYou can also pass in the database connection information separately to each method as\nkeyword arguments. These keyword arguments should be the same ones as required by the\n[psycopg2.connect](http://initd.org/psycopg/docs/module.html#psycopg2.connect) function:\n\n```python\nrtree_id = export_to_postgis(tree, schema='temp', user=\"postgres\", password=\"temp123!\", host=\"localhost\", database=\"mydb\")\n```\n\n## References\n\n[1]: Nanopoulos, Alexandros & Papadopoulos, Apostolos (2003):\n[\"R-Trees Have Grown Everywhere\"](https://pdfs.semanticscholar.org/4e07/e800fe71505fbad686b08334abb49d41fcda.pdf)\n\n[2]: Guttman, A. (1984):\n[\"R-trees: a Dynamic Index Structure for Spatial Searching\"](http://www-db.deis.unibo.it/courses/SI-LS/papers/Gut84.pdf)\n(PDF), *Proceedings of the 1984 ACM SIGMOD international conference on Management of data \u2013 SIGMOD\n'84.* p. 47.\n\n\n", "description_content_type": "text/markdown", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "http://github.com/sergkr/rtreelib", "keywords": "", "license": "MIT", "maintainer": "", "maintainer_email": "", "name": "rtreelib", "package_url": "https://pypi.org/project/rtreelib/", "platform": "", "project_url": "https://pypi.org/project/rtreelib/", "project_urls": { "Homepage": "http://github.com/sergkr/rtreelib" }, "release_url": "https://pypi.org/project/rtreelib/0.0.2/", "requires_dist": [ "matplotlib (>=3.0.0) ; extra == 'diagram'", "pydot (>=1.3.0) ; extra == 'diagram'", "tqdm (>=v4.31.0) ; extra == 'diagram'" ], "requires_python": ">=3.6.0", "summary": "Pluggable R-tree implementation in pure Python.", "version": "0.0.2" }, "last_serial": 5142674, "releases": { "0.0.1": [ { "comment_text": "", "digests": { "md5": "85fd3fa8f756670e7fc44934b1867d14", "sha256": "2c4645e449bd006143719e77dd8b35138d2fc9b9d222e60acde00bc591f97821" }, "downloads": -1, "filename": "rtreelib-0.0.1-py3-none-any.whl", "has_sig": false, "md5_digest": "85fd3fa8f756670e7fc44934b1867d14", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.6.0", "size": 15278, "upload_time": "2019-04-14T00:51:32", "url": "https://files.pythonhosted.org/packages/42/5c/01be84e62b4e3e332a0eec9bc67f2b864c8203a6f39325a7562874e52399/rtreelib-0.0.1-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "ebd3bf3922455ecf889b7c14ee96b971", "sha256": "6faf751c8dd9fae381bb0a05e525a28a05f38625fb784ee7d430c61a89092ef6" }, "downloads": -1, "filename": "rtreelib-0.0.1.tar.gz", "has_sig": false, "md5_digest": "ebd3bf3922455ecf889b7c14ee96b971", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6.0", "size": 17968, "upload_time": "2019-04-14T00:51:34", "url": "https://files.pythonhosted.org/packages/d4/0e/8cce4c74b0c15a5872c3ebe14324971bff400c3ae9095e87f0505e51956f/rtreelib-0.0.1.tar.gz" } ], "0.0.2": [ { "comment_text": "", "digests": { "md5": "10db880fa7b998b9be654fa757b9afdc", "sha256": "18ef3ac7ef01eb4d6e8263483a536192f8dbeed5344ce8758c6d3d1e09697c14" }, "downloads": -1, "filename": "rtreelib-0.0.2-py3-none-any.whl", "has_sig": false, "md5_digest": "10db880fa7b998b9be654fa757b9afdc", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.6.0", "size": 27378, "upload_time": "2019-04-15T03:30:13", "url": "https://files.pythonhosted.org/packages/5f/01/bed0bfdde7a10172c72965ba80772076d4794cdece43cbe7ea2dad60698d/rtreelib-0.0.2-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "95138b4caab429a8dc40abb1be9a6f9f", "sha256": "07aab5614fa0e7adb3e90a0f98c36633ace733f5d63081ad2fb905bcd247ee1b" }, "downloads": -1, "filename": "rtreelib-0.0.2.tar.gz", "has_sig": false, "md5_digest": "95138b4caab429a8dc40abb1be9a6f9f", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6.0", "size": 29715, "upload_time": "2019-04-15T03:30:15", "url": "https://files.pythonhosted.org/packages/2e/fe/16a34be140f53b1d5efd69456ec7c83af86d55e5ce5cfbdf6c39c49ed45e/rtreelib-0.0.2.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "10db880fa7b998b9be654fa757b9afdc", "sha256": "18ef3ac7ef01eb4d6e8263483a536192f8dbeed5344ce8758c6d3d1e09697c14" }, "downloads": -1, "filename": "rtreelib-0.0.2-py3-none-any.whl", "has_sig": false, "md5_digest": "10db880fa7b998b9be654fa757b9afdc", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.6.0", "size": 27378, "upload_time": "2019-04-15T03:30:13", "url": "https://files.pythonhosted.org/packages/5f/01/bed0bfdde7a10172c72965ba80772076d4794cdece43cbe7ea2dad60698d/rtreelib-0.0.2-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "95138b4caab429a8dc40abb1be9a6f9f", "sha256": "07aab5614fa0e7adb3e90a0f98c36633ace733f5d63081ad2fb905bcd247ee1b" }, "downloads": -1, "filename": "rtreelib-0.0.2.tar.gz", "has_sig": false, "md5_digest": "95138b4caab429a8dc40abb1be9a6f9f", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6.0", "size": 29715, "upload_time": "2019-04-15T03:30:15", "url": "https://files.pythonhosted.org/packages/2e/fe/16a34be140f53b1d5efd69456ec7c83af86d55e5ce5cfbdf6c39c49ed45e/rtreelib-0.0.2.tar.gz" } ] }