diff --git a/.github/workflows/build_lint.yml b/.github/workflows/build_lint.yml new file mode 100644 index 00000000..dcfc1c74 --- /dev/null +++ b/.github/workflows/build_lint.yml @@ -0,0 +1,48 @@ +name: build + +on: + push: + branches: + - main + - release** + paths-ignore: + - '**.md' + - '**.rst' + pull_request: + paths-ignore: + - '**.md' + - '**.rst' + +# This will cancel previous run if a newer job that obsoletes the said previous +# run, is started. +# Based on https://github.com/zulip/zulip/commit/4a11642cee3c8aec976d305d51a86e60e5d70522 +concurrency: + group: "${{ github.workflow }}-${{ github.head_ref || github.run_id }}" + cancel-in-progress: true + +jobs: + lint-ruff: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Set up Python 3.10 + uses: actions/setup-python@v4 + with: + python-version: "3.10" + - run: pip install ruff==0.0.275 + - name: Lint with ruff + # Include `--format=github` to enable automatic inline annotations. + # Use settings from pyproject.toml. + run: ruff . --format=github + + lint-black: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Set up Python 3.10 + uses: actions/setup-python@v4 + with: + python-version: "3.10" + - run: pip install black[jupyter] + - name: Lint with black + run: black --check . diff --git a/examples/bank_reserves/bank_reserves/agents.py b/examples/bank_reserves/bank_reserves/agents.py index 1e6453b5..080378da 100644 --- a/examples/bank_reserves/bank_reserves/agents.py +++ b/examples/bank_reserves/bank_reserves/agents.py @@ -11,7 +11,6 @@ """ import mesa - from bank_reserves.random_walk import RandomWalker diff --git a/examples/bank_reserves/bank_reserves/model.py b/examples/bank_reserves/bank_reserves/model.py index 7505df8a..08bbc5b2 100644 --- a/examples/bank_reserves/bank_reserves/model.py +++ b/examples/bank_reserves/bank_reserves/model.py @@ -12,7 +12,6 @@ import mesa import numpy as np - from bank_reserves.agents import Bank, Person """ diff --git a/examples/bank_reserves/bank_reserves/server.py b/examples/bank_reserves/bank_reserves/server.py index c66cd920..f0acbd09 100644 --- a/examples/bank_reserves/bank_reserves/server.py +++ b/examples/bank_reserves/bank_reserves/server.py @@ -1,5 +1,4 @@ import mesa - from bank_reserves.agents import Person from bank_reserves.model import BankReserves diff --git a/examples/bank_reserves/batch_run.py b/examples/bank_reserves/batch_run.py index 3f0249da..8aa642a7 100644 --- a/examples/bank_reserves/batch_run.py +++ b/examples/bank_reserves/batch_run.py @@ -29,7 +29,6 @@ import mesa import numpy as np import pandas as pd - from bank_reserves.agents import Bank, Person # Start of datacollector functions diff --git a/examples/boid_flockers/boid_flockers/model.py b/examples/boid_flockers/boid_flockers/model.py index d694265b..3f7428f0 100644 --- a/examples/boid_flockers/boid_flockers/model.py +++ b/examples/boid_flockers/boid_flockers/model.py @@ -46,7 +46,7 @@ def __init__( self.separation = separation self.schedule = mesa.time.RandomActivation(self) self.space = mesa.space.ContinuousSpace(width, height, True) - self.factors = dict(cohere=cohere, separate=separate, match=match) + self.factors = {"cohere": cohere, "separate": separate, "match": match} self.make_agents() self.running = True diff --git a/examples/boltzmann_wealth_model/app.py b/examples/boltzmann_wealth_model/app.py index 8118cc70..f2dd6da9 100644 --- a/examples/boltzmann_wealth_model/app.py +++ b/examples/boltzmann_wealth_model/app.py @@ -1,13 +1,9 @@ -from boltzmann_wealth_model.model import BoltzmannWealthModel - -import streamlit as st - import time -import pandas as pd - import altair as alt - +import pandas as pd +import streamlit as st +from boltzmann_wealth_model.model import BoltzmannWealthModel model = st.title("Boltzman Wealth Model") num_agents = st.slider( diff --git a/examples/boltzmann_wealth_model_network/boltzmann_wealth_model_network/server.py b/examples/boltzmann_wealth_model_network/boltzmann_wealth_model_network/server.py index abc493a3..fce6b4cd 100644 --- a/examples/boltzmann_wealth_model_network/boltzmann_wealth_model_network/server.py +++ b/examples/boltzmann_wealth_model_network/boltzmann_wealth_model_network/server.py @@ -6,7 +6,7 @@ def network_portrayal(G): # The model ensures there is 0 or 1 agent per node - portrayal = dict() + portrayal = {} portrayal["nodes"] = [ { "id": node_id, diff --git a/examples/caching_and_replay/cacheablemodel.py b/examples/caching_and_replay/cacheablemodel.py index c999526a..0a9e35cd 100644 --- a/examples/caching_and_replay/cacheablemodel.py +++ b/examples/caching_and_replay/cacheablemodel.py @@ -1,5 +1,5 @@ -from model import Schelling from mesa_replay import CacheableModel, CacheState +from model import Schelling class CacheableSchelling(CacheableModel): diff --git a/examples/caching_and_replay/model.py b/examples/caching_and_replay/model.py index 0f718d59..47fa9891 100644 --- a/examples/caching_and_replay/model.py +++ b/examples/caching_and_replay/model.py @@ -66,10 +66,7 @@ def __init__(self, width=20, height=20, density=0.8, minority_pc=0.2, homophily= x = cell[1] y = cell[2] if self.random.random() < self.density: - if self.random.random() < self.minority_pc: - agent_type = 1 - else: - agent_type = 0 + agent_type = 1 if self.random.random() < self.minority_pc else 0 agent = SchellingAgent((x, y), self, agent_type) self.grid.place_agent(agent, (x, y)) diff --git a/examples/caching_and_replay/run.py b/examples/caching_and_replay/run.py index d5c12589..534d2080 100644 --- a/examples/caching_and_replay/run.py +++ b/examples/caching_and_replay/run.py @@ -1,14 +1,8 @@ from pathlib import Path import mesa - -from server import ( - canvas_element, - get_happy_agents, - happy_chart, - model_params, -) from cacheablemodel import CacheableSchelling +from server import canvas_element, get_happy_agents, happy_chart, model_params # As 'replay' is a simulation model parameter in this example, we need to make it available as such model_params["replay"] = mesa.visualization.Checkbox("Replay cached run?", False) diff --git a/examples/caching_and_replay/server.py b/examples/caching_and_replay/server.py index 7d3545d1..529f3dd2 100644 --- a/examples/caching_and_replay/server.py +++ b/examples/caching_and_replay/server.py @@ -1,7 +1,6 @@ """This file was copied over from the original Schelling mesa example.""" import mesa - from model import Schelling diff --git a/examples/charts/charts/agents.py b/examples/charts/charts/agents.py index a526a190..d4252283 100644 --- a/examples/charts/charts/agents.py +++ b/examples/charts/charts/agents.py @@ -11,7 +11,6 @@ """ import mesa - from charts.random_walk import RandomWalker diff --git a/examples/charts/charts/model.py b/examples/charts/charts/model.py index d7dbb886..5b8824e3 100644 --- a/examples/charts/charts/model.py +++ b/examples/charts/charts/model.py @@ -12,7 +12,6 @@ import mesa import numpy as np - from charts.agents import Bank, Person """ diff --git a/examples/charts/charts/server.py b/examples/charts/charts/server.py index ba7bfbdf..48f7e6d9 100644 --- a/examples/charts/charts/server.py +++ b/examples/charts/charts/server.py @@ -1,5 +1,4 @@ import mesa - from charts.agents import Person from charts.model import Charts diff --git a/examples/color_patches/color_patches/model.py b/examples/color_patches/color_patches/model.py index 4ac66920..a6619dab 100644 --- a/examples/color_patches/color_patches/model.py +++ b/examples/color_patches/color_patches/model.py @@ -115,7 +115,7 @@ def grid(self): 80 cell_objects = model.grid.get_cell_list_contents([(x, y)]) AttributeError: 'ColorPatches' object has no attribute 'grid' - """ # noqa: E501 + """ return self._grid @property diff --git a/examples/conways_game_of_life/app.py b/examples/conways_game_of_life/app.py index be739caa..0977b6f3 100644 --- a/examples/conways_game_of_life/app.py +++ b/examples/conways_game_of_life/app.py @@ -1,18 +1,10 @@ -import mesa -import streamlit as st - import time -import pandas as pd - import altair as alt - - import numpy as np -from conways_game_of_life.model import ConwaysGameOfLife - import pandas as pd - +import streamlit as st +from conways_game_of_life.model import ConwaysGameOfLife model = st.title("Boltzman Wealth Model") num_ticks = st.slider("Select number of Steps", min_value=1, max_value=100, value=50) diff --git a/examples/conways_game_of_life/conways_game_of_life/server.py b/examples/conways_game_of_life/conways_game_of_life/server.py index 4167b3d0..6da932f3 100644 --- a/examples/conways_game_of_life/conways_game_of_life/server.py +++ b/examples/conways_game_of_life/conways_game_of_life/server.py @@ -1,8 +1,7 @@ import mesa -from .portrayal import portrayCell from .model import ConwaysGameOfLife - +from .portrayal import portrayCell # Make a world that is 50x50, on a 250x250 display. canvas_element = mesa.visualization.CanvasGrid(portrayCell, 50, 50, 250, 250) diff --git a/examples/epstein_civil_violence/epstein_civil_violence/model.py b/examples/epstein_civil_violence/epstein_civil_violence/model.py index 4784f08b..4ba70ecb 100644 --- a/examples/epstein_civil_violence/epstein_civil_violence/model.py +++ b/examples/epstein_civil_violence/epstein_civil_violence/model.py @@ -1,6 +1,6 @@ import mesa -from .agent import Cop, Citizen +from .agent import Citizen, Cop class EpsteinCivilViolence(mesa.Model): diff --git a/examples/epstein_civil_violence/epstein_civil_violence/server.py b/examples/epstein_civil_violence/epstein_civil_violence/server.py index 6b835bd2..04412835 100644 --- a/examples/epstein_civil_violence/epstein_civil_violence/server.py +++ b/examples/epstein_civil_violence/epstein_civil_violence/server.py @@ -1,8 +1,7 @@ import mesa -from .model import EpsteinCivilViolence from .agent import Citizen, Cop - +from .model import EpsteinCivilViolence COP_COLOR = "#000000" AGENT_QUIET_COLOR = "#0066CC" @@ -37,16 +36,16 @@ def citizen_cop_portrayal(agent): return portrayal -model_params = dict( - height=40, - width=40, - citizen_density=0.7, - cop_density=0.074, - citizen_vision=7, - cop_vision=7, - legitimacy=0.8, - max_jail_term=1000, -) +model_params = { + "height": 40, + "width": 40, + "citizen_density": 0.7, + "cop_density": 0.074, + "citizen_vision": 7, + "cop_vision": 7, + "legitimacy": 0.8, + "max_jail_term": 1000, +} canvas_element = mesa.visualization.CanvasGrid(citizen_cop_portrayal, 40, 40, 480, 480) server = mesa.visualization.ModularServer( diff --git a/examples/hex_snowflake/hex_snowflake/model.py b/examples/hex_snowflake/hex_snowflake/model.py index 43db160b..28abab00 100644 --- a/examples/hex_snowflake/hex_snowflake/model.py +++ b/examples/hex_snowflake/hex_snowflake/model.py @@ -1,5 +1,4 @@ import mesa - from hex_snowflake.cell import Cell diff --git a/examples/hex_snowflake/hex_snowflake/server.py b/examples/hex_snowflake/hex_snowflake/server.py index 3095bd5c..f00f20c9 100644 --- a/examples/hex_snowflake/hex_snowflake/server.py +++ b/examples/hex_snowflake/hex_snowflake/server.py @@ -1,7 +1,6 @@ import mesa - -from hex_snowflake.portrayal import portrayCell from hex_snowflake.model import HexSnowflake +from hex_snowflake.portrayal import portrayCell width, height = 50, 50 diff --git a/examples/pd_grid/pd_grid/server.py b/examples/pd_grid/pd_grid/server.py index 50095311..f2447da3 100644 --- a/examples/pd_grid/pd_grid/server.py +++ b/examples/pd_grid/pd_grid/server.py @@ -1,8 +1,7 @@ import mesa -from .portrayal import portrayPDAgent from .model import PdGrid - +from .portrayal import portrayPDAgent # Make a world that is 50x50, on a 500x500 display. canvas_element = mesa.visualization.CanvasGrid(portrayPDAgent, 50, 50, 500, 500) diff --git a/examples/schelling/model.py b/examples/schelling/model.py index 821b68af..ccc5699e 100644 --- a/examples/schelling/model.py +++ b/examples/schelling/model.py @@ -64,10 +64,7 @@ def __init__(self, width=20, height=20, density=0.8, minority_pc=0.2, homophily= x = cell[1] y = cell[2] if self.random.random() < self.density: - if self.random.random() < self.minority_pc: - agent_type = 1 - else: - agent_type = 0 + agent_type = 1 if self.random.random() < self.minority_pc else 0 agent = SchellingAgent((x, y), self, agent_type) self.grid.place_agent(agent, (x, y)) diff --git a/examples/schelling/run_ascii.py b/examples/schelling/run_ascii.py index 8d70c397..460fabbb 100644 --- a/examples/schelling/run_ascii.py +++ b/examples/schelling/run_ascii.py @@ -1,5 +1,4 @@ import mesa - from model import Schelling diff --git a/examples/schelling/server.py b/examples/schelling/server.py index fd643096..1396e9c7 100644 --- a/examples/schelling/server.py +++ b/examples/schelling/server.py @@ -1,5 +1,4 @@ import mesa - from model import Schelling diff --git a/examples/shape_example/shape_example/server.py b/examples/shape_example/shape_example/server.py index 4f8b59e3..5d31f888 100644 --- a/examples/shape_example/shape_example/server.py +++ b/examples/shape_example/shape_example/server.py @@ -1,6 +1,6 @@ import mesa -from .model import Walker, ShapeExample +from .model import ShapeExample, Walker def agent_draw(agent): diff --git a/examples/sugarscape_cg/sugarscape_cg/server.py b/examples/sugarscape_cg/sugarscape_cg/server.py index 54a3e857..0461cdce 100644 --- a/examples/sugarscape_cg/sugarscape_cg/server.py +++ b/examples/sugarscape_cg/sugarscape_cg/server.py @@ -14,10 +14,7 @@ def SsAgent_portrayal(agent): return {"Shape": "sugarscape_cg/resources/ant.png", "scale": 0.9, "Layer": 1} elif type(agent) is Sugar: - if agent.amount != 0: - color = color_dic[agent.amount] - else: - color = "#D6F5D6" + color = color_dic[agent.amount] if agent.amount != 0 else "#D6F5D6" return { "Color": color, "Shape": "rect", diff --git a/examples/sugarscape_g1mt/run.py b/examples/sugarscape_g1mt/run.py index 2f95cac7..7f2eb274 100644 --- a/examples/sugarscape_g1mt/run.py +++ b/examples/sugarscape_g1mt/run.py @@ -1,8 +1,9 @@ import sys -import pandas as pd + import matplotlib.pyplot as plt -import networkx as nx import mesa +import networkx as nx +import pandas as pd from sugarscape_g1mt.model import SugarscapeG1mt from sugarscape_g1mt.server import server diff --git a/examples/sugarscape_g1mt/sugarscape_g1mt/model.py b/examples/sugarscape_g1mt/sugarscape_g1mt/model.py index 78dc275b..a7ed5200 100644 --- a/examples/sugarscape_g1mt/sugarscape_g1mt/model.py +++ b/examples/sugarscape_g1mt/sugarscape_g1mt/model.py @@ -1,9 +1,8 @@ +import mesa import numpy as np - -import mesa +from .resource_agents import Spice, Sugar from .trader_agents import Trader -from .resource_agents import Sugar, Spice # Helper Functions diff --git a/examples/sugarscape_g1mt/sugarscape_g1mt/server.py b/examples/sugarscape_g1mt/sugarscape_g1mt/server.py index b5a8c32f..fbc10ce6 100644 --- a/examples/sugarscape_g1mt/sugarscape_g1mt/server.py +++ b/examples/sugarscape_g1mt/sugarscape_g1mt/server.py @@ -1,9 +1,8 @@ import mesa -from .resource_agents import Sugar, Spice -from .trader_agents import Trader from .model import SugarscapeG1mt - +from .resource_agents import Spice, Sugar +from .trader_agents import Trader sugar_dic = {4: "#005C00", 3: "#008300", 2: "#00AA00", 1: "#00F800"} spice_dic = {4: "#acac00", 3: "#c5c500", 2: "#dfdf00", 1: "#f8f800"} @@ -23,14 +22,8 @@ def Agent_portrayal(agent): } elif isinstance(agent, Sugar): - if agent.amount != 0: - color = sugar_dic[agent.amount] - else: - color = "#D6F5D6" - if agent.amount > 2: - layer = 1 - else: - layer = 0 + color = sugar_dic[agent.amount] if agent.amount != 0 else "#D6F5D6" + layer = 1 if agent.amount > 2 else 0 return { "Color": color, "Shape": "rect", @@ -41,14 +34,8 @@ def Agent_portrayal(agent): } elif isinstance(agent, Spice): - if agent.amount != 0: - color = spice_dic[agent.amount] - else: - color = "#D6F5D6" - if agent.amount > 2: - layer = 1 - else: - layer = 0 + color = spice_dic[agent.amount] if agent.amount != 0 else "#D6F5D6" + layer = 1 if agent.amount > 2 else 0 return { "Color": color, "Shape": "rect", diff --git a/examples/sugarscape_g1mt/sugarscape_g1mt/trader_agents.py b/examples/sugarscape_g1mt/sugarscape_g1mt/trader_agents.py index 7607a69d..e396f72f 100644 --- a/examples/sugarscape_g1mt/sugarscape_g1mt/trader_agents.py +++ b/examples/sugarscape_g1mt/sugarscape_g1mt/trader_agents.py @@ -1,6 +1,8 @@ import math + import mesa -from .resource_agents import Sugar, Spice + +from .resource_agents import Spice, Sugar # Helper function @@ -111,11 +113,7 @@ def is_occupied_by_other(self, pos): return False # get contents of each cell in neighborhood this_cell = self.model.grid.get_cell_list_contents(pos) - for a in this_cell: - # see if occupied by another agent - if isinstance(a, Trader): - return True - return False + return any(isinstance(a, Trader) for a in this_cell) def calculate_welfare(self, sugar, spice): """ diff --git a/examples/virus_on_network/virus_on_network/model.py b/examples/virus_on_network/virus_on_network/model.py index 6e079ffb..6f952490 100644 --- a/examples/virus_on_network/virus_on_network/model.py +++ b/examples/virus_on_network/virus_on_network/model.py @@ -1,8 +1,8 @@ import math from enum import Enum -import networkx as nx import mesa +import networkx as nx class State(Enum): @@ -148,10 +148,10 @@ def try_remove_infection(self): self.state = State.INFECTED def try_check_situation(self): - if self.random.random() < self.virus_check_frequency: - # Checking... - if self.state is State.INFECTED: - self.try_remove_infection() + if (self.random.random() < self.virus_check_frequency) and ( + self.state is State.INFECTED + ): + self.try_remove_infection() def step(self): if self.state is State.INFECTED: diff --git a/examples/virus_on_network/virus_on_network/server.py b/examples/virus_on_network/virus_on_network/server.py index a8f47c61..c49306a9 100644 --- a/examples/virus_on_network/virus_on_network/server.py +++ b/examples/virus_on_network/virus_on_network/server.py @@ -2,7 +2,7 @@ import mesa -from .model import VirusOnNetwork, State, number_infected +from .model import State, VirusOnNetwork, number_infected def network_portrayal(G): @@ -26,7 +26,7 @@ def edge_width(agent1, agent2): def get_agents(source, target): return G.nodes[source]["agent"][0], G.nodes[target]["agent"][0] - portrayal = dict() + portrayal = {} portrayal["nodes"] = [ { "size": 6, @@ -103,7 +103,7 @@ def get_resistant_susceptible_ratio(model): 0.0, 1.0, 0.1, - description="Frequency the nodes check whether they are infected by " "a virus", + description="Frequency the nodes check whether they are infected by a virus", ), "recovery_chance": mesa.visualization.Slider( "Recovery Chance", diff --git a/examples/wolf_sheep/wolf_sheep/agents.py b/examples/wolf_sheep/wolf_sheep/agents.py index 91a511fd..eef30d54 100644 --- a/examples/wolf_sheep/wolf_sheep/agents.py +++ b/examples/wolf_sheep/wolf_sheep/agents.py @@ -1,4 +1,5 @@ import mesa + from .random_walk import RandomWalker diff --git a/examples/wolf_sheep/wolf_sheep/model.py b/examples/wolf_sheep/wolf_sheep/model.py index ec23c5a6..ac44beff 100644 --- a/examples/wolf_sheep/wolf_sheep/model.py +++ b/examples/wolf_sheep/wolf_sheep/model.py @@ -11,8 +11,8 @@ import mesa +from .agents import GrassPatch, Sheep, Wolf from .scheduler import RandomActivationByTypeFiltered -from .agents import Sheep, Wolf, GrassPatch class WolfSheep(mesa.Model): diff --git a/examples/wolf_sheep/wolf_sheep/scheduler.py b/examples/wolf_sheep/wolf_sheep/scheduler.py index cd3dac61..4279de71 100644 --- a/examples/wolf_sheep/wolf_sheep/scheduler.py +++ b/examples/wolf_sheep/wolf_sheep/scheduler.py @@ -1,4 +1,4 @@ -from typing import Type, Callable +from typing import Callable, Optional, Type import mesa @@ -16,7 +16,7 @@ class RandomActivationByTypeFiltered(mesa.time.RandomActivationByType): def get_type_count( self, type_class: Type[mesa.Agent], - filter_func: Callable[[mesa.Agent], bool] = None, + filter_func: Optional[Callable[[mesa.Agent], bool]] = None, ) -> int: """ Returns the current number of agents of certain type in the queue diff --git a/examples/wolf_sheep/wolf_sheep/server.py b/examples/wolf_sheep/wolf_sheep/server.py index bccf4ec8..7b1b831a 100644 --- a/examples/wolf_sheep/wolf_sheep/server.py +++ b/examples/wolf_sheep/wolf_sheep/server.py @@ -1,6 +1,6 @@ import mesa -from wolf_sheep.agents import Wolf, Sheep, GrassPatch +from wolf_sheep.agents import GrassPatch, Sheep, Wolf from wolf_sheep.model import WolfSheep diff --git a/examples/wolf_sheep/wolf_sheep/test_random_walk.py b/examples/wolf_sheep/wolf_sheep/test_random_walk.py index ab3b044a..0ba480cc 100644 --- a/examples/wolf_sheep/wolf_sheep/test_random_walk.py +++ b/examples/wolf_sheep/wolf_sheep/test_random_walk.py @@ -6,7 +6,7 @@ from mesa import Model from mesa.space import MultiGrid from mesa.time import RandomActivation -from mesa.visualization.TextVisualization import TextVisualization, TextGrid +from mesa.visualization.TextVisualization import TextGrid, TextVisualization from wolf_sheep.random_walk import RandomWalker diff --git a/gis/agents_and_networks/scripts/run.py b/gis/agents_and_networks/scripts/run.py index b46d5197..1a4a71a3 100644 --- a/gis/agents_and_networks/scripts/run.py +++ b/gis/agents_and_networks/scripts/run.py @@ -2,13 +2,12 @@ import mesa import mesa_geo as mg - from src.model.model import AgentsAndNetworks from src.visualization.server import ( agent_draw, clock_element, - status_chart, friendship_chart, + status_chart, ) diff --git a/gis/agents_and_networks/src/agent/building.py b/gis/agents_and_networks/src/agent/building.py index b28069e9..cc260a3b 100644 --- a/gis/agents_and_networks/src/agent/building.py +++ b/gis/agents_and_networks/src/agent/building.py @@ -3,9 +3,9 @@ import uuid from random import randrange -import pyproj import mesa import mesa_geo as mg +import pyproj from shapely.geometry import Polygon diff --git a/gis/agents_and_networks/src/agent/commuter.py b/gis/agents_and_networks/src/agent/commuter.py index c14b2e99..71c59f1e 100644 --- a/gis/agents_and_networks/src/agent/commuter.py +++ b/gis/agents_and_networks/src/agent/commuter.py @@ -2,14 +2,14 @@ import random -import pyproj -import numpy as np import mesa import mesa_geo as mg -from shapely.geometry import Point, LineString +import numpy as np +import pyproj +from shapely.geometry import LineString, Point from src.agent.building import Building -from src.space.utils import redistribute_vertices, UnitTransformer +from src.space.utils import UnitTransformer, redistribute_vertices class Commuter(mg.GeoAgent): diff --git a/gis/agents_and_networks/src/agent/geo_agents.py b/gis/agents_and_networks/src/agent/geo_agents.py index 49ab46ed..09ef1c79 100644 --- a/gis/agents_and_networks/src/agent/geo_agents.py +++ b/gis/agents_and_networks/src/agent/geo_agents.py @@ -1,7 +1,7 @@ import mesa import mesa_geo as mg -from shapely.geometry import Point import pyproj +from shapely.geometry import Point class Driveway(mg.GeoAgent): diff --git a/gis/agents_and_networks/src/model/model.py b/gis/agents_and_networks/src/model/model.py index 662c7441..954440ff 100644 --- a/gis/agents_and_networks/src/model/model.py +++ b/gis/agents_and_networks/src/model/model.py @@ -1,15 +1,15 @@ import uuid from functools import partial -import pandas as pd import geopandas as gpd import mesa import mesa_geo as mg +import pandas as pd from shapely.geometry import Point +from src.agent.building import Building from src.agent.commuter import Commuter from src.agent.geo_agents import Driveway, LakeAndRiver, Walkway -from src.agent.building import Building from src.space.campus import Campus from src.space.road_network import CampusWalkway diff --git a/gis/agents_and_networks/src/space/campus.py b/gis/agents_and_networks/src/space/campus.py index 8682a893..0d415538 100644 --- a/gis/agents_and_networks/src/space/campus.py +++ b/gis/agents_and_networks/src/space/campus.py @@ -1,13 +1,13 @@ import random from collections import defaultdict -from typing import Dict, Tuple, Optional, DefaultDict, Set +from typing import DefaultDict, Dict, Optional, Set, Tuple import mesa import mesa_geo as mg from shapely.geometry import Point -from src.agent.commuter import Commuter from src.agent.building import Building +from src.agent.commuter import Commuter class Campus(mg.GeoSpace): @@ -21,13 +21,13 @@ class Campus(mg.GeoSpace): def __init__(self, crs: str) -> None: super().__init__(crs=crs) - self.homes = tuple() - self.works = tuple() - self.other_buildings = tuple() + self.homes = () + self.works = () + self.other_buildings = () self.home_counter = defaultdict(int) - self._buildings = dict() + self._buildings = {} self._commuters_pos_map = defaultdict(set) - self._commuter_id_map = dict() + self._commuter_id_map = {} def get_random_home(self) -> Building: return random.choice(self.homes) diff --git a/gis/agents_and_networks/src/space/road_network.py b/gis/agents_and_networks/src/space/road_network.py index 7bba95d5..9f4d1940 100644 --- a/gis/agents_and_networks/src/space/road_network.py +++ b/gis/agents_and_networks/src/space/road_network.py @@ -3,10 +3,10 @@ import pickle import geopandas as gpd +import mesa import momepy -import pyproj import networkx as nx -import mesa +import pyproj from sklearn.neighbors import KDTree from src.space.utils import segmented @@ -72,7 +72,7 @@ def __init__(self, campus, lines) -> None: with open(self._path_cache_result, "rb") as cached_result: self._path_select_cache = pickle.load(cached_result) except FileNotFoundError: - self._path_select_cache = dict() + self._path_select_cache = {} def cache_path( self, diff --git a/gis/agents_and_networks/src/space/utils.py b/gis/agents_and_networks/src/space/utils.py index 51178b10..33e68d0f 100644 --- a/gis/agents_and_networks/src/space/utils.py +++ b/gis/agents_and_networks/src/space/utils.py @@ -1,9 +1,9 @@ -from typing import Tuple, List +from typing import List, Tuple import geopandas as gpd +import mesa import numpy as np import pyproj -import mesa from shapely.geometry import LineString, MultiLineString from shapely.ops import transform diff --git a/gis/agents_and_networks/src/visualization/server.py b/gis/agents_and_networks/src/visualization/server.py index f0d0ffd0..c8ea03b8 100644 --- a/gis/agents_and_networks/src/visualization/server.py +++ b/gis/agents_and_networks/src/visualization/server.py @@ -15,7 +15,7 @@ def render(self, model): def agent_draw(agent): - portrayal = dict() + portrayal = {} portrayal["color"] = "White" if isinstance(agent, Driveway): portrayal["color"] = "#D08004" diff --git a/gis/agents_and_networks/src/visualization/utils.py b/gis/agents_and_networks/src/visualization/utils.py index f54835cd..c31d1536 100644 --- a/gis/agents_and_networks/src/visualization/utils.py +++ b/gis/agents_and_networks/src/visualization/utils.py @@ -1,7 +1,7 @@ import datetime -import pandas as pd import matplotlib.pyplot as plt +import pandas as pd import seaborn as sns diff --git a/gis/geo_schelling/model.py b/gis/geo_schelling/model.py index ad90df9a..0f2d9a7b 100644 --- a/gis/geo_schelling/model.py +++ b/gis/geo_schelling/model.py @@ -1,7 +1,6 @@ import random import mesa - import mesa_geo as mg diff --git a/gis/geo_schelling/server.py b/gis/geo_schelling/server.py index f745a55d..0871e219 100644 --- a/gis/geo_schelling/server.py +++ b/gis/geo_schelling/server.py @@ -1,9 +1,8 @@ import mesa +import mesa_geo as mg import xyzservices.providers as xyz from model import GeoSchelling -import mesa_geo as mg - class HappyElement(mesa.visualization.TextElement): """ diff --git a/gis/geo_schelling_points/geo_schelling_points/agents.py b/gis/geo_schelling_points/geo_schelling_points/agents.py index dac03036..1296a207 100644 --- a/gis/geo_schelling_points/geo_schelling_points/agents.py +++ b/gis/geo_schelling_points/geo_schelling_points/agents.py @@ -1,8 +1,7 @@ import random -from shapely.geometry import Point - import mesa_geo as mg +from shapely.geometry import Point class PersonAgent(mg.GeoAgent): diff --git a/gis/geo_schelling_points/geo_schelling_points/model.py b/gis/geo_schelling_points/geo_schelling_points/model.py index b9c83d1b..b8544934 100644 --- a/gis/geo_schelling_points/geo_schelling_points/model.py +++ b/gis/geo_schelling_points/geo_schelling_points/model.py @@ -2,7 +2,6 @@ import uuid import mesa - import mesa_geo as mg from .agents import PersonAgent, RegionAgent diff --git a/gis/geo_schelling_points/geo_schelling_points/server.py b/gis/geo_schelling_points/geo_schelling_points/server.py index 44b2c9ee..b86ff744 100644 --- a/gis/geo_schelling_points/geo_schelling_points/server.py +++ b/gis/geo_schelling_points/geo_schelling_points/server.py @@ -1,5 +1,4 @@ import mesa - import mesa_geo as mg from .agents import PersonAgent, RegionAgent diff --git a/gis/geo_sir/agents.py b/gis/geo_sir/agents.py index 957e3b23..cbf0aff2 100644 --- a/gis/geo_sir/agents.py +++ b/gis/geo_sir/agents.py @@ -1,6 +1,5 @@ -from shapely.geometry import Point - import mesa_geo as mg +from shapely.geometry import Point class PersonAgent(mg.GeoAgent): diff --git a/gis/geo_sir/model.py b/gis/geo_sir/model.py index 741ba5f0..d6265e94 100644 --- a/gis/geo_sir/model.py +++ b/gis/geo_sir/model.py @@ -1,9 +1,8 @@ import mesa +import mesa_geo as mg from agents import NeighbourhoodAgent, PersonAgent from shapely.geometry import Point -import mesa_geo as mg - class GeoSir(mesa.Model): """Model class for a simplistic infection model.""" diff --git a/gis/geo_sir/server.py b/gis/geo_sir/server.py index b13b61d4..6f336ab0 100644 --- a/gis/geo_sir/server.py +++ b/gis/geo_sir/server.py @@ -1,9 +1,8 @@ import mesa +import mesa_geo as mg from agents import PersonAgent from model import GeoSir -import mesa_geo as mg - class InfectedText(mesa.visualization.TextElement): """ diff --git a/gis/population/population/model.py b/gis/population/population/model.py index 0dd48f50..6c1065ad 100644 --- a/gis/population/population/model.py +++ b/gis/population/population/model.py @@ -3,11 +3,10 @@ import uuid import mesa +import mesa_geo as mg import numpy as np from shapely.geometry import Point -import mesa_geo as mg - from .space import UgandaArea diff --git a/gis/population/population/server.py b/gis/population/population/server.py index ac97bb29..c598ed3a 100644 --- a/gis/population/population/server.py +++ b/gis/population/population/server.py @@ -1,7 +1,6 @@ import mesa -from shapely.geometry import Point, Polygon - import mesa_geo as mg +from shapely.geometry import Point, Polygon from .model import Population from .space import UgandaCell diff --git a/gis/population/population/space.py b/gis/population/population/space.py index f634aab4..02536b78 100644 --- a/gis/population/population/space.py +++ b/gis/population/population/space.py @@ -5,7 +5,6 @@ import geopandas as gpd import mesa - from mesa_geo.geoagent import GeoAgent from mesa_geo.geospace import GeoSpace from mesa_geo.raster_layers import Cell, RasterLayer diff --git a/gis/rainfall/rainfall/model.py b/gis/rainfall/rainfall/model.py index f0795049..380ff743 100644 --- a/gis/rainfall/rainfall/model.py +++ b/gis/rainfall/rainfall/model.py @@ -1,11 +1,10 @@ import uuid import mesa +import mesa_geo as mg import numpy as np from shapely.geometry import Point -import mesa_geo as mg - from .space import CraterLake diff --git a/gis/rainfall/rainfall/server.py b/gis/rainfall/rainfall/server.py index c798ec2b..1c92e6dd 100644 --- a/gis/rainfall/rainfall/server.py +++ b/gis/rainfall/rainfall/server.py @@ -1,7 +1,6 @@ from typing import Tuple import mesa - import mesa_geo as mg from .model import Rainfall diff --git a/gis/rainfall/rainfall/space.py b/gis/rainfall/rainfall/space.py index a52f51c3..6307d25f 100644 --- a/gis/rainfall/rainfall/space.py +++ b/gis/rainfall/rainfall/space.py @@ -3,9 +3,8 @@ import gzip import mesa -import numpy as np - import mesa_geo as mg +import numpy as np class LakeCell(mg.Cell): diff --git a/gis/urban_growth/urban_growth/server.py b/gis/urban_growth/urban_growth/server.py index ecc48488..5edfd6e0 100644 --- a/gis/urban_growth/urban_growth/server.py +++ b/gis/urban_growth/urban_growth/server.py @@ -1,7 +1,6 @@ from typing import Tuple import mesa - import mesa_geo as mg from .model import UrbanGrowth diff --git a/gis/urban_growth/urban_growth/space.py b/gis/urban_growth/urban_growth/space.py index bb48f3a2..b13450c0 100644 --- a/gis/urban_growth/urban_growth/space.py +++ b/gis/urban_growth/urban_growth/space.py @@ -4,11 +4,10 @@ import random import mesa +import mesa_geo as mg import numpy as np import rasterio as rio -import mesa_geo as mg - class UrbanCell(mg.Cell): urban: bool | None diff --git a/pyproject.toml b/pyproject.toml index 0462804c..81775f77 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -19,3 +19,61 @@ requires = [ "wheel", ] build-backend = "setuptools.build_meta" + +[tool.ruff] +# See https://github.com/charliermarsh/ruff#rules for error code definitions. +select = [ + # "ANN", # annotations TODO + "B", # bugbear + "C4", # comprehensions + "DTZ", # naive datetime + "E", # style errors + "F", # flakes + "I", # import sorting + "ISC", # string concatenation + "N", # naming + "PGH", # pygrep-hooks + "PIE", # miscellaneous + "PLC", # pylint convention + "PLE", # pylint error + # "PLR", # pylint refactor TODO + "PLW", # pylint warning + "Q", # quotes + "RUF", # Ruff + "S", # security + "SIM", # simplify + "T10", # debugger + "UP", # upgrade + "W", # style warnings + "YTT", # sys.version +] +# Ignore list taken from https://github.com/psf/black/blob/master/.flake8 +# E203 Whitespace before ':' +# E266 Too many leading '#' for block comment +# E501 Line too long (82 > 79 characters) +# W503 Line break occurred before a binary operator +# But we don't specify them because ruff's Black already +# checks for it. +# See https://github.com/charliermarsh/ruff/issues/1842#issuecomment-1381210185 +extend-ignore = [ + "E501", + "S101", # Use of `assert` detected + "B017", # `assertRaises(Exception)` should be considered evil TODO + "PGH004", # Use specific rule codes when using `noqa` TODO + "B905", # `zip()` without an explicit `strict=` parameter + "N802", # Function name should be lowercase + "N999", # Invalid module name. We should revisit this in the future, TODO + "B007", # Loop control variable `i` not used within loop body + "N806", # Variable `N` in function should be lowercase + "N803", # Argument name `N` should be lowercase + "RUF012", # Mutable class attributes should be annotated with `typing.ClassVar` TODO + "S311", # Standard pseudo-random generators are not suitable for cryptographic purposes TODO + "B008", # Do not perform function call `pyproj.CRS` in argument defaults TODO + "S301", # `pickle` and modules that wrap it can be unsafe when used to deserialize untrusted data, possible security issue TODO +] +# Hardcode to Python 3.8. +target-version = "py38" + +[tool.isort] +profile = "black" +sections = ['FUTURE', 'STDLIB', 'THIRDPARTY', 'LOCALFOLDER']