r5py 1.0.3.dev0__py3-none-any.whl → 1.0.5__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of r5py might be problematic. Click here for more details.

r5py/__init__.py CHANGED
@@ -2,12 +2,13 @@
2
2
 
3
3
  """Python wrapper for the R5 routing analysis engine."""
4
4
 
5
- __version__ = "1.0.3.dev0"
5
+ __version__ = "1.0.5"
6
6
 
7
7
 
8
8
  from .r5 import (
9
9
  DetailedItineraries,
10
10
  DetailedItinerariesComputer,
11
+ ElevationCostFunction,
11
12
  Isochrones,
12
13
  RegionalTask,
13
14
  TransportMode,
@@ -19,6 +20,7 @@ from .r5 import (
19
20
  __all__ = [
20
21
  "DetailedItineraries",
21
22
  "DetailedItinerariesComputer",
23
+ "ElevationCostFunction",
22
24
  "Isochrones",
23
25
  "RegionalTask",
24
26
  "TransportMode",
r5py/r5/__init__.py CHANGED
@@ -6,6 +6,7 @@ from .access_leg import AccessLeg
6
6
  from .detailed_itineraries import DetailedItineraries, DetailedItinerariesComputer
7
7
  from .direct_leg import DirectLeg
8
8
  from .egress_leg import EgressLeg
9
+ from .elevation_cost_function import ElevationCostFunction
9
10
  from .isochrones import Isochrones
10
11
  from .regional_task import RegionalTask
11
12
  from .scenario import Scenario
@@ -24,6 +25,7 @@ __all__ = [
24
25
  "DetailedItinerariesComputer",
25
26
  "DirectLeg",
26
27
  "EgressLeg",
28
+ "ElevationCostFunction",
27
29
  "Isochrones",
28
30
  "RegionalTask",
29
31
  "Scenario",
@@ -0,0 +1,50 @@
1
+ #!/usr/bin/env python3
2
+
3
+
4
+ """The elevation cost functions supported by R5 (Tobler, Minetti)."""
5
+
6
+
7
+ import enum
8
+
9
+ import jpype
10
+
11
+ from ..util import start_jvm
12
+
13
+ import com.conveyal.r5
14
+
15
+
16
+ __all__ = ["ElevationCostFunction"]
17
+
18
+
19
+ start_jvm()
20
+
21
+
22
+ class ElevationCostFunction(enum.Enum):
23
+ """
24
+ Elevation cost functions.
25
+
26
+ TOBLER: Waldo Tobler’s hiking function, cf. https://en.wikipedia.org/wiki/Tobler%27s_hiking_function
27
+ MINETTI: Minetti et al.’s perceived effort/energy consumption, cf.
28
+ https://doi.org/10.1152/japplphysiol.01177.2001
29
+ """
30
+
31
+ @classmethod
32
+ def _missing_(cls, value):
33
+ value = str(value).upper()
34
+ for member in cls:
35
+ if value == member.value:
36
+ return member
37
+ return None
38
+
39
+ TOBLER = "TOBLER"
40
+ MINETTI = "MINETTI"
41
+
42
+
43
+ @jpype._jcustomizer.JConversion(
44
+ "com.conveyal.r5.analyst.scenario.RasterCost.CostFunction",
45
+ exact=ElevationCostFunction,
46
+ )
47
+ def _cast_LegMode(java_class, object_):
48
+ return com.conveyal.r5.analyst.scenario.RasterCost.CostFunction.valueOf(
49
+ object_.name
50
+ )
@@ -0,0 +1,84 @@
1
+ #!/usr/bin/env python3
2
+
3
+
4
+ """Load a digital elevation model and apply it to an r5py.TransportNetwork."""
5
+
6
+
7
+ import rasterio
8
+
9
+ from .elevation_cost_function import ElevationCostFunction
10
+ from .file_storage import FileStorage
11
+ from ..util import WorkingCopy
12
+
13
+ import com.conveyal.analysis
14
+ import com.conveyal.r5
15
+
16
+
17
+ __all__ = ["ElevationModel"]
18
+
19
+
20
+ class ElevationModel:
21
+ """Load a digital elevation model and apply it to an r5py.TransportNetwork."""
22
+
23
+ def __init__(
24
+ self,
25
+ elevation_model,
26
+ elevation_cost_function=ElevationCostFunction.TOBLER,
27
+ ):
28
+ """
29
+ Load an elevation model.
30
+
31
+ Arguments
32
+ ---------
33
+ elevation_model : str | pathlib.Path
34
+ file path to a digital elevation model in TIF format,
35
+ single-band, the value of which is the elevation in metres
36
+ elevation_cost_function : r5py.ElevationCostFunction
37
+ which algorithm to use to compute the added effort and travel time
38
+ of slopes
39
+ """
40
+ elevation_model = WorkingCopy(elevation_model)
41
+ elevation_model = self._convert_tiff_to_format_readable_by_r5(elevation_model)
42
+
43
+ # instantiate an com.conveyal.file.FileStorage singleton
44
+ com.conveyal.analysis.components.WorkerComponents.fileStorage = FileStorage()
45
+
46
+ self._elevation_model = com.conveyal.r5.analyst.scenario.RasterCost()
47
+ self._elevation_model.dataSourceId = f"{elevation_model.with_suffix('')}"
48
+ self._elevation_model.costFunction = elevation_cost_function
49
+
50
+ def apply_to(self, transport_network):
51
+ """
52
+ Add the costs associated with elevation traversal to a transport network.
53
+
54
+ Arguments
55
+ ---------
56
+ transport_network : r5py.TransportNetwork
57
+ The transport network to which to add slope costs
58
+ """
59
+ self._elevation_model.resolve(transport_network)
60
+ self._elevation_model.apply(transport_network)
61
+
62
+ @staticmethod
63
+ def _convert_tiff_to_format_readable_by_r5(tiff):
64
+ # javax.imagio does not allow all compression/predictor
65
+ # combinations of TIFFs
66
+ # to work around it, convert the input to a format known to work.
67
+
68
+ input_tiff = tiff.with_stem(f".{tiff.stem}")
69
+ output_tiff = tiff.with_suffix(".tif")
70
+ tiff.rename(input_tiff)
71
+
72
+ with rasterio.open(input_tiff) as source:
73
+ metadata = source.profile
74
+ metadata.update(
75
+ {
76
+ "compress": "LZW",
77
+ "predictor": "2",
78
+ }
79
+ )
80
+ with rasterio.open(output_tiff, "w", **metadata) as destination:
81
+ destination.write(source.read())
82
+ input_tiff.unlink()
83
+
84
+ return output_tiff
@@ -0,0 +1,84 @@
1
+ #!/usr/bin/env python3
2
+
3
+
4
+ """A thin layer around com.conveyal.r5.file.FileStorage."""
5
+
6
+
7
+ import jpype
8
+
9
+ from ..util import start_jvm
10
+
11
+ import com.conveyal.file
12
+ import java.io.File
13
+
14
+
15
+ __all__ = ["FileStorage"]
16
+
17
+
18
+ start_jvm()
19
+
20
+
21
+ @jpype.JImplements(com.conveyal.file.FileStorage)
22
+ class FileStorage:
23
+ """A thin layer around com.conveyal.r5.file.FileStorage."""
24
+
25
+ @jpype.JOverride
26
+ def moveIntoStorage(self, *args):
27
+ """Not implemented."""
28
+ pass
29
+
30
+ @jpype.JOverride
31
+ def getFile(self, file_storage_key):
32
+ """
33
+ Return a java.io.File for the file identified by file_storage_key.
34
+
35
+ Arguments
36
+ ---------
37
+ file_storage_key : com.conveyal.r5.file.FileStorageKey
38
+ An R5 object referencing a certain file
39
+
40
+ Returns
41
+ -------
42
+ java.io.File
43
+ The file identified by file_storage_key
44
+ """
45
+ return java.io.File(file_storage_key.path)
46
+
47
+ @jpype.JOverride
48
+ def getURL(self, file_storage_key):
49
+ """
50
+ Return an URL for the file identified by file_storage_key.
51
+
52
+ Arguments
53
+ ---------
54
+ file_storage_key : com.conveyal.r5.file.FileStorageKey
55
+ An R5 object referencing a certain file
56
+
57
+ Returns
58
+ -------
59
+ str
60
+ An imaginary URL pointing to the file identified by file_storage_key
61
+ """
62
+ return f"file://{file_storage_key.path}"
63
+
64
+ @jpype.JOverride
65
+ def delete(self, *args):
66
+ """Not implemented."""
67
+ pass
68
+
69
+ @jpype.JOverride
70
+ def exists(self, file_storage_key):
71
+ """
72
+ Check whether the file identified by file_storage_key exists.
73
+
74
+ Arguments
75
+ ---------
76
+ file_storage_key : com.conveyal.r5.file.FileStorageKey
77
+ An R5 object referencing a certain file
78
+
79
+ Returns
80
+ -------
81
+ bool
82
+ Whether or not the file identified by file_storage_key exists
83
+ """
84
+ return self.getFile(file_storage_key).exists()
@@ -12,12 +12,15 @@ import warnings
12
12
  import jpype
13
13
  import jpype.types
14
14
 
15
+ from .elevation_cost_function import ElevationCostFunction
16
+ from .elevation_model import ElevationModel
15
17
  from .street_layer import StreetLayer
16
18
  from .transit_layer import TransitLayer
17
19
  from .transport_mode import TransportMode
18
20
  from ..util import Config, contains_gtfs_data, FileDigest, start_jvm, WorkingCopy
19
21
  from ..util.exceptions import GtfsFileError
20
22
 
23
+ import com.conveyal.analysis
21
24
  import com.conveyal.gtfs
22
25
  import com.conveyal.osmlib
23
26
  import com.conveyal.r5
@@ -36,7 +39,14 @@ start_jvm()
36
39
  class TransportNetwork:
37
40
  """Wrap a com.conveyal.r5.transit.TransportNetwork."""
38
41
 
39
- def __init__(self, osm_pbf, gtfs=[], allow_errors=False):
42
+ def __init__(
43
+ self,
44
+ osm_pbf,
45
+ gtfs=[],
46
+ elevation_model=None,
47
+ elevation_cost_function=ElevationCostFunction.TOBLER,
48
+ allow_errors=False,
49
+ ):
40
50
  """
41
51
  Load a transport network.
42
52
 
@@ -46,6 +56,12 @@ class TransportNetwork:
46
56
  file path of an OpenStreetMap extract in PBF format
47
57
  gtfs : str | pathlib.Path | list[str] | list[pathlib.Path]
48
58
  path(s) to public transport schedule information in GTFS format
59
+ elevation_model : str | pathlib.Path
60
+ file path to a digital elevation model in TIF format,
61
+ single-band, the value of which is the elevation in metres
62
+ elevation_cost_function : r5py.ElevationCostFunction
63
+ which algorithm to use to compute the added effort and travel time
64
+ of slopes
49
65
  allow_errors : bool
50
66
  try to proceed with loading the transport network even if input data
51
67
  contain errors
@@ -57,16 +73,18 @@ class TransportNetwork:
57
73
 
58
74
  # a hash representing all input files
59
75
  digest = hashlib.sha256(
60
- "".join([FileDigest(osm_pbf)] + [FileDigest(path) for path in gtfs]).encode(
61
- "utf-8"
62
- )
76
+ "".join(
77
+ [FileDigest(osm_pbf)]
78
+ + [FileDigest(path) for path in gtfs]
79
+ + [FileDigest(elevation_model) if elevation_model is not None else ""]
80
+ ).encode("utf-8")
63
81
  ).hexdigest()
64
82
 
65
83
  try:
66
84
  transport_network = self._load_pickled_transport_network(
67
85
  Config().CACHE_DIR / f"{digest}.transport_network"
68
86
  )
69
- except FileNotFoundError:
87
+ except (FileNotFoundError, java.io.IOError, java.lang.RuntimeException):
70
88
  transport_network = com.conveyal.r5.transit.TransportNetwork()
71
89
  transport_network.scenarioId = PACKAGE
72
90
 
@@ -122,6 +140,12 @@ class TransportNetwork:
122
140
 
123
141
  transport_network.transitLayer.buildDistanceTables(None)
124
142
 
143
+ if elevation_model is not None:
144
+ ElevationModel(
145
+ elevation_model,
146
+ elevation_cost_function,
147
+ ).apply_to(transport_network)
148
+
125
149
  osm_file.close() # not needed after here?
126
150
 
127
151
  self._save_pickled_transport_network(
r5py/util/classpath.py CHANGED
@@ -18,9 +18,9 @@ from .warnings import R5pyWarning
18
18
 
19
19
  # update these to use a newer R5 version if no R5 available locally
20
20
  R5_JAR_URL = (
21
- "https://github.com/r5py/r5/releases/download/v7.3-r5py/r5-v7.3-r5py-all.jar"
21
+ "https://github.com/r5py/r5/releases/download/v7.4-r5py/r5-v7.4-r5py-all.jar"
22
22
  )
23
- R5_JAR_SHA256 = "cb1ccad370757ba229cf17f1bedc9549ff5d77fdbb44b7a3058104fe1f243f53"
23
+ R5_JAR_SHA256 = "c51b566671165d113add84e10e60fb9273014ca4a2e2a52591446954f68e7340"
24
24
  # ---
25
25
 
26
26
 
r5py/util/config.py CHANGED
@@ -92,7 +92,13 @@ class Config:
92
92
  FileNotFoundError, # broken symlink
93
93
  PermissionError,
94
94
  ):
95
- cached_file.unlink()
95
+ try:
96
+ cached_file.unlink()
97
+ except (
98
+ IsADirectoryError, # only available on Linux kernels
99
+ PermissionError, # what’s raised instead on Win and MacOs
100
+ ):
101
+ pass
96
102
 
97
103
  return cache_dir
98
104
 
r5py/util/jvm.py CHANGED
@@ -48,6 +48,7 @@ def start_jvm():
48
48
 
49
49
  jpype.startJVM(
50
50
  f"-Xmx{MAX_JVM_MEMORY:d}",
51
+ "-XX:+RestoreMXCSROnJNICalls", # https://github.com/r5py/r5py/issues/485
51
52
  "-Xcheck:jni",
52
53
  "-Xrs", # https://stackoverflow.com/q/34951812
53
54
  "-Duser.language=en", # Set a default locale, …
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: r5py
3
- Version: 1.0.3.dev0
3
+ Version: 1.0.5
4
4
  Summary: Python wrapper for the R5 routing analysis engine
5
5
  Author: Christoph Fink, Willem Klumpenhouwer, Marcus Sairava, Rafael Pereira, Henrikki Tenkanen
6
6
  License: GPL-3.0-or-later or MIT
@@ -26,6 +26,7 @@ Requires-Dist: numpy
26
26
  Requires-Dist: pandas>=2.1.0
27
27
  Requires-Dist: psutil
28
28
  Requires-Dist: pyproj
29
+ Requires-Dist: rasterio
29
30
  Requires-Dist: requests
30
31
  Requires-Dist: scikit-learn
31
32
  Requires-Dist: shapely>=2.0
@@ -55,7 +56,7 @@ Requires-Dist: pyarrow; extra == "tests"
55
56
  Requires-Dist: pytest; extra == "tests"
56
57
  Requires-Dist: pytest-cov; extra == "tests"
57
58
  Requires-Dist: pytest-lazy-fixtures; extra == "tests"
58
- Requires-Dist: r5py.sampledata.helsinki>=0.1.1; extra == "tests"
59
+ Requires-Dist: r5py.sampledata.helsinki>=1.0.3; extra == "tests"
59
60
  Requires-Dist: r5py.sampledata.sao_paulo>=0.1.1; extra == "tests"
60
61
  Requires-Dist: typing-extensions; extra == "tests"
61
62
  Dynamic: license-file
@@ -1,11 +1,14 @@
1
- r5py/__init__.py,sha256=fmuPx-uivkG0M6kPpYFSiiAHJKYQ4iWAprWSkeq--xA,551
1
+ r5py/__init__.py,sha256=1tPgrbMj7sfKn-uPq_7YhG9CLEMqAcdreD5ytUNBxXw,602
2
2
  r5py/__main__.py,sha256=Wvn0ChD7E-dCSZ8b8k_HhHG0KMOk0qMNFkijGuSH3-0,81
3
- r5py/r5/__init__.py,sha256=BVEeEVc-uUHLPLYBq1LN4exiQIHDw4YyANxNrprb8jQ,1061
3
+ r5py/r5/__init__.py,sha256=ZvzhfO9jHbBsRon6cLjWg_gJWvC4L0rkJtmH5mIUlIg,1149
4
4
  r5py/r5/access_leg.py,sha256=W3GfPEpqmWD1c4xipd6UcVIaBC-yb6srGCZV30E2dPY,293
5
5
  r5py/r5/base_travel_time_matrix.py,sha256=Vl82Wkk2iANNy6L3r937yXNnQ9lmMOErGT_-fQnb1Ms,6978
6
6
  r5py/r5/detailed_itineraries.py,sha256=Oo8JnF5jM2FsYFR1ma9r4y3evOmU7itDYs5M4vbqrZo,11245
7
7
  r5py/r5/direct_leg.py,sha256=T7wX8puhOVIssCpflXthYs-G9OA8pasFbdz9p8k8teg,1054
8
8
  r5py/r5/egress_leg.py,sha256=9rsCIcwlZUzoZE6q4imNY3VWpjJepO1IJvheVrlPi90,297
9
+ r5py/r5/elevation_cost_function.py,sha256=NXkwPRKZiotVugXQeOYLIgouQmKNx3juSAUi8GHVBLY,1074
10
+ r5py/r5/elevation_model.py,sha256=tGXNzIlRt5fZvteCZ1XQYNby8RLxjzONzSp8k9q3GHs,2745
11
+ r5py/r5/file_storage.py,sha256=wujo-IQyhJYsN7uxTemxNCKzt-pnL5zZgfyn7dZYaLY,1986
9
12
  r5py/r5/isochrones.py,sha256=NNpV3Df4NeLdDksGERkb2Eos33ziMBGEeaWyCKPt5P8,12974
10
13
  r5py/r5/regional_task.py,sha256=jpOoskx7Y-j-c4E-56uvJXiiuPYK3w28_FJsoGQLSbE,22062
11
14
  r5py/r5/scenario.py,sha256=nUNAlN3cO7E_b4sMpNqdL0FD7WQaQ49iIvh-k8l4YRM,763
@@ -15,22 +18,22 @@ r5py/r5/transfer_leg.py,sha256=_IpzQJAyW4hDPO5V4k-ZjIPd3uyxhHPa4U6_b8UbKt4,311
15
18
  r5py/r5/transit_layer.py,sha256=vfbzCpTiIpCevSwCTz7EGeFWB4LDrfba1JAqXYo7WXo,2334
16
19
  r5py/r5/transit_leg.py,sha256=R0Qc9YLMEXYu51NIdo7Q0bdmpYIJf5irEDXWrW6pZWE,221
17
20
  r5py/r5/transport_mode.py,sha256=zHSqXb0R4oyjTp069CzO69IgoCKt0nmOAwsSy272rGo,3675
18
- r5py/r5/transport_network.py,sha256=eKq4c4L46k_rpPkO9MxPOWHAZ0ZyPzV27lVouNFHqSk,9055
21
+ r5py/r5/transport_network.py,sha256=BkyrI1ovK3QZMTJ3jt0rlf743z6ZhnkLuOpK3NtP89U,10017
19
22
  r5py/r5/travel_time_matrix.py,sha256=Z_ErylB8mMD_eO2BogV3K_OFdYFVCcmIPmcMe7GGRiU,8003
20
23
  r5py/r5/trip.py,sha256=AqhlhgYaGRL5jVzV08BhsqgWxe8f4wAb5HMP8HIGwc8,2944
21
24
  r5py/r5/trip_leg.py,sha256=9E4vZpBEJCXIVqAXWJvnPloC-upEASKhFnjiuen8i8A,6495
22
25
  r5py/r5/trip_planner.py,sha256=QM3kSx-EC1VWtmReMtwxzG0CdbtlRi3-PpLxOAoHGrA,23754
23
26
  r5py/util/__init__.py,sha256=3iqzebRt7RE1TMzzuGNzyXca0SBcBx1rHLs8eW3ijo4,940
24
27
  r5py/util/camel_to_snake_case.py,sha256=zj5F3PNBvsuS6vqN4USeeo8NI-3hnscGhwun0G95AK0,673
25
- r5py/util/classpath.py,sha256=b16xL94pDxTpc0vrf68R1nvZHnHqZXGcFJaN36eW3wc,2773
26
- r5py/util/config.py,sha256=5jz42iUaftgBfJ2HNnktZw5oXIPE2ytl3Nxt2RjjDoM,5267
28
+ r5py/util/classpath.py,sha256=jBLQ9S_PwGB0iEqURYXyFCvGOElKX2Wm3Zcid4Nkv3k,2773
29
+ r5py/util/config.py,sha256=tBu2FeC4MnlF6-GSvmV0RkhhFUcOwwiontW-Y15y2mw,5516
27
30
  r5py/util/contains_gtfs_data.py,sha256=ooX4hfVDKK0aqX1MI46jSFZ7dZ6riyXaORrgF6PUFrk,1211
28
31
  r5py/util/data_validation.py,sha256=H5Mcp2nS4vu5RKym20mPnGpl-8d0SDchzDRJBrrL6WE,1039
29
32
  r5py/util/environment.py,sha256=cbSM8TKTuhbXsTIIB06pMtydBOiqLkitF2Lj2asVTho,1082
30
33
  r5py/util/exceptions.py,sha256=i1FyTuas43HnlLUIf3zip0Eie2S0j09EcgB9KnmQoKE,1121
31
34
  r5py/util/file_digest.py,sha256=95UbaxbTZLa54j1CupsKria028xZ8f6ueZsTupnjlYE,1061
32
35
  r5py/util/good_enough_equidistant_crs.py,sha256=7FX3Ly3qegSV_YRA4OFk49LC29xUyTte1Gc5qOEi_9E,2458
33
- r5py/util/jvm.py,sha256=NCwoYLDznXydcIRAZl2kzUQA6D6NCvzjVG74pm6ioR0,5027
36
+ r5py/util/jvm.py,sha256=ddLh1GI8dBJE-BAe8ScEvYyCVuU7qPDZK58hn_wICbE,5113
34
37
  r5py/util/memory_footprint.py,sha256=p8efCUs4UXRg6P1GrRxVs71m7SpEw2mASoz6PVTRvgQ,4672
35
38
  r5py/util/parse_int_date.py,sha256=JmnV8TwdUdUp3kSp2e73ZSxCbRyqv2FmQzNt0I_MsM0,667
36
39
  r5py/util/sample_data_set.py,sha256=aqUCx6drWD-WbCauewO4EzgOGnFr35mAZt-YHlqb92k,2463
@@ -39,8 +42,8 @@ r5py/util/spatially_clustered_geodataframe.py,sha256=FxG8V3SSeK-PuCep565p1b3TNcl
39
42
  r5py/util/validating_requests_session.py,sha256=sH5FgpS9eGax5DG2qA2GrGuiwgTJgh8tKsZ9OiXKmvk,1807
40
43
  r5py/util/warnings.py,sha256=CvxKWKlNO_p3riB4SkNqbU5AGPsaY_3-OzqaBObE3B8,139
41
44
  r5py/util/working_copy.py,sha256=sbLbRCi39LtC-0tXxvh2y7ZN2D15chbhleCZXzHAFSc,1432
42
- r5py-1.0.3.dev0.dist-info/licenses/LICENSE,sha256=VAnuGDX1TPylSN9G2xLa-urDpj_SQwn-qqs068dx4tk,51
43
- r5py-1.0.3.dev0.dist-info/METADATA,sha256=GnVvhl0wT1TNeqWnslpiwmvpw2fYJl62oUjkfptcsss,9981
44
- r5py-1.0.3.dev0.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
45
- r5py-1.0.3.dev0.dist-info/top_level.txt,sha256=fOH1R85dkNDOI7jkg-lIsl5CQIO4fE5X868K9dTqs9U,5
46
- r5py-1.0.3.dev0.dist-info/RECORD,,
45
+ r5py-1.0.5.dist-info/licenses/LICENSE,sha256=VAnuGDX1TPylSN9G2xLa-urDpj_SQwn-qqs068dx4tk,51
46
+ r5py-1.0.5.dist-info/METADATA,sha256=gZw-LnQXOwdZur7nz04k6u06GjtbAL4Y7kD5MTBx6eo,10000
47
+ r5py-1.0.5.dist-info/WHEEL,sha256=QZxptf4Y1BKFRCEDxD4h2V0mBFQOVFLFEpvxHmIs52A,91
48
+ r5py-1.0.5.dist-info/top_level.txt,sha256=fOH1R85dkNDOI7jkg-lIsl5CQIO4fE5X868K9dTqs9U,5
49
+ r5py-1.0.5.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (78.1.0)
2
+ Generator: setuptools (80.6.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5