Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use Pathlib #149

Merged
merged 3 commits into from
May 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,13 @@

import sys
import os
from pathlib import Path


# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
sys.path.insert(0, os.path.abspath("."))
# documentation root, use Path.resolve() to make it absolute, like shown here.
sys.path.insert(0, str(Path(".").resolve()))
sys.path.insert(0, "../examples")
sys.path.insert(0, "../mesa_geo")

Expand Down
4 changes: 2 additions & 2 deletions mesa_geo/visualization/modules/MapVisualization.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
from __future__ import annotations

import dataclasses
import os
from dataclasses import dataclass
from pathlib import Path

import geopandas as gpd
import xyzservices
Expand Down Expand Up @@ -45,7 +45,7 @@ class MapModule(VisualizationElement):
"css/external/leaflet.css",
"js/external/leaflet.js",
]
local_dir = os.path.dirname(__file__) + "/../templates"
local_dir = (Path(__file__).parent / "../templates").resolve()

def __init__(
self,
Expand Down
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ long_description_content_type = text/markdown
keywords = agent-based modeling, geographic information system, python, complex system
author = Project Mesa-Geo Team
zip_safe = False
license_file = LICENSE
license_files = LICENSE
license = Apache License Version 2.0
classifiers =
Topic :: Scientific/Engineering
Expand Down
52 changes: 35 additions & 17 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import re
import shutil
import urllib.request
from pathlib import Path

from setuptools import setup
from setuptools.command.build_py import build_py
Expand All @@ -30,41 +31,58 @@ def get_frontend_dep():
leaflet_version = "1.8.0"
ensure_frontend_dep_single(
f"https://unpkg.com/leaflet@{leaflet_version}/dist/leaflet.js",
external_dir_single="mesa_geo/visualization/templates/js/external",
external_dir_single=Path("mesa_geo/visualization/templates/js/external"),
integrity_hash="sha512-BB3hKbKWOc9Ez/TAwyWxNXeoV9c1v6FIeYiBieIWkpLjauysF18NzgR1MBNBXf8/KABdlkX68nAhlwcDFLGPCQ==",
)
ensure_frontend_dep_single(
f"https://unpkg.com/leaflet@{leaflet_version}/dist/leaflet.css",
external_dir_single="mesa_geo/visualization/templates/css/external",
external_dir_single=Path("mesa_geo/visualization/templates/css/external"),
integrity_hash="sha512-hoalWLoI8r4UszCkZ5kL8vayOGVae1oxXe/2A4AO6J9+580uKHDO3JdHb7NzwwzK5xr/Fs0W40kiNHxM9vyTtQ==",
)


def make_hash(filepath):
with open(filepath, "rb") as f:
file_as_bytes = f.read()
file_hash = base64.b64encode(hashlib.sha512(file_as_bytes).digest())
return "sha512-" + file_hash.decode()


def ensure_frontend_dep_single(
url, external_dir_single, out_name=None, integrity_hash=None
):
def _hash(filepath):
with open(filepath, "rb") as f:
file_as_bytes = f.read()
file_hash = base64.b64encode(hashlib.sha512(file_as_bytes).digest())
return "sha512-" + file_hash.decode()

os.makedirs(external_dir_single, exist_ok=True)
external_dir_single.mkdir(parents=True, exist_ok=True)
# Used for downloading e.g. Leaflet single file
if out_name is None:
out_name = url.split("/")[-1]
dst_path = os.path.join(external_dir_single, out_name)
if os.path.isfile(dst_path):
if integrity_hash and (_hash(dst_path) == integrity_hash):
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@wang-boyu : This if/else block doesn't appear to have any function, so we're suggesting removing it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for pointing this out! This looks like a bug introduced via #61. It was meant to compare the hash with existing file if there's any, and avoids downloading if the hashes match.

Instead of removing it, I would suggest to fix the issue. Perhaps we could delete the return after else statement, and indent some of the code below into else?

return
else:
return
dst_path = external_dir_single / out_name
print(f"Checking for presence of {dst_path=} {dst_path.is_file()=}")

if not dst_path.is_file():
download_frontend_dep_single(url, dst_path, out_name, integrity_hash)
return

if integrity_hash is None:
# File is present and assumed to be valid
print(f"{out_name} is present and assumed to be valid; not downloading")
return

if make_hash(dst_path) == integrity_hash:
# File is present and confirmed valid
print("{out_name} is present and confirmed valid; not downloading")
return

download_frontend_dep_single(url, dst_path, out_name, integrity_hash)


def download_frontend_dep_single(url, dst_path, out_name, integrity_hash):
print(f"Downloading the {out_name} dependency from the internet...")
urllib.request.urlretrieve(url, out_name)
if integrity_hash and ((actual_hash := _hash(out_name)) != integrity_hash):
if integrity_hash and ((actual_hash := make_hash(out_name)) != integrity_hash):
os.remove(out_name)
raise ValueError(
f"Integrity check failed for {out_name}. Expected {integrity_hash}, received {actual_hash}."
f"Integrity check failed for {out_name}. Expected {integrity_hash}, "
f"received {actual_hash}."
)
shutil.move(out_name, dst_path)

Expand Down
11 changes: 6 additions & 5 deletions tests/test_Examples.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import contextlib
import importlib
import os.path
import os
import sys
import unittest
from pathlib import Path


def classcase(name):
Expand All @@ -16,17 +17,17 @@ class TestExamples(unittest.TestCase):
details of each example's model.
"""

EXAMPLES = os.path.abspath(os.path.join(os.path.dirname(__file__), "../examples"))
EXAMPLES = (Path(__file__).parent / "../examples").resolve()

@contextlib.contextmanager
def active_example_dir(self, example):
"save and restore sys.path and sys.modules"
old_sys_path = sys.path[:]
old_sys_modules = sys.modules.copy()
old_cwd = os.getcwd()
example_path = os.path.abspath(os.path.join(self.EXAMPLES, example))
old_cwd = Path.cwd()
example_path = self.EXAMPLES / example
try:
sys.path.insert(0, example_path)
sys.path.insert(0, str(example_path))
os.chdir(example_path)
yield
finally:
Expand Down